- GuildMusicState zbiera stan jednego serwera w jedną strukturę. Dotąd było to dziewięć równoległych słowników indeksowanych guild_id (queues, currents, volumes, loop_currents, loop_playlists, last_channels, history, queue_indices, jump_flag), co wymagało pamiętania, że przy każdej zmianie trzeba ruszyć kilka z nich naraz. - LoopMode zastępuje parę booleanów loop_current/loop_playlist, których kombinacja "oba włączone" nie miała sensu, a mimo to była osiągalna. Wartości enuma (off/playlist/single) odpowiadają kontraktowi API panelu. - TrackEmbedFactory zbiera budowanie osadzeń Discorda, powielone dotąd w enqueue_track i play_next. - NotificationChannelResolver opisuje kolejność szukania kanału logów: zapamiętany -> z konfiguracji -> pierwszy zapisywalny na serwerze. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
49 lines
1.5 KiB
Python
49 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
import discord
|
|
from discord.ext import commands
|
|
|
|
from zyrarbot.storage.guild_config_repository import GuildConfigRepository
|
|
|
|
|
|
class NotificationChannelResolver:
|
|
"""Wskazuje kanał tekstowy, na który trafiają powiadomienia o odtwarzaniu.
|
|
|
|
Kolejność: kanał zapamiętany w stanie -> kanał z konfiguracji -> pierwszy
|
|
kanał serwera, na którym bot może pisać.
|
|
"""
|
|
|
|
def __init__(self, bot: commands.Bot, config: GuildConfigRepository):
|
|
self._bot = bot
|
|
self._config = config
|
|
|
|
def resolve(
|
|
self, guild_id: int, remembered: discord.abc.Messageable | None
|
|
) -> discord.abc.Messageable | None:
|
|
if remembered:
|
|
return remembered
|
|
|
|
saved_id = self._config.get_notification_channel_id(guild_id)
|
|
if saved_id:
|
|
channel = self._bot.get_channel(saved_id)
|
|
if channel:
|
|
return channel
|
|
|
|
return self.first_writable(self._bot.get_guild(guild_id))
|
|
|
|
@staticmethod
|
|
def first_writable(guild: discord.Guild | None) -> discord.TextChannel | None:
|
|
for channel in NotificationChannelResolver.writable_channels(guild):
|
|
return channel
|
|
return None
|
|
|
|
@staticmethod
|
|
def writable_channels(guild: discord.Guild | None) -> list[discord.TextChannel]:
|
|
if not guild or not guild.me:
|
|
return []
|
|
return [
|
|
channel
|
|
for channel in guild.text_channels
|
|
if channel.permissions_for(guild.me).send_messages
|
|
]
|