Add rtbf webhook

This commit is contained in:
2026-06-30 21:54:41 -04:00
parent 6da8c2092e
commit 9178ce19ac
+95
View File
@@ -0,0 +1,95 @@
import { jsonError } from "../common.js";
import { Report } from "../../generated/prisma/client.js";
import { getBanList, setBanList } from "../roblox-open-cloud.js";
export async function onRequestPost(context: RequestContext) {
const body = await context.request.text();
const secret = context.env.ROBLOX_WEBHOOK_SECRET;
if (!secret) return jsonError("This endpoint is currently disabled", 503);
const sigHeader = context.request.headers.get("roblox-signature");
if (!sigHeader) return jsonError("Missing signature", 401);
const [timestamp, sig] = sigHeader.split(",");
if (
parseInt(timestamp.replace("t=", "")) <
Math.floor(Date.now() / 1000) - 600
)
return jsonError("This request is stale", 406);
const textEncode = (text: string) => new TextEncoder().encode(text);
const key = await crypto.subtle.importKey(
"raw",
textEncode(secret),
{
hash: "SHA-256",
name: "HMAC",
},
false,
["verify"],
);
if (
!(await crypto.subtle.verify(
"HMAC",
key,
Uint8Array.from(atob(sig.replace("v1=", "")), (c) => c.charCodeAt(0)),
textEncode(`${timestamp.replace("t=", "")}.${body}`),
))
)
return jsonError("Invalid signature", 403);
const data = JSON.parse(body);
if (data.EventType === "SampleNotification")
return new Response(null, {
status: 204,
});
if (data.EventType !== "RightToErasureRequest")
return jsonError("Invalid event type", 400);
const { prisma } = context.data;
const userId = data.EventPrisma.UserId;
if (typeof userId !== "number") return jsonError("Invalid user id", 400);
await prisma.gameModLog.deleteMany({
where: {
target: userId,
},
});
const associatedReports = await prisma.$queryRaw<
Report[]
>`SELECT attachments, id FROM reports WHERE EXISTS (SELECT 1 FROM json_each(target_ids) WHERE VALUE = ${userId});`;
const idsToDelete: string[] = [];
for (const report of associatedReports) {
for (const attachment of report.attachments as string[]) {
await context.env.R2.delete(attachment);
}
idsToDelete.push(report.id);
}
await prisma.report.deleteMany({
where: {
id: {
in: idsToDelete,
},
},
});
const { etag, value } = await getBanList(context);
delete value[userId];
await setBanList(context, value, etag);
return new Response(null, {
status: 204,
});
}