# Jellybit Jellybit — связующий сервис между qBittorrent и Jellyfin. Принимает торрент (magnet, `.torrent` или ссылку) вместе с текстовым контекстом, ставит загрузку в qBittorrent, дожидается её завершения, распознаёт содержимое (фильм или сериал, сезоны и серии) и раскладывает готовые файлы по конвенциям библиотеки Jellyfin. Полный замысел и причины — в [BRIEF.md](BRIEF.md). ## Зачем Arr-стек (prowlarr/radarr/sonarr) плохо ложится на русские трекеры, аниме и ручные раздачи. Jellybit намеренно сокращает путь: одна точка входа → готовая раскладка для Jellyfin, без каталога индексаторов и сложных правил качества. Распознавание делает LLM, которому помогает переданный человеком контекст и (опционально) внешние базы метаданных. ## Как работает 1. Точка входа принимает torrent/magnet + контекст (HTTP API, веб-UI или Telegram-бот). 2. Загрузка ставится в qBittorrent в выделенную категорию. 3. Сервис отслеживает завершение загрузки. 4. По именам файлов, контексту и (опц.) базам метаданных определяется фильм/сериал и нужная раскладка. 5. Файлы **хардлинкаются** в библиотеку Jellyfin — источник остаётся в раздаче, место на диске не дублируется. При высокой уверенности раскладка выполняется автоматически, иначе — уходит на подтверждение человеку. ## Статус Ранняя разработка. Готовы каркас (Ф0) и приём + трекинг (Ф1): добавление magnet в qBittorrent, идемпотентность по infohash, поллинг завершения и машина состояний (`downloading → completed`, плюс stuck/failed); наружу — REST API, веб-UI и `jellybit add`. Источники кроме magnet (.torrent/url) и распознавание (Ф2) — дальше. См. [дорожную карту](docs/drafts/roadmap.md). ## Документация - [docs/specs/](docs/specs/) — спецификации: целевое устройство системы. Начать с [architecture.md](docs/specs/architecture.md). - [docs/adr/](docs/adr/) — журнал архитектурных решений (почему так). - [docs/drafts/](docs/drafts/) — черновики: планы, идеи, нерешённое. ## Стек Go (один статический бинарь), SQLite (`modernc.org/sqlite` + `sqlx`, миграции `goose`), HTTP — `chi` + `html/template` + htmx, конфигурация — TOML, логи — структурированный JSON (`slog`). Подробнее — в [architecture.md](docs/specs/architecture.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 --dry-run [--context "..."] --config ./config.toml ``` Берёт торрент из qBittorrent по infohash, прогоняет распознавание (LLM + метабазы) и печатает план: тип/название/год, матч в базе, решение авто/review и превью целевых путей — то, что создалось бы при Apply. ## Доставка Сборка здесь → готовый бинарь копируется на медиа-сервер umbar (`/home/av/projects/private/umbar`). Деплой-обвязка живёт в umbar. Артефакты этого репозитория: статический бинарь (`task build`) и `Dockerfile` (упаковка в `distroless/static`). Образ собирается **на сервере** из доставленного бинаря — Go-тулчейн на сервере не нужен. В distroless нет shell/curl, поэтому HEALTHCHECK зовёт сам бинарь: `jellybit healthcheck` (GET `/healthz` по порту из конфига, exit 0/1). Деплой одной командой из umbar (собирает бинарь локально, доставляет, строит образ на сервере, рендерит конфиг с секретами из vault, поднимает compose): ```sh inv pl -- jellybit # umbar/playbook-jellybit.yml ``` Контейнер: `user 1000:1000`, порт `8080` на хост, mount `/srv/media` (единая песочница для хардлинков) + data-том с `config.toml`/SQLite, к qBittorrent — через `host.docker.internal`.