From fe78bf812c6cfedfd576cde751c1777871329235 Mon Sep 17 00:00:00 2001 From: fattiger <1106842466@qq.com> Date: Wed, 29 Apr 2026 20:51:21 +0800 Subject: [PATCH] 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. --- src/audio/queue.ts | 5 +++++ src/bot/instance.ts | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/audio/queue.ts b/src/audio/queue.ts index b97444d..f63980c 100644 --- a/src/audio/queue.ts +++ b/src/audio/queue.ts @@ -161,4 +161,9 @@ export class PlayQueue { getCurrentIndex(): number { return this.currentIndex; } + + /** Number of songs not yet played in Random mode. */ + unplayedCount(): number { + return this.songs.length - this.playedIndices.size; + } } diff --git a/src/bot/instance.ts b/src/bot/instance.ts index 22314b8..8af5c0b 100755 --- a/src/bot/instance.ts +++ b/src/bot/instance.ts @@ -609,7 +609,7 @@ export class BotInstance extends EventEmitter { for (const song of songs) { this.queue.add({ ...song, platform: "netease" }); } - this.queue.setMode(PlayMode.RandomLoop); + this.queue.setMode(PlayMode.Random); this.isFmMode = true; this.player.resetFailures(); @@ -756,12 +756,12 @@ export class BotInstance extends EventEmitter { if (!started) { this.player.stop(); 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 this.refillFm().catch(err => this.logger.error({ err }, "Proactive FM refill failed")); } } 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) { await this.refillFm(); const refillNext = this.queue.next();