Commit Graph
45 Commits
Author SHA1 Message Date
lgooseandClaude Bot 0879120c85 test: regresja arytmetyki kolejki wskaźnikowej
Kolejka jest nieusuwalna, a pozycję śledzi indeks, więc przeskoki,
usuwanie i zmiana kolejności muszą ten indeks poprawnie przesuwać. To
najbardziej podatna na błędy część przeniesionego kodu, więc dostaje
testy przypinające zachowanie:

- start odtwarzania przy dodaniu do pustej kolejki
- limit odtworzeń usuwający utwór i cofający indeks
- przechodzenie dalej oraz oba tryby zapętlania
- koniec kolejki czyszczący aktualny utwór
- przeskok, usunięcie utworu przed indeksem i usunięcie odtwarzanego
- zmiana kolejności zachowująca indeks na odtwarzanym utworze
- stosowanie głośności serwera i zatrzymanie przy niedziałających utworach

16 przypadków na atrapach Discorda, bez sieci i ffmpega. Uruchamiane
przez python -m unittest discover -s tests -t . - bez nowych zależności.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:11:37 +02:00
lgooseandClaude Bot c8a188647b fix(music): zatrzymanie pomijania, gdy nie da się odtworzyć żadnego utworu
Utwór, dla którego nie udało się zbudować świeżego źródła, był pomijany
przez rekurencyjne wywołanie play_next(advance=True). Przy włączonym
zapętlaniu kolejki - a przy zapętlaniu jednego utworu tym bardziej -
kolejny indeks wskazywał znowu na utwór niedziałający, więc pomijanie
kręciło się w kółko, zasypując kanał powiadomieniami.

Licznik nieudanych prób wędruje teraz przez play_next. Po liczbie
niepowodzeń równej długości kolejki odtwarzanie zatrzymuje się z jednym
komunikatem zamiast pętli.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:11:22 +02:00
lgooseandClaude Bot ab1d0d4a91 fix(music): stosowanie głośności serwera do nowo uruchamianych utworów
YTDLSource powstaje z domyślną głośnością 0.5, a ustawienie głośności
zmieniało tylko źródło aktualnie odtwarzane. Nowy utwór startował więc
na 50%, podczas gdy panel i /api/status raportowały stan serwera - domyślnie
100%. Zmiana głośności "znikała" po przejściu do kolejnego utworu.

Teraz play_next ustawia na źródle głośność ze stanu serwera, zanim
przekaże je do odtworzenia.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:11:10 +02:00
lgooseandClaude Bot 526e9ab644 refactor: korzeń kompozycji i usunięcie starych modułów
- Application składa wszystkie zależności w jednym miejscu i prowadzi bota
  równolegle z serwerem web. Panel przeżywa awarię logowania do Discorda,
  tak jak dotąd, ale komunikat idzie przez logging zamiast print.
- zyrarbot/__main__.py pozwala uruchomić pakiet przez python -m zyrarbot
  i konfiguruje logowanie; main.py zostaje cienkim punktem wejścia.
- Usunięte bot.py, web.py i ytdl.py - ich zawartość rozeszła się po
  pakiecie. Zniknął przy tym globalny obiekt bota tworzony przy imporcie
  modułu, który wymuszał kolejność importów między bot.py a web.py.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:10:59 +02:00
lgooseandClaude Bot 3fb1e26fb4 refactor(web): routery tematyczne i wstrzykiwanie zależności
22 endpointy z jednego pliku rozdzielone na routery według obszaru:
status, playback, queue, voice, uploads, settings i websocket.

- Powtarzany w każdym endpoincie blok "pobierz cog, sprawdź czy istnieje,
  ustal aktywny serwer, w razie czego rzuć 400" zastąpiony zależnościami
  z dependencies.py. Zniknęło 22-krotne bot.get_cog("MusicBot").
- Zależności wędrują przez app.state zamiast importu globalnego obiektu
  bota, więc warstwa web nie ma już zależności cyklicznej z modułem bota.
- create_app składa aplikację i montuje routery.
- Wycofane @app.on_event("startup") zastąpione lifespanem, który dodatkowo
  sprząta po sobie: odpina hook i zatrzymuje pętlę rozgłaszania.

Kontrakt HTTP pozostaje bez zmian - te same ścieżki, metody, kody błędów
i kształt odpowiedzi.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:10:59 +02:00
lgooseandClaude Bot c2f6d265c1 refactor(web): rozgłaszanie stanu po WebSockecie
- ConnectionManager - rejestr aktywnych połączeń (bez zmian poza typami).
- StatusService - budowanie obrazu stanu bota. Endpoint get_status miał
  126 linii i składał odpowiedź w dwóch wariantach; teraz jest to zestaw
  metod budujących poszczególne fragmenty payloadu.
- StatusBroadcaster - rozgłaszanie na żądanie oraz pętla cykliczna, wraz
  z zatrzymywaniem zadania przy wyłączaniu aplikacji. Wcześniej zadanie
  było tworzone w on_event("startup") i nigdy nie anulowane.

Wariant odpowiedzi dla bota bez serwerów zwraca teraz komplet kluczy
(dochodzi queue_index: -1), więc panel dostaje zawsze ten sam kształt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:10:42 +02:00
lgooseandClaude Bot 6e61892c04 refactor(web): modele żądań w osobnych plikach
Jedenaście klas pydantic zadeklarowanych jednym blokiem na górze web.py
rozdzielone na pliki zgodnie z zasadą jedna klasa = jeden plik. Każdy
model dostaje docstring mówiący, do czego służy - z samych nazw pól
(np. channel_id akceptujące pusty string jako reset) nie wynikało to
w oczywisty sposób.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:10:42 +02:00
lgooseandClaude Bot b2651bb957 refactor(bot): klient Discorda i cienki cog komend
- ZyrarBot buduje intencje, rejestruje cog i synchronizuje drzewo komend.
- MusicCog zawiera już wyłącznie obsługę komend ukośnikowych: walidację
  argumentów, komunikaty dla użytkownika i wywołania MusicPlayer. Cała
  praca ze stanem zniknęła z tego pliku.
- GuildResolver ustala kontekst serwera dla panelu webowego, który nie ma
  interakcji Discorda - wcześniej robiła to funkcja get_active_guild
  w web.py, sięgająca po globalny obiekt bota.
- Powtarzana w czterech komendach odpowiedź "dodano do kolejki" albo
  "teraz odtwarzane" zebrana w jednym helperze.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:10:28 +02:00
lgooseandClaude Bot a143cb21d3 refactor(music): MusicPlayer jako jedyny właściciel stanu odtwarzania
Logika odtwarzania wyprowadzona z coga Discorda do osobnej klasy. Dotąd
kolejkę modyfikowały dwie niezależne ścieżki: metody MusicBot oraz
endpointy w web.py sięgające po music_cog.queues[guild_id] i ustawiające
music_cog.jump_flag wprost. Teraz obie warstwy wołają MusicPlayer.

Przeniesione bez zmiany zachowania: enqueue, play_next wraz z arytmetyką
indeksu i limitem odtworzeń, remove, reorder, jump, sterowanie głośnością
oraz hook on_state_change rozgłaszający stan po WebSockecie.

Wybór kolejnego indeksu wydzielony do _next_index, dzięki czemu reguły
trybów zapętlania i przeskoku dają się czytać bez śledzenia całej metody.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:10:28 +02:00
lgooseandClaude Bot 4cc00618d1 refactor(music): stan serwera, tryb zapętlania i budowanie powiadomień
- GuildMusicState zbiera stan jednego serwera w jedną strukturę. Dotąd
  było to dziewięć równoległych słowników indeksowanych guild_id
  (queues, currents, volumes, loop_currents, loop_playlists, last_channels,
  history, queue_indices, jump_flag), co wymagało pamiętania, że przy
  każdej zmianie trzeba ruszyć kilka z nich naraz.
- LoopMode zastępuje parę booleanów loop_current/loop_playlist, których
  kombinacja "oba włączone" nie miała sensu, a mimo to była osiągalna.
  Wartości enuma (off/playlist/single) odpowiadają kontraktowi API panelu.
- TrackEmbedFactory zbiera budowanie osadzeń Discorda, powielone dotąd
  w enqueue_track i play_next.
- NotificationChannelResolver opisuje kolejność szukania kanału logów:
  zapamiętany -> z konfiguracji -> pierwszy zapisywalny na serwerze.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:10:11 +02:00
lgooseandClaude Bot 53ffae1663 refactor(audio): wydzielenie warstwy pozyskiwania dźwięku
ytdl.py rozbity na cztery pliki o rozłącznych rolach:

- YtdlOptions   opcje yt-dlp i FFmpeg, wcześniej moduły-globalne
- MediaProbe    odczyt długości pliku przez ffprobe
- YTDLSource    samo źródło audio - dane utworu i zliczanie odtworzonego
                czasu; dochodzą właściwości is_local, filepath, display_url
                i has_web_link, które zastępują powtarzane w kilku miejscach
                data.get("webpage_url") or url
- TrackFactory  budowanie źródeł z zapytania, adresu lub pliku

Rozdzielenie źródła od sposobu jego tworzenia usuwa globalną instancję
YoutubeDL i pozwala podmienić fabrykę w testach. Metoda recreate zbiera
w jednym miejscu odtwarzanie utworu od nowa z zachowaniem jego tożsamości
i pozostałej liczby odtworzeń.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:10:11 +02:00
lgooseandClaude Bot e59b4ad9f1 refactor(storage): repozytoria konfiguracji, historii i plików
Dostęp do danych trwałych schodzi za trzy repozytoria, zamiast być
rozsmarowany po metodach coga i endpointach:

- GuildConfigRepository - kanały powiadomień per serwer i domyślna liczba
  odtworzeń.
- HistoryRepository - historia per serwer z buforem w pamięci i limitem
  wpisów. Zasada odsiewania duplikatów (zgodny tytuł albo adres) siedzi
  teraz w HistoryEntry.is_same_track_as zamiast w warunku wbudowanym
  w listę składaną.
- UploadsRepository - katalog uploadów. Każda nazwa przechodzi przez
  os.path.basename w jednym miejscu, co zamyka temat ścieżek względnych
  przychodzących z API.

Wpisy historii i pliki opisują struktury HistoryEntry oraz UploadFileInfo
zamiast luźnych słowników z kluczami sprawdzanymi przez .get().

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:09:52 +02:00
lgooseandClaude Bot e194a8611c refactor(config): Settings i JsonFileStore jako podstawa pakietu
Początek pakietu zyrarbot, budowanego wedle zasady jedna klasa = jeden plik.

- Settings zbiera konfigurację ze zmiennych środowiskowych oraz ścieżki
  i limity, które dotąd były literałami rozsianymi po bot.py i web.py
  ("config/config.json", "uploads", zakres 1-999, domyślne 5 odtworzeń).
- JsonFileStore zastępuje sześć niemal identycznych bloków open/json.load
  z ręcznym try/except. Brakujący lub uszkodzony plik daje pusty słownik
  zamiast wyjątku, a zapis sam tworzy katalog.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 01:09:52 +02:00
mmacierzanka edf317d21e feat: dodanie mechanizmu limitu odtworzeń (TTL) w kolejce oraz konfiguracji w UI i na Discordzie 2026-07-05 16:03:58 +02:00
mmacierzanka 5c98f29782 feat: ograniczenie widocznych plików do 10 ostatnio używanych, dodanie okna modalnego z całą bazą plików oraz zmiana ikony na plus przy przycisku Dodaj 3.0 2026-07-04 17:05:18 +02:00
mmacierzanka a900097134 feat: przebudowa systemu kolejki od podstaw z użyciem wskaźnika indeksu (nieusuwalna kolejka z możliwością przeskoku i przewijania) 2026-07-04 16:53:20 +02:00
mmacierzanka ab6f16b57d feat: połączenie przycisków zapętlania w jeden przycisk z cyklem Wyłączone -> Kolejka -> Utwór (styl YT Music/Spotify) 2026-07-04 16:41:17 +02:00
mmacierzanka 2a399364d8 feat: zmiana ikony play/pause w dashboardzie zależnie od stanu odtwarzania 2026-07-04 16:38:12 +02:00
mmacierzanka 55c9b7207f fix: wyświetlanie kanałów głosowych ze wszystkich serwerów na liście do połączenia w dashboardzie 2026-07-04 16:37:19 +02:00
mmacierzanka d05615a079 chore: dodanie katalogu uploads do .gitignore 2026-07-04 16:35:57 +02:00
mmacierzanka c0ec3a5f95 style: dodanie limitów szerokości kolumn i kontenerów zapobiegających rozjeżdżaniu się layoutu przy długich tytułach 2026-07-04 16:17:54 +02:00
mmacierzanka 8f0b398843 feat: deduplikacja wpisów w historii odtwarzania (każde nagranie widoczne tylko raz) 2026-07-04 16:14:40 +02:00
mmacierzanka 11a1834312 style: poprawa kontrastu i widoczności przycisku zamknięcia w panelu ustawień 2026-07-04 16:13:46 +02:00
mmacierzanka d074df571c fix: przywrócenie deklaracji voiceSelect w app.js rozwiązujące brak ładowania kanałów w interfejsie 2026-07-04 16:02:46 +02:00
mmacierzanka ebee5ac9d3 fix: dodanie brakującego importu Optional w bot.py oraz wyłączenie buforowania logów w Dockerze 2026-07-04 15:57:20 +02:00
mmacierzanka f2d19bd708 fix: dodanie python-multipart do requirements.txt dla obsługi przesyłania plików w FastAPI 2026-07-04 15:53:45 +02:00
mmacierzanka dcbd7859d7 refactor: przeniesienie konfiguracji kanału logów do dedykowanego modalu Ustawienia z wybierakiem per-serwer 2026-07-04 15:53:03 +02:00
mmacierzanka 89137f7d1c feat: dodanie trybu zapętlania całej kolejki (playlisty) w Discord (/loopplaylist) i w dashboardzie web 2026-07-04 15:39:32 +02:00
mmacierzanka 4f5ca391fa fix: naprawa działania pętli utworu - wyłączanie pętli pojedynczego utworu przy ręcznym pominięciu (/skip, przycisk w web) 2026-07-04 15:37:02 +02:00
mmacierzanka 65d797a1a6 feat: dodanie historii kolejki z możliwością ponownego odtwarzania w dashboardzie oraz komendy /history i /replay w Discord 2026-07-04 15:35:53 +02:00
mmacierzanka dfd681be04 feat: dodanie możliwości przesyłania własnych plików na serwer (wszystkie formaty ffmpeg), odtwarzanie jednym kliknięciem z web i komenda /playfile w Discord 2026-07-04 15:33:43 +02:00
mmacierzanka 444b797cd0 feat: sanityzacja tytułów w Discordzie oraz linki i embedy dla powiadomień z panelu web 2026-07-04 15:31:45 +02:00
mmacierzanka 867edf302f perf: usunięto redundantne zapytania HTTP statusu po kliknięciach przycisków, techniczne notyfikacje WS 2.0 2026-05-23 15:15:20 +02:00
mmacierzanka a8b2c89735 feat: zmigrowano panel webowy na WebSockets w czasie rzeczywistym 2026-05-23 15:10:19 +02:00
mmacierzanka 3eee27edfd feat: dodano pasek postępu odtwarzania w czasie rzeczywistym w panelu webowym 2026-05-23 15:04:42 +02:00
mmacierzanka c550215070 feat: add multi-guild support and text channel mapping persistence via Docker volume 2026-05-23 14:45:37 +02:00
mmacierzanka 07e32c1a1d chore: default volume to 100%, translate discord logs to Polish, rename project to ŻyrarBOT 2026-05-23 14:37:16 +02:00
mmacierzanka 71800c8fd5 feat: add beautiful web queue dashboard with loop, reordering, and text channel settings persistence 2026-05-23 14:32:43 +02:00
mmacierzanka 6382955b3f Remove yt-dlp version lock 1.0 2026-05-23 00:58:19 +02:00
mmacierzanka e24ca36ccb Remove redundant youtube_dl bug report suppression logic
Caused issues with playback
2025-06-14 02:13:21 +02:00
mmacierzanka bf724efe4d Update yt-dlp version in requirements.txt to 2025.6.9 2025-06-14 02:13:09 +02:00
mmacierzanka fcedb7e8c0 Pin yt-dlp version in requirements.txt to 2025.3.31 2025-06-01 00:30:58 +02:00
mmacierzanka cd0a738fdf Refactor bot to use Discord app commands and modernize structure
Replaced old commands-based approach with Discord app commands for slash command functionality. Simplified error handling, removed redundant code, and improved voice channel management. Updated bot's initialization and ensured proper command syncing for global or guild-specific contexts.
2025-04-28 03:56:57 +02:00
mmacierzanka 78cacc3a17 Add Docker and Compose setup for Discord bot deployment
Introduce Dockerfile for containerizing the Discord bot, including required dependencies for audio handling. Add compose.yaml for simplified service orchestration. Update .gitignore to exclude compiled files and environment-specific artifacts.
2025-04-27 02:09:29 +02:00
mmacierzanka 514df72a03 Initial commit
Add music bot with YouTube integration and basic commands

Implemented a Discord bot with commands for playing, pausing, skipping, and managing a music queue utilizing yt_dlp and FFmpeg. Includes opus library loading fallback logic and gitignore entry for environment files.
2025-04-27 01:22:13 +02:00