From 131da9c566285dbeca4c9bead984da5daa808f0c Mon Sep 17 00:00:00 2001 From: Seth Etter Date: Fri, 3 Jul 2026 10:56:51 -0500 Subject: [PATCH] basic command handling structure --- src/commands/commands.ts | 36 ++++++++++++++++++++++++++++++++++++ src/commands/events.ts | 23 +++++++++++++++++++++++ src/lib/events.ts | 16 ++++++++++++++++ src/lib/slack.ts | 7 +++++++ 4 files changed, 82 insertions(+) create mode 100644 src/commands/commands.ts create mode 100644 src/commands/events.ts create mode 100644 src/lib/events.ts create mode 100644 src/lib/slack.ts diff --git a/src/commands/commands.ts b/src/commands/commands.ts new file mode 100644 index 0000000..1549fb0 --- /dev/null +++ b/src/commands/commands.ts @@ -0,0 +1,36 @@ +import type { GenericMessageEvent } from "@slack/web-api"; +import type { EventsClient } from "../lib/events.ts"; +import { handleEventsCommand, type EventsCmd } from "./events.ts"; +import type { SlackClient } from "../lib/slack.ts"; + +interface CommandHandler { + handleSlackMessage(msg: GenericMessageEvent): Promise; +} + +interface CommandHandlerDeps { + eventsClient: EventsClient; + slackClient: SlackClient; +} + +type Command = EventsCmd; + +export function newCommandHandler(deps: CommandHandlerDeps): CommandHandler { + function msgToCommand(msg: GenericMessageEvent): Command | null { + if (msg.text?.startsWith("!events")) { + return { type: "events", thread: msg.thread_ts ?? msg.ts }; + } + return null; + } + + return { + async handleSlackMessage(msg: GenericMessageEvent): Promise { + const cmd = msgToCommand(msg); + if (!cmd) return; + + switch (cmd.type) { + case "events": + await handleEventsCommand({ cmd, ...deps }); + } + }, + }; +} diff --git a/src/commands/events.ts b/src/commands/events.ts new file mode 100644 index 0000000..7e4fa88 --- /dev/null +++ b/src/commands/events.ts @@ -0,0 +1,23 @@ +import type { Event, EventsClient } from "../lib/events.ts"; +import type { SlackClient } from "../lib/slack.ts"; + +export type EventsCmd = { type: "events"; thread: string }; + +export async function handleEventsCommand({ + cmd, + eventsClient, + slackClient, +}: { + cmd: EventsCmd; + eventsClient: EventsClient; + slackClient: SlackClient; +}): Promise { + const events = await eventsClient.getUpcomingEvents(); + const msg = formatEvents(events); + await slackClient.sendMessage({ msg, thread: cmd.thread }); +} + +// TODO: make this formatting better +function formatEvents(events: Event[]): string { + return events.map((e) => e.title).join("\n"); +} diff --git a/src/lib/events.ts b/src/lib/events.ts new file mode 100644 index 0000000..2bd5446 --- /dev/null +++ b/src/lib/events.ts @@ -0,0 +1,16 @@ +// TODO: Get this schema from the events repo (https://tangled.org/devict.org/events) +export type Event = { + title: string; +}; + +export interface EventsClient { + getUpcomingEvents(): Promise; +} + +export function makeEventsClient(): EventsClient { + return { + async getUpcomingEvents(): Promise { + return [{ title: "sup" }]; + }, + }; +} diff --git a/src/lib/slack.ts b/src/lib/slack.ts new file mode 100644 index 0000000..9388dbc --- /dev/null +++ b/src/lib/slack.ts @@ -0,0 +1,7 @@ +type ThreadMessage = { msg: string; thread: string }; + +type ChannelMessage = { msg: string; channel: string }; + +export interface SlackClient { + sendMessage(args: ThreadMessage | ChannelMessage): Promise; +} -- 2.51.2