2026-08-21 21:32:12 +02:00

Ż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.
POSTGRES_PASSWORD Hasło użytkownika bazy; domyślnie zyrarbot, zalecana zmiana w .env.
POSTGRES_DB / POSTGRES_USER Opcjonalna nazwa bazy i użytkownika; domyślnie zyrarbot.

Panel działa pod http://localhost:8000 podczas uruchomienia lokalnego.

Docker: development i production

Środowisko deweloperskie uruchom poleceniem:

docker compose up --build

Kod Pythona jest montowany z katalogu projektu; po zmianach zrestartuj backend poleceniem docker compose restart discord-bot. Frontend działa w osobnym kontenerze i przebudowuje frontend/dist w trybie watch. Python serwuje ten sam współdzielony katalog pod http://localhost. Port PostgreSQL 5432 jest dostępny lokalnie. Obraz dev zawiera też Ruff, a kontener frontendu instaluje narzędzia z package-lock.json (ESLint i vue-tsc). Sprawdzenia uruchom w kontenerze backendu, np. docker compose exec discord-bot ruff check . i docker compose exec discord-bot pytest; dla frontendu użyj docker compose exec frontend npm run lint lub npm run typecheck.

Production uruchom z pliku compose.prod.yaml:

docker compose -f compose.prod.yaml up --build -d

W tym wariancie frontend jest budowany podczas tworzenia obrazu, a port PostgreSQL nie jest publikowany na hoście.

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. Ustawienia, historia i migawki kolejek przechodzą przez porty persystencji, a PostgreSQL jest obecnym adapterem wybranym w korzeniu aplikacji. Baza działa jako usługa Compose, a jej dane trwale przechowuje wolumen postgres_data. Przy pierwszym uruchomieniu bot importuje istniejące pliki JSON z config/ do bazy, a pliki źródłowe zostają na miejscu jako kopia. Starsze wspólne dane są przypisywane do pierwszego serwera, do którego bot należy. Historia jest zapisywana w kolumnach id, title, url, duration i is_local, wraz z guild_id oraz pozycją. Uploady pozostają w katalogach uploads/<guild_id>/.

Migracje bazy

Przy uruchomieniu bot automatycznie stosuje oczekujące migracje PostgreSQL. Można je też uruchomić jawnie przez make migrate. Makefile korzysta wyłącznie z Dockera i sprawdza, czy dostępne są Docker oraz docker compose. Zastosowane wersje i ich nazwy są zapisywane w tabeli schema_migrations. Każda migracja jest osobną klasą z metodami apply i rollback, w osobnym pliku w zyrarbot/storage/adapters/postgres/migrations/. Pliki należy nazywać numerami z zerami wiodącymi, aby porządek leksykograficzny pokrywał się z kolejnością, na przykład 0001_initial_schema.py, 0002_add_something.py. Migrację trzeba dodać także do krotki MIGRATIONS w migrations/__init__.py. Obecna migracja 0001_initial_schema tworzy początkowy schemat.

Rollback wszystkich wersji wykonaj poleceniem:

make migration-rollback

Aby cofnąć wersje nowsze niż wskazana, ustaw TO, na przykład make migration-rollback TO=1 pozostawi migrację w wersji 1. Przed rollbackiem zatrzymaj bota poleceniem docker compose stop discord-bot. Rollback wykonuje migracje w odwrotnej kolejności, usuwa ich wpisy z schema_migrations i może trwale skasować dane z cofanych tabel. Po rollbacku uruchomienie bota ponownie zastosuje brakujące migracje.

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/
│   ├── ports/          GuildConfigRepository, HistoryRepository,
│   │                   QueueRepository, UploadsRepository, Persistence
│   ├── adapters/
│   │   ├── postgres/   adaptery PostgreSQL oraz migrations/ z runnerem
│   │   ├── filesystem/ Adapter plików uploadu
│   │   └── json/       Adapter plikowego magazynu JSON
│   └── 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

  • MusicPlayer jest 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.state i funkcje z api/dependencies.py. Nie ma globalnych singletonów.
S
Description
Discord music bot utilizing yt-dlp with web dashboard
Readme
3 MiB
0 Stars 2 Watchers 0 Forks
ŻyrarBOT 5.0
Latest
2026-09-13 17:34:19 +02:00
Languages
Python 68.5%
Vue 16%
CSS 8.1%
TypeScript 4.5%
JavaScript 2.4%
Other 0.5%