a fun bot for the hc slack
1import { handleApiError } from "../../../libs/apiError";
2import { db } from "../../../libs/db";
3import { takes as takesTable } from "../../../libs/schema";
4import { eq, and } from "drizzle-orm";
5
6export default async function getVideo(url: URL): Promise<Response> {
7 try {
8 const path = url.pathname.split("/").filter(Boolean);
9 const videoId = path[2];
10 const thumbnail = path[3] === "thumbnail";
11
12 if (!videoId) {
13 return new Response(JSON.stringify({ error: "Invalid video id" }), {
14 status: 400,
15 headers: { "Content-Type": "application/json" },
16 });
17 }
18
19 const video = await db
20 .select()
21 .from(takesTable)
22 .where(eq(takesTable.id, videoId));
23
24 if (video.length === 0) {
25 return new Response(JSON.stringify({ error: "Video not found" }), {
26 status: 404,
27 headers: { "Content-Type": "application/json" },
28 });
29 }
30
31 const videoData = video[0];
32
33 if (thumbnail) {
34 return Response.redirect(
35 `https://cachet.dunkirk.sh/users/${videoData?.userId}/r`,
36 );
37 }
38
39 return new Response(
40 `<!DOCTYPE html>
41 <html>
42 <head>
43 <title>Video Player</title>
44 <style>
45 body, html {
46 margin: 0;
47 padding: 0;
48 height: 100vh;
49 overflow: hidden;
50 }
51 .video-container {
52 position: fixed;
53 top: 0;
54 left: 0;
55 width: 100vw;
56 height: 100vh;
57 display: flex;
58 flex-direction: column;
59 justify-content: center;
60 background: linear-gradient(180deg, #000000 25%, #ffffff 50%, #000000 75%);
61 }
62 video {
63 width: 100vw;
64 height: 100vh;
65 object-fit: contain;
66 position: absolute;
67 bottom: 0;
68 }
69 </style>
70 </head>
71 <body>
72 <div class="video-container">
73 <video autoplay controls>
74 <source src="${videoData?.takeUrl}" type="video/mp4">
75 Your browser does not support the video tag.
76 </video>
77 </div>
78 </body>
79 </html>`,
80 {
81 headers: {
82 "Content-Type": "text/html",
83 },
84 },
85 );
86 } catch (error) {
87 return handleApiError(error, "getVideo");
88 }
89}