a fun bot for the hc slack
at v0.0.3 4.0 kB view raw
1import { slackApp } from "../../../index"; 2import { db } from "../../../libs/db"; 3import { blog } from "../../../libs/Logger"; 4import { takes as takesTable } from "../../../libs/schema"; 5import handleHelp from "../handlers/help"; 6import { handleHistory } from "../handlers/history"; 7import handlePause from "../handlers/pause"; 8import handleResume from "../handlers/resume"; 9import handleStart from "../handlers/start"; 10import handleStatus from "../handlers/status"; 11import handleStop from "../handlers/stop"; 12import { getActiveTake } from "../services/database"; 13import upload from "../services/upload"; 14import type { MessageResponse } from "../types"; 15import { getDescriptionBlocks, getEditDescriptionBlocks } from "../ui/blocks"; 16import * as Sentry from "@sentry/bun"; 17 18export default function setupActions() { 19 // Handle button actions 20 slackApp.action(/^takes_(\w+)$/, async ({ payload, context }) => { 21 try { 22 const userId = payload.user.id; 23 const channelId = context.channelId || ""; 24 const actionId = payload.actions[0]?.action_id as string; 25 const command = actionId.replace("takes_", ""); 26 const descriptionInput = 27 payload.state.values.note_block?.note_input; 28 29 let response: MessageResponse | undefined; 30 31 const activeTake = await getActiveTake(userId); 32 33 // Route to the appropriate handler function 34 switch (command) { 35 case "start": { 36 if (activeTake.length > 0) { 37 if (context.respond) { 38 response = await handleStatus(userId); 39 } 40 } else { 41 if (!descriptionInput?.value?.trim()) { 42 response = getDescriptionBlocks( 43 "Please enter a note for your session.", 44 ); 45 } else { 46 response = await handleStart( 47 userId, 48 channelId, 49 descriptionInput?.value?.trim(), 50 ); 51 } 52 } 53 break; 54 } 55 case "pause": 56 response = await handlePause(userId); 57 break; 58 case "resume": 59 response = await handleResume(userId); 60 break; 61 case "stop": 62 response = await handleStop(userId); 63 break; 64 case "edit": { 65 if (!activeTake.length && context.respond) { 66 await context.respond({ 67 text: "You don't have an active takes session to edit!", 68 response_type: "ephemeral", 69 }); 70 return; 71 } 72 73 if (!descriptionInput) { 74 response = getEditDescriptionBlocks( 75 activeTake[0]?.description || "", 76 ); 77 } else if (descriptionInput.value?.trim()) { 78 const takeToUpdate = activeTake[0]; 79 if (!takeToUpdate) return; 80 81 // Update the note for the active session 82 await db.update(takesTable).set({ 83 description: descriptionInput.value.trim(), 84 }); 85 86 response = await handleStatus(userId); 87 } else { 88 response = getEditDescriptionBlocks( 89 "", 90 "Please enter a note for your session.", 91 ); 92 } 93 break; 94 } 95 96 case "status": 97 response = await handleStatus(userId); 98 break; 99 case "history": 100 response = await handleHistory(userId); 101 break; 102 default: 103 response = await handleHelp(); 104 break; 105 } 106 107 // Send the response 108 if (response && context.respond) { 109 await context.respond(response); 110 } 111 } catch (error) { 112 if (error instanceof Error) 113 blog( 114 `Error in \`${payload.actions[0]?.action_id}\` action: ${error.message}`, 115 "error", 116 ); 117 118 // Capture the error in Sentry 119 Sentry.captureException(error, { 120 extra: { 121 actionId: payload.actions[0]?.action_id, 122 userId: payload.user.id, 123 channelId: context.channelId, 124 }, 125 }); 126 127 // Respond with error message to user 128 if (context.respond) { 129 await context.respond({ 130 text: "An error occurred while processing your request. Please stand by while we try to put out the fire.", 131 response_type: "ephemeral", 132 }); 133 } 134 } 135 }); 136 137 // setup the upload actions 138 try { 139 upload(); 140 } catch (error) { 141 Sentry.captureException(error, { 142 extra: { 143 context: "upload setup", 144 }, 145 }); 146 } 147}