94 lines
4.4 KiB
Markdown
94 lines
4.4 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.
|
|
|
|
## 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.
|