providing password reset services for a long while: circa 2025
1import { slackApp } from "../index";
2import { fetchUserData } from "./unfurl";
3
4const command = async () => {
5 slackApp.command("/hackatime", async ({ context, payload }) => {
6 if (!context?.respond) return;
7 const hackatimeUser: { apiKey: string } | null = await fetch(
8 `https://waka.hackclub.com/api/special/apikey?user=${context.userId}`,
9 {
10 headers: {
11 Authorization: `Bearer ${process.env.HACKATIME_API_KEY}`,
12 },
13 },
14 ).then((res) => (res.status === 200 ? res.json() : null));
15 console.log(payload.text);
16 if (hackatimeUser) {
17 if (payload.text.includes("summary")) {
18 const interval = payload.text.split(" ")[1] || "month";
19 const userData = await fetchUserData(context.userId, interval);
20 if (!userData) {
21 await context.respond({
22 response_type: "ephemeral",
23 text: "uh oh! something went wrong :ohnoes:",
24 blocks: [
25 {
26 type: "section",
27 text: {
28 type: "mrkdwn",
29 text: "uh oh! something went wrong :ohnoes:",
30 },
31 },
32 {
33 type: "context",
34 elements: [
35 {
36 type: "mrkdwn",
37 text: "if this keeps happening dm <@U062UG485EE> and let them know",
38 },
39 ],
40 },
41 ],
42 });
43 return;
44 }
45
46 const projectTotal = userData.projects.reduce((total, project) => {
47 return total + project.total;
48 }, 0);
49 userData.projects.sort((a, b) => b.total - a.total);
50
51 await context.respond({
52 response_type: "ephemeral",
53 text: "here's your summary! :yay:",
54 blocks: [
55 {
56 type: "section",
57 text: {
58 type: "mrkdwn",
59 text: `here's your summary <@${context.userId}>! :roo-yay:`,
60 },
61 },
62 {
63 type: "divider",
64 },
65 {
66 type: "context",
67 elements: [
68 {
69 type: "mrkdwn",
70 text: `you have spent ${Math.floor(projectTotal / 3600)} hours, ${Math.floor((projectTotal % 3600) / 60)} minutes, and ${projectTotal % 60} seconds coding in the ${interval.replaceAll("_", " ")}${interval.includes("days") || interval.includes("month") ? "" : " interval"}`,
71 },
72 ],
73 },
74 {
75 type: "divider",
76 },
77 {
78 type: "context",
79 elements: [
80 {
81 type: "mrkdwn",
82 text: `your most active project was \`${userData.projects[0].key}\`, where you spent ${Math.floor(userData.projects[0].total / 3600)} hours, ${Math.floor((userData.projects[0].total % 3600) / 60)} minutes, and ${userData.projects[0].total % 60} seconds`,
83 },
84 ],
85 },
86 {
87 type: "divider",
88 },
89 {
90 type: "context",
91 elements: [
92 {
93 type: "mrkdwn",
94 text: `here's a list of the rest of your projects:\n\n${userData.projects
95 .slice(1)
96 .map(
97 (project) =>
98 `\`${project.key}\`: ${Math.floor(project.total / 3600)} hours, ${Math.floor((project.total % 3600) / 60)} minutes, and ${project.total % 60} seconds`,
99 )
100 .join("\n")}`,
101 },
102 ],
103 },
104 {
105 type: "divider",
106 },
107 {
108 type: "actions",
109 elements: [
110 {
111 type: "button",
112 text: {
113 type: "plain_text",
114 text: "share with channel",
115 },
116 value: interval,
117 action_id: "share-summary",
118 },
119 ],
120 },
121 ],
122 });
123 return;
124 }
125
126 await context.respond({
127 response_type: "ephemeral",
128 text: "Hi there! I'm the Hackatime bot :hyper-dino-wave:",
129 blocks: [
130 {
131 type: "section",
132 text: {
133 type: "mrkdwn",
134 text: "Hi there! I'm the Hackatime bot :hyper-dino-wave:",
135 },
136 },
137 {
138 type: "section",
139 text: {
140 type: "mrkdwn",
141 text: `It looks like you already have an account! You can log in to the <https://waka.hackclub.com/login|Hackatime dashboard> with your username \`${context.userId}\` and password :3c:`,
142 },
143 },
144 {
145 type: "actions",
146 elements: [
147 {
148 type: "button",
149 text: {
150 type: "plain_text",
151 text: "Reset Password",
152 },
153 action_id: "reset-password",
154 style: "danger",
155 },
156 {
157 type: "button",
158 text: {
159 type: "plain_text",
160 text: "gutentag!",
161 },
162 action_id: "bye",
163 },
164 ],
165 },
166 {
167 type: "context",
168 elements: [
169 {
170 type: "mrkdwn",
171 text: `your api key for the Hackatime API is \`${hackatimeUser.apiKey}\``,
172 },
173 ],
174 },
175 ],
176 });
177 return;
178 }
179
180 context.respond({
181 response_type: "ephemeral",
182 text: "Hi there! I'm the Hackatime bot :hyper-dino-wave:",
183 blocks: [
184 {
185 type: "section",
186 text: {
187 type: "mrkdwn",
188 text: "Hi there! I'm the Hackatime bot :hyper-dino-wave:",
189 },
190 },
191 {
192 type: "section",
193 text: {
194 type: "mrkdwn",
195 text: "I can see that you don't have an account yet. Do you want me to make you one?",
196 },
197 },
198 {
199 type: "actions",
200 elements: [
201 {
202 type: "button",
203 text: {
204 type: "plain_text",
205 text: "Yes, please!",
206 },
207 value: "yes",
208 style: "primary",
209 action_id: "create-account",
210 },
211 {
212 type: "button",
213 text: {
214 type: "plain_text",
215 text: "No, thanks",
216 },
217 value: "no",
218 action_id: "no-thanks",
219 },
220 ],
221 },
222 ],
223 });
224 });
225
226 slackApp.action("no-thanks", async ({ context }) => {
227 if (context?.respond)
228 await context.respond({
229 response_type: "ephemeral",
230 text: "No worries! If you change your mind just type `/hackatime` again ^-^",
231 });
232 });
233
234 slackApp.action("bye", async ({ context }) => {
235 if (context?.respond)
236 await context.respond({
237 response_type: "ephemeral",
238 text: "bye!!! :goodnight:",
239 });
240 });
241};
242
243export default command;