import type { PlayerSession } from "./types"; import { requestOnlineJson } from "./onlineAccountClient"; import type { DungeonReplaySummary, DungeonReplayV1, DungeonRouteApproval, DungeonRouteReview, DungeonRouteReviewStatus, DungeonSimulationReportV1, } from "../game/dungeonSimulationTypes"; function gmToken(session: PlayerSession | null): string { if (session?.kind !== "account" || !session.accessToken || !session.roles?.includes("gm")) { throw new Error("Game Master access is required."); } return session.accessToken; } export async function fetchDungeonRouteApprovals(): Promise { return (await requestOnlineJson<{ approvals: DungeonRouteApproval[] }>("/api/dungeon-route-approvals")).approvals; } export async function fetchGmDungeonRoutes(session: PlayerSession | null): Promise<{ readonly reviews: readonly DungeonRouteReview[]; readonly latestReplays: readonly DungeonReplaySummary[]; }> { return requestOnlineJson("/api/gm/dungeon-routes", {}, gmToken(session)); } export async function putDungeonRouteReview( session: PlayerSession | null, route: { readonly dungeonId: string; readonly routeId: string; readonly routeHash: string }, update: { readonly status: DungeonRouteReviewStatus; readonly expectedRevision: number; readonly note?: string; readonly criticalOverrideNote?: string; }, ): Promise { const response = await requestOnlineJson<{ review: DungeonRouteReview }>( `/api/gm/dungeon-routes/${encodeURIComponent(route.dungeonId)}/${encodeURIComponent(route.routeId)}/review`, { method: "PUT", body: JSON.stringify({ ...update, routeHash: route.routeHash }) }, gmToken(session), ); return response.review; } export async function fetchDungeonSimulationReplays( session: PlayerSession | null, dungeonId?: string, ): Promise { const query = dungeonId ? `?dungeon=${encodeURIComponent(dungeonId)}` : ""; return (await requestOnlineJson<{ replays: DungeonReplaySummary[] }>( `/api/gm/dungeon-sim/replays${query}`, {}, gmToken(session), )).replays; } export async function saveDungeonSimulationReplay( session: PlayerSession | null, replay: DungeonReplayV1, ): Promise { return (await requestOnlineJson<{ replay: DungeonReplaySummary }>( "/api/gm/dungeon-sim/replays", { method: "POST", body: JSON.stringify(replay) }, gmToken(session), )).replay; } export function fetchDungeonSimulationReplay( session: PlayerSession | null, replayId: string, ): Promise { return requestOnlineJson(`/api/gm/dungeon-sim/replays/${encodeURIComponent(replayId)}`, {}, gmToken(session)); } export function fetchDungeonSimulationReport( session: PlayerSession | null, replayId: string, ): Promise { return requestOnlineJson(`/api/gm/dungeon-sim/replays/${encodeURIComponent(replayId)}/report`, {}, gmToken(session)); } export function deleteDungeonSimulationReplay(session: PlayerSession | null, replayId: string): Promise<{ readonly ok: true }> { return requestOnlineJson(`/api/gm/dungeon-sim/replays/${encodeURIComponent(replayId)}`, { method: "DELETE" }, gmToken(session)); }