fix(bot): harden ws.ts integration seam
- maybeAbandon Promise no longer floats from setTimeout - broadcastSinceLast loses dead extra parameter - bot-slot token is randomized so a third party can't hijack the bot's color by guessing a fixed placeholder
This commit is contained in:
@@ -93,10 +93,11 @@ function makeSlot(token: PlayerToken, now: number) {
|
||||
}
|
||||
|
||||
function makeBotSlot(now: number) {
|
||||
// Synthetic slot: occupies the player's color but never connects.
|
||||
// Token is a 24-char placeholder; never matches a real client.
|
||||
// Synthetic slot: occupies the player's color but never connects. The token
|
||||
// is randomized (same shape as a real client token) so a third party can't
|
||||
// hijack the bot's color by guessing a fixed placeholder.
|
||||
return {
|
||||
token: 'bot' + 'x'.repeat(21),
|
||||
token: newPlayerToken(),
|
||||
socket: null,
|
||||
joinedAt: now,
|
||||
rateBucket: { tokens: RATE_LIMIT.capacity, last: now },
|
||||
|
||||
@@ -32,20 +32,12 @@ async function pokeBot(game: Game): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
function broadcastSinceLast(
|
||||
game: Game,
|
||||
extra?: { touchedPieceFor?: Color; touchedPiece?: import('@blind-chess/shared').Square },
|
||||
): void {
|
||||
function broadcastSinceLast(game: Game): void {
|
||||
for (const c of ['w', 'b'] as const) {
|
||||
const lastIdx = game.lastBroadcastIdx[c];
|
||||
const all = game.announcements;
|
||||
const slice = all.slice(lastIdx).filter((a) => a.audience === 'both' || a.audience === c);
|
||||
sendUpdateTo(
|
||||
game,
|
||||
c,
|
||||
slice,
|
||||
extra?.touchedPieceFor === c ? { touchedPiece: extra.touchedPiece } : undefined,
|
||||
);
|
||||
sendUpdateTo(game, c, slice);
|
||||
game.lastBroadcastIdx[c] = all.length;
|
||||
}
|
||||
}
|
||||
@@ -249,7 +241,7 @@ function onClose(ctx: SocketCtx): void {
|
||||
if (game.status === 'active') {
|
||||
game.disconnectAt[color] = Date.now();
|
||||
// Schedule grace timer.
|
||||
setTimeout(() => maybeAbandon(game, color), GRACE_MS + 100);
|
||||
setTimeout(() => { void maybeAbandon(game, color); }, GRACE_MS + 100);
|
||||
}
|
||||
notifyPeer(game, color, false, Date.now() + GRACE_MS);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user