Skip to content

Commit 1ac150a

Browse files
committed
feat: morning greeting
1 parent 26f5f59 commit 1ac150a

File tree

8 files changed

+1292
-54
lines changed

8 files changed

+1292
-54
lines changed

app.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { App, LogLevel } from '@slack/bolt';
2-
import * as dotenv from 'dotenv';
3-
import registerListeners from './listeners';
1+
import { App, LogLevel } from "@slack/bolt";
2+
import * as dotenv from "dotenv";
3+
import registerListeners from "./listeners";
4+
import { setUpDailyGreeting } from "./intervals/morning";
45

56
dotenv.config();
67

@@ -9,18 +10,25 @@ const app = new App({
910
token: process.env.SLACK_BOT_TOKEN,
1011
socketMode: true,
1112
appToken: process.env.SLACK_APP_TOKEN,
12-
logLevel: LogLevel.DEBUG,
13+
logLevel: LogLevel.INFO,
1314
});
1415

1516
/** Register Listeners */
1617
registerListeners(app);
17-
18+
// setInterval(() => {
19+
// app.client.chat.postMessage({
20+
// text: "hi",
21+
// channel: "C0933GKG93Q",
22+
// });
23+
// }, 500);
1824
/** Start Bolt App */
25+
1926
(async () => {
2027
try {
2128
await app.start(process.env.PORT || 3000);
22-
app.logger.info('⚡️ Bolt app is running! ⚡️');
29+
app.logger.info("⚡️ Bolt app is running! ⚡️");
30+
setUpDailyGreeting(app, "C043UV30DHA");
2331
} catch (error) {
24-
app.logger.error('Unable to start App', error);
32+
app.logger.error("Unable to start App", error);
2533
}
2634
})();

intervals/morning.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { App, StringIndexed } from "@slack/bolt";
2+
import { DateTime } from "luxon";
3+
4+
const greetingTime = {
5+
hour: 9,
6+
minute: 0,
7+
second: 0,
8+
millisecond: 0,
9+
};
10+
const currentTime = DateTime.local({ zone: "America/New_York" });
11+
let nextMorningTime =
12+
currentTime.hour < greetingTime.hour
13+
? currentTime.set(greetingTime)
14+
: currentTime.set(greetingTime).plus({ days: 1 });
15+
const greetings = [
16+
"ohayou cmueats!",
17+
"morning",
18+
"yawwn good morning cmueats!",
19+
"How's life? Good morning!",
20+
"Do you ever wonder if you have free will?",
21+
];
22+
export const scheduleNextGreeting = (
23+
sendMessage: (msg: string) => Promise<unknown>,
24+
nextMorningTime: DateTime<true> // should be in desired timezone
25+
) => {
26+
const currentTime = DateTime.local({ zone: "America/New_York" });
27+
console.log(nextMorningTime);
28+
setTimeout(() => {
29+
sendMessage(greetings[Math.floor(Math.random() * greetings.length)]);
30+
scheduleNextGreeting(sendMessage, nextMorningTime.plus({ days: 1 })); // this actually accounts for DST properly
31+
}, nextMorningTime.diff(currentTime).toMillis());
32+
};
33+
34+
export const setUpDailyGreeting = (
35+
app: App<StringIndexed>,
36+
channelId: string
37+
) => {
38+
scheduleNextGreeting((msg: string) => {
39+
return app.client.chat
40+
.postMessage({
41+
text: msg,
42+
channel: channelId,
43+
})
44+
.catch(app.logger.error);
45+
}, nextMorningTime);
46+
};

listeners/events/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import type { App } from '@slack/bolt';
2-
import appHomeOpenedCallback from './app-home-opened';
1+
import type { App } from "@slack/bolt";
2+
import appHomeOpenedCallback from "./app-home-opened";
33

44
const register = (app: App) => {
5-
app.event('app_home_opened', appHomeOpenedCallback);
5+
app.event("app_home_opened", appHomeOpenedCallback);
6+
app.event("app_mention", async ({ payload, say }) => {
7+
await say("hai! I'm here to let you know when cmueats goes down :3");
8+
});
69
};
710

811
export default { register };

listeners/index.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import type { App } from '@slack/bolt';
2-
import actions from './actions';
3-
import commands from './commands';
4-
import events from './events';
5-
import messages from './messages';
6-
import shortcuts from './shortcuts';
7-
import views from './views';
1+
import type { App } from "@slack/bolt";
2+
import actions from "./actions";
3+
import commands from "./commands";
4+
import events from "./events";
5+
import messages from "./messages";
6+
import shortcuts from "./shortcuts";
7+
import views from "./views";
88

99
const registerListeners = (app: App) => {
1010
actions.register(app);

listeners/messages/index.ts

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,52 @@
1-
import type { App } from '@slack/bolt';
2-
import sampleMessageCallback from './sample-message';
1+
import type { App } from "@slack/bolt";
2+
import sampleMessageCallback from "./sample-message";
3+
4+
class GabeSenpaiMessages {
5+
index = 0;
6+
messages = [
7+
"who ya calling senpai? He's mine!",
8+
"~Stop playing with my feelings >_<",
9+
"...",
10+
"...",
11+
"okay now you're just taunting me",
12+
"I'm 25! geez",
13+
"...",
14+
"",
15+
"",
16+
"*pouty face",
17+
"",
18+
"",
19+
"",
20+
"Please stop",
21+
];
22+
lastMessageSentTimestamp = 0;
23+
FORGET_TIME_INTERVAL = 1000 * 60 * 30; // 30 min
24+
25+
getNextMessage() {
26+
const curTimestamp = +new Date();
27+
if (
28+
curTimestamp - this.lastMessageSentTimestamp >=
29+
this.FORGET_TIME_INTERVAL
30+
) {
31+
this.index = 0;
32+
}
33+
this.lastMessageSentTimestamp = curTimestamp;
34+
if (this.index < this.messages.length) {
35+
return this.messages[this.index++];
36+
}
37+
return "";
38+
}
39+
}
340

441
const register = (app: App) => {
5-
app.message(/^(hi|hello|hey).*/, sampleMessageCallback);
42+
const gabeMessages = new GabeSenpaiMessages();
43+
44+
app.message("gabe-senpai", async ({ say }) => {
45+
const nextMessage = gabeMessages.getNextMessage();
46+
if (nextMessage !== "") {
47+
await say(nextMessage);
48+
}
49+
});
650
};
751

852
export default { register };

manifest.json

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,19 @@
11
{
2-
"_metadata": {
3-
"major_version": 1,
4-
"minor_version": 1
5-
},
62
"display_information": {
7-
"name": "Bolt Template App"
3+
"name": "mem-cho (cmueats uptime monitor)"
84
},
95
"features": {
10-
"app_home": {
11-
"home_tab_enabled": true,
12-
"messages_tab_enabled": false,
13-
"messages_tab_read_only_enabled": true
14-
},
156
"bot_user": {
16-
"display_name": "Bolt Template App",
17-
"always_online": false
18-
},
19-
"shortcuts": [
20-
{
21-
"name": "Run sample shortcut",
22-
"type": "global",
23-
"callback_id": "sample_shortcut_id",
24-
"description": "Runs a sample shortcut"
25-
}
26-
],
27-
"slash_commands": [
28-
{
29-
"command": "/sample-command",
30-
"description": "Runs a sample command",
31-
"should_escape": false
32-
}
33-
]
7+
"display_name": "mem-cho (cmueats uptime monitor)",
8+
"always_online": true
9+
}
3410
},
3511
"oauth_config": {
3612
"scopes": {
3713
"bot": [
38-
"channels:history",
14+
"chat:write.public",
3915
"chat:write",
40-
"commands"
16+
"channels:read"
4117
]
4218
}
4319
},
@@ -48,9 +24,6 @@
4824
"message.channels"
4925
]
5026
},
51-
"interactivity": {
52-
"is_enabled": true
53-
},
5427
"org_deploy_enabled": false,
5528
"socket_mode_enabled": true,
5629
"token_rotation_enabled": false

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
},
2828
"dependencies": {
2929
"@slack/bolt": "^4.4.0",
30-
"dotenv": "~16.5.0"
30+
"@types/luxon": "^3.6.2",
31+
"dotenv": "~16.5.0",
32+
"luxon": "^3.6.1"
3133
},
3234
"devDependencies": {
3335
"@biomejs/biome": "^1.9.4",

0 commit comments

Comments
 (0)