Add tournament and multiplayer community chat moderation
All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 12m17s

This commit is contained in:
2026-10-27 12:54:15 +05:00
parent b8a430d4c2
commit 9c314ecb4e
19 changed files with 1070 additions and 16 deletions

View File

@@ -93,6 +93,64 @@ export async function multiplayerApi(
409,
);
const action = path[2] ?? "view";
if (
action === "community" &&
path.length === 3 &&
["GET", "POST"].includes(request.method)
) {
if (!savedSecret)
throw new ServiceError("Room membership permission required", 403);
const input =
request.method === "POST" ? await jsonBody(request) : { action: "view" };
const schema = z.discriminatedUnion("action", [
z.object({ action: z.literal("view") }).strict(),
z
.object({
action: z.literal("slow"),
seconds: z.number().int().min(0).max(300),
})
.strict(),
...(["admin", "unadmin", "kick", "ban"] as const).map((action) =>
z
.object({ action: z.literal(action), playerId: z.string().uuid() })
.strict(),
),
z
.object({ action: z.literal("unban"), banId: z.string().uuid() })
.strict(),
z
.object({
action: z.literal("tag"),
playerId: z.string().uuid(),
tag: z
.string()
.trim()
.max(32)
.refine(
(value) =>
!/[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u.test(
value,
),
),
})
.strict(),
]);
const body = schema.parse(input);
if (request.method === "POST") {
if (body.action === "view") throw new ServiceError("Not found", 404);
await limit(`multiplayer:moderation:${accessHash}`, 30, 60);
}
return respond(
required(
await client.rpc("party_community", {
p_room: id,
p_access_hash: accessHash,
p_action: body.action,
p_payload: body,
}),
),
);
}
if (action === "discord" && path.length === 3 && request.method === "POST") {
const view = required(
await client.rpc("multiplayer_action", {