app · 930d3ec

Dev index Recent changes / versions Changelog About TODO

fix(youtube): 未啟用時不再輸出斷線收尾

930d3ec · 2026-11-10 23:37 · app
ScriptLib/youtube/chat.mjsTest/youtube_stop.test.mjsTikTok.js
commit 930d3ecb28f028457fc773d8ef9e97dd6265836dAuthor: Nuclear0709 <agp05432@gmail.com>Date:   Tue Nov 10 23:37:20 2026 +0800     fix(youtube): 未啟用時不再輸出斷線收尾        - 只有真正啟動 YouTube 才標記 active,收尾時才輸出停止訊息    - handleExit 加上冪等 guard,避免重複退出造成重複收尾    - 補未啟用 YouTube 的收尾測試 diff --git a/ScriptLib/youtube/chat.mjs b/ScriptLib/youtube/chat.mjsindex 81028ce..ca89218 100644--- a/ScriptLib/youtube/chat.mjs+++ b/ScriptLib/youtube/chat.mjs@@ -38,6 +38,7 @@ let youtubeNextPageToken = null; let youtubeViewerInterval = null; let youtubeBrowserFallbackStarted = false; let youtubeSourceMode = 'auto';+let youtubeActive = false;  function loadYoutubeCache() {     try {@@ -199,6 +200,7 @@ function handleYoutubeText(payload, deps, transport = 'native') { /** 每 60 秒用 API Key 更新觀眾數;瀏覽器 fallback 與原生 API 共用。 */ function startYoutubeViewerPolling(videoId, deps) {     clearInterval(youtubeViewerInterval);+    youtubeActive = true;     youtubeVideoId = videoId;     youtubeViewerInterval = setInterval(async () => {         if (!youtubeVideoId) return;@@ -218,6 +220,7 @@ function startYoutubeViewerPolling(videoId, deps) {  function connect(liveChatId, videoId, channelName, deps) {     const { axios, apiKey, pollIntervalS, writeLog, notify, sendSystem, sendChat } = deps;+    youtubeActive = true;     youtubeLiveChatId = liveChatId;     youtubeNextPageToken = null;     youtubeBrowserFallbackStarted = false;@@ -423,6 +426,7 @@ export async function startYoutubeChat(channelName, deps) {                     onText: payload => handleYoutubeText(payload, deps, 'browser')                 }             });+            youtubeActive = true;             sendSystem(`Youtube 已透過專用瀏覽器 discovery 連線 ${channelName}`);             notify("Youtube 連線", `已透過專用瀏覽器 discovery 連線 ${channelName}`, "");         } catch (error) {@@ -508,6 +512,8 @@ export async function startYoutubeChat(channelName, deps) {  * @returns {Promise<void>}  */ export async function stopYoutubeChat() {+    const wasActive = youtubeActive+        || Boolean(youtubePollInterval || youtubeViewerInterval || youtubeLiveChatId || youtubeVideoId);     clearTimeout(youtubePollInterval);     clearInterval(youtubeViewerInterval);     youtubePollInterval = null;@@ -516,10 +522,11 @@ export async function stopYoutubeChat() {     youtubeVideoId = null;     youtubeNextPageToken = null;     youtubeBrowserFallbackStarted = false;+    youtubeActive = false;     try {         await stopYoutubeBrowser();     } catch (error) {         console.error('❌ 關閉 Youtube 專用瀏覽器失敗:', error.message);     }-    console.log('❌ Youtube 聊天室已斷線');+    if (wasActive) console.log('⏹️ Youtube 聊天室已停止'); }diff --git a/Test/youtube_stop.test.mjs b/Test/youtube_stop.test.mjsnew file mode 100644index 0000000..370293c--- /dev/null+++ b/Test/youtube_stop.test.mjs@@ -0,0 +1,24 @@+import test from 'node:test';+import assert from 'node:assert/strict';+import { startYoutubeChat, stopYoutubeChat } from '../ScriptLib/youtube/chat.mjs';++test('未啟動 YouTube 時,收尾不應輸出聊天室已斷線', async () => {+    const logs = [];+    const original = console.log;+    console.log = (...args) => logs.push(args.join(' '));+    try {+        await startYoutubeChat('', {+            writeLog: () => {}, sendSystem: () => {}, notify: () => {},+            axios: {}, apiKey: '', pollIntervalS: 5, sendChat: () => {},+            reportTraffic: () => {}, reportFiltered: () => {}, filter: () => ({ blocked: false }),+            recordHeat: () => true, replaceEmojis: value => value, translate: async value => value,+            onViewerCount: () => {}+        });+        await stopYoutubeChat();+        await stopYoutubeChat();+    } finally {+        console.log = original;+    }+    assert.equal(logs.some(line => line.includes('Youtube 聊天室已斷線')), false);+    assert.equal(logs.some(line => line.includes('Youtube 聊天室已停止')), false);+});diff --git a/TikTok.js b/TikTok.jsindex fd24297..ae66cf0 100644--- a/TikTok.js+++ b/TikTok.js@@ -353,10 +353,13 @@ const tiktokConn = createTikTokConnectionManager({   var isEnd=false+let exitStarted=false  const EXIT_TIMEOUT_MS = 8000;  async function handleExit() {+    if (exitStarted) return;+    exitStarted = true;     console.log("⏹️ 程式結束,開始收尾...");      // 收尾若卡住(網路 / Puppeteer),必須有硬性上限,否則行程永遠不退出,