mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-01 20:42:50 +08:00
fix(local-audio): reference-aware cleanup, upload quota, stricter validation
Uploaded local files were deleted whenever a track left the current slot, with no check on whether the file was still needed — causing data loss in several flows. Replace with reference-aware cleanup: a file is deleted only once it has been played AND is no longer referenced by ANY bot's queue (BotManager.getReferencedLocalSongIds wired into the provider via setInUseResolver), with the sweep run AFTER each queue mutation. Fixes: - play-song replay no longer deletes the file it is about to play - loop / repeat-all / prev no longer destroy uploads mid-cycle - a shared upload queued on multiple bots is not deleted while still in use - !play / play-playlist / play-album clean the whole replaced queue, and an empty/failed playlist/album load keeps the previous queue + files intact - bound disk use with an upload quota (evict oldest UNREFERENCED files) - validate uploads by extension against the audio whitelist (never trust the client Content-Type); the stored extension is always a known audio type Deletion now unlinks the file FIRST and drops the record only on success, with a bounded non-blocking retry for briefly-locked files (Windows/ffmpeg), so a failed unlink never orphans a file or diverges index.json. The quota never evicts the just-uploaded file, and long filenames keep their extension. Adds src/music/local.test.ts covering the cleanup lifecycle, quota eviction, and upload validation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
e12cbf8863
commit
e849db2286
5 files changed
+453
-77
No files matched your search
@@ -297,7 +297,6 @@ export function createPlayerRouter(
|
||||
|
||||
// Stop current playback
|
||||
bot.getPlayer().stop();
|
||||
bot.cleanupQueuedLocalSongs?.("queue_replaced");
|
||||
bot.getPlayer().resetFailures();
|
||||
|
||||
const songs = await provider.getPlaylistSongs(playlistId);
|
||||
@@ -330,11 +329,14 @@ export function createPlayerRouter(
|
||||
}
|
||||
|
||||
const queue = bot.getQueueManager();
|
||||
bot.cleanupQueuedLocalSongs?.("queue_replaced");
|
||||
queue.clear();
|
||||
for (const song of queueable) {
|
||||
queue.add({ ...song, platform: provider.platform });
|
||||
}
|
||||
// Sweep AFTER the queue is rebuilt: the previous queue's local uploads are
|
||||
// released and deleted, but an empty/failed playlist (early return above)
|
||||
// leaves the previous queue — and its files — intact.
|
||||
bot.cleanupQueuedLocalSongs?.("queue_replaced");
|
||||
|
||||
// Use queue.play() for sequential, or pick random index for random modes
|
||||
const mode = queue.getMode();
|
||||
@@ -388,7 +390,6 @@ export function createPlayerRouter(
|
||||
|
||||
// Stop current playback
|
||||
bot.getPlayer().stop();
|
||||
bot.cleanupQueuedLocalSongs?.("queue_replaced");
|
||||
bot.getPlayer().resetFailures();
|
||||
|
||||
const songs = await provider.getAlbumSongs(albumId);
|
||||
@@ -414,11 +415,12 @@ export function createPlayerRouter(
|
||||
}
|
||||
|
||||
const queue = bot.getQueueManager();
|
||||
bot.cleanupQueuedLocalSongs?.("queue_replaced");
|
||||
queue.clear();
|
||||
for (const song of queueable) {
|
||||
queue.add({ ...song, platform: provider.platform });
|
||||
}
|
||||
// Sweep AFTER the queue is rebuilt (see play-playlist).
|
||||
bot.cleanupQueuedLocalSongs?.("queue_replaced");
|
||||
|
||||
const mode = queue.getMode();
|
||||
let first;
|
||||
@@ -464,13 +466,15 @@ export function createPlayerRouter(
|
||||
}
|
||||
const queue = bot.getQueueManager();
|
||||
bot.getPlayer().stop();
|
||||
bot.cleanupQueuedLocalSongs?.("queue_replaced");
|
||||
queue.clear();
|
||||
queue.add(song);
|
||||
queue.play();
|
||||
|
||||
bot.getPlayer().resetFailures();
|
||||
const ok = await bot.resolveAndPlay(queue.current()!);
|
||||
// Sweep AFTER the new song is queued+resolved, so replaying a local song
|
||||
// that was still in the queue doesn't delete the file we're about to play.
|
||||
bot.cleanupQueuedLocalSongs?.("queue_replaced");
|
||||
if (!ok) {
|
||||
res.json({ ok: false, message: `无法播放「${song.name || song.id}」(区域/版权限制)` });
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user