Add community content reports, map bans, and appeals

This commit is contained in:
2026-10-06 13:00:10 +05:00
parent 5f43e97d32
commit dd67b5c0de
18 changed files with 1167 additions and 50 deletions

52
shared/moderation.ts Normal file
View File

@@ -0,0 +1,52 @@
import { z } from "zod";
export const reportCategories = {
inappropriate: "Inappropriate or offensive content",
privacy: "Personal or private information",
wrong_world: "Wrong world or misleading map",
broken: "Broken panorama or map",
spam: "Spam or advertising",
other: "Other",
} as const;
export const reportSchema = z
.object({
datasetId: z.string().uuid().optional(),
sessionId: z.string().uuid().optional(),
round: z.number().int().min(0).max(4).optional(),
target: z.enum(["map", "panorama"]),
category: z.enum(
Object.keys(reportCategories) as [
keyof typeof reportCategories,
...Array<keyof typeof reportCategories>,
],
),
reason: z.string().trim().min(10).max(2000),
evidenceUrl: z
.string()
.trim()
.url()
.max(1000)
.refine(
(url) => /^https?:\/\//i.test(url),
"Use an HTTP or HTTPS evidence link",
)
.optional(),
})
.superRefine((report, context) => {
if (Boolean(report.datasetId) === Boolean(report.sessionId))
context.addIssue({
code: "custom",
message: "Choose a map or a game session",
});
if (
report.target === "panorama" &&
(!report.sessionId || report.round === undefined)
)
context.addIssue({
code: "custom",
message: "Choose a panorama from your game",
});
});
export const contributionCutoff = (now = Date.now()) =>
new Date(now - 5 * 24 * 60 * 60 * 1000).toISOString();