Fix song counter and inconsistent queue state

This commit is contained in:
mmacierzanka committed 2026-08-21 14:56:29 +02:00
1 parent 4468f96c3b
commit fff320d3f2
2 files changed
+44 -6

No files matched your search

+23 -2
View File
@@ -25,15 +25,36 @@ class MusicPlayerQueueTest(unittest.IsolatedAsyncioTestCase):
self.assertIs(voice_client.playing, track)
self.assertEqual(player.state(GUILD).index, 0)
async def test_single_play_budget_drops_track_from_queue(self):
async def test_last_play_remains_pointed_to_until_playback_finishes(self):
player, _ = build_player(default_plays=1)
track = FakeTrack("a")
await player.enqueue(GUILD, track)
state = player.state(GUILD)
self.assertEqual(state.queue, [track])
self.assertEqual(state.index, 0)
self.assertIs(state.current, track)
await player.play_next(GUILD, advance=True)
self.assertEqual(state.queue, [])
self.assertEqual(state.index, -1)
self.assertIs(state.current, track)
self.assertIsNone(state.current)
async def test_last_play_of_recreated_track_is_removed_after_callback(self):
player, _, state = await self._queue_abc(default_plays=2)
state.loop_mode = LoopMode.TRACK
await player.play_next(GUILD, advance=True)
self.assertEqual([track.id for track in state.queue], ["a", "b", "c"])
self.assertEqual(state.index, 0)
self.assertEqual(state.current.plays_left, 0)
await player.play_next(GUILD, advance=True)
self.assertEqual([track.id for track in state.queue], ["b", "c"])
self.assertEqual(state.index, 0)
self.assertEqual(state.current.id, "b")
async def test_enqueue_while_playing_only_appends(self):
_, _, state = await self._queue_abc()
+21 -4
View File
@@ -189,11 +189,29 @@ class MusicPlayer:
if state.consume_jump():
advance = False
# Utwór z ostatnim odtworzeniem musi pozostać w kolejce do chwili
# zakończenia źródła. W przeciwnym razie panel dostaje `current`, ale
# `queue_index` wskazuje pozycję spoza kolejki podczas faktycznego
# odtwarzania ostatniej kopii.
retired_index: int | None = None
if advance and state.current is not None and 0 <= state.index < len(state.queue):
current = state.queue[state.index]
if current is state.current and self.plays_left(current) <= 0:
retired_index = state.index
state.queue.pop(state.index)
state.index -= 1
if not state.queue:
state.index = -1
state.current = None
await self.trigger_state_change()
return
if retired_index is not None:
next_index = retired_index
if state.loop_mode.loops_queue:
next_index %= len(state.queue)
else:
next_index = self._next_index(state, advance=advance)
if next_index >= len(state.queue):
state.index = next_index
@@ -220,13 +238,12 @@ class MusicPlayer:
track.plays_left = self.plays_left(track) - 1
track.volume = state.volume
state.queue[next_index] = track
if track.plays_left <= 0:
state.queue.pop(next_index)
state.index = next_index - 1
# Usunięcie nastąpi dopiero po callbacku discord.py, po tym jak
# ostatnie odtworzenie rzeczywiście się zakończy.
if state.loop_mode.loops_track:
state.loop_mode = LoopMode.OFF
else:
state.queue[next_index] = track
state.current = track
self._record_history(guild_id, track)