mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-01 20:42:50 +08:00
fix(qq): batch-precheck playable URLs before queueing playlist
Many users' QQ playlists (especially collected/subscribed ones) contain a large fraction of songs that return result=104003 (region/copyright restricted) for the current account. Sequential retry-skip wasted time guessing — for the user's ACG古风 collected playlist, only 3 of 115 songs are actually streamable, so a 20-retry budget had < 50% chance of finding a hit before giving up. Add a getPlayableSongIds(ids) method to the QQ provider that calls the upstream /getMusicPlay with a comma-separated batch of mids — the wrapper resolves all of them in a single upstream call (~2-3s for 100+ songs). /play-playlist now duck-types this method and, when present, filters the playlist down to playable songs before queueing. Response message reports "Loaded N of M songs (rest are copyright/ region restricted)" so the user sees exactly what's happening instead of guessing why the queue is short or playback didn't start. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4301da2e37
commit
3d0aca52d0
2 files changed
+57
-3
No files matched your search
+27
-3
@@ -249,9 +249,30 @@ export function createPlayerRouter(
|
||||
return;
|
||||
}
|
||||
|
||||
// QQ-specific optimization: many users' QQ playlists contain a
|
||||
// large fraction of songs that return result=104003 (region/copyright
|
||||
// restricted). Batch-resolve URLs once and only queue the playable
|
||||
// ones, otherwise the playback retry loop wastes time guessing.
|
||||
let queueable: { id: string }[] = songs;
|
||||
const totalCount = songs.length;
|
||||
const qqLike = provider as { getPlayableSongIds?: (ids: string[]) => Promise<Set<string>> };
|
||||
if (typeof qqLike.getPlayableSongIds === "function") {
|
||||
const playable = await qqLike.getPlayableSongIds(songs.map((s: { id: string }) => s.id));
|
||||
if (playable.size > 0) {
|
||||
queueable = songs.filter((s: { id: string }) => playable.has(s.id));
|
||||
}
|
||||
// If batch returned nothing, leave queueable as-is and let the
|
||||
// sequential retry path try anyway (handles the case where the
|
||||
// batch endpoint failed entirely).
|
||||
}
|
||||
if (queueable.length === 0) {
|
||||
res.json({ message: `Loaded ${totalCount} songs but none were playable (likely copyright/region restrictions).` });
|
||||
return;
|
||||
}
|
||||
|
||||
const queue = bot.getQueueManager();
|
||||
queue.clear();
|
||||
for (const song of songs) {
|
||||
for (const song of queueable) {
|
||||
queue.add({ ...song, platform: provider.platform });
|
||||
}
|
||||
|
||||
@@ -276,10 +297,13 @@ export function createPlayerRouter(
|
||||
}
|
||||
|
||||
const playing = queue.current();
|
||||
const loadedMsg = queueable.length < totalCount
|
||||
? `Loaded ${queueable.length} of ${totalCount} songs (rest are copyright/region restricted)`
|
||||
: `Loaded ${queueable.length} songs`;
|
||||
if (started && playing) {
|
||||
res.json({ message: `Loaded ${songs.length} songs. Now playing: ${playing.name}` });
|
||||
res.json({ message: `${loadedMsg}. Now playing: ${playing.name}` });
|
||||
} else {
|
||||
res.json({ message: `Loaded ${songs.length} songs but none were playable (likely copyright/region restrictions).` });
|
||||
res.json({ message: `${loadedMsg}, but couldn't start playback.` });
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error({ err }, "Play playlist failed");
|
||||
|
||||
Reference in new issue
Block a user