refactor: move Discord theme into bot package
This commit is contained in:
10 files changed
+194
-54
No files matched your search
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
import discord
|
||||
|
||||
from zyrarbot.audio.ytdl_source import YTDLSource
|
||||
from zyrarbot.ui.bot.discord_theme import BRAND_PURPLE
|
||||
|
||||
AUTHOR_ICON = "https://cdn-icons-png.flaticon.com/512/3844/3844724.png"
|
||||
|
||||
@@ -11,14 +12,14 @@ class TrackEmbedFactory:
|
||||
"""Buduje osadzenia Discorda opisujące utwór dodany do kolejki lub odtwarzany."""
|
||||
|
||||
def queued(self, track: YTDLSource, *, position: int, from_web: bool) -> discord.Embed:
|
||||
embed = self._base(track, discord.Color.blue())
|
||||
embed = self._base(track, BRAND_PURPLE)
|
||||
source = "Dodano do kolejki z panelu Web" if from_web else "Dodano do kolejki"
|
||||
embed.set_author(name=source, icon_url=AUTHOR_ICON)
|
||||
embed.set_footer(text=f"Pozycja w kolejce: {position}")
|
||||
return embed
|
||||
|
||||
def now_playing(self, track: YTDLSource, *, position: int, total: int) -> discord.Embed:
|
||||
embed = self._base(track, discord.Color.green(), prefix="▶️")
|
||||
embed = self._base(track, BRAND_PURPLE, prefix="▶️")
|
||||
embed.set_footer(text=f"Pozycja w kolejce: {position} / {total}")
|
||||
return embed
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import discord
|
||||
from discord.ext import commands
|
||||
|
||||
from zyrarbot.music.music_player import MusicPlayer
|
||||
from zyrarbot.ui.bot.discord_theme import message_embed
|
||||
|
||||
|
||||
class MusicCogBase(commands.Cog):
|
||||
@@ -16,7 +17,8 @@ class MusicCogBase(commands.Cog):
|
||||
async def _ensure_voice(self, interaction: discord.Interaction) -> bool:
|
||||
if not interaction.user.voice:
|
||||
await interaction.response.send_message(
|
||||
"Nie jesteś połączony z kanałem głosowym.", ephemeral=True
|
||||
embed=message_embed("Kanał głosowy", "Nie jesteś połączony z kanałem głosowym."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -25,7 +27,10 @@ class MusicCogBase(commands.Cog):
|
||||
await interaction.user.voice.channel.connect()
|
||||
elif voice_client.channel != interaction.user.voice.channel:
|
||||
await interaction.response.send_message(
|
||||
"Jestem już połączony z innym kanałem głosowym.", ephemeral=True
|
||||
embed=message_embed(
|
||||
"Kanał głosowy", "Jestem już połączony z innym kanałem głosowym."
|
||||
),
|
||||
ephemeral=True,
|
||||
)
|
||||
return False
|
||||
return True
|
||||
@@ -36,4 +41,4 @@ class MusicCogBase(commands.Cog):
|
||||
result = await self.player.enqueue(interaction.guild.id, track, channel=interaction.channel)
|
||||
title = discord.utils.escape_markdown(track.title or "Nieznany tytuł")
|
||||
action = "Dodano do kolejki" if result["status"] == "queued" else "Teraz odtwarzane"
|
||||
await interaction.followup.send(f"{action}{prefix}: {title}")
|
||||
await interaction.followup.send(embed=message_embed(f"{action}{prefix}", title))
|
||||
@@ -5,6 +5,7 @@ from discord import app_commands
|
||||
|
||||
from zyrarbot.music.loop_mode import LoopMode
|
||||
from zyrarbot.ui.bot.cogs.common import MusicCogBase
|
||||
from zyrarbot.ui.bot.discord_theme import message_embed
|
||||
|
||||
|
||||
class ControlCog(MusicCogBase, name="Control"):
|
||||
@@ -17,33 +18,38 @@ class ControlCog(MusicCogBase, name="Control"):
|
||||
if state.loop_mode.loops_track:
|
||||
state.loop_mode = LoopMode.OFF
|
||||
if not self.player.is_active(guild_id):
|
||||
await interaction.response.send_message("Nic nie jest odtwarzane.", ephemeral=True)
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Odtwarzanie", "Nic nie jest odtwarzane."), ephemeral=True
|
||||
)
|
||||
return
|
||||
self.player.skip(guild_id)
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message("Pominięto aktualny utwór.")
|
||||
await interaction.response.send_message(embed=message_embed("Pominięto utwór", "⏭️"))
|
||||
|
||||
@app_commands.command(name="pause", description="Wstrzymaj odtwarzanie")
|
||||
async def pause(self, interaction: discord.Interaction) -> None:
|
||||
voice_client = interaction.guild.voice_client
|
||||
if not voice_client or not voice_client.is_playing():
|
||||
await interaction.response.send_message("Nic nie jest odtwarzane.", ephemeral=True)
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Odtwarzanie", "Nic nie jest odtwarzane."), ephemeral=True
|
||||
)
|
||||
return
|
||||
voice_client.pause()
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message("Odtwarzanie wstrzymane.")
|
||||
await interaction.response.send_message(embed=message_embed("Odtwarzanie", "Wstrzymano."))
|
||||
|
||||
@app_commands.command(name="resume", description="Wznów odtwarzanie")
|
||||
async def resume(self, interaction: discord.Interaction) -> None:
|
||||
voice_client = interaction.guild.voice_client
|
||||
if not voice_client or not voice_client.is_paused():
|
||||
await interaction.response.send_message(
|
||||
"Odtwarzanie nie jest wstrzymane.", ephemeral=True
|
||||
embed=message_embed("Odtwarzanie", "Odtwarzanie nie jest wstrzymane."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
voice_client.resume()
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message("Odtwarzanie wznowione.")
|
||||
await interaction.response.send_message(embed=message_embed("Odtwarzanie", "Wznowiono."))
|
||||
|
||||
@app_commands.command(name="stop", description="Zatrzymaj odtwarzanie i wyczyść kolejkę")
|
||||
async def stop(self, interaction: discord.Interaction) -> None:
|
||||
@@ -54,32 +60,38 @@ class ControlCog(MusicCogBase, name="Control"):
|
||||
voice_client.stop()
|
||||
self.player.clear(guild_id)
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message("Zatrzymano odtwarzanie i wyczyszczono kolejkę.")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Odtwarzanie zatrzymane", "Kolejka została wyczyszczona.")
|
||||
)
|
||||
|
||||
@app_commands.command(name="volume", description="Zmień głośność odtwarzacza")
|
||||
@app_commands.describe(volume="Poziom głośności (1-100)")
|
||||
async def volume(self, interaction: discord.Interaction, volume: int) -> None:
|
||||
if interaction.guild.voice_client is None:
|
||||
await interaction.response.send_message(
|
||||
"Nie połączono z kanałem głosowym.", ephemeral=True
|
||||
embed=message_embed("Głośność", "Nie połączono z kanałem głosowym."), ephemeral=True
|
||||
)
|
||||
return
|
||||
if not 0 < volume <= 100:
|
||||
await interaction.response.send_message(
|
||||
"Wprowadź wartość z przedziału od 1 do 100.", ephemeral=True
|
||||
embed=message_embed("Głośność", "Wprowadź wartość z przedziału od 1 do 100."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
self.player.set_volume(interaction.guild.id, volume / 100)
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message(f"Zmieniono głośność na {volume}%")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Głośność", f"Ustawiono głośność na {volume}%.")
|
||||
)
|
||||
|
||||
@app_commands.command(name="nowplaying", description="Pokaż aktualnie odtwarzany utwór")
|
||||
async def now_playing(self, interaction: discord.Interaction) -> None:
|
||||
current = self.player.state(interaction.guild.id).current
|
||||
if not current:
|
||||
await interaction.response.send_message(
|
||||
"Nic nie jest obecnie odtwarzane.", ephemeral=True
|
||||
embed=message_embed("Teraz odtwarzane", "Nic nie jest obecnie odtwarzane."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
title = discord.utils.escape_markdown(current.title or "")
|
||||
await interaction.response.send_message(f"Teraz odtwarzane: {title}")
|
||||
await interaction.response.send_message(embed=message_embed("Teraz odtwarzane", title))
|
||||
@@ -13,6 +13,7 @@ from zyrarbot.audio.track_factory import TrackFactory
|
||||
from zyrarbot.music.music_player import MusicPlayer
|
||||
from zyrarbot.storage.uploads_repository import UploadsRepository
|
||||
from zyrarbot.ui.bot.cogs.common import MusicCogBase
|
||||
from zyrarbot.ui.bot.discord_theme import BRAND_PURPLE, message_embed
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
AUTOCOMPLETE_LIMIT = 25
|
||||
@@ -41,6 +42,25 @@ class HistorySelect(discord.ui.Select):
|
||||
await view.cog.replay_entry(interaction, self.values[0])
|
||||
|
||||
|
||||
class FileView(discord.ui.View):
|
||||
def __init__(self, cog: PlaybackCog, guild_id: int):
|
||||
super().__init__(timeout=900)
|
||||
self.cog = cog
|
||||
files = cog._uploads.list(guild_id)[:25]
|
||||
self.add_item(FileSelect([item.filename for item in files]))
|
||||
|
||||
|
||||
class FileSelect(discord.ui.Select):
|
||||
def __init__(self, filenames: list[str]):
|
||||
options = [discord.SelectOption(label=name[:100], value=name) for name in filenames]
|
||||
super().__init__(placeholder="Wybierz plik do odtworzenia", options=options)
|
||||
|
||||
async def callback(self, interaction: discord.Interaction) -> None:
|
||||
view = self.view
|
||||
if isinstance(view, FileView):
|
||||
await view.cog.play_filename(interaction, self.values[0])
|
||||
|
||||
|
||||
class PlaybackCog(MusicCogBase, name="Playback"):
|
||||
"""Komendy dodawania i ponownego odtwarzania utworów."""
|
||||
|
||||
@@ -63,13 +83,29 @@ class PlaybackCog(MusicCogBase, name="Playback"):
|
||||
)
|
||||
return [app_commands.Choice(name=name, value=name) for name in names]
|
||||
|
||||
@app_commands.command(name="files", description="Wybierz plik z biblioteki do odtworzenia")
|
||||
async def files(self, interaction: discord.Interaction) -> None:
|
||||
if not self._uploads.list(interaction.guild.id):
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Biblioteka plików", "Brak plików na tym serwerze."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Biblioteka plików", "Wybierz plik z listy poniżej."),
|
||||
view=FileView(self, interaction.guild.id),
|
||||
)
|
||||
|
||||
@app_commands.command(name="upload", description="Prześlij plik audio lub wideo do biblioteki")
|
||||
@app_commands.describe(file="Plik multimedialny")
|
||||
async def upload(self, interaction: discord.Interaction, file: discord.Attachment) -> None:
|
||||
filename = file.filename or ""
|
||||
if not self._uploads.is_supported_filename(filename):
|
||||
await interaction.response.send_message(
|
||||
"❌ Obsługiwane są tylko pliki audio i wideo.", ephemeral=True
|
||||
embed=message_embed(
|
||||
"Przesyłanie pliku", "Obsługiwane są tylko pliki audio i wideo."
|
||||
),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
suffix = os.path.splitext(filename)[1]
|
||||
@@ -77,21 +113,31 @@ class PlaybackCog(MusicCogBase, name="Playback"):
|
||||
await file.save(temporary.name)
|
||||
if not await MediaProbe().is_media(temporary.name):
|
||||
await interaction.response.send_message(
|
||||
"❌ Przesłany plik nie jest prawidłowym plikiem multimedialnym.", ephemeral=True
|
||||
embed=message_embed(
|
||||
"Przesyłanie pliku",
|
||||
"Przesłany plik nie jest prawidłowym plikiem multimedialnym.",
|
||||
),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
with open(temporary.name, "rb") as source:
|
||||
saved = self._uploads.save(filename, source, interaction.guild.id)
|
||||
await interaction.response.send_message(f"✅ Dodano plik **{saved}** do biblioteki.")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Plik przesłany", f"Dodano plik **{saved}** do biblioteki.")
|
||||
)
|
||||
|
||||
@app_commands.command(name="deletefile", description="Usuń plik z biblioteki serwera")
|
||||
@app_commands.describe(filename="Plik z biblioteki")
|
||||
@app_commands.autocomplete(filename=_uploads_autocomplete)
|
||||
async def delete_file(self, interaction: discord.Interaction, filename: str) -> None:
|
||||
if not self._uploads.delete(filename, interaction.guild.id):
|
||||
await interaction.response.send_message("Nie znaleziono pliku.", ephemeral=True)
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Biblioteka plików", "Nie znaleziono pliku."), ephemeral=True
|
||||
)
|
||||
return
|
||||
await interaction.response.send_message(f"✅ Usunięto plik **{filename}**.")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Plik usunięty", f"Usunięto plik **{filename}**.")
|
||||
)
|
||||
|
||||
async def _history_autocomplete(
|
||||
self, interaction: discord.Interaction, current: str
|
||||
@@ -119,7 +165,7 @@ class PlaybackCog(MusicCogBase, name="Playback"):
|
||||
embed=discord.Embed(
|
||||
title="📜 Historia odtwarzania",
|
||||
description=listing,
|
||||
color=discord.Color.gold(),
|
||||
color=BRAND_PURPLE,
|
||||
),
|
||||
view=HistoryView(self, interaction.guild.id),
|
||||
)
|
||||
@@ -140,17 +186,25 @@ class PlaybackCog(MusicCogBase, name="Playback"):
|
||||
await self._enqueue_and_reply(interaction, track)
|
||||
except Exception as error: # noqa: BLE001
|
||||
logger.error("Komenda /play nie powiodła się: %s", error)
|
||||
await interaction.followup.send(f"Wystąpił błąd: {error}", ephemeral=True)
|
||||
await interaction.followup.send(
|
||||
embed=message_embed("Odtwarzanie", f"Wystąpił błąd: {error}"), ephemeral=True
|
||||
)
|
||||
|
||||
@app_commands.command(name="playfile", description="Odtwórz plik przesłany na serwer")
|
||||
@app_commands.describe(filename="Wybierz plik z listy przesłanych")
|
||||
@app_commands.autocomplete(filename=_uploads_autocomplete)
|
||||
async def playfile(self, interaction: discord.Interaction, filename: str) -> None:
|
||||
await self.play_filename(interaction, filename)
|
||||
|
||||
async def play_filename(self, interaction: discord.Interaction, filename: str) -> None:
|
||||
if not await self._ensure_voice(interaction):
|
||||
return
|
||||
await interaction.response.defer()
|
||||
if not self._uploads.exists(filename, interaction.guild.id):
|
||||
await interaction.followup.send("Nie znaleziono pliku na serwerze.", ephemeral=True)
|
||||
await interaction.followup.send(
|
||||
embed=message_embed("Odtwarzanie pliku", "Nie znaleziono pliku na serwerze."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
try:
|
||||
track = await self._tracks.from_file(
|
||||
@@ -159,7 +213,10 @@ class PlaybackCog(MusicCogBase, name="Playback"):
|
||||
await self._enqueue_and_reply(interaction, track)
|
||||
except Exception as error: # noqa: BLE001
|
||||
logger.error("Komenda /playfile nie powiodła się: %s", error)
|
||||
await interaction.followup.send(f"Wystąpił błąd: {error}", ephemeral=True)
|
||||
await interaction.followup.send(
|
||||
embed=message_embed("Odtwarzanie pliku", f"Wystąpił błąd: {error}"),
|
||||
ephemeral=True,
|
||||
)
|
||||
|
||||
@app_commands.command(name="replay", description="Odtwórz ponownie utwór z historii")
|
||||
@app_commands.describe(track_id="Wybierz utwór z historii odtwarzania")
|
||||
@@ -179,14 +236,20 @@ class PlaybackCog(MusicCogBase, name="Playback"):
|
||||
if 0 <= position < len(entries):
|
||||
entry = entries[position]
|
||||
if entry is None:
|
||||
await interaction.followup.send("Nie znaleziono utworu w historii.", ephemeral=True)
|
||||
await interaction.followup.send(
|
||||
embed=message_embed("Historia", "Nie znaleziono utworu w historii."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
try:
|
||||
if entry.is_local:
|
||||
filepath = entry.replay_source or ""
|
||||
if not self._uploads.exists(filepath, guild_id):
|
||||
await interaction.followup.send(
|
||||
"Plik lokalny z historii już nie istnieje na serwerze.", ephemeral=True
|
||||
embed=message_embed(
|
||||
"Historia", "Plik lokalny z historii już nie istnieje na serwerze."
|
||||
),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
track = await self._tracks.from_file(
|
||||
@@ -197,4 +260,6 @@ class PlaybackCog(MusicCogBase, name="Playback"):
|
||||
await self._enqueue_and_reply(interaction, track, prefix=" z historii")
|
||||
except Exception as error: # noqa: BLE001
|
||||
logger.error("Komenda /replay nie powiodła się: %s", error)
|
||||
await interaction.followup.send(f"Wystąpił błąd: {error}", ephemeral=True)
|
||||
await interaction.followup.send(
|
||||
embed=message_embed("Historia", f"Wystąpił błąd: {error}"), ephemeral=True
|
||||
)
|
||||
@@ -8,6 +8,7 @@ from discord import app_commands
|
||||
|
||||
from zyrarbot.music.music_player import MusicPlayer
|
||||
from zyrarbot.ui.bot.cogs.common import MusicCogBase
|
||||
from zyrarbot.ui.bot.discord_theme import BRAND_PURPLE, message_embed
|
||||
|
||||
|
||||
def player_embed(player: MusicPlayer, guild: discord.Guild) -> discord.Embed:
|
||||
@@ -22,7 +23,9 @@ def player_embed(player: MusicPlayer, guild: discord.Guild) -> discord.Embed:
|
||||
if current.has_web_link:
|
||||
description = f"[{description}]({current.display_url})"
|
||||
|
||||
embed = discord.Embed(title=f"🎵 Odtwarzacz — {guild.name}", description=description)
|
||||
embed = discord.Embed(
|
||||
title=f"🎵 Odtwarzacz — {guild.name}", description=description, color=BRAND_PURPLE
|
||||
)
|
||||
embed.add_field(name="Kolejka", value=f"{len(state.queue)} utworów", inline=True)
|
||||
embed.add_field(name="Głośność", value=f"{int(state.volume * 100)}%", inline=True)
|
||||
embed.add_field(name="Zapętlanie", value=state.loop_mode.label, inline=True)
|
||||
@@ -61,7 +64,8 @@ class PlayerView(discord.ui.View):
|
||||
)
|
||||
except (discord.DiscordException, RuntimeError, ValueError) as error:
|
||||
await interaction.response.send_message(
|
||||
f"❌ Nie udało się wykonać akcji: {error}", ephemeral=True
|
||||
embed=message_embed("Odtwarzacz", f"Nie udało się wykonać akcji: {error}"),
|
||||
ephemeral=True,
|
||||
)
|
||||
|
||||
@discord.ui.button(label="Pauza", emoji="⏯️", style=discord.ButtonStyle.primary)
|
||||
@@ -73,7 +77,8 @@ class PlayerView(discord.ui.View):
|
||||
operation = voice.resume
|
||||
else:
|
||||
await interaction.response.send_message(
|
||||
"Nic nie jest obecnie odtwarzane.", ephemeral=True
|
||||
embed=message_embed("Odtwarzanie", "Nic nie jest obecnie odtwarzane."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
await self.action(interaction, operation)
|
||||
@@ -133,7 +138,8 @@ class PlayerView(discord.ui.View):
|
||||
count = await self.player.restore_queue(self.guild_id)
|
||||
if not count:
|
||||
await interaction.response.send_message(
|
||||
"Nie ma zapisanej kolejki dla tego serwera.", ephemeral=True
|
||||
embed=message_embed("Kolejka", "Nie ma zapisanej kolejki dla tego serwera."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
await self.player.trigger_state_change()
|
||||
@@ -171,10 +177,14 @@ class VolumeModal(discord.ui.Modal, title="Ustaw głośność"):
|
||||
try:
|
||||
value = int(self.volume.value)
|
||||
except ValueError:
|
||||
await interaction.response.send_message("Podaj liczbę od 1 do 100.", ephemeral=True)
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Głośność", "Podaj liczbę od 1 do 100."), ephemeral=True
|
||||
)
|
||||
return
|
||||
if not 1 <= value <= 100:
|
||||
await interaction.response.send_message("Podaj liczbę od 1 do 100.", ephemeral=True)
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Głośność", "Podaj liczbę od 1 do 100."), ephemeral=True
|
||||
)
|
||||
return
|
||||
self.player_view.player.set_volume(self.player_view.guild_id, value / 100)
|
||||
await self.player_view.player.trigger_state_change()
|
||||
|
||||
@@ -7,6 +7,7 @@ from discord.ext import commands
|
||||
from zyrarbot.music.music_player import MusicPlayer
|
||||
from zyrarbot.settings import Settings
|
||||
from zyrarbot.ui.bot.cogs.common import MusicCogBase
|
||||
from zyrarbot.ui.bot.discord_theme import BRAND_PURPLE, message_embed
|
||||
|
||||
QUEUE_PREVIEW_LIMIT = 30
|
||||
AUTOCOMPLETE_LIMIT = 25
|
||||
@@ -36,7 +37,9 @@ class QueueCog(MusicCogBase, name="Queue"):
|
||||
async def show_queue(self, interaction: discord.Interaction) -> None:
|
||||
state = self.player.state(interaction.guild.id)
|
||||
if not state.queue:
|
||||
await interaction.response.send_message("Kolejka jest pusta.", ephemeral=True)
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Kolejka", "Kolejka jest pusta."), ephemeral=True
|
||||
)
|
||||
return
|
||||
lines: list[str] = []
|
||||
if state.current and not 0 <= state.index < len(state.queue):
|
||||
@@ -58,7 +61,7 @@ class QueueCog(MusicCogBase, name="Queue"):
|
||||
embed = discord.Embed(
|
||||
title="🎶 Aktualna kolejka",
|
||||
description=preview,
|
||||
color=discord.Color.blurple(),
|
||||
color=BRAND_PURPLE,
|
||||
)
|
||||
embed.set_footer(text=f"{len(state.queue)} utworów w kolejce")
|
||||
await interaction.response.send_message(embed=embed)
|
||||
@@ -78,10 +81,15 @@ class QueueCog(MusicCogBase, name="Queue"):
|
||||
count = await self.player.restore_queue(interaction.guild.id)
|
||||
if not count:
|
||||
await interaction.response.send_message(
|
||||
"Nie ma zapisanej kolejki dla tego serwera.", ephemeral=True
|
||||
embed=message_embed(
|
||||
"Przywracanie kolejki", "Nie ma zapisanej kolejki dla tego serwera."
|
||||
),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
await interaction.response.send_message(f"✅ Przywrócono kolejkę ({count} utworów).")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Kolejka przywrócona", f"Przywrócono kolejkę ({count} utworów).")
|
||||
)
|
||||
|
||||
@app_commands.command(name="remove", description="Usuń wybrany utwór z kolejki")
|
||||
@app_commands.describe(track_id="Utwór z kolejki")
|
||||
@@ -93,7 +101,9 @@ class QueueCog(MusicCogBase, name="Queue"):
|
||||
)
|
||||
return
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message("✅ Usunięto utwór z kolejki.")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Kolejka", "Usunięto utwór z kolejki.")
|
||||
)
|
||||
|
||||
@app_commands.command(name="jump", description="Odtwórz wybrany utwór z kolejki")
|
||||
@app_commands.describe(track_id="Utwór z kolejki")
|
||||
@@ -107,7 +117,9 @@ class QueueCog(MusicCogBase, name="Queue"):
|
||||
return
|
||||
await self.player.jump(interaction.guild.id, position)
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message("▶️ Rozpoczęto wybrany utwór.")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Kolejka", "▶️ Rozpoczęto wybrany utwór.")
|
||||
)
|
||||
|
||||
@app_commands.command(name="move", description="Przenieś utwór przed inny utwór")
|
||||
@app_commands.describe(track_id="Utwór do przeniesienia", before_id="Utwór docelowy")
|
||||
@@ -123,7 +135,9 @@ class QueueCog(MusicCogBase, name="Queue"):
|
||||
ids.insert(ids.index(before_id), track_id)
|
||||
self.player.reorder(interaction.guild.id, ids)
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message("✅ Zmieniono kolejność kolejki.")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Kolejka", "Zmieniono kolejność kolejki.")
|
||||
)
|
||||
|
||||
@app_commands.command(
|
||||
name="trackplays", description="Zmień liczbę odtworzeń dla utworu w kolejce"
|
||||
@@ -136,17 +150,21 @@ class QueueCog(MusicCogBase, name="Queue"):
|
||||
track = self.player.state(interaction.guild.id).find(track_id)
|
||||
if track is None:
|
||||
await interaction.response.send_message(
|
||||
"❌ Nie znaleziono utworu w kolejce.", ephemeral=True
|
||||
embed=message_embed("Liczba odtworzeń", "Nie znaleziono utworu w kolejce."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
if not self._settings.is_valid_plays(count):
|
||||
await interaction.response.send_message(
|
||||
"❌ Liczba odtworzeń musi być z przedziału 1-999.", ephemeral=True
|
||||
embed=message_embed("Liczba odtworzeń", "Wartość musi być z przedziału 1-999."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
track.plays_left = count
|
||||
await self.player.trigger_state_change()
|
||||
title = discord.utils.escape_markdown(track.title or "")
|
||||
await interaction.response.send_message(
|
||||
f"✅ Ustawiono liczbę odtworzeń dla utworu **{title}** na **{count}**."
|
||||
embed=message_embed(
|
||||
"Liczba odtworzeń", f"Ustawiono dla utworu **{title}** wartość **{count}**."
|
||||
)
|
||||
)
|
||||
@@ -8,6 +8,7 @@ from zyrarbot.music.loop_mode import LoopMode
|
||||
from zyrarbot.music.music_player import MusicPlayer
|
||||
from zyrarbot.settings import Settings
|
||||
from zyrarbot.ui.bot.cogs.common import MusicCogBase
|
||||
from zyrarbot.ui.bot.discord_theme import message_embed
|
||||
|
||||
|
||||
class SettingsCog(MusicCogBase, name="Settings"):
|
||||
@@ -23,7 +24,7 @@ class SettingsCog(MusicCogBase, name="Settings"):
|
||||
async def loop_command(self, interaction: discord.Interaction) -> None:
|
||||
mode = self.player.cycle_loop_mode(interaction.guild.id)
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message(mode.label)
|
||||
await interaction.response.send_message(embed=message_embed("Zapętlanie", mode.label))
|
||||
|
||||
@app_commands.command(
|
||||
name="loopplaylist", description="Włącz/wyłącz zapętlanie całej kolejki (tryb playlisty)"
|
||||
@@ -36,7 +37,9 @@ class SettingsCog(MusicCogBase, name="Settings"):
|
||||
description = (
|
||||
"włączone (utwory po zakończeniu wracają na koniec kolejki)" if enabled else "wyłączone"
|
||||
)
|
||||
await interaction.response.send_message(f"🔁 Zapętlanie całej kolejki: **{description}**.")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Zapętlanie kolejki", f"🔁 {description}.")
|
||||
)
|
||||
|
||||
@app_commands.command(
|
||||
name="defaultplays",
|
||||
@@ -46,11 +49,14 @@ class SettingsCog(MusicCogBase, name="Settings"):
|
||||
async def default_plays_command(self, interaction: discord.Interaction, count: int) -> None:
|
||||
if not self._settings.is_valid_plays(count):
|
||||
await interaction.response.send_message(
|
||||
"❌ Liczba odtworzeń musi być z przedziału 1-999.", ephemeral=True
|
||||
embed=message_embed("Liczba odtworzeń", "Wartość musi być z przedziału 1-999."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
self.player.set_default_plays(interaction.guild.id, count)
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message(
|
||||
f"✅ Domyślna liczba odtworzeń dla nowych utworów została ustawiona na: **{count}**."
|
||||
embed=message_embed(
|
||||
"Domyślna liczba odtworzeń", f"Ustawiono wartość dla nowych utworów: **{count}**."
|
||||
)
|
||||
)
|
||||
@@ -5,6 +5,7 @@ from discord.ext import commands
|
||||
|
||||
from zyrarbot.music.notification_channel_resolver import NotificationChannelResolver
|
||||
from zyrarbot.ui.bot.cogs.common import MusicCogBase
|
||||
from zyrarbot.ui.bot.discord_theme import message_embed
|
||||
|
||||
|
||||
class VoiceCog(MusicCogBase, name="Voice"):
|
||||
@@ -42,7 +43,9 @@ class VoiceCog(MusicCogBase, name="Voice"):
|
||||
interaction.guild.id, NotificationChannelResolver.first_writable(interaction.guild)
|
||||
)
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message(f"✅ Połączono z kanałem **{channel.name}**.")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Kanał głosowy", f"Połączono z kanałem **{channel.name}**.")
|
||||
)
|
||||
|
||||
@discord.app_commands.command(name="notificationchannel", description="Ustaw kanał logów")
|
||||
@discord.app_commands.describe(channel="Kanał tekstowy")
|
||||
@@ -51,22 +54,28 @@ class VoiceCog(MusicCogBase, name="Voice"):
|
||||
) -> None:
|
||||
if channel not in NotificationChannelResolver.writable_channels(interaction.guild):
|
||||
await interaction.response.send_message(
|
||||
"Bot nie może pisać na tym kanale.", ephemeral=True
|
||||
embed=message_embed("Kanał logów", "Bot nie może pisać na tym kanale."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
self.player.set_notification_channel(interaction.guild.id, channel)
|
||||
self.bot.config.set_notification_channel_id(interaction.guild.id, channel.id)
|
||||
await self.player.trigger_state_change()
|
||||
await interaction.response.send_message(f"✅ Kanał logów ustawiony na {channel.mention}.")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Kanał logów", f"Ustawiono kanał: {channel.mention}.")
|
||||
)
|
||||
|
||||
@discord.app_commands.command(name="leave", description="Odłącz bota od kanału głosowego")
|
||||
async def leave(self, interaction: discord.Interaction) -> None:
|
||||
if interaction.guild.voice_client is None:
|
||||
await interaction.response.send_message(
|
||||
"Nie jestem na kanale głosowym.", ephemeral=True
|
||||
embed=message_embed("Kanał głosowy", "Bot nie jest na kanale głosowym."),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
self.player.save_queue(interaction.guild.id)
|
||||
await interaction.guild.voice_client.disconnect()
|
||||
self.player.clear(interaction.guild.id)
|
||||
await interaction.response.send_message("Rozłączono z kanału głosowego.")
|
||||
await interaction.response.send_message(
|
||||
embed=message_embed("Kanał głosowy", "Rozłączono z kanału głosowego.")
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import discord
|
||||
|
||||
BRAND_PURPLE = discord.Color.from_rgb(139, 92, 246)
|
||||
|
||||
|
||||
def message_embed(title: str, description: str, *, footer: str | None = None) -> discord.Embed:
|
||||
embed = discord.Embed(title=title, description=description, color=BRAND_PURPLE)
|
||||
if footer:
|
||||
embed.set_footer(text=footer)
|
||||
return embed
|
||||
Reference in new issue
Block a user