fix: preserve plays when skipping tracks

This commit is contained in:
mmacierzanka committed 2026-08-21 17:26:02 +02:00
1 parent 03611e3226
commit b19f3e1923
4 files changed
+35 -5

No files matched your search

+24 -3
View File
@@ -50,6 +50,7 @@ class MusicPlayer:
self._queues = queues
self._states: dict[int, GuildMusicState] = {}
self._playback_tokens: dict[int, int] = {}
self._interrupted_playbacks: set[int] = set()
self.on_state_change: StateChangeHook | None = None
# --- Stan ---------------------------------------------------------------
@@ -94,6 +95,7 @@ class MusicPlayer:
def clear(self, guild_id: int) -> None:
self._playback_tokens[guild_id] = self._playback_tokens.get(guild_id, 0) + 1
self._interrupted_playbacks.discard(guild_id)
self.state(guild_id).reset()
def has_saved_queue(self, guild_id: int) -> bool:
@@ -121,6 +123,13 @@ class MusicPlayer:
if current is state.current:
current.plays_left = max(self.plays_left(current, guild_id) - 1, 0)
def skip(self, guild_id: int) -> None:
"""Stop the current source without consuming a play."""
voice_client = self.voice_client(guild_id)
if voice_client and (voice_client.is_playing() or voice_client.is_paused()):
self._interrupted_playbacks.add(guild_id)
voice_client.stop()
async def restore_queue(self, guild_id: int) -> int:
if not self._queues:
return 0
@@ -128,6 +137,7 @@ class MusicPlayer:
state = self.state(guild_id)
playback_token = self._playback_tokens.get(guild_id, 0) + 1
self._playback_tokens[guild_id] = playback_token
self._interrupted_playbacks.discard(guild_id)
voice_client = self.voice_client(guild_id)
if voice_client and (voice_client.is_playing() or voice_client.is_paused()):
voice_client.stop()
@@ -272,13 +282,20 @@ class MusicPlayer:
async def _restart_playback(self, guild_id: int) -> None:
voice_client = self.voice_client(guild_id)
if voice_client and (voice_client.is_playing() or voice_client.is_paused()):
self._interrupted_playbacks.add(guild_id)
voice_client.stop() # `after` wywoła play_next, flaga przeskoku zablokuje advance
else:
await self.play_next(guild_id, advance=False)
# --- Odtwarzanie --------------------------------------------------------
async def play_next(self, guild_id: int, advance: bool = True, _failures: int = 0) -> None:
async def play_next(
self,
guild_id: int,
advance: bool = True,
_failures: int = 0,
consume_current: bool = True,
) -> None:
"""Przechodzi do kolejnego utworu; ``_failures`` chroni przed pętlą pomijania."""
state = self.state(guild_id)
playback_token = self._playback_tokens.get(guild_id, 0)
@@ -290,7 +307,7 @@ class MusicPlayer:
if state.consume_jump():
advance = False
if advance:
if advance and consume_current:
self.finish_current(guild_id)
# Utwór z ostatnim odtworzeniem musi pozostać w kolejce do chwili
@@ -390,9 +407,13 @@ class MusicPlayer:
def _schedule_next(self, guild_id: int, error: Exception | None, playback_token: int) -> None:
if self._playback_tokens.get(guild_id) != playback_token:
return
consume_current = guild_id not in self._interrupted_playbacks
self._interrupted_playbacks.discard(guild_id)
if error:
logger.error("Odtwarzanie zakończone błędem na serwerze %s: %s", guild_id, error)
asyncio.run_coroutine_threadsafe(self.play_next(guild_id, advance=True), self._bot.loop)
asyncio.run_coroutine_threadsafe(
self.play_next(guild_id, advance=True, consume_current=consume_current), self._bot.loop
)
def _record_history(self, guild_id: int, track: YTDLSource) -> None:
if not track.title:
+1 -1
View File
@@ -122,7 +122,7 @@ async def skip(
if not player.is_active(guild.id):
raise HTTPException(status_code=400, detail="Bot is not playing anything on this server")
player.voice_client(guild.id).stop()
player.skip(guild.id)
await broadcaster.broadcast()
return {"status": "skipped"}
+1 -1
View File
@@ -19,7 +19,7 @@ class ControlCog(MusicCogBase, name="Control"):
if not self.player.is_active(guild_id):
await interaction.response.send_message("Nic nie jest odtwarzane.", ephemeral=True)
return
interaction.guild.voice_client.stop()
self.player.skip(guild_id)
await self.player.trigger_state_change()
await interaction.response.send_message("Pominięto aktualny utwór.")