a fun bot for the hc slack
1import { eq, desc, or } from "drizzle-orm";
2import { db } from "../../../libs/db";
3import { takes as takesTable, users as usersTable } from "../../../libs/schema";
4import { handleApiError } from "../../../libs/apiError";
5
6export type RecentTake = {
7 id: string;
8 userId: string;
9 notes: string;
10 createdAt: Date;
11 mediaUrls: string[];
12 /* elapsed time in seconds */
13 elapsedTime: number;
14 project: string;
15 /* total time in seconds */
16 totalTakesTime: number;
17};
18
19export async function recentTakes(url: URL): Promise<Response> {
20 try {
21 const userId = url.searchParams.get("user");
22
23 if (userId) {
24 // Verify user exists if userId provided
25 const user = await db
26 .select()
27 .from(usersTable)
28 .where(eq(usersTable.id, userId))
29 .limit(1);
30
31 if (user.length === 0) {
32 return new Response(
33 JSON.stringify({
34 error: "User not found",
35 takes: [],
36 }),
37 {
38 status: 404,
39 headers: {
40 "Content-Type": "application/json",
41 },
42 },
43 );
44 }
45 }
46
47 const recentTakes = await db
48 .select()
49 .from(takesTable)
50 .orderBy(desc(takesTable.createdAt))
51 .where(eq(takesTable.userId, userId ? userId : takesTable.userId))
52 .limit(40);
53
54 if (recentTakes.length === 0) {
55 return new Response(
56 JSON.stringify({
57 takes: [],
58 }),
59 {
60 headers: {
61 "Content-Type": "application/json",
62 },
63 },
64 );
65 }
66
67 // Get unique user IDs
68 const userIds = [...new Set(recentTakes.map((take) => take.userId))];
69
70 // Query users from takes table
71 const users = await db
72 .select()
73 .from(usersTable)
74 .where(or(...userIds.map((id) => eq(usersTable.id, id))));
75
76 // Create map of user data by ID
77 const userMap = users.reduce(
78 (acc, user) => {
79 acc[user.id] = user;
80 return acc;
81 },
82 {} as Record<string, (typeof users)[number]>,
83 );
84
85 const takes: RecentTake[] =
86 recentTakes.map((take) => ({
87 id: take.id,
88 userId: take.userId,
89 notes: take.notes,
90 createdAt: new Date(take.createdAt),
91 mediaUrls: take.media ? JSON.parse(take.media) : [],
92 elapsedTime: take.elapsedTime,
93 project: userMap[take.userId]?.projectName || "unknown project",
94 totalTakesTime:
95 userMap[take.userId]?.totalTakesTime || take.elapsedTime,
96 })) || [];
97
98 return new Response(
99 JSON.stringify({
100 takes,
101 }),
102 {
103 headers: {
104 "Content-Type": "application/json",
105 },
106 },
107 );
108 } catch (error) {
109 return handleApiError(error, "recentTakes");
110 }
111}