Capture team chat and expose moderation match archives

This commit is contained in:
2026-10-17 20:11:49 -04:00
parent b678de2f6f
commit 870f13b150
28 changed files with 943 additions and 81 deletions
+33 -8
View File
@@ -139,7 +139,7 @@ describe('server chat API', () => {
).toEqual(['first', 'retry me']);
});
it('skips empty, stopped and offline servers and collects one last time after players leave', async () => {
it('checks idle servers once, skips stopped and offline servers and collects after players leave', async () => {
const { db } = await import('../../src/lib/server/db/index.js');
const { createHost } = await import('../../src/lib/server/hosts/index.js');
const logs = await import('../../src/lib/server/fleet/logs.js');
@@ -147,25 +147,27 @@ describe('server chat API', () => {
const { collectFleetChat } = await import('../../src/lib/server/fleet/chat.js');
db().prepare("UPDATE servers SET last_players=0,container_state='running'").run();
await collectFleetChat();
expect(read).not.toHaveBeenCalled();
expect(read).toHaveBeenCalledTimes(2);
await collectFleetChat();
expect(read).toHaveBeenCalledTimes(2);
db().prepare('UPDATE servers SET last_players=1 WHERE name=?').run(SERVER);
await log(['60:50 say;abc;0;Player;playing'], 50);
await collectFleetChat();
expect(read).toHaveBeenCalledTimes(1);
expect(read).toHaveBeenCalledTimes(3);
db().prepare('UPDATE servers SET last_players=0 WHERE name=?').run(SERVER);
await log(['60:50 say;abc;0;Player;playing', '61:00 say;abc;0;Player;goodbye']);
expect((await (await get()).json()).entries).toHaveLength(1);
expect(read).toHaveBeenCalledTimes(1);
expect(read).toHaveBeenCalledTimes(3);
await collectFleetChat();
await collectFleetChat();
expect(read).toHaveBeenCalledTimes(2);
expect(read).toHaveBeenCalledTimes(4);
expect((await (await get()).json()).entries).toHaveLength(2);
expect(read).toHaveBeenCalledTimes(2);
expect(read).toHaveBeenCalledTimes(4);
db()
.prepare("UPDATE servers SET last_players=1,container_state='stopped' WHERE name=?")
.run(SERVER);
await collectFleetChat();
expect(read).toHaveBeenCalledTimes(2);
expect(read).toHaveBeenCalledTimes(4);
const host = createHost({ name: 'Offline' });
db().prepare("UPDATE servers SET container_state='running' WHERE name=?").run(SERVER);
db()
@@ -175,7 +177,30 @@ describe('server chat API', () => {
)
.run(SERVER, host.id, at(0));
await collectFleetChat();
expect(read).toHaveBeenCalledTimes(2);
expect(read).toHaveBeenCalledTimes(4);
});
it('archives surviving idle match logs with distinct stable public and team message identities', async () => {
await report('game_start', 0);
await report('heartbeat', 20, 4);
await report('game_end', 60, 4);
await log(['60:30 say;abc;0;Player;hello', '60:30 sayteam;abc;0;Player;hello'], 30);
const { db } = await import('../../src/lib/server/db/index.js');
db().prepare('UPDATE servers SET last_players=0').run();
const { collectFleetChat, matchChatTimeline } =
await import('../../src/lib/server/fleet/chat.js');
await collectFleetChat();
const saved = matchChatTimeline(1);
expect(saved).toHaveLength(2);
expect(saved[0]).toMatchObject({ message: { message: 'hello' } });
expect(saved[0].type === 'message' && saved[0].message.channel).toBeUndefined();
expect(saved[1]).toMatchObject({ message: { message: 'hello', channel: 'team' } });
expect(new Set(saved.map((entry) => entry.messageId)).size).toBe(2);
expect(saved.every((entry) => typeof entry.messageId === 'string')).toBe(true);
advanceTime();
await get();
await collectFleetChat();
expect(matchChatTimeline(1)).toEqual(saved);
});
it('keeps real timestamps and historical match context stable across refreshes', async () => {