docs: README z opisem struktury pakietu

Opisane uruchamianie, zmienne środowiskowe, testy oraz mapa pakietu
z klasą przypisaną do pliku. Spisane też trzy zasady, które trzymają
strukturę w ryzach: MusicPlayer jest jedynym właścicielem stanu, kolejka
jest nieusuwalna i śledzona indeksem, a zależności idą przez konstruktory
zamiast globalnych singletonów.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
lgooseandClaude Bot committed 2026-08-21 01:11:37 +02:00
1 parent 0879120c85
commit ccfb0d2e34
1 file changed
+77
+77
View File
@@ -0,0 +1,77 @@
# Ż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`. W Dockerze: `docker compose up --build`.
## 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 serwer web
├── 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
├── bot/ Warstwa Discorda
│ ├── client.py ZyrarBot
│ ├── guild_resolver.py GuildResolver
│ └── cogs/music_cog.py MusicCog
└── web/ Panel webowy (FastAPI)
├── factory.py create_app
├── connection_manager.py ConnectionManager
├── status_service.py StatusService
├── status_broadcaster.py StatusBroadcaster
├── dependencies.py wstrzykiwanie zależności z app.state
├── schemas/ modele żądań - jeden na plik
└── routers/ trasy pogrupowane tematycznie
```
### 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 warstwie web przez `app.state`
i funkcje z `web/dependencies.py`. Nie ma globalnych singletonów.