Files
jellybit/README.md
T
av 69853a96c9 docs: разобран урожай судей после подъёма канона
- перечень команд пользователя убран из architecture.md в спеки review и
  state-reconciliation, где ему дом: обзор успел разойтись с ними в обе стороны
- README перестал дублировать деплой и статус — теперь ссылается на дом
- статус «заведена ли задача под пробел» сведён в один регистр открытых вопросов
- шаги tasks.py и openspec.py названы в перечне «что красит безусловно»
- из спеки download-tracking сняты числа умолчаний: их дом — database.md
2026-08-09 19:24:59 +03:00

127 lines
8.1 KiB
Markdown

# Jellybit
Jellybit — связующий сервис между qBittorrent и Jellyfin. Принимает
magnet-ссылку или `.torrent`-файл вместе с текстовым контекстом, ставит загрузку в
qBittorrent, дожидается её завершения, распознаёт содержимое (фильм или
сериал, сезоны и серии) и раскладывает готовые файлы по конвенциям
библиотеки Jellyfin.
Полный замысел, границы домена и типовые сценарии — в
[docs/passport.md](docs/passport.md).
## Зачем
Arr-стек (prowlarr/radarr/sonarr) плохо ложится на русские трекеры,
аниме и ручные раздачи. Jellybit намеренно сокращает путь: одна точка
входа → готовая раскладка для Jellyfin, без каталога индексаторов и
сложных правил качества. Распознавание делает LLM, которому помогает
переданный человеком контекст и (опционально) внешние базы метаданных.
## Как работает
1. Точка входа принимает magnet + контекст (HTTP API, веб-UI,
Telegram-бот или CLI).
2. Загрузка ставится в qBittorrent в выделенную категорию.
3. Сервис отслеживает завершение загрузки.
4. По именам файлов, контексту и (опц.) базам метаданных определяется
фильм/сериал и нужная раскладка.
5. Файлы **хардлинкаются** в библиотеку Jellyfin — источник остаётся в
раздаче, место на диске не дублируется.
6. После раскладки сервис (опц.) просит Jellyfin пересканировать
медиатеку, чтобы новые файлы быстрее появились в проигрывателе.
При высокой уверенности раскладка выполняется автоматически, иначе —
уходит на подтверждение человеку.
## Статус
Рабочий прототип: сквозной путь приём → загрузка → распознавание → раскладка
работает целиком, автоматически при уверенном результате либо через
подтверждение человеком. Что уже умеет и что дальше —
[tasks/ROADMAP.md](tasks/ROADMAP.md).
## Документация
Разработка идёт по **Spec-Driven Development** через
[OpenSpec](https://github.com/Fission-AI/OpenSpec): изменение сначала
описывается спекой, потом реализуется.
- [openspec/specs/](openspec/specs/) — **что система делает**, нормативно:
capability-спеки. Изменения (proposal → design → tasks → archive) — в
`openspec/changes/`.
- [docs/passport.md](docs/passport.md) — зачем и для кого, чем **не** является.
- [docs/architecture.md](docs/architecture.md) — как сложено: компоненты,
внешние границы, эксплуатация, единые точки, деплой.
- [docs/database.md](docs/database.md) — схема хранилища и настройки.
- [docs/security.md](docs/security.md) — периметр и модель угроз.
- [docs/conventions/](docs/conventions/README.md) — как пишем код:
[логи](docs/conventions/logging.md), [ошибки](docs/conventions/errors.md),
[конфиг](docs/conventions/config.md), [БД](docs/conventions/database.md),
[веб-UI](docs/conventions/web-ui.md).
- [docs/adr/](docs/adr/README.md) — журнал решений (почему так), неизменяемый.
- [docs/research/](docs/research/README.md) — наблюдения за чужими форматами.
- [tasks/](tasks/BACKLOG.md) — задачи и цели.
Раскладка документации задана каноном av-dev и проверяется шагом `canon` в
`task gate`.
## Стек
Go (один статический бинарь), SQLite (`modernc.org/sqlite` + `sqlx`,
миграции `goose`), HTTP — `chi` + `html/template` + htmx, конфигурация —
TOML, логи — структурированный JSON (`slog`). Полный перечень с версиями —
[CLAUDE.md](CLAUDE.md) → «Стек»; как эти компоненты сложены —
[docs/architecture.md](docs/architecture.md).
## Конфигурация
Конфигурация — один файл TOML. По умолчанию ищется `config.toml` в рабочей
директории; путь переопределяется опцией `--config=path`. Образец со всеми
секциями и описанием каждого поля (назначение, диапазон значений, единицы
измерения) — [config.example.toml](config.example.toml); скопируй его в
`config.toml` и заполни под себя. Конфиг валидируется на старте: при
ошибке сервис не стартует.
Секреты (пароль qBittorrent, ключи LLM/метабаз, токен Telegram) в репозиторий
не коммитятся — их подставляет деплой прямо в файл. Доступ к внешним сервисам
(LLM, базы метаданных, Telegram) при необходимости идёт через HTTP-прокси —
поле `proxy` в соответствующих секциях. Правила — в
[docs/conventions/config.md](docs/conventions/config.md).
## Разработка
Нужны Go 1.26 и [Task](https://taskfile.dev). Полный список задач —
`task --list`.
```bash
cp config.example.toml config.toml # локально: db_path -> ./jellybit.db
task setup # golangci-lint + git-хуки lefthook
task tidy # go mod tidy
task run # go run ./cmd/jellybit --config ./config.toml
task test lint # тесты и golangci-lint
task build # статический бинарь (linux/amd64) для сервера
task image # docker-образ из готового бинаря
```
Отладка распознавания на реальной раздаче (только чтение, без раскладки):
```bash
jellybit recognize <infohash> --dry-run [--context "..."] --config ./config.toml
```
Берёт торрент из qBittorrent по infohash, прогоняет распознавание (LLM +
метабазы) и печатает план: тип/название/год, матч в базе, решение авто/review
и превью целевых путей — то, что создалось бы при Apply.
## Доставка
Рассчитан на домашний медиа-сервер. Артефакты репозитория — статический бинарь
(`task build`) и `Dockerfile`; образ собирается целиком локально на
control-хосте (`task image`) и едет на сервер через `docker save`/`load`.
Конкретная деплой-обвязка (плейбук, секреты) держится в отдельном приватном
репозитории и в комплект не входит.
Параметры запуска — сеть, пользователь, монтирования, healthcheck, — разделение
ответственности с umbar и единая песочница `/srv/media`:
[docs/architecture.md](docs/architecture.md) → «Деплой».