Add moderation permissions and durable player records

This commit is contained in:
2026-10-15 21:06:08 -04:00
parent c1758cce25
commit c91d49c298
17 changed files with 699 additions and 21 deletions
+109
View File
@@ -0,0 +1,109 @@
export type ModerationGame = 't5' | 't6';
export type ModerationScope = 'server' | 'game' | 'fleet';
export type ModerationActionKind = 'warn' | 'message' | 'kick' | 'announce';
export type ModerationState =
'queued' | 'delivered' | 'confirmed' | 'failed' | 'expired' | 'unknown';
export interface ModerationPlayer {
game: ModerationGame;
guid: string;
name: string;
aliases: string[];
firstSeen: string;
lastSeen: string;
servers: string[];
restrictions: number;
}
export interface ModerationSanction {
id: string;
game: ModerationGame;
guid: string;
kind: 'ban' | 'mute';
scope: ModerationScope;
server: string | null;
reason: string;
note: string;
createdAt: string;
expiresAt: string | null;
revokedAt: string | null;
actorId: string;
actor: string;
revision: number;
active: boolean;
}
export interface ModerationAction {
id: string;
game: ModerationGame;
guid: string | null;
server: string;
kind: ModerationActionKind;
reason: string;
actor: string;
createdAt: string;
expiresAt: string;
state: ModerationState;
detail: string | null;
}
export interface ModerationCase {
id: string;
game: ModerationGame;
guid: string;
title: string;
status: 'open' | 'resolved' | 'dismissed';
actor: string;
createdAt: string;
updatedAt: string;
revision: number;
evidence: { id: string; text: string; source: string; createdAt: string; actor: string }[];
}
export interface ModerationEvent {
id: number;
game: ModerationGame | null;
guid: string | null;
action: string;
subjectId: string | null;
actor: string;
detail: string;
createdAt: string;
}
export interface ModerationCoverage {
server: string;
game: ModerationGame;
connectedAt: string | null;
revision: number | null;
desiredRevision: number;
state: 'current' | 'pending' | 'offline' | 'unavailable';
capabilities: string[];
}
export interface ModerationQuery {
view: 'players' | 'restrictions' | 'cases' | 'history';
q: string;
game: '' | ModerationGame;
guid: string;
offset: number;
}
export interface ModerationOverview {
query: ModerationQuery;
players: ModerationPlayer[];
sanctions: ModerationSanction[];
cases: ModerationCase[];
events: ModerationEvent[];
actions: ModerationAction[];
coverage: ModerationCoverage[];
total: number;
limit: number;
checkedAt: string;
}
/** RCON T6 IDs are hexadecimal, while the game scripts send decimal strings. */
export function moderationGuid(
game: ModerationGame,
guid: string,
source: 'game' | 'rcon' = 'game'
): string {
const value = guid.trim();
if (game === 't6' && source === 'rcon' && /^(?:0x)?[0-9a-f]+$/i.test(value))
return BigInt(`0x${value.replace(/^0x/i, '')}`).toString();
if (/^\d+$/.test(value)) return BigInt(value).toString();
return value;
}