105 lines
2.5 KiB
TypeScript
105 lines
2.5 KiB
TypeScript
import { jsonError, jsonResponse } from "../../common.js";
|
|
|
|
export async function onRequestPost(context: RequestContext) {
|
|
let formData: FormData;
|
|
|
|
try {
|
|
formData = await context.request.formData();
|
|
} catch {
|
|
return jsonError("Malformed form data", 400);
|
|
}
|
|
|
|
const files: File[] = [];
|
|
|
|
for (const file of formData.getAll("file")) {
|
|
if (typeof file === "string") {
|
|
return jsonError("'file' must be a file", 400);
|
|
}
|
|
|
|
if (file.type === "image") {
|
|
}
|
|
|
|
files.push(file);
|
|
}
|
|
|
|
let bytes = 0;
|
|
for (const file of files) {
|
|
bytes += new Blob([file]).size;
|
|
}
|
|
|
|
if (bytes > 26214400) return jsonError("Files too large (max 25MB)", 413);
|
|
|
|
const type = formData.get("type");
|
|
|
|
if (
|
|
typeof type !== "string" ||
|
|
["purchase", "reset", "transfer"].includes(type)
|
|
)
|
|
return jsonError(
|
|
"'type' must be one of ('purchase', 'reset', 'transfer')",
|
|
400,
|
|
);
|
|
|
|
const { R2 } = context.env;
|
|
const { prisma } = context.data;
|
|
const requestId = `${Date.now()}${crypto.randomUUID().replaceAll("-", "")}`;
|
|
|
|
await prisma.dataRequest.create({
|
|
data: {
|
|
id: requestId,
|
|
status: type === "transfer" ? "verification_required" : "pending",
|
|
target_user: 0,
|
|
type,
|
|
},
|
|
});
|
|
|
|
const attachmentIds = [];
|
|
|
|
for (let i = 0; i < files.length; i++) {
|
|
attachmentIds.push(
|
|
`${Date.now()}${crypto.randomUUID().replaceAll("-", "")}`,
|
|
);
|
|
}
|
|
|
|
const uploadPromises = [];
|
|
|
|
for (let i = 0; i < attachmentIds.length; i++) {
|
|
uploadPromises.push(R2.put(`dt/${attachmentIds[i]}`, files[i]));
|
|
}
|
|
|
|
const settledUploads = (await Promise.allSettled(uploadPromises)).filter(
|
|
(p) => p.status === "fulfilled",
|
|
);
|
|
const attachmentList = settledUploads.map((u) =>
|
|
(u.value as R2Object).key.replace("dt/", ""),
|
|
);
|
|
|
|
if (attachmentList.length > 0) {
|
|
await prisma.dataRequest.update({
|
|
data: {
|
|
attachments: attachmentList,
|
|
},
|
|
where: {
|
|
id: requestId,
|
|
},
|
|
});
|
|
|
|
const url = new URL(context.request.url);
|
|
url.pathname = "/data-transfers/verify";
|
|
|
|
return jsonResponse(
|
|
JSON.stringify({
|
|
url: `https://apis.roblox.com/oauth/v1/authorize?client_id=${context.env.ROBLOX_OAUTH_CLIENT_ID}&redirect_uri=${encodeURIComponent(url.href)}&response_type=code&scope=openid&state=${requestId}`,
|
|
}),
|
|
);
|
|
}
|
|
|
|
return new Response("{}", {
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Location: `/data-request/status/${requestId}`,
|
|
},
|
|
status: 201,
|
|
});
|
|
}
|