fix: 停止机器人后UI消失 & UDP send error日志刷屏

- botDisconnected事件改为更新状态而非删除,停止机器人后正确显示离线状态
- 节流UDP send error日志,2秒内重复错误只输出一条汇总

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
saopig1andClaude Opus 4.6 committed 2026-03-30 21:50:04 +08:00
1 parent d0d2f57066
commit 43004fc44a
3 files changed
+43 -3

No files matched your search

+23 -1
View File
@@ -56,11 +56,33 @@ export class TS3Client extends EventEmitter {
const addr = `${this.options.host}:${this.options.port}`; const addr = `${this.options.host}:${this.options.port}`;
this.logger.info({ addr }, "Connecting to TeamSpeak server (full client protocol)"); this.logger.info({ addr }, "Connecting to TeamSpeak server (full client protocol)");
// Throttle repeated "udp send error" warnings (fires every 20ms during playback if UDP breaks)
let udpErrorCount = 0;
let udpErrorTimer: ReturnType<typeof setTimeout> | null = null;
const throttledWarn = (msg: string, ...args: unknown[]) => {
if (typeof msg === "string" && msg.includes("udp send error")) {
udpErrorCount++;
if (udpErrorCount === 1) {
this.logger.warn(msg);
// After 2 seconds, log a summary and reset
udpErrorTimer = setTimeout(() => {
if (udpErrorCount > 1) {
this.logger.warn(`udp send error (repeated ${udpErrorCount} times, connection may be lost)`);
}
udpErrorCount = 0;
udpErrorTimer = null;
}, 2000);
}
return;
}
this.logger.warn(msg);
};
this.client = new TS3FullClient(this.identity, addr, this.options.nickname, { this.client = new TS3FullClient(this.identity, addr, this.options.nickname, {
logger: { logger: {
debug: (msg) => this.logger.debug(msg), debug: (msg) => this.logger.debug(msg),
info: (msg) => this.logger.info(msg), info: (msg) => this.logger.info(msg),
warn: (msg) => this.logger.warn(msg), warn: throttledWarn,
error: (msg) => this.logger.error(msg), error: (msg) => this.logger.error(msg),
}, },
}); });
+5 -1
View File
@@ -65,7 +65,11 @@ export function setupWebSocket(
}; };
const onDisconnected = () => { const onDisconnected = () => {
broadcast({ type: "botDisconnected", botId: bot.id }); broadcast({
type: "botDisconnected",
botId: bot.id,
status: bot.getStatus(),
});
}; };
bot.on("stateChange", onStateChange); bot.on("stateChange", onStateChange);
+15 -1
View File
@@ -40,7 +40,21 @@ export function useWebSocket() {
store.updateBotStatus(data.botId, data.status); store.updateBotStatus(data.botId, data.status);
break; break;
case 'botDisconnected': case 'botDisconnected':
store.removeBotStatus(data.botId); // Bot disconnected from TS3 but still exists — update status, don't remove
if (data.status) {
store.updateBotStatus(data.botId, data.status);
} else {
const existing = store.bots.find((b) => b.id === data.botId);
if (existing) {
store.updateBotStatus(data.botId, {
...existing,
connected: false,
playing: false,
paused: false,
currentSong: null,
});
}
}
break; break;
} }
}; };