Add player moderation workflows and game integration
CI / checks (push) Successful in 7m27s

This commit is contained in:
2026-10-15 21:33:50 -04:00
parent c91d49c298
commit 8b372fa2c1
50 changed files with 4744 additions and 354 deletions
+91
View File
@@ -0,0 +1,91 @@
import type { ModerationGame } from '$lib/moderation.js';
import { serverTitle } from './server-labels.js';
export function moderationHref(context: {
game?: string;
guid?: string;
q?: string;
server?: string;
matchId?: number;
message?: string;
}): string {
const params = new URLSearchParams();
if (context.game === 't5' || context.game === 't6') params.set('game', context.game);
if (context.guid) params.set('guid', context.guid);
if (context.q) params.set('q', context.q);
if (context.server) params.set('server', context.server);
if (context.matchId !== undefined && context.message) {
params.set('matchId', String(context.matchId));
params.set('message', context.message);
}
return `/moderation?${params}`;
}
export function moderationGameName(game: ModerationGame): string {
return game === 't5' ? 'Black Ops I' : 'Black Ops II';
}
export const moderationActionLabels: Record<string, string> = {
warn: 'Warning',
message: 'Private message',
kick: 'Kick',
announce: 'Announcement',
'create-sanction': 'Restriction created',
'revoke-sanction': 'Restriction revoked',
'create-case': 'Case opened',
'case-note': 'Case note added',
'resolve-case': 'Case reviewed',
note: 'Private note',
'restriction.created': 'Restriction created',
'restriction.revoked': 'Restriction revoked',
'action.queued': 'Live action requested',
'action.confirmed': 'Live action confirmed',
'action.failed': 'Live action failed',
'action.expired': 'Live action expired',
'action.unknown': 'Live action outcome unknown',
'case.opened': 'Case opened',
'case.note': 'Case note added',
'case.resolved': 'Case resolved',
'case.dismissed': 'Case dismissed',
'player.note': 'Private player note',
'runtime.configure': 'Integration configuration requested'
};
export function moderationEventDetail(detail: string, action: string): string {
if (!['restriction.created', 'action.queued'].includes(action)) return detail;
try {
const value: unknown = JSON.parse(detail);
if (
!value ||
typeof value !== 'object' ||
!('reason' in value) ||
typeof value.reason !== 'string'
)
return detail;
const record = value as Record<string, unknown>;
const context = [
typeof record.kind === 'string'
? (moderationActionLabels[record.kind] ??
(record.kind === 'ban' ? 'Ban' : record.kind === 'mute' ? 'Mute' : ''))
: '',
typeof record.server === 'string'
? serverTitle(record.server)
: record.scope === 'fleet'
? 'Entire fleet'
: record.scope === 'game'
? 'Game scope'
: ''
]
.filter(Boolean)
.join(' · ');
return [
context,
record.reason,
typeof record.note === 'string' && record.note ? `Private note: ${record.note}` : ''
]
.filter(Boolean)
.join('\n');
} catch {
return detail;
}
}