import { GenerateUploadURL } from "../../gcloud.js"; import { jsonError } from "../../common.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 jsonError("Forbidden", 403); if ( context.request.headers .get("content-type") ?.startsWith("multipart/form-data; boundary=") ) return jsonError("Invalid content type", 400); let body: FormData; try { body = await context.request.formData(); } catch { return jsonError("Invalid form data", 400); } if ( ![ "verbal", "warn", "mute", "ban_temp", "ban_perm", "ban_unappealable", ].includes(body.get("punishment") as string) ) return jsonError("Invalid punishment", 400); if (!(body.get("user") as string).match(/^\d{17,19}$/)) return jsonError("Invalid user", 400); // @ts-expect-error const files: File[] = body.keys().find((key) => key.match(/^files\[\d]$/)); const urlPromises = []; const origin = context.request.headers.get("Origin"); if (!origin) return jsonError("Origin header missing", 400); for (const file of files) { if (!allowedFileTypes.includes(file.type)) return jsonError(`File ${file.name} is not valid`, 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], origin, ), ); } const settledURLPromises = await Promise.allSettled(urlPromises); if (settledURLPromises.find((p) => p.status === "rejected")) return jsonError("Failed to process one or more files", 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, }); }