providing password reset services for a long while: circa 2025
1import { SlackApp } from "slack-edge";
2import SlackMessageQueue, { type SlackMessage } from "./features/message-queue";
3
4import * as features from "./features/index";
5
6import { version, name } from "./package.json";
7const environment = process.env.NODE_ENV;
8import quip from "./quip";
9
10console.log(
11 `----------------------------------\n${name} server\n----------------------------------\n`,
12);
13console.log(`🏗️ Starting ${name}...`);
14console.log("📦 Loading Slack App...");
15console.log("🔑 Loading environment variables...");
16
17if (
18 !process.env.SLACK_BOT_TOKEN ||
19 !process.env.SLACK_SIGNING_SECRET ||
20 !process.env.ADMINS
21) {
22 throw new Error(
23 "Missing required environment variables: SLACK_BOT_TOKEN SLACK_SIGNING_SECRET or ADMINS",
24 );
25}
26
27const slackApp = new SlackApp({
28 env: {
29 SLACK_BOT_TOKEN: process.env.SLACK_BOT_TOKEN,
30 SLACK_SIGNING_SECRET: process.env.SLACK_SIGNING_SECRET,
31 SLACK_LOGGING_LEVEL: "INFO",
32 },
33 startLazyListenerAfterAck: true,
34});
35const slackClient = slackApp.client;
36
37const messageQueue = new SlackMessageQueue(slackClient, "data/slack-queue.db");
38console.log(`👔 Message Queue Size: ${await messageQueue.queueLength()}`);
39
40console.log(`⚒️ Loading ${Object.entries(features).length} features...`);
41for (const [feature, handler] of Object.entries(features)) {
42 console.log(`📦 ${feature} loaded`);
43 if (typeof handler === "function") {
44 handler();
45 }
46}
47
48export default {
49 port: process.env.PORT || 3000,
50 async fetch(request: Request) {
51 const url = new URL(request.url);
52 const path = url.pathname;
53
54 switch (path) {
55 case "/":
56 return new Response(`Hello World from ${name}@${version}`);
57 case "/health":
58 return new Response("OK");
59 case "/slack":
60 return slackApp.run(request);
61 case "/slack/message": {
62 if (
63 request.headers.get("Authorization") !==
64 `Bearer ${process.env.API_KEY}`
65 ) {
66 return new Response("Unauthorized", { status: 401 });
67 }
68
69 const message: SlackMessage = await request.json();
70 const { channel, text } = message;
71
72 if (!channel || !text) {
73 return new Response(
74 `Invalid fields: ${[
75 !channel && "channel is required",
76 !text && "text is required",
77 ]
78 .filter(Boolean)
79 .join(", ")}`,
80 { status: 400 },
81 );
82 }
83
84 await messageQueue.enqueue(message);
85
86 return new Response(JSON.stringify({ ok: true }), { status: 200 });
87 }
88 default:
89 return new Response("404 Not Found", { status: 404 });
90 }
91 },
92};
93
94console.log(
95 `🚀 Server Started in ${Bun.nanoseconds() / 1000000} milliseconds on version: ${version}!\n\n----------------------------------\n`,
96);
97
98console.log(quip());
99
100console.log("\n----------------------------------\n");
101
102export { slackApp, slackClient, version, name, environment };