Aoi banner

# Aoi **Aoi** (Аой-тян) — домашний Matrix-бот для музыкальной библиотеки. Она следит за Navidrome и discovery-playlist, аккуратно докладывает о новых альбомах, свежих Discovery-плейлистах и предстоящих релизах любимых артистов, обогащая карточки данными Last.fm и ссылками на внешние источники. ## Что умеет | Блок | Что происходит | | --- | --- | | Navidrome albums | Поллинг библиотек `main` и `anime` — новые альбомы превращаются в карточки с обложкой, описанием, тегами и рейтингом. | | Discovery playlists | Свежесгенерированные плейлисты discovery-playlist (имя содержит «Discovery») приходят в Matrix отдельным постом. | | Release watch | Аналитика по любимым/высоко оцененным артистам: анонсы и фактические релизы из дискографии, отслеживаемой discovery-playlist. | | Rich-описания | Last.fm-биография, теги, обложка из `album.getInfo`, ссылки на Last.fm и поиск Bandcamp. | | Baseline | На первом запуске можно зафиксировать всё уже существующее как «уже видела», чтобы не получить спам с историей. | | State & dedupe | SQLite хранит увиденные альбомы, плейлисты и релизы — повторов не будет. | ## Как устроена логика Aoi не делает запросов к LLM и не пытается «угадывать» — она опирается на конкретные источники и кеширует увиденное: 1. По расписанию опрашивает Navidrome и discovery-playlist (раздельные интервалы для альбомов, плейлистов и релизов). 2. Сравнивает с локальным state и забирает только новые сущности. 3. Обогащает карточки Last.fm-данными при наличии ключа. 4. Шлёт карточку в Matrix-комнату с обложкой, описанием и ссылками. 5. Помечает сущность как обработанную в SQLite. Каждый источник работает независимо, так что падение Navidrome не валит discovery, и наоборот. ## Сообщения в Matrix Карточка нового альбома выглядит примерно так: ```text 🎧 Новый альбом в Navidrome Artist — Album Title (2026) ━━ ОПИСАНИЕ ━━ Краткая биография/описание альбома из Last.fm… ━━ ТЕГИ ━━ shoegaze · indie · dream-pop 🔗 Last.fm: https://www.last.fm/music/Artist/Album 🔗 Bandcamp: https://bandcamp.com/search?q=Artist+Album ``` Discovery-плейлисты приходят отдельной карточкой со списком треков, release watch — отдельной с пометкой типа релиза (`announced`, `released`). ## Файлы проекта | Файл | Назначение | | --- | --- | | `aoi.py` | Основной сервис. | | `config.example.json` | Безопасный пример конфигурации. | | `config.json` | Локальная конфигурация с секретами, не коммитится. | | `requirements.txt` | Python-зависимости. | | `deploy/aoi.service` | systemd unit для production. | | `assets/banner.png` | Баннер README. | | `aoi.db` | SQLite-состояние, не коммитится. | | `aoi.log` | Лог сервиса, не коммитится. | ## Конфигурация Создать конфиг из примера: ```bash cp config.example.json config.json ``` Заполнить: - `matrix.homeserver`, `matrix.room_id`, `matrix.access_token`, `matrix.user_id`; - `bot.name` (по умолчанию `Аой-тян`) и `bot.avatar_path` для Matrix-профиля; - `navidrome.url`, `navidrome.username`, `navidrome.password`, идентификаторы библиотек; - `discovery.db_path` — путь к SQLite базе discovery-playlist; - `metadata.lastfm_api_key` — ключ Last.fm для био и тегов; - `polling.*` — интервалы опроса источников; - `polling.baseline_existing_on_first_run` — `true` на первом запуске, чтобы не спамить историей. Production-путь: ```text /storage/scripts/aoi ``` ## Установка В production Aoi использует виртуальное окружение Watcher (общие зависимости): ```bash cd /storage/scripts/watcher python3 -m venv .venv . .venv/bin/activate pip install -r /storage/scripts/aoi/requirements.txt ``` Можно завести отдельный venv — тогда обновить `deploy/aoi.service`. ## Запуск ```bash /storage/scripts/watcher/.venv/bin/python /storage/scripts/aoi/aoi.py ``` Healthcheck: ```bash curl -fsS http://127.0.0.1:18323/healthz ``` Ожидаемый ответ: ```json {"ok":true} ``` ## systemd Unit хранится в репозитории: ```text deploy/aoi.service ``` Установка или обновление: ```bash sudo cp /storage/scripts/aoi/deploy/aoi.service /etc/systemd/system/aoi.service sudo systemctl daemon-reload sudo systemctl enable aoi.service sudo systemctl restart aoi.service ``` Операции: ```bash sudo systemctl restart aoi.service systemctl --no-pager -l status aoi.service journalctl -u aoi.service -f tail -f /storage/scripts/aoi/aoi.log ``` ## Ручные команды ```bash curl -X POST http://127.0.0.1:18323/run/navidrome-albums curl -X POST http://127.0.0.1:18323/run/discovery-playlists curl -X POST http://127.0.0.1:18323/run/release-watch ``` ## Что не коммитить - `config.json` - `*.db` - `*.log` - `.venv/` - `__pycache__/`