61 KiB
Executable File
title, created, updated, type, namespace, tags, related
| title | created | updated | type | namespace | tags | related | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Arr Stack — Kraken | 2026-05-23 | 2026-09-22 | tech | family |
|
Arr Stack — Kraken
Pipeline
Prowlarr → Radarr + Sonarr → Transmission → Jellyfin
↓
router.py (cron 10min)
↓
symlinks → /media/{movies,cartoons,series,documentaries,...}/
Два параллельных пути поступления контента:
- Radarr/Sonarr → качают в
/media/movies-radarr/и/media/series-sonarr/ - Transmission (ручные торренты) →
on-download-complete.sh→sync.py→/media/{movies,cartoons,...}/
router.py — жанровая маршрутизация
router.py читает NFO-файлы (которые Radarr/Sonarr создают при загрузке), определяет жанр и возрастной рейтинг, и создаёт symlink в нужную Jellyfin-библиотеку:
| Источник | Условие | Цель |
|---|---|---|
| movies-radarr/ | Documentary | /media/documentaries/ |
| movies-radarr/ | Animation + !R/18+ | /media/cartoons/ |
| movies-radarr/ | всё остальное | /media/movies/ |
| series-sonarr/ | Documentary | /media/documentaries-series/ |
| series-sonarr/ | Animation + !TV-MA | /media/cartoons-series/ |
| series-sonarr/ | всё остальное | /media/series/ |
Расположение: /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/docker/media-pipeline/router.py
Запуск: python3 router.py --dry-run (проверка) / python3 router.py --apply (исполнение)
media-router.sh — cron-скрипт для Telegram-уведомлений
Обёртка над router.py, которая:
- запускает
router.py --apply - если
Nothing to do— SILENT, ничего не шлёт - если созданы symlink'и или ошибка — отправляет отчёт в Telegram Kraken
Расположение: рядом с router.py — media-router.sh
Cron (Kraken crontab): каждые 10 минут
Telegram: kraken_htpc_bot → чат @mallex87
sync.py — обработка ручных торрентов (Transmission)
sync.py работает внутри Transmission-контейнера. При завершении загрузки:
- Определяет название через TMDB API
- Определяет жанр
- Перемещает файл в
/media/{movies,cartoons,series,documentaries}/ - Обновляет
downloadDirв Transmission через RPC
Расположение: /srv/.../docker/media-pipeline/sync.py
Триггер: on-download-complete.sh (смонтирован в Transmission как /config/on-download-complete.sh:ro)
Transmission
- download-dir:
/downloads(безcomplete) - incomplete-dir:
/downloads/incomplete - Язык: отключён auth для локальных
- RPC:
localhost:9091
При перемещении файлов для уже завершённых торрентов:
- Переименовать файл/папку под кейс торрента (Linux ext4 case-sensitive)
- Вызвать
torrent-set-locationсmove=false - Запустить торрент на сидирование
Cron'ы на Kraken (crontab)
✅ Watchlist-крон ВОССТАНОВЛЕН 2026-09-20 21:21 (был мёртв с 2026-06-20). Бэкап ~/crontab-backup-20260920-212155.txt. Детали и разбор — в family/projects/watchlist-automation.
Актуальное crontab -l юзера kraken (проверено 2026-09-22):
0 * * * * bash ~/scripts/sync-vault.sh # Obsidian sync
0 * * * * pgs-to-srt.sh /media/downloads/complete # PGS→SRT новые
0 3 * * * pgs-to-srt.sh /media # PGS→SRT вся библиотека
0 2 * * * bash ~/scripts/watchlist-cleanup.sh --apply # cleanup просмотренного
0 1 * * * bash ~/scripts/watchlist-nightly.sh # watchlist nightly (БЕЗ sync-down)
0 9 * * 0 bash ~/scripts/watchlist-discover.sh # watchlist discover
30 2 * * * bash ~/scripts/watchlist-catalog.sh # JSON-каталог для Lampa ← НОВЫЙ 2026-09-22
🔴 *watchlist-catalog.sh (30 2 * * ) — генерация watchlist.json для модуля Catalog
в Lampa + маркера ❓. Порядок намеренный: nightly 01:00 → cleanup 02:00 → catalog 02:30.
Детали: personal/tech/lampac-deployment, разбор генератора —
personal/plans/watchlist-tmdb-missing-marker.
⚠️ media-router.sh (роутер symlink'ов, каждые 10 мин) в crontab ОТСУТСТВУЕТ. В таблице «Два параллельных пути» выше он описан как работающий по cron 10min — фактически его там нет. Проверить, нужен ли: без него symlink'и в /media/{movies,cartoons,...}/ не создаются автоматически.
Точная проверка наличия любого крон-джоба (не верить доке, смотреть систему):
crontab -l # юзер kraken
sudo crontab -l # root
sudo ls -la /var/spool/cron/crontabs/ # все юзерские
sudo grep -rl watchlist /var/spool/cron/ /etc/cron.d/ /etc/crontab
systemctl --user list-timers --all ; systemctl list-timers --all | grep -i watchlist
systemctl is-active cron # демон жив?
Установка крон-джоба безопасно (с бэкапом):
crontab -l > ~/crontab-backup-$(date +%Y%m%d-%H%M%S).txt
cp ~/crontab-backup-*.txt /tmp/crontab-new.txt
# дописать строки в /tmp/crontab-new.txt
crontab /tmp/crontab-new.txt
crontab -l # проверка
grep -c watchlist /var/spool/cron/crontabs/kraken # демон подхватил?
API Keys
| Service | API Key |
|---|---|
| Radarr | cbcb8ec3... |
| Sonarr | 15fbec32... |
| Prowlarr | 134ac38a... |
(Full keys truncated — retrieve from each service's settings page.)
Качество загрузки для НОВЫХ фильмов/сериалов (2026-09-04)
watchlist-sync (автодобавление из watchlist) использует профиль WEB-4K (no remux) (Radarr id 7, Sonarr id 7) вместо бывшего Any/id=1.
Что разрешает профиль (в порядке предпочтения, кодированные, БЕЗ remux/BR-DISK):
- 2160p: HDTV / WEBDL / WEBRip / BluRay-2160p (кодир.)
- fallback 1080p: HDTV / WEBDL / WEBRip / BluRay-1080p (кодир.)
- fallback 720p: HDTV / WEBDL / WEBRip / BluRay-720p (кодир.)
- Запрещены: Remux-1080p, Remux-2160p, BR-DISK, Raw-HD, SDTV/DVD/480/576.
- cutoff = Bluray-2160p (кодир.); upgrade выключен после скачивания.
Где менять: watchlist-sync/watchlist_sync/arr.py строки qualityProfileId: 7 (radarr_add ~L77, sonarr_add ~L112). НЕ редактировать профили вручную иначе watchlist-sync надо обновить на новый id. Создать/править профиль «WEB-4K (no remux)» — Radarr/Sonarr → Settings → Quality Profiles.
✅ Профиль подтверждён в бою (2026-09-20): первый же фильм, добавленный через обновлённый arr.py (Gladiator 2000), взял релиз UHD BDRip [H.265/2160p] [4K] — то есть 4K, но кодированный BDRip, БЕЗ Remux. Профиль фильтрует корректно, цель (4K без 60GB-ремьюксов) достигнута.
Подтверждение через API (рабочие вызовы):
# список профилей Sonarr (проверить что id=7 существует)
curl -s "http://localhost:8989/sonarr/api/v3/qualityprofile" -H "X-Api-Key: $SONARR_KEY"
# корневые папки (проверить /media/series-sonarr и freeSpace)
curl -s "http://localhost:8989/sonarr/api/v3/rootfolder" -H "X-Api-Key: $SONARR_KEY"
📁 Актуальные пути контейнеров (проверено 2026-09-20)
Пути на дисках легко перепутать — два HDD с разными UUID. Точные значения через docker inspect:
| Сервис | Хост-путь конфига |
|---|---|
| Radarr | /srv/dev-disk-by-uuid-6194539b-.../docker/radarr/config/ (внутри config.xml с ApiKey) |
| Transmission | /srv/dev-disk-by-uuid-6194539b-.../docker/transmission/ → /config (внутри settings.json) |
| Медиа (общая) | /srv/dev-disk-by-uuid-49e8f586-.../media/ → /media и /downloads |
⚠️ НЕ /srv/...49e8f586.../docker/transmission/config/settings.json — такого файла нет. Transmission на 6194539b, Radarr-конфиг тоже на 6194539b (в подпапке config/, не в корне radarr). Проверять через:
docker inspect radarr --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}'
docker inspect transmission --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}'
Чтение ApiKey Radarr: grep -oP '(?<=<ApiKey>)[^<]+' /srv/...6194539b.../docker/radarr/config/config.xml
Transmission RPC: docker exec transmission transmission-remote --list (без -n работает, rpc-username пустой)
Ports (Docker network media_net)
All services in the shared external network media_net — доступны друг другу по имени контейнера (radarr:7878, prowlarr:9696, transmission:9091, flaresolverr:8191) и с хоста по kraken:<port>:
| Service | Port |
|---|---|
| Radarr | 7878 |
| Sonarr | 8989 |
| Prowlarr | 9696 |
| Transmission | 9091 |
| Jellyfin | 8096 |
| FlareSolverr | 8191 |
Сеть (проверено 2026-09-20): radarr, sonarr, prowlarr, transmission, flaresolverr — все в media_net. Пересечение сетей (radarr и transmission дополнительно ещё в docker_default) — нормально, роутинг по media_net.
Порядок починки, если контейнер выпал из сети: sudo docker network connect media_net <container> (обратимо, без пересоздания) либо docker compose up -d из каталога сервиса.
Jellyfin библиотеки
| Библиотека | Тип | Путь |
|---|---|---|
| Movies | movies | /media/movies |
| Series | tvshows | /media/series |
| Cartoons | movies | /media/cartoons |
| Cartoon Series | tvshows | /media/cartoons-series |
| Documentaries | movies | /media/documentaries |
| Documentary Series | tvshows | /media/documentaries-series |
movies-radarrиseries-sonarrНЕ добавлены в Jellyfin — router.py создаёт symlink'и из них в перечисленные пути.
Индексера Prowlarr — диагностика и починка (2026-09-20)
✅ Задача закрыта в тот же день. Ниже — история диагностики (полезна как метод), а актуальное решение с командами — в секции «🔴 Индексера Prowlarr — починка Cloudflare (2026-09-20)». Итог: было 3 «красных» из 6, стало 6/6 рабочих. Radarr 4/4, Sonarr 5/5 зелёные.
Запрос Alex: «что с torrent трекерами в arr, красные». Диагноз снят по логам Prowlarr, не по теории.
Что показывал UI на момент диагностики
| id | Индексер | privacy | Было | Стало |
|---|---|---|---|---|
| 1 | RuTracker | semiPrivate | ❌ красный (Cloudflare) | ✅ 48 результатов на «matrix» |
| 5 | Kinozal | semiPrivate | ❌ красный (Cloudflare) | ✅ 50 |
| 6 | Kinozal (M) | semiPrivate | ❌ красный (Cloudflare) | ✅ 50 |
| 2 | RuTor | public | ✅ 100 | ✅ 100 |
| 4 | NoNaMe Club | public | ✅ 50 | ✅ 50 |
| 3 | Byrutor | public | ✅ 6 | ✅ 6 |
Root cause #1 — Cloudflare (RuTracker + Kinozal + Kinozal (M))
Из /srv/.../docker/prowlarr/config/logs/prowlarr.debug.txt:
Warn|IndexerHttpClient|HTTP Error - Res: HTTP/2.0 [POST] https://rutracker.org/forum/login.php: 403.Forbidden (5620 bytes)
<title>Just a moment...</title> ... challenges.cloudflare.com ... cType: 'managed'
Warn|RuTracker|RuTracker HTTP request failed: [403:Forbidden] [POST] at [https://rutracker.org/forum/login.php]
at NzbDrone.Core.Indexers.Definitions.RuTracker.DoLogin() in ./NzbDrone.Core/Indexers/Definitions/RuTracker.cs:line 103
Error|Cardigann|Cloudflare protection detected for [Kinozal], Flaresolverr may be required.
Error|Cardigann|Cloudflare protection detected for [Kinozal (M)], Flaresolverr may be required.
Debug|IndexerFactory|Temporarily ignoring indexer RuTracker till 09/21/2026 17:30:42 due to recent failures.
- RuTracker: CF managed Turnstile на
/forum/login.php→ Prowlarr не может залогиниться (нужен JS-челлендж). Аккаунт при этом может быть жив — падает именно логин. - Kinozal / Kinozal (M): kinozal.me тоже за Cloudflare, Prowlarr сам пишет «Flaresolverr may be required».
- Лечится FlareSolverr-прокси (см. решение). На момент диагностики версия была v2.5.2.5491.
Root cause #2 — Docker network split (Radarr полностью без индексеров)
radarr: docker_default 172.22.0.3 ← НЕ видел prowlarr
sonarr: media_net 172.23.0.2
prowlarr: media_net 172.23.0.3
transmission: docker_default 172.22.0.2 ← НЕ был виден сонаром
Radarr POST /api/v3/indexer/testall → все 4 индексера false:
Unable to connect to indexer... Name does not resolve (prowlarr:9696)
Вывод: Radarr был красный не из-за трекеров, а из-за сети. У Sonarr красные = реальные трекеры (CF).
Ключевой урок: compose-файлы уже содержали media_net, но контейнеры остались в старой сети — проверять фактическое docker inspect, а не compose-файл.
⚠️ Питфолл: POST /api/v3/indexer/test по одному id НЕ работает
{"indexerId": N} на Radarr/Sonarr/Prowlarr возвращает HTTP 400 со списком validationFailures: 'Name' must not be empty, 'Implementation' must not be empty, 'ConfigContract' must not be empty, 'App Profile Id' must be greater than '0', 'Priority' must be between 1 and 50. То есть эндпоинт валидирует тело как новый индексер, а не берёт существующий по id.
Рабочий способ тестирования — testall:
# Radarr
curl -s -X POST -H "X-Api-Key: $RKEY" \
"http://localhost:7878/radarr/api/v3/indexer/testall" \
| jq -r '.[] | "\(.id)\t\(.isValid)\t\(.validationFailures[0].errorMessage // "")"'
# Sonarr (UrlBase /sonarr)
curl -s -X POST -H "X-Api-Key: $SKEY" \
"http://localhost:8989/sonarr/api/v3/indexer/testall" \
| jq -r '.[] | "\(.id)\t\(.isValid)\t\(.validationFailures[0].errorMessage // "")"'
# Prowlarr: тест одного индексера требует полного объекта из GET, не {indexerId}
# Быстрая проверка «кто живой» — сразу поиском:
curl -s -H "X-Api-Key: $PKEY" "http://localhost:9696/prowlarr/api/v1/search?query=matrix&type=search" \
| jq -r 'group_by(.indexer)[] | "\(.[0].indexer): \(length)"'
Поиск через Prowlarr полезнее теста индексеров: ?query=X&type=search по умолчанию возвращает до 100 результатов на индексер (был соблазн прочитать «156 всего» как «по 26 на каждый» — неверно; смотреть group_by(.indexer)).
Итог и уроки
Все три причины были независимы и требовали независимых фиксов:
- Сеть —
docker network connect media_net radarr|transmission(обратимо, без пересоздания контейнеров). - FlareSolverr не применялся — нужен одинаковый tag на прокси И на индексере (главная засада: при
tags=[]молча не работает). - Блокировки в
IndexerStatus— рестарт контейнера их НЕ сбрасывает, чистить черезsqlite3между stop/start.
Плюс побочно: RuTor не фильтрует по категориям → ему нужна категория 8000(Other), не 5000.
⚠️ Безопасность: FlareSolverr на LOG_LEVEL=info пишет логин и пароль RuTracker в plaintext в свои логи. Обязательно warning.
Известные проблемы
🔴 2026-09-22: авто-закачка УБРАНА ПОЛНОСТЬЮ
Требование Alex: закачек быть не должно. Сделано:
sync-downвырезан из крона.watchlist-nightly.shстр. 32-36 — вызов закомментирован, вместо негоlog "sync-down: ПРОПУЩЕН (автозакачка отключена 2026-09-22)". Бэкапwatchlist-nightly.sh.bak-20260922-182655. Кодsync_down.pyНЕ удалён — можно запустить вручную.- 16 авто-закачек удалены из Radarr (все с
added >= 2026-09-20) через API сdeleteFiles=true— без этого параметра файл остаётся на диске сиротой. 50 → 34 фильма, 12 с файлами, ошибок 0. Дамп для отката:/tmp/radarr-sonarr-dump-20260922-184351/radarr-movies.json. - Sonarr не тронут — 13 сериалов, авто-закачек там не было.
- Все 34 фильма
monitored=false— Radarr не будет ничего докачивать.
⚠️ Порядок при удалении закачки критичен: сначала PUT monitored=false, потом
DELETE с deleteFiles=true. Иначе Radarr скачает заново.
Ранее: инцидент переполнения диска (2026-09-21, устранён)
Три страховки sync-down (введены 2026-09-21, коммиты 2642882, a131208)
Читать перед любой правкой sync_down.py / watchlist-nightly.sh:
| Страховка | Где | Значение | Поведение |
|---|---|---|---|
| Проверка места | sync_down.py |
MIN_FREE_GB = 100.0 |
free < 100 GiB → [STOP], ничего не очередь |
| Фильтр ужасов | sync_down.py:95 |
candidate.is_horror() |
ужас без ⭐ → [🧟] skipped |
| Приоритет | sync_down.py |
⭐ (U+2B50) |
обходит и рейтинг, и ужасы |
| Рейтинг | sync_down.py |
MIN_RATING = 6.0 |
ниже → [−] skipped |
| Батч | watchlist-nightly.sh |
--batch 2 |
было 5 |
⚠️ Проверка места — через shutil.disk_usage, НЕ df (df учитывает root-резерв
ext4 и завышает заполнение на ~4%). Путь из env WATCHLIST_MEDIA_ROOT, иначе — родитель
watchlist-файла.
⚠️ ⭐ (U+2B50) ≠ ✭ (U+272D). ✭ — декоративная звёздочка в конце названия,
срезается _clean() и приоритетом НЕ является. Не путать при чтении списка.
Фильтр ужасов работает по ЖАНРУ (TMDB id 27), не по эмодзи. В dry-run отсекается
33 записи, хотя эмодзи 🧟♀️ стоит на 41 строке — жанр надёжнее ручной метки. Решение
Alex: ожидаемое поведение; если фильм нужен — ставить ⭐.
mark_queued / unmark_queued — надёжность (те же коммиты)
parser.py: mark_queued возвращает bool, поглощает эмодзи-префикс
(🧟♀️, 🗓️, ⭐, ✭, ⬇️…) и ставит метку перед ним:
- [ ] ⬇️ 🧟♀️ midsommar 2019. Добавлена unmark_queued (её не было).
sync_down._mark() логирует [!] could not write ⬇️ marker при промахе — раньше
функция молча ничего не делала, и фильмы попадали в Radarr без метки.
⚠️ Правило для будущих правок: любая функция, мутирующая файл, должна возвращать результат, а вызывающий — его проверять. Молчаливый провал regex = тихая потеря данных.
_clean — эмодзи и год (коммит a131208)
-
_EMOJI_PREFIX:^(?:[chars]+\s*)+— повторяющиеся группы. Старая форма^[chars]+\s*брала только первый эмодзи, и🧟♀️оставался внутриtitle(уходил в TMDB и Radarr). -
Год:
\(\d{4}(?:/\d{4})*\)—*, не+. С+одиночный(2022)не срезался. Пара(1995/2003)отmark_year_ambiguousобрабатывается так же. -
sync_up._mark_watched: учитывает эмодзи-префикс по обе стороны⬇️, сохраняет его. -
⚠️ 2026-09-20: compose-файл может ВРАТЬ про сеть. Ранее в compose Radarr был указан
jellyfin_default, а реально контейнер жил вdocker_default; при починке выяснилось, что compose уже писалmedia_net, но контейнеры не были пересозданы. Всегда проверять фактическоеdocker inspect -f '{{range $k,$v := .NetworkSettings.Networks}}{{$k}} {{end}}' <container>, а не docker-compose.yml. -
17 фильмов в Radarr
hasFile=False— ждут подходящего релиза в Prowlarr. Scream (1996) в процессе загрузки. -
Prowlarr — если долго не находит релизы, проверить статус индексеров (
/api/v1/health). ⚠️ health врёт, реальную причину блокировки смотреть вconfig/logs/prowlarr.debug.txt— см. секцию «🔴 Индексера Prowlarr — починка Cloudflare (2026-09-20)» ниже. -
✅ 2026-09-20: все индексера Prowlarr починены (6/6), Radarr 4/4 и Sonarr 5/5 зелёные. Причины были: сеть (
docker_defaultвместоmedia_net), непривязанный tag у FlareSolverr-прокси, и блокировки вIndexerStatus. Детали и команды — в секции ниже. -
🔴 2026-09-24: РЕЦИДИВ — «6/6» больше не действует. RuTracker (1), Kinozal (5), Kinozal (M) (6) снова заблокированы,
EscalationLevel=9,disabledTill=2026-09-25T10:17Z— то есть сутки. Первопричина не Cloudflare и не теги (они на месте), а FlareSolverr в crash-loop: Chrome не поднимается под chromedriver (session not created: cannot connect to chrome at 127.0.0.1:PORT), HTTP:8191не отвечает. Симптом в UI:error IndexerProxyStatusCheck: All indexer proxies are unavailable due to failures. Диагноз и незавершённый фикс (shm_size: 1gb+ снятиеIndexerStatus): personal/tech/prowlarr-flaresolverr-cloudflare §«2026-09-24». ⚠️ НиGET /api/v1/health, ни/api/v1/indexerstatusпустотой не отделались — на этот раз они показали блокировки; но авторитет всё равно заprowlarr.debug.txtи таблицейIndexerStatus. -
🔴 2026-09-24: swap на Кра́кене может быть МЁРТВ.
/proc/swapsпуст при живом/var/swap(512 MB),dphys-swapfileне поднимает его автоматически, строки в/etc/fstabнет. Лечение:sudo swapon /var/swap(⚠️swapoff -a && swapon -aдаётSwapFree: 0 kB). Без swap Chrome-контейнеры падают при пике старта. Проверка:cat /proc/swaps. -
🔴 2026-09-04: 4K UHD Remux при Direct Play подтормаживает на ТВ (webOS). Симптом у
Неистовый (Unhinged 2020)— 60.9GB...Remux.2160p.mkvavg ~99 Мбит/с. После фикса eth0 Kraken → 1G (был 100M, см. kraken-network) торможение сохранилось. Подтверждено по логу Jellyfinlog_20260904.log: сессия 10:18→10:28 «Jellyfin for WebOS 1.2.2», Stop at 400916ms (~6:40), ни одной строки transcode → это Direct Play, не CPU-рендер субтитров. -
🔴🔴 2026-09-04 (вживую): тормозит Direct Play даже лёгкого 4K → пока шло по Wi-Fi, причина не сервер/диск. В живом воспроизведении по Wi-Fi
Project Hail Mary (2026)(...2160p.iT.WEB-DL...mkv, HEVC Main10 4K HDR10+, avg ~24.5-25.7 Мбит/с, 30.2GB, Direct Play) подёргивание было, при этом: транскода нет (0 ffmpeg, CPU Kraken load 0.1), сервер отдаёт всего ~21 Мбит/с, Wi-Fi ТВ «чист» по MAC-счётчикам (0 CRC/0 retries, -53 dBm), линки с запасом ×10+. -
✅ 2026-09-04 РАЗРЕШЕНИЕ (проверено пользователем вживую): после двух правок — (1) eth0 Kraken возвращён на 1G (замена патч-корда) и (2) ТВ переведён на проводной Ethernet (100M downshift-линк) — и
Unhinged(remux, ~89 Мбит/с), иProject Hail Mary(лёгкий 4K) идут без тормозов. Вывод: причиной были НЕ пропускная способность и НЕ декодер-клиента, а нестабильный Wi-Fi-линк последней мили ТВ (даже при чистых MAC-счётчиках — джиттер/переупорядочивание в зашумлённом эфире). Провод (даже 100M) стабильно отдаёт. ПрофильWEB-4K (no remux)остаётся разумной страховкой, но не был обязательной причиной тормозов.
Radarr Quality Profiles на Kraken (проверено 2026-09-04)
Via http://kraken:7878/radarr/api/v3/qualityprofile (X-Api-Key из config.xml; UrlBase=/radarr). Linuxserver image, сеть media_net (с 2026-09-20; ранее ошибочно жил в docker_default). Версия — см. таблицу актуальных версий ниже.
| id | Профиль | Разрешённые качества | Cutoff |
|---|---|---|---|
| 1 | Any | весь диапазон CAM..BR-DISK, вкл. все 2160p | Remux-1080p |
| 2 | SD | до Bluray-576p | — |
| 3 | HD-720p | до Bluray-720p | — |
| 4 | HD-1080p | HDTV/Bluray/Remux-1080p | Bluray-1080p |
| 5 | Ultra-HD | HDTV/Bluray/Remux-2160p (BR-DISK не allowed) | Remux-2160p |
| 6 | HD-720p/1080p | 1080p и ниже | — |
| 7 | WEB-4K (no remux) ✅ создан | кодир. HDTV/WEB/BluRay 2160p+1080p+720p | Bluray-2160p (кодир.) |
| 8 | (если появится из id авто-инкремента — перепроверить) | — | — |
Профиль id=7 разрешает код HDTV/WEBDL/WEBRip/BluRay в 2160/1080/720; запрещает Remux-1080p, Remux-2160p, BR-DISK, Raw-HD, SDTV/DVD/480/576. upgrade выключен. Sonarr: аналогичный профиль тоже id=7.
- Корень «почему новые качаются в любой жир»:
watchlist-sync(который добавляет фильмы/сериалы из watchlist в Radarr/Sonarr) жёстко прописывает"qualityProfileId": 1(= профильAny) вarr.py:- Реальный путь репо:
/srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/watchlist-sync(НЕ~/Developer/watchlist-sync, хотя симлинк~/Developer/watchlist-sync→.../49e8.../watchlist-syncесть; 49e8 — симлинк на 6194). watchlist_sync/arr.py→radarr_add()(~стр 77) иsonarr_add()(~стр 112), обе"qualityProfileId": 1. Radarr POST/api/v3/moviecaddOptions.searchForMovie:true; Sonarr POST/api/v3/series.
- Реальный путь репо:
- ✅ Решение принято и применено (см. выше): профиль
WEB-4K (no remux)(Radarr/Sonarr id 7), fallback 1080→720, remux запрещён. Применено 2026-09-04. - ✅ 2026-09-04: стратегия качества РЕШЕНА И ПРИМЕНЕНА. Новые фильмы/сериалы (через watchlist-sync) добавляются с профилем
WEB-4K (no remux)(Radarr id 7, Sonarr id 7) — см. секцию «Качество загрузки для НОВЫХ». Fallback: если нет 2160p-кодированного — 1080p → 720p; remux не берётся никогда. Было принято так (fallback=1080, если нет — 720). Существующие файлы НЕ трогаются.
Реальный состав жирного remux (пример Unhinged, ffprobe 2026-09-04)
Важно для понимания «что даёт remux» перед выбором профиля. Файл Неистовый.2020.UHD.Blu-Ray.Remux.2160p.mkv = 60.9GB, 1:31:05, контейнер 89.17 Мбит/с средний.
FFprobe потоки:
| idx | тип | кодек | каналы | язык / роль |
|---|---|---|---|---|
| 0 | video | HEVC Main10, 3840×2160, 24fps | — | HDR10 (BT.2020, PQ smpte2084) |
| 1 | audio | AC3 | 5.1(side) 384k | rus «Dub, iTunes» |
| 2 | audio | DTS-HD MA | 7.1 | rus «Д. Есарев» |
| 3 | audio | TrueHD | 7.1 | eng |
| 4 | audio | AC3 | 5.1 640k | eng |
| 5 | audio | DTS | stereo 320k | eng Commentary (реж. Деррик Борте) |
| 6-8 | sub | SRT/SPU | — | rus / eng full / eng SDH |
Вывод: размер 60GB раздувает НЕ видео (HDR10 HEVC-часть типичная), а множество звуковых дорожек (lossless DTS-HD MA + TrueHD) + аудиокомментарий. «Что даёт remux» на бытовом ТВ: видео-выигрыш против аккуратного 4K-рипа почти незаметен с дивана; бонус реализуется только при lossless-прокачке звука (AVR/eARC). Если ТВ играет через собственные динамики/стерео или делает audio-transcode — плюс remux теряется, а вес/сеть/лаг остаются. Это аргумент за профиль «2160p без Remux» для бытового просмотра на webOS-TB.
Бенчмарк WEB-4K (замерено по библиотеке Kraken, 2026-09-04)
«Поддерживаемое качество» для сравнения с жирным remux — это кодированные 2160p. Замер файлов с WEB+2160 в имени в /media:
- Полнометражки (2ч):
Project Hail Mary28.1GB,The Drama19.2GB,The Crow17.4GB,They Will Kill You17.2GB,Кот в сапогах19.9GB → range 17–28GB, медиана ~19GB. - 45-50 мин эпизоды док-сериалов (
prehistoric.planets01): ~7.2–7.7GB каждый. - Статсводка по всем 10 файлам: min 7.2 / median 12.5 / mean 13.9 / max 28.1 GB. Средний битрейт ~20–40 Мбит/с.
- Практичный floor benchmark: «нормальная» копия 4K для этого ТВ ≈ 17–28GB/фильм (в 2.5–3× меньше remux). ⚠️ ⚠️ Важно: подёргивание 4K Direct Play (и лёгкого, и remux) было вызвано Wi-Fi-линком последней мили ТВ — по проводу оба идут (см. «РАЗРЕШЕНИЕ» в «Известные проблемы»). Напротив клиента webOS не виноват.
🔴 Индексера Prowlarr — починка Cloudflare (2026-09-20)
Итог: было 3 «красных» из 6, стало 6/6 рабочих. Radarr 4/4, Sonarr 5/5 зелёные.
Симптом
Radarr: error IndexerLongTermStatusCheck — «All indexers are unavailable due to failures for more than 6 hours».
Sonarr: error DownloadClientCheck — «Unable to communicate with Transmission. Name does not resolve (transmission:9091)».
В UI Prowlarr индексера RuTracker / Kinozal / Kinozal (M) показывались красными.
Три независимые причины (все три надо было починить)
(1) Сеть — Radarr и Transmission в неправильной сети.
Compose-файлы УЖЕ были прописаны на media_net, но живые контейнеры остались в docker_default (compose обновили, контейнеры не пересоздали). Итог: Radarr не резолвит prowlarr:9696 → все индексеры false; Sonarr не резолвит transmission:9091.
sudo docker network connect media_net radarr
sudo docker network connect media_net transmission
# проверка: docker exec radarr getent hosts prowlarr
# docker exec sonarr curl -sw "%{http_code}" http://transmission:9091/transmission/rpc → 409 = связь есть (штатный CSRF-ответ)
(2) FlareSolverr-прокси в Prowlarr не применялся (главный баг).
Контейнер flaresolverr был жив, запись прокси создана (id=1), но в логе Prowlarr — прямой 403 login.php, а FlareSolverr вообще не вызывался.
Причина: в Prowlarr v2.x прокси применяется к индексерам ТОЛЬКО если у прокси И у индексера стоит одинаковый tag. При tags=[] с обеих сторон прокси молча НЕ применяется, никакой ошибки в UI нет.
KEY=$(grep -oP "(?<=<ApiKey>)[^<]+" .../docker/prowlarr/config/config.xml)
# 1. создать тег
curl -X POST -H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
-d '{"label":"flaresolverr"}' http://localhost:9696/prowlarr/api/v1/tag
# 2. повесить tag на ПРОКСИ
curl -s -H "X-Api-Key: $KEY" http://localhost:9696/prowlarr/api/v1/indexerproxy/1 | jq ".tags=[1]" > /tmp/p.json
curl -X PUT -H "X-Api-Key: $KEY" -H "Content-Type: application/json" -d @/tmp/p.json \
http://localhost:9696/prowlarr/api/v1/indexerproxy/1
# 3. повесить ТОТ ЖЕ tag на индексера (RuTracker=1, Kinozal=5, Kinozal M=6)
curl -s -H "X-Api-Key: $KEY" http://localhost:9696/prowlarr/api/v1/indexer/1 | jq ".tags=[1]" > /tmp/i.json
curl -X PUT -H "X-Api-Key: $KEY" -H "Content-Type: application/json" -d @/tmp/i.json \
http://localhost:9696/prowlarr/api/v1/indexer/1
Пруф работы — только лог FlareSolverr, не UI:
sudo docker logs --tail 30 flaresolverr
# → Challenge detected. Title found: Just a moment...
# → Challenge solved!
Проверка поиска: curl "http://localhost:9696/prowlarr/1/api?t=search&q=matrix&apikey=$KEY" → RuTracker 48 items, Kinozal 50, Kinozal M 50, RuTor 100, NoNaMe 50.
(3) Блокировки индексера в БД — рестарт их НЕ сбрасывает.
Prowlarr сам выключает упавший индексер на 24ч: Temporarily ignoring indexer X till +24h. В health API и /api/v1/indexerstatus это НЕ видно (оба возвращают пусто, врут) — только в debug-логе. Состояние лежит в таблице IndexerStatus в prowlarr.db.
sudo docker stop prowlarr
sqlite3 /srv/.../docker/prowlarr/config/prowlarr.db "DELETE FROM IndexerStatus WHERE ProviderId IN (1,5,6);"
sudo docker start prowlarr
⚠️ В контейнерах sqlite3 НЕТ; на хосте Kraken /usr/bin/sqlite3 ЕСТЬ.
Побочно: RuTor не фильтрует по категориям. У него в caps заявлены 2000(Movies)/5000(TV)/8000(Other), но при передаче cat=5000 он возвращает 0 результатов, а без cat — 100. Prowlarr сам подсказывает в полях индексера: «RuTor does not return categories in its search results. To sync to your apps, include 8000(Other)». Поэтому в Sonarr (indexer id=8) категория RuTor переставлена 5000 → 8000.
Версии и сервис
- Prowlarr обновлён 2.5.2.5491 → 2.6.5.5623 (в 2.5.2 прокси-модель ещё только вводилась).
- FlareSolverr
ghcr.io/flaresolverr/flaresolverr:latestv3.5.2, порт 8191, сетьmedia_net, envPROWLARR__FLARESOLVERR_URL=http://flaresolverr:8191. - ⚠️ FlareSolverr
LOG_LEVELпониженinfo→warning: на levelinfoFlareSolverr пишетpostDataзапросов в лог, т.е. логин и пароль RuTracker в plaintext. После понижения — лог пуст, пароль не пишется.
Бэкапы (перед изменениями)
/home/kraken/arr-fix-backup-20260920/ — networks.txt, 4× docker inspect, 3 compose-файла, prowlarr.db.bak, prowlarr-config-preupgrade.tar.gz.
Диагностические грабли
POST /api/v3/indexer/testс телом{"indexerId":N}→ HTTP 400 (валидирует как НОВЫЙ индексер, требует Name/Implementation). Для теста всех сразу:POST /api/v3/indexer/testall.GET /api/v1/healthв Prowlarr и/api/v1/indexerstatusНЕ показывают причины блокировки. Смотреть.../docker/prowlarr/config/logs/prowlarr.debug.txt(grep по имени индексера иCloudflare/403).
Sonarr sonarr_add() не проверяет дубли → 400 SeriesExistsValidator (2026-09-20)
Симптом: при sync-down для уже существующей серии в логе появляется шум:
[!] 'Волшебный участок' — error: Client error '400 Bad Request' for url
'http://localhost:8989/sonarr/api/v3/series?apikey=...'
Причина (безобидная): серия уже есть в Sonarr. Тело ответа:
[{"propertyName":"TvdbId","errorMessage":"This series has already been added",
"attemptedValue":442038,"errorCode":"SeriesExistsValidator"}]
«Волшебный участок» → TVDB Magical Police Department (tvdbId=442038).
Корень: watchlist_sync/arr.py::sonarr_add() шлёт POST /api/v3/series без pre-check, в отличие от radarr_add(), где есть radarr_exists(). Sonarr отвечает ошибкой валидатора, sync_down ловит её как исключение и печатает [!], не помечая позицию ⬇️.
Следствие: позиция остаётся [ ] и будет заново пытаться добавиться на каждом прогоне, каждый раз занимая слот батча и не помечаясь.
Починка (не сделана): добавить проверку по tvdbId перед POST — как в Radarr. Реэкспорт series/lookup в Sonarr дубли не отсекает, проверять надо по библиотеке:
GET /api/v3/series → сверить tvdbId
Обновление Radarr / Sonarr (2026-09-20)
Watchtower их не обновлял (см. family/how-to/kraken-watchtower), поэтому обновлено вручную: Radarr 6.1.1.10360 → 6.4.4.10685, Sonarr 4.0.17.2952 → 4.0.20.3014.
# Sonarr — метаданные проекта правильные, обычный up:
cd /srv/.../docker/sonarr && sudo docker compose pull sonarr && sudo docker compose up -d sonarr
⚠️ Ловушка: Radarr принадлежал ЧУЖОМУ compose-проекту
docker compose up -d radarr из docker/radarr/ падал:
Conflict. The container name "/radarr" is already in use.
Причина: контейнеры radarr и transmission были созданы 17.05.2026 из общего проекта docker (файл /srv/.../docker/docker-compose.yml, сейчас его нет — удалён). Метаданные: com.docker.compose.project=docker. При этом docker/radarr/docker-compose.yml существовал и не использовался.
Проверка, к какому проекту принадлежит контейнер:
sudo docker inspect radarr -f '{{index .Config.Labels "com.docker.compose.project"}} {{index .Config.Labels "com.docker.compose.project.config_files"}}'
Фикс (данные в config/ не трогаются, только контейнер):
sudo docker stop radarr && sudo docker rm radarr
cd /srv/.../docker/radarr && sudo docker compose up -d radarr
# стало: project=radarr file=.../docker/radarr/docker-compose.yml, сеть media_net
transmission остался в проекте docker (его compose-файл в docker/transmission/), но подключён к media_net — работает.
Диагностические грабли (Radarr/Sonarr API)
POST /api/v3/indexer/testс телом{"indexerId":N}→ HTTP 400 (валидирует как НОВЫЙ индексер, требует Name/Implementation/AppProfileId). ИспользоватьPOST /api/v3/indexer/testall.- То же для клиентов:
POST /api/v3/downloadclient/testall. - Триггер
UrlBase: Radarr/radarr/api/v3/..., Sonarr/sonarr/api/v3/....
Итоговое состояние compose-проектов и сетей (2026-09-20)
После всех правок важно, потому что docker compose up -d надо запускать из своего каталога, иначе будет конфликт имени контейнера.
| Контейнер | Compose-проект | Файл | Сеть |
|---|---|---|---|
| radarr | radarr ✅ |
docker/radarr/docker-compose.yml |
media_net |
| sonarr | sonarr ✅ |
docker/sonarr/docker-compose.yml |
media_net |
| prowlarr | prowlarr ✅ |
docker/prowlarr/docker-compose.yml |
media_net |
| flaresolverr | (в том же файле prowlarr) | docker/prowlarr/docker-compose.yml |
media_net |
| transmission | transmission ✅ |
docker/transmission/docker-compose.yml |
media_net |
| watchtower | watchtower |
docker/watchtower/docker-compose.yml |
— |
✅ transmission тоже исправлен (2026-09-20, позже в той же сессии). Был в проекте docker, пересоздан так же: stop → rm → up -d из docker/transmission/. Данные не пострадали: 244 торрента в ./torrents/ + 244 resume-файла на месте, RPC вернул torrents: 244. Проверка перед пересозданием обязательна — считать торренты ДО и ПОСЛЕ:
sudo ls $D/transmission/torrents/ | wc -l # до и после должно совпасть
Общее правило: если docker compose up -d даёт Conflict. The container name "/X" is already in use — контейнер принадлежит чужому (возможно, удалённому) compose-проекту. Смотреть com.docker.compose.project и project.config_files, затем stop → rm → up -d из правильного каталога. Данные в bind-mount (config/, torrents/) при этом не трогаются.
Проверка принадлежности любого контейнера:
sudo docker inspect <name> -f '{{index .Config.Labels "com.docker.compose.project"}} {{index .Config.Labels "com.docker.compose.project.config_files"}}'
Версии после обновления (2026-09-20)
| Сервис | Версия |
|---|---|
| Radarr | 6.4.4.10685 |
| Sonarr | 4.0.20.3014 |
| Prowlarr | 2.6.5.5623 |
| FlareSolverr | 3.5.2 |
| Watchtower | 1.22.2 (nickfedor/watchtower, см. family/how-to/kraken-watchtower) |
Автообновлением занимается Watchtower — проверить его конфиг перед тем, как ждать обновлений: family/how-to/kraken-watchtower, теория — personal/tech/watchtower-docker-updates.
Автообновление (Watchtower) — 2026-09-20
Все сервисы стека (radarr, sonarr, prowlarr, flaresolverr, transmission) плюс jellyfin и portainer размечены label com.centurylinklabs.watchtower.enable=true → обновляются автоматически (7 контейнеров, проверено scanned=7). Полный разбор и список того, что НЕ обновляется: family/how-to/kraken-watchtower. Теория: personal/tech/watchtower-docker-updates.
Watchlist-sync: ручной запуск и баг дублирования (2026-09-20)
Детальный разбор бага и полная механика — в family/projects/watchlist-automation. Здесь — операционная выжимка.
Ручной запуск (пока крон не восстановлен)
ssh kraken
bash ~/scripts/watchlist-nightly.sh # pull → process-thumbs → resolve → sync-down → sync-up → push
Отдельные шаги:
cd /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/watchlist-sync
uv run --project . watchlist-sync <resolve|sync-down|sync-up|process-thumbs|discover> [--apply] [--recheck] [--batch N]
uv = ~/.local/bin/uv. Без --apply — dry-run.
🔴 Баг mark_ambiguous() — исправлен
watchlist_sync/parser.py, функция mark_ambiguous(): паттерн снимал только саму ❓-строку, а замена вставляла новые кандидаты перед старыми → под-буллеты дублировались на каждом прогоне resolve (+3 строки / +100 байт за раз). ❓-строки при этом НЕ дублировались — только под-буллеты под ними.
# ФИКС: захват всего блока — маркер + под-буллеты
_SUB_BULLETS = r'(?:\n[ \t]{4,}-[ \t]*(?!\[[ xX]\])[^\n]*)'
pattern = re.compile(
r'(^[ \t]*-[ \t]*\[ \][ \t]*)[❓]?[ \t]*(' + escaped + r')[ \t]*'
r'(?P<subs>' + _SUB_BULLETS + r'*)',
re.MULTILINE
)
Правило для парсеров этого файла: под-буллет кандидата = отступ ≥4 пробела + буллет + НЕ чекбокс (- [ ]/- [x]). Строки фильмов имеют отступ 2 пробела — их надо исключать явно. Внутри *-группы перенос строки обязателен ((?: + \n + ...) + *): если сделать \n? опциональным, regex перешагивает на следующую строку и проглатывает соседние фильмы (проверено — так потеряли ❓ The kill room, The burial, Past lives).
Верификация: прогнать mark_ambiguous() 3× на свежей копии → размер обязан быть идентичным. Плюс проверка, что 0 не-кандидатных строк потеряно.
Скрипт дедупа кандидатов
Одноразовая чистка накопленных дублей: под каждой ❓/🗓️-строкой оставить уникальные под-буллеты (ключ title|year|rating), порядок не менять, строки фильмов не трогать.
python3 /tmp/wl_dedupe.py # dry-run
python3 /tmp/wl_dedupe.py --apply # запись + авто-бэкап .dedupe-backup-<ts>
Прогон 2026-09-20: 168 дублей в 15 блоках, 26430 → 21032 байт (838 → 670 строк).
⚠️ Скрипты этой сессии — в /tmp на Кракене (wl_dedupe.py, wl_fix_parser*.py, wl_verify*.py); /tmp чистится при перезагрузке. Для постоянной копии — перенести в ~/scripts/.
Sonarr 400 «This series has already been added» — не сбой
При sync-down уже существующей серии Sonarr отвечает 400 SeriesExistsValidator («Волшебный участок» = «Magical Police Department», tvdbId=442038). arr.py::sonarr_add() не проверяет дубли перед POST — в отличие от radarr_add(). Шумит в логе, данные не портит. Диагноз смотреть в теле ответа: errorCode: SeriesExistsValidator.
Zulip-пинг не настроен
_zulip_ping() (cli.py) требует ZULIP_URL / ZULIP_API_KEY / ZULIP_BOT_EMAIL, которых нет в .env репо → [warn] not set — skipping ping. Уведомления о нерезолвленных items до Alex не доходят (59 штук ушли молча).
Подготовка к авто-удалению просмотренного (2026-09-20)
Требование Alex: удалять [x] при заполнении диска >90%, через API Radarr. План и открытые вопросы — family/plans/watchlist-cleanup. Здесь — только инфраструктурные факты, добытые при разведке.
⚠️ df ВРЁТ про заполнение — считать через shutil.disk_usage
df -h → 88% (учитывает root-резерв ext4)
shutil.disk_usage → 83.7% (реальные 1647 / 1968 GB, free 220.8 GB)
Разница ~4%. Порог «>90%» проверять только через shutil.disk_usage, иначе сработает на 86%.
Jellyfin: заголовок авторизации и отсутствие DatePlayed
# ПРАВИЛЬНО (как в watchlist_sync/jellyfin.py:_auth)
{"Authorization": 'MediaBrowser Token="<token>"'}
# НЕПРАВИЛЬНО
{"X-Emby-Token": token} # → 401
Рабочие вызовы:
GET /Users → 200; юзеры alex, lisa
GET /Users/{uid}/Items?IsPlayed=true&IncludeItemTypes=Movie&Fields=DatePlayed,Path
🔴 DatePlayed возвращается None для всех просмотренных. Логику, зависящую от даты просмотра, строить нельзя. IsPlayed=true работает, UserData.Played работает — дата нет.
Jellyfin видит просмотренными всего 6 фильмов (Король Лев, Меч короля, Эль рояль, Остров сокровищ, Схватка с дьяволом, Труп невесты) — все из /media/movies (ручные торренты). Ни одного из /media/movies-radarr (на 2026-09-21 — 28 фильмов). То есть пересечение [x] ∩ Radarr-файлы пусто.
⚠️ Это не косметика, а причина, по которой авто-очистка диска не работает. sync-up переносит watched-историю Jellyfin в [x], а cleanup удаляет только то, что помечено [x]. Пока Jellyfin не видит Radarr-библиотеку, диск (94.7%) будет заполняться, а cleanup будет ежедневно писать «nothing to delete». Разбираться с этим, а не с cleanup. Детали — family/plans/watchlist-cleanup.
Radarr: состояние библиотеки (замер 2026-09-22)
- 34 фильма в базе, 12 с файлами (до удаления 16 авто-закачек было 50/28).
- 🔴
monitored=0— ни один фильм не отслеживается. Radarr ничего не докачает. - Объём библиотеки на диске: 251.9 GB.
- Топ по размеру: Chaos Walking 63 GB, Oldboy 31, Project Hail Mary 30, Whiplash 25, The Drama 21.
- Диск: 73%, свободно 477 GB (
/dev/sda1, 1.8T). - ✅ Диск был освобождён 2026-09-21: 100% → 77%. История:
sync-down --batch 5качал 5 фильмов ежедневно без проверки места → диск в 0 байт, Radarr отдавалdisk I/O error(SQLite не пишет при нуле места). Удалены 5 remux = 403.4 ГБ (Babylon 92.0, Schindler's List 89.4, Midsommar 85.6, Triangle of Sadness 79.7, Unhinged 56.7). Бэкапы:~/backup-movies-watchlist-20260921-150759.md,~/backup-radarr-unmonitor-20260921-151117.json. Порядок при удалении:RescanMovie→PUT monitored=false→DELETE. Без снятия monitored Radarr перекачал бы все 403 ГБ. - ✅ Стоп-кран
MIN_FREE_GB = 100.0вsync_down.py(коммит2642882): проверка черезshutil.disk_usage, НЕdf(dfврёт на ~4%, учитывает root-резерв ext4). При нехватке —[STOP] free space ... < 100 GiBи выход без добавления. Там же фильтр ужасов (is_horror(),⭐обходит). Разбор — family/plans/watchlist-disk-overflow-fix. - ⚠️ С 2026-09-22
sync-downв кроне не запускается вообще — стоп-кран и профиль качества остаются как страховка для ручного запуска. recycleBin: ''— корзины нет, и настраивать её решено НЕ будет (2026-09-21).PUT config/mediamanagementс путём хоста даёт400 FolderWritableValidator: not writable by user 'abc': внутри контейнера Radarr медиа замаплено как/media, хостового пути/srv/...6194539b.../media/.recyclebinтам не существует. Обходить маппингом ради корзины признано нецелесообразным — удаление идёт через Radarr API, а неrm.recycleBinCleanupDays: 7,deleteEmptyFolders: False.- 🔴 Все
monitored=false(2026-09-22). Если удалять файл —PUT monitored=falseдоDELETE(порядок критичен, иначе скачает заново).
Проверка одним вызовом:
KEY=$(grep -oP '(?<=<ApiKey>)[^<]+' /srv/...6194539b.../docker/radarr/config/config.xml)
# только фильмы с файлами
curl -s "http://localhost:7878/radarr/api/v3/movie?apikey=$KEY" \
| jq -r '.[] | select(.hasFile) | "\(.id)\t\(.sizeOnDisk/1e9|floor)GB\t\(.monitored)\t\(.title)"'
# сводка одной строкой
curl -s "http://localhost:7878/radarr/api/v3/movie?apikey=$KEY" | jq -r '
"всего=\(length) сФайлом=\([.[]|select(.hasFile)]|length) monitored=\([.[]|select(.monitored)]|length)"'
Watchlist → Lampa: JSON-каталог (2026-09-22)
Второй потребитель watchlist, помимо Radarr/Sonarr: модуль Catalog в Lampa. Пайплайн:
movies-watchlist.md (боевой .md)
↓ gen_watchlist.py ← крон 30 2 * * * (watchlist-catalog.sh)
watchlist.json + missing.json
↓
Lampa (Catalog): карточки с постерами + маркер ❓ для нерезолвленных
Пути
| Что | Путь |
|---|---|
| Генератор | $H/lampac/scripts/gen_watchlist.py |
| Маркер | $H/lampac/scripts/mark_missing.py |
| Крон-скрипт | ~/scripts/watchlist-catalog.sh |
Боевой .md |
$H/obsidian/family/documents/movies-watchlist.md |
| Вывод | $H/lampac/wwwroot/watchlist.json (376 позиций) |
| Нерезолвленные | $H/lampac/wwwroot/missing.json |
| Кэш | $H/lampac/cache/.lampac_tmdb_{cache,details}.json (скрытые файлы) |
где $H = /srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f
Резолв позиции — три уровня
1. Radarr (по названию) ← самый надёжный
2. TMDB поиск по названию (+год ±1)
2b. эвристика КП по названию
2c. kp_id из ссылки в .md → КП → TMDB ← машинный, однозначный (проверяется ПЕРВЫМ из КП)
3. промах → маркер ❓ в .md
KP_SIM_THRESHOLD = 0.75 — порог совпадения названия в КП.
⚠️ watchlist.json использует channels.*.items[].name, НЕ title. Поле title там отсутствует — не путать при парсинге.
🔴 Кириллица в ключе каталога Lampa → ModInit.goInit чистит [^a-z0-9\-] → HTTP 400.
Нужен plugin: watchlist + числовой tmdb_id (format: "long.TryParse(...)").
Проверять через /catalog/card?...&type=movie, НЕ /card.
Маркеры в боевом .md
| Маркер | Значение |
|---|---|
❓ |
не резолвлен (нет в TMDB/КП) |
🗓️ |
ещё не вышел |
👎 |
не надо |
[x] |
смотрел |
⭐ |
приоритет (обходит фильтр ужасов и рейтинг) |
mark_missing.py работает в обе стороны: нет позиции в missing.json → маркер ❓ снимается.
Полный разбор генератора: personal/plans/watchlist-tmdb-missing-marker. Деплой и плагин: personal/tech/lampac-deployment.
Notes
- See arr-stack-taiga for Taiga (secondary) arr stack
- Media pipeline pitfalls: media-pipeline-pitfalls
- FlareSolverr / Cloudflare / Prowlarr-питфоллы: prowlarr-flaresolverr-cloudflare
- Watchlist pipeline (полный flow, cron, баги): family/projects/watchlist-automation
- Синтез: concepts/kraken-media-stack