75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
export const RCON_COMMAND_REQUESTED = "games.minecraft.account-manager.rcon.command.requested";
|
|
export const RCON_COMMAND_COMPLETED = "games.minecraft.account-manager.rcon.command.completed";
|
|
|
|
export type RconHistoryEvent = {
|
|
id: string;
|
|
time: Date;
|
|
correlationId: string | null;
|
|
data: Record<string, unknown>;
|
|
};
|
|
|
|
export type RconCommandHistoryRow = {
|
|
eventId: string;
|
|
time: Date;
|
|
command: string;
|
|
serverId: string;
|
|
serverName: string;
|
|
adminEmail: string | null;
|
|
adminName: string | null;
|
|
status: "pending" | "succeeded" | "failed";
|
|
reason: string | null;
|
|
durationMs: number | null;
|
|
};
|
|
|
|
type SearchParams = Record<string, string | string[] | undefined>;
|
|
|
|
function first(value: string | string[] | undefined) {
|
|
return (Array.isArray(value) ? value[0] : value)?.trim() ?? "";
|
|
}
|
|
|
|
function text(data: Record<string, unknown>, key: string) {
|
|
const value = data[key];
|
|
return typeof value === "string" && value ? value : null;
|
|
}
|
|
|
|
export function normalizeRconHistoryFilters(query: SearchParams, availableServerIds: string[]) {
|
|
const requestedServerId = first(query.server);
|
|
return {
|
|
command: first(query.command).slice(0, 1024),
|
|
admin: first(query.admin).slice(0, 320),
|
|
serverId: availableServerIds.includes(requestedServerId) ? requestedServerId : "",
|
|
};
|
|
}
|
|
|
|
export function buildRconCommandHistory(
|
|
requestedEvents: RconHistoryEvent[],
|
|
completedEvents: RconHistoryEvent[],
|
|
): RconCommandHistoryRow[] {
|
|
const completions = new Map(completedEvents
|
|
.filter((event) => event.correlationId)
|
|
.map((event) => [event.correlationId, event]));
|
|
|
|
return requestedEvents.flatMap((event) => {
|
|
const command = text(event.data, "command");
|
|
const serverId = text(event.data, "serverId");
|
|
const serverName = text(event.data, "name");
|
|
if (!command || !serverId || !serverName) return [];
|
|
|
|
const completed = event.correlationId ? completions.get(event.correlationId) : undefined;
|
|
const success = completed?.data.success;
|
|
const duration = completed?.data.durationMs;
|
|
return [{
|
|
eventId: event.id,
|
|
time: event.time,
|
|
command,
|
|
serverId,
|
|
serverName,
|
|
adminEmail: text(event.data, "adminEmail"),
|
|
adminName: text(event.data, "adminName"),
|
|
status: success === true ? "succeeded" as const : success === false ? "failed" as const : "pending" as const,
|
|
reason: completed ? text(completed.data, "reason") : null,
|
|
durationMs: typeof duration === "number" && Number.isFinite(duration) ? duration : null,
|
|
}];
|
|
});
|
|
}
|