Add account based multiplayer hosting and bug report retention

This commit is contained in:
2026-10-10 16:24:34 +05:00
parent 9af71c85c2
commit fc6da6756d
33 changed files with 1538 additions and 102 deletions

View File

@@ -41,7 +41,15 @@ export type BugReportRecord = {
title: string;
description: string;
page_path: string;
state: "draft" | "pending" | "open";
state: "draft" | "pending" | "open" | "done";
closed_at?: string | null;
delete_after?: string | null;
linear_done_synced?: boolean;
cleanup_run_id?: string | null;
cleanup_lease_until?: string | null;
cleanup_error?: string | null;
purge_started_at?: string | null;
status_checked_at?: string | null;
screenshot_expected: boolean;
screenshot_path: string | null;
linear_asset_url: string | null;
@@ -76,6 +84,10 @@ export type BugReportView = Pick<
| "linear_identifier"
| "glow_requested"
| "created_at"
| "closed_at"
| "delete_after"
| "linear_done_synced"
| "cleanup_error"
> & {
screenshot: string | null;
isGuest: boolean;
@@ -88,8 +100,10 @@ export type BugReportView = Pick<
};
export type SupportCommand =
| { kind: "reply"; text: string }
| { kind: "glow"; enabled: boolean };
| { kind: "glow"; enabled: boolean }
| { kind: "close" };
export function supportCommand(body: string): SupportCommand | null {
if (body.trim() === "#player-report-close") return { kind: "close" };
const reply = /^#player-report-send\s+([\s\S]+)$/.exec(body.trim());
if (reply) {
const parsed = text(1, 6000).safeParse(reply[1]);

View File

@@ -702,6 +702,45 @@ export type Database = {
[_ in never]: never;
};
Functions: {
receive_bug_close: {
Args: { p_report: string; p_external: string };
Returns: boolean;
};
set_bug_report_done: {
Args: {
p_report: string;
p_done: boolean;
p_closed_at?: string | null;
};
Returns: boolean;
};
claim_bug_cleanup: {
Args: { p_report: string; p_worker: string };
Returns: import("./bug-reports").BugReportRecord[];
SetofOptions: {
from: "*";
to: "bug_reports";
isOneToOne: false;
isSetofReturn: true;
};
};
begin_bug_purge: {
Args: { p_report: string; p_closed_at: string };
Returns: boolean;
};
finish_bug_purge: {
Args: { p_report: string; p_closed_at: string };
Returns: boolean;
};
join_multiplayer_room: {
Args: {
p_room: string;
p_access_hash: string;
p_owner: string | null;
p_name: string;
};
Returns: Json;
};
claim_discord_cleanup: {
Args: { p_worker: string; p_target?: string | null };
Returns: import("./discord").DiscordAnnouncement[];

View File

@@ -830,5 +830,16 @@
"Discord rate limit. Delivery will retry.": "Discord ограничил частоту запросов. Отправка будет повторена.",
"Discord rejected this notification.": "Discord отклонил это объявление.",
"Discord did not confirm delivery.": "Discord не подтвердил отправку.",
"Discord delivery could not be confirmed. Delivery will retry.": "Не удалось подтвердить отправку в Discord. Она будет повторена."
"Discord delivery could not be confirmed. Delivery will retry.": "Не удалось подтвердить отправку в Discord. Она будет повторена.",
"Host display name": "Отображаемое имя ведущего",
"Log in to create a multiplayer room": "Войдите в аккаунт, чтобы создать комнату",
"Done": "Завершено",
"Close report": "Закрыть обращение",
"Report closed.": "Обращение закрыто.",
"This bug report is Done": "Это обращение уже завершено",
"Wait for support to receive this report before closing it": "Дождитесь получения обращения поддержкой, прежде чем закрыть его",
"This report is closed and will be deleted from MineGeo and Linear after three days.": "Обращение закрыто и будет удалено из MineGeo и Linear через три дня.",
"Scheduled deletion": "Дата удаления",
"Syncing Done status with Linear…": "Синхронизируем статус «Завершено» с Linear…",
"Support cleanup paused. The support team may need to update Linear permissions.": "Удаление обращения приостановлено. Поддержке может потребоваться обновить права доступа к Linear."
}

View File

@@ -2,12 +2,13 @@ import { z } from "zod";
import { displayNameSchema } from "./account";
import type { Bounds, Difficulty } from "./protocol";
export const createRoomSchema = z.object({
datasetId: z.string().uuid(),
difficulty: z.enum(["easy", "normal", "hard"]),
displayName: displayNameSchema,
playerLimit: z.number().int().min(2).max(16),
});
export const createRoomSchema = z
.object({
datasetId: z.string().uuid(),
difficulty: z.enum(["easy", "normal", "hard"]),
playerLimit: z.number().int().min(2).max(16),
})
.strict();
export const joinRoomSchema = z.object({ displayName: displayNameSchema });
export const chatMessageSchema = z.object({
clientId: z.string().uuid(),