fix(music): zatrzymanie pomijania, gdy nie da się odtworzyć żadnego utworu

Utwór, dla którego nie udało się zbudować świeżego źródła, był pomijany
przez rekurencyjne wywołanie play_next(advance=True). Przy włączonym
zapętlaniu kolejki - a przy zapętlaniu jednego utworu tym bardziej -
kolejny indeks wskazywał znowu na utwór niedziałający, więc pomijanie
kręciło się w kółko, zasypując kanał powiadomieniami.

Licznik nieudanych prób wędruje teraz przez play_next. Po liczbie
niepowodzeń równej długości kolejki odtwarzanie zatrzymuje się z jednym
komunikatem zamiast pętli.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
lgooseandClaude Bot committed 2026-08-21 01:11:22 +02:00
1 parent ab1d0d4a91
commit c8a188647b
1 file changed
+15 -2
+15 -2
View File
@@ -177,7 +177,8 @@ class MusicPlayer:
# --- Odtwarzanie -------------------------------------------------------- # --- Odtwarzanie --------------------------------------------------------
async def play_next(self, guild_id: int, advance: bool = True) -> None: async def play_next(self, guild_id: int, advance: bool = True, _failures: int = 0) -> None:
"""Przechodzi do kolejnego utworu; ``_failures`` chroni przed pętlą pomijania."""
state = self.state(guild_id) state = self.state(guild_id)
voice_client = self.voice_client(guild_id) voice_client = self.voice_client(guild_id)
if not voice_client: if not voice_client:
@@ -211,7 +212,7 @@ class MusicPlayer:
await self.notify( await self.notify(
guild_id, f"⚠️ Nie udało się odtworzyć: {track.title} ({error}). Pomijam." guild_id, f"⚠️ Nie udało się odtworzyć: {track.title} ({error}). Pomijam."
) )
await self.play_next(guild_id, advance=True) await self._skip_failed(guild_id, _failures + 1)
return return
track.played = True track.played = True
@@ -236,6 +237,18 @@ class MusicPlayer:
embed = self._embeds.now_playing(track, position=next_index + 1, total=total) embed = self._embeds.now_playing(track, position=next_index + 1, total=total)
await self.notify(guild_id, embed=embed) await self.notify(guild_id, embed=embed)
async def _skip_failed(self, guild_id: int, failures: int) -> None:
"""Pomija niedziałający utwór, ale zatrzymuje się, gdy zawiodła cała kolejka."""
state = self.state(guild_id)
if failures >= max(len(state.queue), 1):
state.current = None
await self.trigger_state_change()
await self.notify(
guild_id, "⛔ Nie udało się odtworzyć żadnego utworu z kolejki. Zatrzymuję."
)
return
await self.play_next(guild_id, advance=True, _failures=failures)
def _next_index(self, state: GuildMusicState, *, advance: bool) -> int: def _next_index(self, state: GuildMusicState, *, advance: bool) -> int:
index = state.index if state.index != -1 else 0 index = state.index if state.index != -1 else 0