Fix command invocation

This commit is contained in:
2026-01-23 00:34:31 +01:00
parent 6925e3f560
commit 445c96110a

View File

@@ -322,10 +322,15 @@ async function streamFeed(state) {
state.whiteClock = null; state.whiteClock = null;
state.blackClock = null; state.blackClock = null;
state.feedBuffer = "";
state.feedDecoder = new TextDecoder();
state.feedReader = null;
state.feedReading = false;
state.streamEnded = false;
const controller = new AbortController(); const controller = new AbortController();
state.abortController = controller; state.abortController = controller;
let streamEnded = false;
try { try {
const response = await fetch(FEED_URL, { const response = await fetch(FEED_URL, {
method: "GET", method: "GET",
@@ -335,51 +340,24 @@ async function streamFeed(state) {
if (!response.ok || !response.body) { if (!response.ok || !response.body) {
throw new Error("Unable to load Lichess TV feed"); throw new Error("Unable to load Lichess TV feed");
} }
state.feedReader = response.body.getReader();
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
if (state.shouldStop) {
break;
}
const { value, done } = await reader.read();
if (done) {
streamEnded = true;
break;
}
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
lines.forEach((line) => {
if (!line.trim()) {
return;
}
try {
const event = JSON.parse(line);
updateFromEvent(event, state);
} catch (_error) {
// Ignore malformed events.
}
});
if (state.gameOver) {
state.shouldStop = true;
}
}
} catch (error) { } catch (error) {
if (error?.name !== "AbortError") { if (error?.name !== "AbortError") {
state.error = error?.message || String(error); state.error = error?.message || String(error);
} }
} finally {
if (state.abortController === controller) {
state.abortController = null;
}
state.feedActive = false;
if (streamEnded && !state.shouldStop) {
state.shouldStop = true; state.shouldStop = true;
} }
}
function finalizeFeed(state) {
if (state.abortController) {
state.abortController.abort();
state.abortController = null;
}
state.feedReader = null;
state.feedReading = false;
state.feedActive = false;
state.streamEnded = false;
if (state.shouldStop) { if (state.shouldStop) {
state.boardVisible = false; state.boardVisible = false;
state.board = null; state.board = null;
@@ -394,14 +372,49 @@ async function streamFeed(state) {
state.needsClear = true; state.needsClear = true;
} }
} }
async function readFeedChunk(state) {
if (!state.feedReader || state.feedReading || state.shouldStop) {
return;
}
state.feedReading = true;
try {
const { value, done } = await state.feedReader.read();
if (done) {
state.streamEnded = true;
state.shouldStop = true;
return;
}
state.feedBuffer += state.feedDecoder.decode(value, { stream: true });
const lines = state.feedBuffer.split("\n");
state.feedBuffer = lines.pop() || "";
lines.forEach((line) => {
if (!line.trim()) {
return;
}
try {
const event = JSON.parse(line);
updateFromEvent(event, state);
} catch (_error) {
// Ignore malformed events.
}
});
if (state.gameOver) {
state.shouldStop = true;
}
} catch (error) {
if (error?.name !== "AbortError") {
state.error = error?.message || String(error);
}
state.shouldStop = true;
} finally {
state.feedReading = false;
}
} }
function stopFeed(state) { function stopFeed(state) {
state.shouldStop = true; state.shouldStop = true;
if (state.abortController) { finalizeFeed(state);
state.abortController.abort();
}
state.needsClear = true;
} }
function processChatCommands(chatMessages, state) { function processChatCommands(chatMessages, state) {
@@ -424,14 +437,12 @@ function processChatCommands(chatMessages, state) {
} }
latestSeen = Math.max(latestSeen, timestamp); latestSeen = Math.max(latestSeen, timestamp);
if (!shouldStart && isCommandMatch(message?.message)) { if (!shouldStart && isCommandMatch(message?.message)) {
console.log("Lichess TV: Detected command to start stream feed.");
shouldStart = true; shouldStart = true;
} }
}); });
state.lastChatTimestamp = latestSeen; state.lastChatTimestamp = latestSeen;
console.log(`Lichess TV: shouldStart=${shouldStart}, feedActive=${state.feedActive}, boardVisible=${state.boardVisible}`);
if (shouldStart && !state.feedActive && !state.boardVisible) { if (shouldStart && !state.feedActive && !state.boardVisible) {
streamFeed(state); streamFeed(state);
} }
@@ -549,6 +560,10 @@ function tick(context, state) {
processChatCommands(chatMessages, state); processChatCommands(chatMessages, state);
if (state.feedActive) {
readFeedChunk(state);
}
if (state.needsClear) { if (state.needsClear) {
ctx.clearRect(0, 0, width, height); ctx.clearRect(0, 0, width, height);
state.needsClear = false; state.needsClear = false;