feat: include publicID in admin-bot live stats players (#4404)

## Description:

The live stats endpoint enriches each player with username/connected but
not publicId, so an account-keyed caller (e.g. an admin bot, which knows
players by account, not per-session clientID) can't map a stats row back
to a player directly. Add publicId from the same activeClients source —
mirrors the kick_player targetPublicID path.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory

## Please put your Discord username so you can be contacted if a bug or
regression is found:

zixer._
This commit is contained in:
Zixer1
2026-06-24 21:44:51 -04:00
committed by GitHub
parent 181368f962
commit c8a42d4c33
2 changed files with 34 additions and 8 deletions
+10 -5
View File
@@ -1419,6 +1419,7 @@ export class GameServer {
turn: number;
players: (PlayerLiveStats & {
username: string | null;
publicID: string | null;
connected: boolean;
})[];
} | null {
@@ -1427,11 +1428,15 @@ export class GameServer {
}
return {
turn: this.latestLiveStats.turn,
players: this.latestLiveStats.players.map((p) => ({
...p,
username: this.allClients.get(p.clientID)?.username ?? null,
connected: !this.isClientDisconnected(p.clientID),
})),
players: this.latestLiveStats.players.map((p) => {
const client = this.allClients.get(p.clientID);
return {
...p,
username: client?.username ?? null,
publicID: client?.publicId ?? null,
connected: !this.isClientDisconnected(p.clientID),
};
}),
};
}
}
+24 -3
View File
@@ -24,7 +24,13 @@ describe("GameServer.handleLiveStats", () => {
});
function makeClient(clientID: string, ip: string, username: string) {
return { clientID, ip, persistentID: `pid-${clientID}`, username } as any;
return {
clientID,
ip,
persistentID: `pid-${clientID}`,
username,
publicId: clientID.replace("client", "public"), // 8-char ID, e.g. public01
} as any;
}
// A GameServer with three distinct-IP active clients wired up.
@@ -83,7 +89,14 @@ describe("GameServer.handleLiveStats", () => {
// 2 of 3 IPs -> consensus.
expect(game.liveStats()).toEqual({
turn: 100,
players: [{ ...players[0], username: "Alice", connected: true }],
players: [
{
...players[0],
username: "Alice",
publicID: "public01",
connected: true,
},
],
});
});
@@ -138,7 +151,14 @@ describe("GameServer.handleLiveStats", () => {
report(game, clients[1], 200, snapshot(42));
expect(game.liveStats()).toEqual({
turn: 200,
players: [{ ...snapshot(42)[0], username: "Alice", connected: true }],
players: [
{
...snapshot(42)[0],
username: "Alice",
publicID: "public01",
connected: true,
},
],
});
});
@@ -204,6 +224,7 @@ describe("admin bot stats endpoint", () => {
isAlive: true,
team: null,
username: "Alice",
publicID: "public01",
connected: true,
},
],