fix: prevent overwriting saved queue with empty track lists in repository and music player
This commit is contained in:
4 files changed
+53
-5
No files matched your search
@@ -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):
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -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."""
|
||||||
|
|||||||
@@ -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]]:
|
||||||
|
|||||||
Reference in new issue
Block a user