Aoi (Аой-тян): Matrix-бот для Navidrome и discovery-playlist — новые альбомы, discovery-плейлисты и предстоящие релизы любимых артистов.
Find a file
Rinka Makise-Okabe 8f2b349ed9 Gate discovery-playlist notifications on Navidrome availability
Aoi was sending Matrix cards as soon as a playlist row appeared in the
discovery-playlist SQLite, before Navidrome had scanned and indexed it.
That produced 'ready' notifications for playlists that were not yet
playable.

The gate now requires the matching playlist (exact name match,
case-insensitive) to be visible in Navidrome via getPlaylists with at
least N entries (default 1, knob 'polling.discovery_min_tracks_in_navidrome')
before the notification fires. If a playlist stays missing from
Navidrome past 'polling.discovery_stale_after_hours' (default 48h), it
is marked sent without notification so we don't loop forever.

Refactored navidrome_playlist_cover into navidrome_find_playlist (name
match) and navidrome_playlist_cover_for (cover for an already-resolved
playlist), so the gate and the cover lookup share a single Navidrome
roundtrip.
2026-04-28 21:25:35 +03:00
assets Initial commit: Aoi (Аой-тян) — Matrix notifier for Navidrome and discovery-playlist 2026-04-28 20:15:50 +03:00
deploy Initial commit: Aoi (Аой-тян) — Matrix notifier for Navidrome and discovery-playlist 2026-04-28 20:15:50 +03:00
.gitignore Initial commit: Aoi (Аой-тян) — Matrix notifier for Navidrome and discovery-playlist 2026-04-28 20:15:50 +03:00
aoi-avatar.png Initial commit: Aoi (Аой-тян) — Matrix notifier for Navidrome and discovery-playlist 2026-04-28 20:15:50 +03:00
aoi.py Gate discovery-playlist notifications on Navidrome availability 2026-04-28 21:25:35 +03:00
config.example.json Gate discovery-playlist notifications on Navidrome availability 2026-04-28 21:25:35 +03:00
README.md Initial commit: Aoi (Аой-тян) — Matrix notifier for Navidrome and discovery-playlist 2026-04-28 20:15:50 +03:00
requirements.txt Initial commit: Aoi (Аой-тян) — Matrix notifier for Navidrome and discovery-playlist 2026-04-28 20:15:50 +03:00

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

Карточка нового альбома выглядит примерно так:

🎧 Новый альбом в 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 Лог сервиса, не коммитится.

Конфигурация

Создать конфиг из примера:

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_runtrue на первом запуске, чтобы не спамить историей.

Production-путь:

/storage/scripts/aoi

Установка

В production Aoi использует виртуальное окружение Watcher (общие зависимости):

cd /storage/scripts/watcher
python3 -m venv .venv
. .venv/bin/activate
pip install -r /storage/scripts/aoi/requirements.txt

Можно завести отдельный venv — тогда обновить deploy/aoi.service.

Запуск

/storage/scripts/watcher/.venv/bin/python /storage/scripts/aoi/aoi.py

Healthcheck:

curl -fsS http://127.0.0.1:18323/healthz

Ожидаемый ответ:

{"ok":true}

systemd

Unit хранится в репозитории:

deploy/aoi.service

Установка или обновление:

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

Операции:

sudo systemctl restart aoi.service
systemctl --no-pager -l status aoi.service
journalctl -u aoi.service -f
tail -f /storage/scripts/aoi/aoi.log

Ручные команды

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__/