fix: prevent overwriting saved queue with empty track lists in repository and music player

This commit is contained in:
mmacierzanka committed 2026-09-11 01:29:31 +02:00
1 parent 06238b0438
commit 9143c6029a
4 files changed
+53 -5

No files matched your search

+30
View File
@@ -296,6 +296,36 @@ class MusicPlayerQueueTest(unittest.IsolatedAsyncioTestCase):
with self.assertRaisesRegex(ValueError, "not connected"): with self.assertRaisesRegex(ValueError, "not connected"):
await player.restore_queue(GUILD) await player.restore_queue(GUILD)
def test_save_queue_does_not_overwrite_with_empty_queue(self):
with tempfile.TemporaryDirectory() as directory:
player, _ = build_player()
player._queues = QueueRepository(directory)
saved = [{"id": "saved", "title": "Saved", "plays_left": 2}]
player._queues.save(GUILD, saved)
# Kolejka w stanie odtwarzacza jest pusta
player.state(GUILD).queue = []
player.save_queue(GUILD)
# Zapisana wcześniej kolejka powinna pozostać nienaruszona
self.assertEqual(player._queues.load(GUILD), saved)
def test_save_queue_does_not_save_when_all_plays_consumed(self):
with tempfile.TemporaryDirectory() as directory:
player, _ = build_player()
player._queues = QueueRepository(directory)
saved = [{"id": "saved", "title": "Saved", "plays_left": 2}]
player._queues.save(GUILD, saved)
# Wszystkie utwory w kolejce mają plays_left = 0
track = FakeTrack("consumed")
track.plays_left = 0
player.state(GUILD).queue = [track]
player.save_queue(GUILD)
# Zapisana wcześniej kolejka powinna pozostać nienaruszona
self.assertEqual(player._queues.load(GUILD), saved)
class LoopModeTest(unittest.TestCase): class LoopModeTest(unittest.TestCase):
def test_cycle_order(self): def test_cycle_order(self):
+16
View File
@@ -20,6 +20,22 @@ class QueueRepositoryTest(unittest.TestCase):
self.assertTrue((Path(directory) / "10.json").exists()) self.assertTrue((Path(directory) / "10.json").exists())
self.assertTrue((Path(directory) / "20.json").exists()) self.assertTrue((Path(directory) / "20.json").exists())
def test_save_empty_tracks_does_nothing(self):
with tempfile.TemporaryDirectory() as directory:
repository = QueueRepository(directory)
tracks = [{"id": "first", "title": "First", "plays_left": 2}]
repository.save(10, tracks)
self.assertEqual(repository.load(10), tracks)
# Próba zapisania pustej listy nie powinna nadpisać poprzedniej
repository.save(10, [])
self.assertEqual(repository.load(10), tracks)
# Zapis pustej kolejki dla nowego serwera nie powinien tworzyć pliku
repository.save(20, [])
self.assertFalse(repository.exists(20))
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
+5 -5
View File
@@ -111,14 +111,14 @@ class MusicPlayer:
if not self._queues: if not self._queues:
return return
state = self.state(guild_id) state = self.state(guild_id)
self._queues.save( tracks = [
guild_id,
[
self._track_snapshot(track) self._track_snapshot(track)
for track in state.queue for track in state.queue
if self.plays_left(track, guild_id) > 0 if self.plays_left(track, guild_id) > 0
], ]
) if not tracks:
return
self._queues.save(guild_id, tracks)
def finish_current(self, guild_id: int) -> None: def finish_current(self, guild_id: int) -> None:
"""Consume one play when playback ends outside the regular callback.""" """Consume one play when playback ends outside the regular callback."""
+2
View File
@@ -21,6 +21,8 @@ class QueueRepository:
return self._stores[guild_id] return self._stores[guild_id]
def save(self, guild_id: int, tracks: list[dict[str, Any]]) -> None: def save(self, guild_id: int, tracks: list[dict[str, Any]]) -> None:
if not tracks:
return
self._store(guild_id).set("tracks", tracks) self._store(guild_id).set("tracks", tracks)
def load(self, guild_id: int) -> list[dict[str, Any]]: def load(self, guild_id: int) -> list[dict[str, Any]]: