a fun bot for the hc slack
1import { eq, desc, and } from "drizzle-orm";
2import { db } from "../../../libs/db";
3import { takes as takesTable } from "../../../libs/schema";
4import { handleApiError } from "../../../libs/apiError";
5
6export async function recentTakes(): Promise<Response> {
7 try {
8 const recentTakes = await db
9 .select()
10 .from(takesTable)
11 .where(eq(takesTable.status, "approved"))
12 .orderBy(desc(takesTable.completedAt))
13 .limit(40);
14
15 if (recentTakes.length === 0) {
16 return new Response(
17 JSON.stringify({
18 takes: [],
19 }),
20 {
21 headers: {
22 "Content-Type": "application/json",
23 },
24 },
25 );
26 }
27
28 const takes = recentTakes.map((take) => ({
29 id: take.id,
30 userId: take.userId,
31 description: take.description,
32 completedAt: take.completedAt,
33 status: take.status,
34 mp4Url: take.takeUrl,
35 elapsedTime: take.elapsedTimeMs,
36 }));
37
38 return new Response(
39 JSON.stringify({
40 takes,
41 }),
42 {
43 headers: {
44 "Content-Type": "application/json",
45 },
46 },
47 );
48 } catch (error) {
49 return handleApiError(error, "recentTakes");
50 }
51}
52
53export async function takesPerUser(userId: string): Promise<Response> {
54 try {
55 const rawTakes = await db
56 .select()
57 .from(takesTable)
58 .where(and(eq(takesTable.userId, userId)))
59 .orderBy(desc(takesTable.completedAt));
60
61 const takes = rawTakes.map((take) => ({
62 id: take.id,
63 description: take.description,
64 completedAt: take.completedAt,
65 status: take.status,
66 mp4Url: take.takeUrl,
67 elapsedTime: take.elapsedTimeMs,
68 }));
69
70 const approvedTakes = rawTakes.reduce((acc, take) => {
71 if (take.status !== "approved") return acc;
72 const multiplier = Number.parseFloat(take.multiplier || "1.0");
73 return Number(
74 (
75 acc +
76 (take.elapsedTimeMs * multiplier) / (1000 * 60 * 60)
77 ).toFixed(1),
78 );
79 }, 0);
80
81 const waitingTakes = rawTakes.reduce((acc, take) => {
82 if (take.status !== "waitingUpload" && take.status !== "uploaded")
83 return acc;
84 const multiplier = Number.parseFloat(take.multiplier || "1.0");
85 return Number(
86 (
87 acc +
88 (take.elapsedTimeMs * multiplier) / (1000 * 60 * 60)
89 ).toFixed(1),
90 );
91 }, 0);
92
93 const rejectedTakes = rawTakes.reduce((acc, take) => {
94 if (take.status !== "rejected") return acc;
95 const multiplier = Number.parseFloat(take.multiplier || "1.0");
96 return Number(
97 (
98 acc +
99 (take.elapsedTimeMs * multiplier) / (1000 * 60 * 60)
100 ).toFixed(1),
101 );
102 }, 0);
103
104 return new Response(
105 JSON.stringify({
106 approvedTakes,
107 waitingTakes,
108 rejectedTakes,
109 takes,
110 }),
111 {
112 headers: {
113 "Content-Type": "application/json",
114 },
115 },
116 );
117 } catch (error) {
118 return handleApiError(error, "takesPerUser");
119 }
120}