Files
NaviWatcher/docs/Specification.md
2026-05-19 17:42:12 +03:00

151 lines
9.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ЦЕЛЬ ПРОЕКТА
## 1. Общее описание проекта
**NaviWatcher** — это автономный сервисный инструмент (демон), предназначенный для автоматического мониторинга музыкальных коллекций, хранящихся в Navidrome (или любом сервере с поддержкой Subsonic API).
**Основная задача:** сопоставлять текущую медиатеку пользователя с полной дискографией артистов во внешних базах данных (MusicBrainz), находить отсутствующие релизы (альбомы, синглы, сборники) и уведомлять об этом пользователя через Telegram и встроенный веб-интерфейс.
## 2. Технологический стек
* **Язык программирования:** Go 1.21+
* **База данных:** SQLite 3 (для хранения кэша, настроек и состояний).
* **HTTP-сервер:** Стандартная библиотека Go (`net/http`) + `html/template`.
* **Внешние зависимости (библиотеки):**
* `github.com/mattn/go-sqlite3` — драйвер базы данных.
* `github.com/lithammer/fuzzysearch` — библиотека для нечеткого сравнения строк.
* `gopkg.in/yaml.v3` — парсинг конфигурационных файлов.
### 2.1. Аутентификация в Navidrome (Subsonic API)
NaviWatcher взаимодействует с Navidrome через **Subsonic API v1.16.1** (эндпоинты `/rest/*`).
Используется **токенная аутентификация** — стандартный метод Subsonic API:
* Формула токена: `token = md5(password + salt)`
* Salt генерируется клиентом случайно при каждом запросе.
* Пароль пользователя **не передаётся** в открытом виде.
* Это обеспечивает совместимость с любыми Subsonic-совместимыми серверами (Navidrome, Airsonic, Ampache).
**Пример запроса:**
```
/rest/getArtists?u=watcher_service&t=<md5_hash>&s=<random_salt>&v=1.16.1&c=NaviWatcher
```
**Создание сервисного пользователя в Navidrome:**
1. В веб-интерфейсе Navidrome: Settings → Users → Add User.
2. Задать username и надёжный пароль.
3. Убедиться, что роль имеет доступ к нужным медиатекам.
4. Указать эти данные в `config.yaml` (поля `user` и `password`).
## 3. Архитектура системы
Проект разделен на логические модули:
1. **Navidrome Client:** Взаимодействие с Subsonic API v1.16.1 (чтение артистов и локальных альбомов). Аутентификация — токенная (md5), пароль не передаётся в открытом виде. Используются эндпоинты: `getArtists`, `getArtist`, `getAlbum`, `ping`.
2. **MusicBrainz Provider:** Запрос дискографий с механизмом кэширования и соблюдением Rate Limit (1 запрос в секунду).
3. **Scanner Engine:** Логика нормализации строк и сравнения списков (Diff).
4. **Database Layer:** Персистентное хранение данных и пользовательских фильтров.
5. **Notifier:** Планировщик задач и отправка уведомлений в Telegram.
6. **Web UI:** Интерфейс для просмотра находок и управления исключениями.
## 4. Алгоритмы и бизнес-логика
### 4.1. Работа с внешними данными (MusicBrainz)
Для минимизации дубликатов (разные издания одного альбома) сервис должен работать с сущностью **Release Group (RG)**, а не с конкретными релизами.
* **Кэширование:** Данные о дискографии артиста сохраняются в SQLite на 24 часа. Повторные запросы в этот период идут только в БД.
### 4.2. Фильтрация контента
При получении списка Release Groups из MusicBrainz применяется многоуровневый фильтр:
1. **По статусу:** Игнорировать `Bootleg`, `Promotion`, `Pseudo-Release`.
2. **По типу (глобально):** Разрешены `Album`, `Single`, `EP`, `Compilation`.
3. **По типу (персонально для артиста):** Возможность отключить `Single` или `Compilation` для конкретного исполнителя через Web UI.
4. **По вторичным признакам:** Опциональное игнорирование `Live`, `Remix`, `Soundtrack`.
### 4.3. Сравнение (Fuzzy Matching)
Чтобы избежать ложных срабатываний (например, «The Wall» vs «The Wall (Remastered)»), используется алгоритм:
1. **Нормализация:** Приведение к нижнему регистру, удаление спецсимволов, удаление года (20xx), удаление ключевых слов в скобках (Deluxe, Anniversary, Expanded).
2. **Сравнение:** Если коэффициент сходства строк выше 0.85 (настраиваемо), альбом считается «уже имеющимся».
### 4.4. Жизненный цикл уведомлений
1. Найден новый релиз -> Проверка, нет ли его в таблице `ignored_releases` или `notifications_sent`.
2. Если нет -> Добавление в очередь на отправку.
3. Раз в сутки -> Отправка сводного сообщения в Telegram -> Пометка в `notifications_sent`.
## 5. Модель данных (SQLite)
### Таблица `artist_settings`
Хранит параметры мониторинга для каждого артиста из Navidrome.
* `id`: string (MBID или имя)
* `name`: string
* `ignore_singles`: boolean (default: false)
* `ignore_compilations`: boolean (default: false)
* `monitored`: boolean (default: true)
### Таблица `external_releases`
Кэш релизов, найденных во внешнем мире.
* `rgid`: string (MusicBrainz Release Group ID) — Primary Key.
* `artist_id`: string (FK)
* `title`: string
* `type`: string (album/single/ep)
* `release_date`: string
* `is_ignored`: boolean (флаг скрытия из списка новинок)
### Таблица `notifications_sent`
* `rgid`: string (FK)
* `sent_at`: datetime
## 6. Требования к интерфейсу
### 6.1. Web UI (Dashboard)
* **Главный экран:** Список артистов, у которых есть «Missing Albums».
* **Страница артиста:**
* Список альбомов в Navidrome (Source: Subsonic).
* Список найденных новинок (Source: MB Cache).
* Действия: «Игнорировать этот релиз», «Игнорировать все синглы артиста».
* **Страница «Архив»:** Просмотр ранее проигнорированных релизов с возможностью их восстановления.
### 6.2. Telegram
* Сообщение должно содержать список имен артистов и количество найденных новинок.
* Ссылка на Web UI для детального просмотра.
## 7. Конфигурация (config.yaml)
```yaml
server:
host: "0.0.0.0"
port: 8080
# Basic Auth для доступа к веб-интерфейсу
username: "admin"
password: "password123"
navidrome:
url: "http://localhost:4533"
user: "watcher_service"
password: "user_password"
# Токен и salt генерируются автоматически при каждом запросе (md5(password + salt))
musicbrainz:
user_agent: "NaviWatcher/1.0 ( mail@example.com )"
cache_ttl: 24h
telegram:
enabled: true
token: "bot_token"
chat_id: "your_chat_id"
cron_schedule: "0 10 * * *" # Каждый день в 10:00
scanner:
fuzzy_threshold: 0.85
ignore_bootlegs: true
include_compilations: true
```
## 8. Программные требования и ограничения
1. **Rate Limiting:** MusicBrainz API позволяет делать не более 1 запроса в секунду. Демон должен строго соблюдать этот интервал.
2. **Concurrency:** Запросы к Navidrome и MusicBrainz должны выполняться в отдельных горутинах, чтобы веб-интерфейс оставался отзывчивым.
3. **Graceful Shutdown:** При получении сигнала завершения (SIGTERM) демон должен корректно закрыть соединение с SQLite.
4. **Static Files:** Все HTML-шаблоны должны быть встроены в бинарный файл (использование `//go:embed`).
5. **Docker:** Проект должен быть запущен через `docker compose`.