6.2 KiB
ŻyrarBOT
Bot muzyczny Discord z panelem webowym: kolejka odtwarzania, historia, serwerowa baza plików i sterowanie na żywo przez WebSocket.
Uruchomienie
pip install -r requirements.txt
python main.py # albo: python -m zyrarbot
Wymagane zmienne środowiskowe (plik .env):
| Zmienna | Opis |
|---|---|
DISCORD_TOKEN |
Token bota Discord. |
GUILD_ID |
Opcjonalnie - synchronizuje komendy tylko z jednym serwerem. |
Panel działa pod http://localhost:8000 podczas uruchomienia lokalnego. W Dockerze
jest dostępny pod http://localhost po wykonaniu docker compose up --build.
Panel obsługuje wiele serwerów Discorda. Wybór serwera w nagłówku przełącza jego
osobną kolejkę, historię, bazę plików i ustawienia odtwarzania. Istniejące dane ze
starego, wspólnego formatu są przypisywane do pierwszego użytego serwera.
Historia jest zapisywana w osobnych plikach config/history/<guild_id>.json, a
uploady w katalogach uploads/<guild_id>/.
Ostatnia kolejka jest zapisywana w config/queues/<guild_id>.json przy zatrzymaniu
lub rozłączeniu i może zostać przywrócona z widoku kolejki.
Komendy Discorda
Wszystkie komendy działają w kontekście bieżącego serwera. Discord pokazuje wybór utworów przez autocomplete, a kanały przez natywne selektory — nie trzeba wpisywać indeksów ręcznie.
| Komenda | Działanie |
|---|---|
/player |
Publiczny panel odtwarzacza z przyciskami sterowania |
/play query |
Dodaje utwór, link lub zapytanie wyszukiwania |
/playfile filename |
Odtwarza plik z biblioteki serwera |
/files |
Otwiera listę plików z natywnym wyborem Discorda |
/upload file |
Przesyła i waliduje plik audio/wideo do biblioteki |
/deletefile filename |
Usuwa wybrany plik z biblioteki |
/replay track_id |
Ponownie odtwarza utwór z historii |
/queue |
Pokazuje kolejkę w embedzie |
/history |
Pokazuje historię odtwarzania |
/restorequeue |
Przywraca ostatnią zapisaną kolejkę |
/jump track_id |
Rozpoczyna wybrany utwór z kolejki |
/remove track_id |
Usuwa wybrany utwór z kolejki |
/move track_id before_id |
Przenosi utwór przed wybrany utwór docelowy |
/trackplays track_id count |
Ustawia liczbę odtworzeń utworu |
/pause, /resume |
Wstrzymuje lub wznawia odtwarzanie |
/seek seconds |
Przewija bieżący utwór do wskazanej sekundy |
/skip |
Pomija bieżący utwór |
/stop |
Zatrzymuje odtwarzanie i czyści kolejkę |
/volume volume |
Ustawia głośność w zakresie 1–100 |
/nowplaying |
Pokazuje bieżący utwór |
/loop |
Przełącza tryb zapętlania |
/loopplaylist |
Włącza lub wyłącza zapętlanie kolejki |
/defaultplays count |
Ustawia domyślną liczbę odtworzeń dla nowych utworów |
/connect channel |
Łączy bota z wybranym kanałem głosowym |
/notificationchannel channel |
Ustawia kanał powiadomień |
/leave |
Rozłącza bota z kanału głosowego |
Testy
python -m unittest discover -s tests -t .
Struktura pakietu
Każda klasa mieszka w osobnym pliku, a pliki są pogrupowane w przestrzenie nazw odpowiadające warstwom aplikacji:
zyrarbot/
├── settings.py Settings - konfiguracja ze zmiennych środowiskowych
├── application.py Application - korzeń kompozycji, spina bota i API
├── storage/ Warstwa trwałości (pliki JSON, katalog uploadów)
│ ├── json_file_store.py JsonFileStore
│ ├── guild_config_repository.py GuildConfigRepository
│ ├── history_repository.py HistoryRepository
│ ├── uploads_repository.py UploadsRepository
│ └── upload_file_info.py UploadFileInfo
├── audio/ Pozyskiwanie dźwięku
│ ├── ytdl_options.py YtdlOptions
│ ├── ytdl_source.py YTDLSource
│ ├── media_probe.py MediaProbe
│ └── track_factory.py TrackFactory
├── music/ Domena odtwarzania
│ ├── loop_mode.py LoopMode
│ ├── history_entry.py HistoryEntry
│ ├── guild_music_state.py GuildMusicState
│ ├── track_embed_factory.py TrackEmbedFactory
│ ├── notification_channel_resolver.py NotificationChannelResolver
│ └── music_player.py MusicPlayer
└── ui/ Warstwa interfejsów użytkownika
├── api/ API panelu (FastAPI)
│ ├── factory.py mount_api - konfiguracja i routery API
│ ├── connection_manager.py ConnectionManager
│ ├── status_service.py StatusService
│ ├── status_broadcaster.py StatusBroadcaster
│ ├── dependencies.py wstrzykiwanie zależności z app.state
│ ├── requests/ modele żądań - jeden na plik
│ └── routers/ trasy pogrupowane tematycznie
└── bot/ Warstwa Discorda
├── client.py MusicBot
├── discord_theme.py wspólny styl embedów Discorda
├── guild_resolver.py GuildResolver
└── cogs/ komendy i listenery Discorda
├── common.py wspólne zależności i helpery
├── playback_cog.py PlaybackCog
├── queue_cog.py QueueCog
├── control_cog.py ControlCog
├── voice_cog.py VoiceCog
└── settings_cog.py SettingsCog
Zasady
MusicPlayerjest jedynym właścicielem stanu odtwarzania. Zarówno komendy Discorda, jak i endpointy panelu operują wyłącznie przez niego - nie ma już dwóch niezależnych ścieżek modyfikujących kolejkę.- Kolejka jest nieusuwalna, pozycję śledzi indeks (
GuildMusicState.index), dzięki czemu działa przeskakiwanie i przewijanie w tył. - Zależności wędrują przez konstruktory, a w API przez
app.statei funkcje zapi/dependencies.py. Nie ma globalnych singletonów.