a fun bot for the hc slack
1import TakesConfig from "../../../libs/config";
2import { generateSlackDate, prettyPrintTime } from "../../../libs/time";
3import {
4 getPausedTimeRemaining,
5 getRemainingTime,
6} from "../../../libs/time-periods";
7import {
8 getActiveTake,
9 getCompletedTakes,
10 getPausedTake,
11} from "../services/database";
12import { expirePausedSessions } from "../services/notifications";
13import type { MessageResponse } from "../types";
14
15export default async function handleStatus(
16 userId: string,
17): Promise<MessageResponse | undefined> {
18 const activeTake = await getActiveTake(userId);
19
20 // First, check for expired paused sessions
21 await expirePausedSessions();
22
23 if (activeTake.length > 0) {
24 const take = activeTake[0];
25 if (!take) {
26 return;
27 }
28
29 const endTime = getRemainingTime(take.targetDurationMs, take.periods);
30
31 // Add description to display if present
32 const descriptionText = take.description
33 ? `\n\n*Working on:* ${take.description}`
34 : "";
35
36 return {
37 text: `🎬 You have an active takes session with ${prettyPrintTime(endTime.remaining)} remaining.${descriptionText}`,
38 response_type: "ephemeral",
39 blocks: [
40 {
41 type: "section",
42 text: {
43 type: "mrkdwn",
44 text: `🎬 You have an active takes session${descriptionText}`,
45 },
46 },
47 {
48 type: "divider",
49 },
50 {
51 type: "context",
52 elements: [
53 {
54 type: "mrkdwn",
55 text: `You have ${prettyPrintTime(endTime.remaining)} remaining until ${generateSlackDate(endTime.endTime)}.`,
56 },
57 ],
58 },
59 {
60 type: "actions",
61 elements: [
62 {
63 type: "button",
64 text: {
65 type: "plain_text",
66 text: "✍️ edit",
67 emoji: true,
68 },
69 value: "edit",
70 action_id: "takes_edit",
71 },
72 {
73 type: "button",
74 text: {
75 type: "plain_text",
76 text: "⏸️ Pause",
77 emoji: true,
78 },
79 value: "pause",
80 action_id: "takes_pause",
81 },
82 {
83 type: "button",
84 text: {
85 type: "plain_text",
86 text: "⏹️ Stop",
87 emoji: true,
88 },
89 value: "stop",
90 action_id: "takes_stop",
91 style: "danger",
92 },
93
94 {
95 type: "button",
96 text: {
97 type: "plain_text",
98 text: "🔄 Refresh",
99 emoji: true,
100 },
101 value: "status",
102 action_id: "takes_status",
103 },
104 ],
105 },
106 ],
107 };
108 }
109
110 // Check for paused session
111 const pausedTakeStatus = await getPausedTake(userId);
112
113 if (pausedTakeStatus.length > 0) {
114 const pausedTake = pausedTakeStatus[0];
115 if (!pausedTake) {
116 return;
117 }
118
119 // Calculate how much time remains before auto-completion
120 const endTime = getRemainingTime(
121 pausedTake.targetDurationMs,
122 pausedTake.periods,
123 );
124 const pauseExpires = getPausedTimeRemaining(pausedTake.periods);
125
126 // Add notes to display if present
127 const descriptionText = pausedTake.description
128 ? `\n\n*Working on:* ${pausedTake.description}`
129 : "";
130
131 return {
132 text: `⏸️ You have a paused takes session. It will auto-complete in ${prettyPrintTime(pauseExpires)} if not resumed.`,
133 response_type: "ephemeral",
134 blocks: [
135 {
136 type: "section",
137 text: {
138 type: "mrkdwn",
139 text: `⏸️ Session paused! You have ${prettyPrintTime(endTime.remaining)} remaining.${descriptionText}`,
140 },
141 },
142 {
143 type: "divider",
144 },
145 {
146 type: "context",
147 elements: [
148 {
149 type: "mrkdwn",
150 text: `It will automatically finish in ${prettyPrintTime(pauseExpires)} (by ${generateSlackDate(new Date(new Date().getTime() - pauseExpires))}) if not resumed.`,
151 },
152 ],
153 },
154 {
155 type: "actions",
156 elements: [
157 {
158 type: "button",
159 text: {
160 type: "plain_text",
161 text: "▶️ Resume",
162 emoji: true,
163 },
164 value: "resume",
165 action_id: "takes_resume",
166 },
167 {
168 type: "button",
169 text: {
170 type: "plain_text",
171 text: "⏹️ Stop",
172 emoji: true,
173 },
174 value: "stop",
175 action_id: "takes_stop",
176 style: "danger",
177 },
178 {
179 type: "button",
180 text: {
181 type: "plain_text",
182 text: "🔄 Refresh",
183 emoji: true,
184 },
185 value: "status",
186 action_id: "takes_status",
187 },
188 ],
189 },
190 ],
191 };
192 }
193
194 // Check history of completed sessions
195 const completedSessions = await getCompletedTakes(userId);
196 const takeTime = completedSessions.length
197 ? (() => {
198 const diffMs =
199 new Date().getTime() -
200 // @ts-expect-error - TS doesn't know that we are checking the length
201 completedSessions[completedSessions.length - 1]
202 ?.completedAt;
203
204 const hours = Math.ceil(diffMs / (1000 * 60 * 60));
205 if (hours < 24) return `${hours} hours`;
206
207 const weeks = Math.floor(diffMs / (1000 * 60 * 60 * 24 * 7));
208 if (weeks > 0 && weeks < 4) return `${weeks} weeks`;
209
210 const months = Math.floor(diffMs / (1000 * 60 * 60 * 24 * 30));
211 return `${months} months`;
212 })()
213 : 0;
214
215 return {
216 text: `You have no active takes sessions. You've completed ${completedSessions.length} sessions in the last ${takeTime}.`,
217 response_type: "ephemeral",
218 blocks: [
219 {
220 type: "section",
221 text: {
222 type: "mrkdwn",
223 text: `You have no active takes sessions. You've completed ${completedSessions.length} sessions in the last ${takeTime}.`,
224 },
225 },
226 {
227 type: "actions",
228 elements: [
229 {
230 type: "button",
231 text: {
232 type: "plain_text",
233 text: "🎬 Start New Session",
234 emoji: true,
235 },
236 value: "start",
237 action_id: "takes_start",
238 },
239 {
240 type: "button",
241 text: {
242 type: "plain_text",
243 text: "📋 History",
244 emoji: true,
245 },
246 value: "history",
247 action_id: "takes_history",
248 },
249 ],
250 },
251 ],
252 };
253}