mmacierzanka 2a4fbf8567
Panel / Lint, typy i build (pull_request) Failing after 21s
Backend / Testy i kontrakt API (pull_request) Failing after 28s
Backend / Lint i formatowanie (pull_request) Failing after 32s
Backend / Testowy build obrazu (pull_request) Skipped
Merge branch 'feature/auth' into feature/discord-login
# Conflicts:
#	zyrarbot/ui/api/routers/auth_router.py
2026-10-01 18:46:37 +02:00
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

Zmienne środowiskowe (plik .env):

Zmienna Opis
DISCORD_TOKEN Token bota Discord.
DISCORD_CLIENT_ID / DISCORD_CLIENT_SECRET Dane aplikacji OAuth2 z Discord Developer Portal.
DISCORD_REDIRECT_URI Publiczny adres callbacku, np. https://bot.example.com/api/auth/discord/callback.
DISCORD_ADMIN_IDS Opcjonalne, przecinkami oddzielone Discord User ID administratorów panelu.
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.

Konta i dostępy panelu

Panel obsługuje logowanie hasłem oraz Discord OAuth2. Przy logowaniu przez Discord dostęp do sterowania na danym serwerze dostaje użytkownik, który ma tam uprawnienie Manage Server (lub Administratora), o ile bot również jest na tym serwerze. Dostęp odświeża się przy każdym logowaniu. Administratorów panelu wskaż przez DISCORD_ADMIN_IDS (Discord User ID, oddzielone przecinkami); mają dostęp do /admin i wszystkich serwerów, na których działa bot. Uprawnienie Administratora na serwerze daje dostęp do sterowania tym serwerem, ale samo nie czyni użytkownika administratorem panelu. Logowanie hasłem nadal działa. Przycisk Discord pojawia się tylko, gdy ustawione są wszystkie trzy zmienne OAuth: Client ID, Client Secret i Redirect URI.

Dodaj do .env wartości aplikacji OAuth2 (nie publikuj Client Secret):

DISCORD_CLIENT_ID=123456789012345678
DISCORD_CLIENT_SECRET=wklej_client_secret
DISCORD_REDIRECT_URI=https://bot.example.com/api/auth/discord/callback
DISCORD_ADMIN_IDS=123456789012345678

Konfiguracja Discord Developer Portal

  1. Wybierz lub utwórz aplikację w Discord Developer Portal.
  2. W OAuth2 → General skopiuj Client ID i wygeneruj Client Secret.
  3. W OAuth2 → General → Redirects dodaj dokładnie wartość DISCORD_REDIRECT_URI, np. https://bot.example.com/api/auth/discord/callback. Adres musi być osiągalny przez przeglądarkę użytkownika. Lokalnie z Docker Compose użyj http://localhost/api/auth/discord/callback; przy uruchomieniu bezpośrednio na porcie 8000 użyj http://localhost:8000/api/auth/discord/callback.
  4. Ustaw DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET i DISCORD_REDIRECT_URI w .env. DISCORD_ADMIN_IDS jest opcjonalne; wpisz tam własny User ID, jeśli konto ma zarządzać panelem. Aby skopiować ID, włącz Developer Mode w Discordzie, kliknij swój profil prawym przyciskiem i wybierz Copy User ID. Kolejne ID oddzielaj przecinkami.
  5. Aby dodać bota na serwery, w Installation włącz instalację dla serwerów i zakresy bot oraz applications.commands; przyznaj wymagane uprawnienia bota (co najmniej View Channels, Connect, Speak i Send Messages). OAuth logowania używa zakresów identify i guilds; nie wymaga dodatkowych intentów Gateway.
  6. Zrestartuj usługę: docker compose up -d --build. Otwórz panel i wybierz Zaloguj przez Discord. Discord poprosi o zakresy identify i guilds; zaakceptuj je, aby panel mógł sprawdzić konto i serwery użytkownika.

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%