127 lines
6.0 KiB
Markdown
127 lines
6.0 KiB
Markdown
# ŻyrarBOT
|
||
|
||
Bot muzyczny Discord z panelem webowym: kolejka odtwarzania, historia, serwerowa
|
||
baza plików i sterowanie na żywo przez WebSocket.
|
||
|
||
## Uruchomienie
|
||
|
||
```bash
|
||
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 |
|
||
| `/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 |
|
||
| `/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
|
||
|
||
```bash
|
||
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
|
||
├── 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.
|