mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-02 04:52:50 +08:00
fix(player): retry-skip in /play-playlist when first song can't resolve
QQ Music sometimes refuses to issue a play URL for individual songs (upstream returns result=104003, "no copyright/payment"). The /play-playlist endpoint only called resolveAndPlay once on the first song, so when that one was 104003 the bot would sit silently with no feedback — exactly what looked like "播放全部 没有反应". Make BotInstance.playNext() public and call it as a fallback when the first resolveAndPlay fails. playNext already has the 3-attempt retry-skip used by trackEnd auto-advance, so we get the same graceful skip behavior for explicit playlist plays. Also tighten the response message so the user can tell when the bot loaded songs but none were playable. Single-song /play-song still returns "Cannot play" on failure (no queue to advance through); UX surfacing of that goes in a follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
5799891e4f
commit
82655afa20
2 files changed
+21
-4
No files matched your search
+7
-1
@@ -734,7 +734,13 @@ export class BotInstance extends EventEmitter {
|
|||||||
].join("\n");
|
].join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async playNext(): Promise<void> {
|
/**
|
||||||
|
* Advance the queue and play the next song. If the resolved URL fails
|
||||||
|
* (e.g., copyright/region restrictions for QQ), skips up to 3 more
|
||||||
|
* songs looking for a playable one. Public so REST endpoints that
|
||||||
|
* seed the queue can fall back to this retry-skip behavior.
|
||||||
|
*/
|
||||||
|
async playNext(): Promise<void> {
|
||||||
if (this.isAdvancing || !this.connected) return;
|
if (this.isAdvancing || !this.connected) return;
|
||||||
this.isAdvancing = true;
|
this.isAdvancing = true;
|
||||||
try {
|
try {
|
||||||
|
|||||||
+14
-3
@@ -265,11 +265,22 @@ export function createPlayerRouter(
|
|||||||
first = queue.play();
|
first = queue.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first) {
|
// If the first picked song can't resolve (e.g., QQ song with no
|
||||||
await bot.resolveAndPlay(first);
|
// streaming entitlement → result 104003), fall back to the same
|
||||||
|
// retry-skip behavior playNext uses for trackEnd auto-advance.
|
||||||
|
// Otherwise the bot would sit silently on a dead song.
|
||||||
|
let started = first ? await bot.resolveAndPlay(first) : false;
|
||||||
|
if (first && !started) {
|
||||||
|
await bot.playNext();
|
||||||
|
started = !!queue.current();
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json({ message: `Loaded ${songs.length} songs. Now playing: ${first?.name ?? "unknown"}` });
|
const playing = queue.current();
|
||||||
|
if (started && playing) {
|
||||||
|
res.json({ message: `Loaded ${songs.length} songs. Now playing: ${playing.name}` });
|
||||||
|
} else {
|
||||||
|
res.json({ message: `Loaded ${songs.length} songs but none were playable (likely copyright/region restrictions).` });
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error({ err }, "Play playlist failed");
|
logger.error({ err }, "Play playlist failed");
|
||||||
res.status(500).json({ error: (err as Error).message });
|
res.status(500).json({ error: (err as Error).message });
|
||||||
|
|||||||
Reference in new issue
Block a user