mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-02 04:52:50 +08:00
fix(spotify): per-bot Connect device name to avoid multi-bot device collision/misroute [corner-case R2-5]
config.spotify is a single process-wide object shared by every BotInstance, so
config.spotify.deviceName was identical for all bots. On the Rust (librespot)
backend each bot spawned `librespot --name <deviceName>` with no per-bot
uniqueness, registering two Connect devices with the same name under the one
shared account. findDeviceByName()/waitForDevice() match by name, so bot A's
transfer()+play() could drive bot B's librespot (misroute) and a bot could
report ready on seeing the OTHER bot's same-named device (false readiness).
Fix: derive a per-bot-unique Connect identity from the shared base name.
- controller.ts: new exported pure helper perBotDeviceName(base, instanceId?)
(`${base}-${instanceId}` when an id is given, else base). Add optional
instanceId to SpotifyControllerOptions; buildBackend() computes the effective
name once and passes the SAME value to both the Rust and go backends so
--name, findDeviceByName, and waitForDevice all key on one identity.
- instance.ts: pass instanceId: this.id into buildController(); add instanceId
to the spotifyControllerFactory param type (test seam).
The user-configured config.spotify.deviceName base is left untouched; the suffix
applies only to the backend/Connect identity. Behavior-preserving for callers
that pass no instanceId (base name used unchanged).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
9a32f3c602
commit
2e05d276bf
4 files changed
+97
-5
No files matched your search
@@ -626,9 +626,9 @@ describe("BotInstance.seek — spotify routing (C4)", () => {
|
||||
describe("BotInstance — spotifyOAuth threading to the controller factory (C3.1)", () => {
|
||||
function makeInstanceOptions(over: Partial<BotInstanceOptions> = {}): {
|
||||
options: BotInstanceOptions;
|
||||
captured: { param?: { oauth?: SpotifyOAuth } };
|
||||
captured: { param?: { oauth?: SpotifyOAuth; instanceId?: string } };
|
||||
} {
|
||||
const captured: { param?: { oauth?: SpotifyOAuth } } = {};
|
||||
const captured: { param?: { oauth?: SpotifyOAuth; instanceId?: string } } = {};
|
||||
const provider = { platform: "netease" } as unknown as MusicProvider;
|
||||
const logger: any = {
|
||||
info() {}, warn() {}, error() {}, debug() {},
|
||||
@@ -677,6 +677,17 @@ describe("BotInstance — spotifyOAuth threading to the controller factory (C3.1
|
||||
expect(captured.param).toBeDefined();
|
||||
expect(captured.param?.oauth).toBeUndefined();
|
||||
});
|
||||
|
||||
// R2-5: the bot id must reach the controller as `instanceId` so the backend
|
||||
// derives a UNIQUE Spotify Connect device name (<base>-<id>). Without it two
|
||||
// bots share the process-global deviceName and Connect commands misroute.
|
||||
it("forwards the bot id to the controller factory as `instanceId` (corner-case R2-5)", () => {
|
||||
const { options, captured } = makeInstanceOptions({ id: "bot-xyz" });
|
||||
// eslint-disable-next-line no-new
|
||||
new BotInstance(options);
|
||||
expect(captured.param).toBeDefined();
|
||||
expect(captured.param?.instanceId).toBe("bot-xyz");
|
||||
});
|
||||
});
|
||||
|
||||
describe("spotifyPortsForBotId — per-bot go-librespot ports (Fix 3)", () => {
|
||||
|
||||
Reference in new issue
Block a user