This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

feat: add api and add recent takes route

+80 -9
+18
src/features/api/index.ts
··· 1 + import recentTakes from "./routes/recentTakes"; 2 + import video from "./routes/video"; 3 + 1 4 export { default as video } from "./routes/video"; 5 + 6 + export async function apiRouter(url: URL) { 7 + const path = url.pathname.split("/")[2]; 8 + 9 + console.log(`API path: ${path}`); 10 + 11 + switch (path) { 12 + case "video": 13 + return video(url); 14 + case "recentTakes": 15 + return recentTakes(); 16 + default: 17 + return new Response("404 Not Found", { status: 404 }); 18 + } 19 + }
+46
src/features/api/routes/recentTakes.ts
··· 1 + import { eq, desc } from "drizzle-orm"; 2 + import { db } from "../../../libs/db"; 3 + import { takes as takesTable } from "../../../libs/schema"; 4 + 5 + export default async function recentTakes(): Promise<Response> { 6 + const recentTakes = await db 7 + .select() 8 + .from(takesTable) 9 + .where(eq(takesTable.status, "approved")) 10 + .orderBy(desc(takesTable.completedAt)) 11 + .limit(40); 12 + 13 + if (recentTakes.length === 0) { 14 + return new Response( 15 + JSON.stringify({ 16 + takes: [], 17 + }), 18 + { 19 + headers: { 20 + "Content-Type": "application/json", 21 + }, 22 + }, 23 + ); 24 + } 25 + 26 + const takes = recentTakes.map((take) => ({ 27 + id: take.id, 28 + userId: take.userId, 29 + description: take.description, 30 + completedAt: take.completedAt, 31 + status: take.status, 32 + mp4Url: take.takeUrl, 33 + elapsedTime: take.elapsedTimeMs, 34 + })); 35 + 36 + return new Response( 37 + JSON.stringify({ 38 + takes, 39 + }), 40 + { 41 + headers: { 42 + "Content-Type": "application/json", 43 + }, 44 + }, 45 + ); 46 + }
+3 -4
src/features/takes/handlers/stop.ts
··· 5 5 import { getActiveTake, getPausedTake } from "../services/database"; 6 6 import type { MessageResponse } from "../types"; 7 7 import { prettyPrintTime } from "../../../libs/time"; 8 - import { 9 - calculateElapsedTime, 10 - getRemainingTime, 11 - } from "../../../libs/time-periods"; 8 + import { calculateElapsedTime } from "../../../libs/time-periods"; 12 9 13 10 export default async function handleStop( 14 11 userId: string, ··· 74 71 status: "waitingUpload", 75 72 ts: res.ts, 76 73 completedAt: new Date(), 74 + elapsedTimeMs: elapsed, 77 75 ...(notes && { notes }), 78 76 }) 79 77 .where(eq(takesTable.id, pausedTakeToStop.id)); ··· 126 124 status: "waitingUpload", 127 125 ts: res.ts, 128 126 completedAt: new Date(), 127 + elapsedTimeMs: elapsed, 129 128 ...(notes && { notes }), 130 129 }) 131 130 .where(eq(takesTable.id, activeTakeToStop.id));
+8
src/features/takes/services/notifications.ts
··· 4 4 import { takes as takesTable } from "../../../libs/schema"; 5 5 import { eq } from "drizzle-orm"; 6 6 import { 7 + calculateElapsedTime, 7 8 getPausedDuration, 8 9 getRemainingTime, 9 10 } from "../../../libs/time-periods"; ··· 67 68 error, 68 69 ); 69 70 } 71 + 72 + // Calculate elapsed time 73 + const elapsedTime = calculateElapsedTime(JSON.parse(take.periods)); 70 74 71 75 await db 72 76 .update(takesTable) 73 77 .set({ 74 78 status: "waitingUpload", 75 79 completedAt: now, 80 + elapsedTimeMs: elapsedTime, 76 81 ts, 77 82 notes: take.notes 78 83 ? `${take.notes} (Automatically completed due to pause timeout)` ··· 134 139 ); 135 140 } 136 141 142 + const elapsedTime = calculateElapsedTime(JSON.parse(take.periods)); 143 + 137 144 await db 138 145 .update(takesTable) 139 146 .set({ 140 147 status: "waitingUpload", 141 148 completedAt: now, 149 + elapsedTimeMs: take.targetDurationMs, 142 150 ts, 143 151 notes: take.notes 144 152 ? `${take.notes} (Automatically completed - time expired)`
+2 -2
src/features/takes/services/upload.ts
··· 121 121 }, 122 122 { 123 123 type: "video", 124 - video_url: `${process.env.API_URL}/video/${take.id}`, 125 - title_url: `${process.env.API_URL}/video/${take.id}`, 124 + video_url: `${process.env.API_URL}/api/video/${take.id}`, 125 + title_url: `${process.env.API_URL}/api/video/${take.id}`, 126 126 title: { 127 127 type: "plain_text", 128 128 text: `takes from ${takeUploadedAt?.toISOString()}`,
+3 -3
src/index.ts
··· 5 5 import { t } from "./libs/template"; 6 6 import { blog } from "./libs/Logger"; 7 7 import { version, name } from "../package.json"; 8 - import { video } from "./features/api"; 8 + import { apiRouter, video } from "./features/api"; 9 9 const environment = process.env.NODE_ENV; 10 10 11 11 import * as Sentry from "@sentry/bun"; ··· 71 71 return new Response("OK"); 72 72 case "/slack": 73 73 return slackApp.run(request); 74 - case "/video": 75 - return video(url); 74 + case "/api": 75 + return apiRouter(url); 76 76 default: 77 77 return new Response("404 Not Found", { status: 404 }); 78 78 }