fix: use Random mode for FM instead of RandomLoop to prevent song repeats

RandomLoop randomly selects from queue, causing the same song to play
multiple times when the queue is small (~3 songs from personal_fm API).
Random mode ensures each song plays once before repeating, relying on
refillFm() to fetch fresh songs before exhaustion.

Also fix the proactive refill condition to use unplayedCount() instead
of size() - getCurrentIndex(), which was meaningless for non-sequential
play modes.
This commit is contained in:
fattiger committed 2026-04-29 20:51:21 +08:00
1 parent 4de8ac1810
commit fe78bf812c
2 files changed
+8 -3

No files matched your search

+5
View File
@@ -161,4 +161,9 @@ export class PlayQueue {
getCurrentIndex(): number { getCurrentIndex(): number {
return this.currentIndex; return this.currentIndex;
} }
/** Number of songs not yet played in Random mode. */
unplayedCount(): number {
return this.songs.length - this.playedIndices.size;
}
} }
+3 -3
View File
@@ -609,7 +609,7 @@ export class BotInstance extends EventEmitter {
for (const song of songs) { for (const song of songs) {
this.queue.add({ ...song, platform: "netease" }); this.queue.add({ ...song, platform: "netease" });
} }
this.queue.setMode(PlayMode.RandomLoop); this.queue.setMode(PlayMode.Random);
this.isFmMode = true; this.isFmMode = true;
this.player.resetFailures(); this.player.resetFailures();
@@ -756,12 +756,12 @@ export class BotInstance extends EventEmitter {
if (!started) { if (!started) {
this.player.stop(); this.player.stop();
this.profileManager.onSongChange(null).catch(() => {}); this.profileManager.onSongChange(null).catch(() => {});
} else if (this.isFmMode && this.queue.size() - this.queue.getCurrentIndex() <= 3) { } else if (this.isFmMode && this.queue.unplayedCount() <= 3) {
// Proactive refill: when queue is running low, fetch more FM songs // Proactive refill: when queue is running low, fetch more FM songs
this.refillFm().catch(err => this.logger.error({ err }, "Proactive FM refill failed")); this.refillFm().catch(err => this.logger.error({ err }, "Proactive FM refill failed"));
} }
} else { } else {
// Defensive: only reached if play mode is changed away from RandomLoop during FM // Queue exhausted — in FM Random mode, refill and continue
if (this.isFmMode) { if (this.isFmMode) {
await this.refillFm(); await this.refillFm();
const refillNext = this.queue.next(); const refillNext = this.queue.next();