53 lines
1.5 KiB
TypeScript
53 lines
1.5 KiB
TypeScript
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();
|