mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-02 04:52:50 +08:00
fix(auto-pause): never treat a failed clientlist as "channel empty"; default OFF
Auto-pause within the first seconds of playback (and re-pause after a manual
play) whenever a listener is actually in the channel.
Root cause (confirmed live against a TS3 server): the full-client
`clientlist -uid -away -voice -groups` command TIMES OUT when other clients are
present in the bot's channel. `getClientsInChannel()` catches the error and
returns `[]`, so the occupancy callers computed `userCount = [].length - 1 = -1`,
which `decideOccupancyAction` reads as `-1 <= 0` → "channel empty" → pause. With
the bot alone, clientlist succeeds (returns just the bot), so the bug only
surfaced when someone was listening — exactly the report.
Fix: a connected bot is always a member of its own channel, so a valid query
returns >= 1 (itself). A length of 0 therefore means the query FAILED, not that
the channel is empty. New pure helper `occupancyFromClientList()` maps a
0-length result to `null` ("occupancy unknown"); `refreshOccupancy()` and the
30s idle poller skip the auto-pause / idle-disconnect decision when the count is
unknown instead of mis-reading it as empty. This also removes a latent
false-positive idle-disconnect on the same failed query.
Also default `autoPauseOnEmpty` to OFF (occupancy detection is unreliable on
some servers); users can opt in from Settings.
Verified live with two clients in one channel: clientlist returns 0 → helper
returns null → no false pause (control: bot alone returns 1 → 0 others, normal).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
75f09694a3
commit
d3fd547ea0
6 files changed
+57
-11
No files matched your search
+9
-4
@@ -18,7 +18,7 @@ import type { BotDatabase, ProfileConfig } from "../data/database.js";
|
||||
import type { BotConfig } from "../data/config.js";
|
||||
import { BotProfileManager } from "./profile.js";
|
||||
import type { AvatarStore } from "../data/avatars.js";
|
||||
import { decideOccupancyAction } from "./auto-pause.js";
|
||||
import { decideOccupancyAction, occupancyFromClientList } from "./auto-pause.js";
|
||||
|
||||
export interface BotInstanceOptions {
|
||||
id: string;
|
||||
@@ -175,7 +175,11 @@ export class BotInstance extends EventEmitter {
|
||||
if (!this.connected) return;
|
||||
try {
|
||||
const clients = await this.tsClient.getClientsInChannel();
|
||||
this.handleOccupancy(clients.length - 1);
|
||||
// A 0-length result means the clientlist query failed (the bot is always
|
||||
// in its own channel) — occupancy is unknown, so don't act. Acting on it
|
||||
// would mis-read it as "empty" and falsely auto-pause / idle-disconnect.
|
||||
const userCount = occupancyFromClientList(clients.length);
|
||||
if (userCount !== null) this.handleOccupancy(userCount);
|
||||
} catch {
|
||||
// ignore — the 30s poll is the fallback
|
||||
}
|
||||
@@ -229,8 +233,9 @@ export class BotInstance extends EventEmitter {
|
||||
if (!this.connected) return;
|
||||
try {
|
||||
const clients = await this.tsClient.getClientsInChannel();
|
||||
const userCount = clients.length - 1; // 排除 bot 自身
|
||||
this.handleOccupancy(userCount);
|
||||
// null = clientlist query failed (occupancy unknown) → don't act.
|
||||
const userCount = occupancyFromClientList(clients.length);
|
||||
if (userCount !== null) this.handleOccupancy(userCount);
|
||||
} catch { /* ignore */ }
|
||||
setTimeout(poll, 30_000);
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user