import { GenerateUploadURL } from "../../gcloud.js"; const allowedFileTypes = [ "image/gif", "image/heic", "image/heif", "image/jpeg", "image/png", "video/mp4", "video/webm", ]; export async function onRequestPost(context: RequestContext) { if ( !context.data.current_user?.permissions || ![1 << 0, 1 << 2, 1 << 11].find( (p) => context.data.current_user.permissions & p, ) ) return new Response('{"error":"Forbidden"}', { headers: { "content-type": "application/json", }, status: 403, }); if ( context.request.headers .get("content-type") ?.startsWith("multipart/form-data; boundary=") ) return new Response('{"error":"Invalid content type"}', { headers: { "content-type": "application/json", }, status: 400, }); let body: FormData; try { body = await context.request.formData(); } catch { return new Response('{"error":"Invalid form data"}', { headers: { "content-type": "application/json", }, status: 400, }); } if ( ![ "verbal", "warn", "mute", "ban_temp", "ban_perm", "ban_unappealable", ].includes(body.get("punishment") as string) ) return new Response('{"error":"Invalid punishment"}', { headers: { "content-type": "application/json", }, status: 400, }); if (!(body.get("user") as string).match(/^\d{17,19}$/)) return new Response('{"error":"Invalid user"}', { headers: { "content-type": "application/json", }, status: 400, }); // @ts-expect-error const files: File[] = body.keys().find((key) => key.match(/^files\[\d]$/)); const urlPromises = []; for (const file of files) { if (!allowedFileTypes.includes(file.type)) return new Response(`{"error":"File ${file.name} is not valid"}`, { headers: { "content-type": "application/json", }, status: 415, }); const attachmentKey = `${Date.now()}${Math.round( Math.random() * 10000000, ).toString()}/${file.name}`; urlPromises.push( GenerateUploadURL( context.env, attachmentKey, file.size, (allowedFileTypes.find((t) => t === file.type) as string).split("/")[1], ), ); } const settledURLPromises = await Promise.allSettled(urlPromises); if (settledURLPromises.find((p) => p.status === "rejected")) return new Response('{"error":"Failed to process one or more files"}', { headers: { "content-type": "application/json", }, status: 500, }); const infractionId = `${body.get( "user", )}${Date.now()}${context.request.headers.get("cf-ray")?.split("-")[0]}`; const uploadReqs = []; for (let i = 0; i < files.length; i++) { uploadReqs.push( fetch(settledURLPromises[i] as unknown as string, { body: files[i], method: "PUT", }), ); } await context.env.DATA.put( infractionId, JSON.stringify({ created_at: Date.now(), moderator: context.data.current_user.id, }), ); return new Response(null, { status: 204, }); }