[2026-09-20] eagle: family/how-to/arr-stack-kraken.md family/plans/watchlist-cleanup.md family/projects/watchlist-automation.md
This commit is contained in:
1 parent
bbb970dcd7
commit
7e5cff5704
3 files changed
+191
-19
No files matched your search
@@ -81,21 +81,18 @@ Prowlarr → Radarr + Sonarr → Transmission → Jellyfin
|
||||
|
||||
## Cron'ы на Kraken (crontab)
|
||||
|
||||
⚠️ **Фактическое состояние (проверено 2026-09-20): строки watchlist в crontab ОТСУТСТВУЮТ.** Watchlist pipeline мёртв с 2026-06-20 — детали и разбор в [[family/projects/watchlist-automation]].
|
||||
✅ **Watchlist-крон ВОССТАНОВЛЕН 2026-09-20 21:21** (был мёртв с 2026-06-20). Бэкап `~/crontab-backup-20260920-212155.txt`. Детали и разбор — в [[family/projects/watchlist-automation]].
|
||||
|
||||
Фактически в `crontab -l` юзера `kraken` сейчас:
|
||||
Актуальное `crontab -l` юзера `kraken`:
|
||||
```
|
||||
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 1 * * * bash ~/scripts/watchlist-nightly.sh # watchlist nightly ✅ восстановлен
|
||||
0 9 * * 0 bash ~/scripts/watchlist-discover.sh # watchlist discover ✅ восстановлен
|
||||
```
|
||||
|
||||
Должно быть (НЕ восстановлено, ждёт решения Alex):
|
||||
```
|
||||
0 1 * * * bash ~/scripts/watchlist-nightly.sh # watchlist nightly
|
||||
0 9 * * 0 bash ~/scripts/watchlist-discover.sh # watchlist discover
|
||||
*/10 * * * * bash .../media-pipeline/media-router.sh # media router (Telegram)
|
||||
```
|
||||
⚠️ **`media-router.sh` (роутер symlink'ов, каждые 10 мин) в crontab ОТСУТСТВУЕТ.** В таблице «Два параллельных пути» выше он описан как работающий по cron 10min — фактически его там нет. Проверить, нужен ли: без него symlink'и в `/media/{movies,cartoons,...}/` не создаются автоматически.
|
||||
|
||||
Точная проверка наличия любого крон-джоба (не верить доке, смотреть систему):
|
||||
```bash
|
||||
@@ -104,6 +101,17 @@ 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 # демон жив?
|
||||
```
|
||||
|
||||
**Установка крон-джоба безопасно (с бэкапом):**
|
||||
```bash
|
||||
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
|
||||
@@ -555,6 +563,50 @@ python3 /tmp/wl_dedupe.py --apply # запись + авто-бэкап .dedup
|
||||
|
||||
`_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`
|
||||
|
||||
```python
|
||||
# ПРАВИЛЬНО (как в 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` (18 фильмов, 702 ГБ). То есть пересечение `[x]` ∩ Radarr-файлы **пусто**.
|
||||
|
||||
### Radarr: состояние библиотеки (замер 2026-09-20)
|
||||
|
||||
- 46 фильмов в базе, **18 с файлами**, суммарно **702 ГБ**.
|
||||
- Топ по размеру: Babylon 98.8 GB, Schindler's List 95.9, Midsommar 91.9, Triangle of Sadness 85.6, Chaos Walking 62.7, Unhinged 60.9.
|
||||
- `recycleBin: ''` (корзина не настроена), `recycleBinCleanupDays: 7`, `deleteEmptyFolders: False`.
|
||||
- **Все 18 monitored=True.** Если удалить файл, не сняв monitored, Radarr скачает заново.
|
||||
|
||||
Проверка одним вызовом:
|
||||
```bash
|
||||
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)"'
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- See [[arr-stack-taiga]] for Taiga (secondary) arr stack
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# План: авто-удаление просмотренного (watchlist cleanup)
|
||||
|
||||
**Дата:** 2026-09-20
|
||||
**Статус:** требование получено, механизм НЕ написан
|
||||
**Связано:** [[watchlist-automation]], [[arr-stack-kraken]]
|
||||
|
||||
---
|
||||
|
||||
## Что сказал Alex (дословно)
|
||||
|
||||
> «Да, давай удалять то на чем стоит чекбокс при заполнении более 90%»
|
||||
|
||||
Расшифровка — **три факта, и всё**:
|
||||
1. Удалять то, **на чём стоит чекбокс** → `[x]` в watchlist.
|
||||
2. **При заполнении диска > 90%.**
|
||||
3. Механизм — **через API Radarr** (Alex: «Видимо через апи»), не `rm`.
|
||||
|
||||
## ❌ Чего Alex НЕ говорил (придумано агентом, отвергнуто)
|
||||
|
||||
Первая версия этого плана содержала выдуманные параметры, выданные за решение Alex. Alex отреагировал: **«Не как в твоём блядь предложении»**.
|
||||
|
||||
**Выдумано и НЕ подтверждено:**
|
||||
- ~~Задержка 7 дней после просмотра~~ — не просил
|
||||
- ~~Только секция `## Фильмы`~~ — не ограничивал
|
||||
- ~~`monitored: false`~~ — не обсуждал
|
||||
- ~~`recycleBin` / корзина~~ — не просил
|
||||
- ~~Лимит 10 файлов за прогон~~ — не просил
|
||||
|
||||
⚠️ **Урок:** не выдавать свои догадки за решение пользователя. Alex сказал три слова — делать ровно это, остальное спрашивать.
|
||||
|
||||
## Секция `## Правила отбора` — что проверено фактами
|
||||
|
||||
## Факты, замеренные 2026-09-20
|
||||
|
||||
### Заполнение диска
|
||||
|
||||
**Реальное заполнение — 83.7%**, порог 90% НЕ достигнут.
|
||||
|
||||
```python
|
||||
shutil.disk_usage(media) → total 1967.8 GB | used 1647.0 GB | free 220.8 GB → 83.7%
|
||||
```
|
||||
|
||||
⚠️ `df -h` показывает **88%** — считает с root-резервом (~5% ext4). Для порога «90%» брать **`shutil.disk_usage`**, а не `df`, иначе порог сработает раньше на ~4%.
|
||||
|
||||
### Кандидаты на удаление: 0
|
||||
|
||||
Пересечение `[x]` в watchlist ∩ фильмы с файлами в Radarr → **пусто**.
|
||||
|
||||
- Фильмов в Radarr с файлами: **18** (702 ГБ). Топ: Babylon 98.8, Schindler's List 95.9, Midsommar 91.9, Triangle of Sadness 85.6 ГБ.
|
||||
- Все 18 — недавние закачки, ещё не отмечены `[x]`.
|
||||
- Jellyfin считает просмотренными **6** фильмов: Король Лев, Меч короля, Эль рояль, Остров сокровищ, Схватка с дьяволом, Труп невесты — все старые файлы из `/media/movies`, ни один **не из `/media/movies-radarr`**.
|
||||
|
||||
**Вывод:** механизм напишется и будет работать, но сегодня удалит 0 файлов. Сработает, когда посмотришь что-то из Radarr-библиотеки. Если нужно, чтобы он **реально освобождал место** — сначала разобраться, почему `[x]` не появляется у новых фильмов (Jellyfin видит только 6 старых).
|
||||
|
||||
### 🔴 Jellyfin НЕ отдаёт `DatePlayed`
|
||||
|
||||
Все просмотренные вернули `DatePlayed=None`. **Опираться на дату просмотра в логике нельзя.**
|
||||
|
||||
Рабочий вызов (заголовок важен — `Authorization`, НЕ `X-Emby-Token`):
|
||||
```python
|
||||
headers = {"Authorization": 'MediaBrowser Token="%s"' % token}
|
||||
# GET /Users → 200, юзеры alex / lisa
|
||||
# GET /Users/{uid}/Items?IsPlayed=true&IncludeItemTypes=Movie&Fields=DatePlayed,Path
|
||||
```
|
||||
⚠️ `X-Emby-Token` даёт **401**. Именно так делает `watchlist_sync/jellyfin.py:_auth()`.
|
||||
|
||||
## Архитектура (черновик, требует подтверждения Alex)
|
||||
|
||||
```
|
||||
1. disk_usage(media) < 90% ? → exit 0 (silent)
|
||||
2. parse watchlist → [x] строки
|
||||
3. Radarr: найти фильм, hasFile?
|
||||
4. DELETE /api/v3/movie/{id}?deleteFiles=true ← через API, как сказал Alex
|
||||
5. лог
|
||||
```
|
||||
|
||||
**Открытые вопросы (спрашивать, не додумывать):**
|
||||
- [ ] Удалять вместе с файлом запись из Radarr, или оставлять? (иначе Radarr monitored → скачает заново)
|
||||
- [ ] Все секции или только `## Фильмы`?
|
||||
- [ ] Корзина или безвозвратно?
|
||||
- [ ] Лимит за прогон?
|
||||
- [ ] Ставить ли в cron, или запускать вручную?
|
||||
|
||||
## Безопасность
|
||||
|
||||
- **Порог проверять через `shutil.disk_usage`, не `df`.**
|
||||
- **Dry-run обязателен** — первый прогон только показывает, что удалил бы.
|
||||
- Операция необратима при отсутствии корзины — подтверждение Alex перед первым реальным запуском.
|
||||
|
||||
---
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
- [[watchlist-automation]] — полный pipeline, статус крона, правила отбора sync-down
|
||||
- [[arr-stack-kraken]] — *arr стек, пути конфигов, API
|
||||
@@ -83,9 +83,37 @@ Jellyfin (8096) → rescan → виден контент
|
||||
|
||||
**Важно:** `process_thumbs` автоматически определяет отступ из `## Фильмы` и сохраняет при переносе. `SECTION_THUMBDN = "## Новинки👎"` (без пробела) — должно точно совпадать с заголовком.
|
||||
|
||||
## 🔴 Крон pipeline ОТСУТСТВУЕТ (аудит 2026-09-20) — но баг с мусором УЖЕ ИСПРАВЛЕН
|
||||
## ✅ Крон pipeline ВОССТАНОВЛЕН (2026-09-20 21:21)
|
||||
|
||||
**Автодобавление фильмов НЕ работает по расписанию.** Скрипты живы, но их никто не запускает.
|
||||
**Задача закрыта.** Pipeline был мёртв с 2026-06-20 (проверено аудитом ниже), теперь расписание вернули.
|
||||
|
||||
Установлено в crontab юзера `kraken`:
|
||||
```
|
||||
# Watchlist: process-thumbs + resolve + sync-down + sync-up (ежедневно 01:00)
|
||||
0 1 * * * bash /home/kraken/scripts/watchlist-nightly.sh >> /tmp/watchlist-nightly.log 2>&1
|
||||
|
||||
# Watchlist: discover — новинки из KP API (воскресенье 09:00)
|
||||
0 9 * * 0 bash /home/kraken/scripts/watchlist-discover.sh >> /tmp/watchlist-discover.log 2>&1
|
||||
```
|
||||
|
||||
**Как ставилось** (идемпотентный скрипт, бэкап перед установкой):
|
||||
```bash
|
||||
crontab -l > ~/crontab-backup-$(date +%Y%m%d-%H%M%S).txt # бэкап
|
||||
crontab /tmp/crontab-new.txt # установка
|
||||
crontab -l # проверка
|
||||
```
|
||||
Бэкап: `~/crontab-backup-20260920-212155.txt`
|
||||
|
||||
**Проверено после установки:**
|
||||
- `systemctl is-active cron` → `active`
|
||||
- `grep -c watchlist /var/spool/cron/crontabs/kraken` → **2** (обе строки подхвачены демоном)
|
||||
- Логи пишутся в `/tmp/` — **теряются при перезагрузке**. Перенести в постоянное место, если нужно сохранять историю.
|
||||
|
||||
⚠️ **В `docker exec hermes-kraken hermes cron list` по-прежнему «No scheduled jobs»** — это НЕ про watchlist. Watchlist-скрипты детерминированные, живут в системном cron, в Hermes-планировщике их не должно быть. Не искать их там.
|
||||
|
||||
## 🔴 Аудит 2026-09-20: как выглядело состояние ДО восстановления (историческая справка)
|
||||
|
||||
**На момент аудита автодобавление фильмов НЕ работало по расписанию.** Скрипты были живы, но их никто не запускал.
|
||||
|
||||
Доказательства (проверено 2026-09-20):
|
||||
- `crontab -l` юзера `kraken` — watchlist-строк **НЕТ**. Есть только `sync-vault.sh` (каждый час) и два `pgs-to-srt` (часовой + 03:00).
|
||||
@@ -447,16 +475,16 @@ Sonarr API base: http://localhost:8989/sonarr/api/v3/
|
||||
```
|
||||
Проверка закачки: `queue` в Radarr показывает `grabbed/downloading`; `history` даёт точное имя взятого релиза. Transmission — `docker exec transmission transmission-remote --list` (RPC-юзер в `settings.json` пустой).
|
||||
|
||||
## Cron Jobs (на Кракене с 2026-05-27)
|
||||
## Cron Jobs (на Кракене, восстановлены 2026-09-20)
|
||||
|
||||
Весь watchlist pipeline работает на Кракене (мигрировал с Eagle 2026-05-27).
|
||||
Весь watchlist pipeline работает на Кракене (мигрировал с Eagle 2026-05-27). **Крон был мёртв с 2026-06-20 по 2026-09-20, восстановлен** (детали в начале документа).
|
||||
|
||||
| Job | Расписание | Скрипт |
|
||||
|-----|-----------|--------|
|
||||
| `watchlist-nightly` | ежедн. 01:00 | `~/scripts/watchlist-nightly.sh` |
|
||||
| `watchlist-discover` | вс 09:00 | `~/scripts/watchlist-discover.sh` |
|
||||
|
||||
⚠️ Фактический путь — `~/scripts/`, **не** `~/.hermes/scripts/` (в доке ранее было ошибочно). Оба скрипта вызывают CLI напрямую через `uv run --project $WS`, без LLM. `uv` лежит в `~/.local/bin/uv`.
|
||||
⚠️ Фактический путь — `~/scripts/`, **не** `~/.hermes/scripts/`. Оба скрипта вызывают CLI напрямую через `uv run --project $WS`, без LLM. `uv` лежит в `~/.local/bin/uv`.
|
||||
|
||||
`WS` в обоих скриптах: `/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/watchlist-sync` — **другой UUID**, чем фактический корень репо (см. ниже). Возможный источник поломки: проверить, что путь резолвится.
|
||||
|
||||
@@ -564,12 +592,9 @@ Jellyfin library mapping: Movies → `movies`, Cartoons → `mixed` (movies + ep
|
||||
- ✅ **[2026-09-20] Фикс `sync_down.py` РЕАЛИЗОВАН** — коммит `ada47da`. `resolved.sort()` убран, добавлен `MIN_RATING = 6.0` с видимым `print`. Нулевые рейтинги отсекаются (решение Alex: «отсекать»).
|
||||
- ✅ **[2026-09-20] Приоритет `⭐` (U+2B50) РЕАЛИЗОВАН** — коммит `7db9385`. ⭐ первыми из всех секций, **обходит** фильтр `MIN_RATING`. `⭐` срезается из запроса TMDB (`parser._clean` через `str.replace`, НЕ через end-anchored класс). `✭` (U+272D) приоритетом не считается; `[x]` пропускается; под-буллеты кандидатов не считаются.
|
||||
- ✅ **[2026-09-20] Реальный прогон с новой логикой выполнен** — 19:53, `Done`, +3 фильма. Батч по порядку файла, ⭐ первым.
|
||||
- 🔴 **[2026-09-20] Восстановить cron для watchlist pipeline** — ГЛАВНАЯ незакрытая задача. Pipeline мёртв с 20 июня. Скрипты проверены вручную (2 прогона 2026-09-20 прошли чисто), нужно вернуть в crontab юзера `kraken`:
|
||||
```
|
||||
0 1 * * * bash ~/scripts/watchlist-nightly.sh
|
||||
0 9 * * 0 bash ~/scripts/watchlist-discover.sh
|
||||
```
|
||||
⚠️ В [[arr-stack-kraken]] эти строки в секции «Cron'ы на Kraken» указаны как действующие, хотя фактически их НЕТ — док в той части расходится с реальностью.
|
||||
- ✅ **[2026-09-20] Крон ВОССТАНОВЛЕН** — установлен 21:21 в crontab юзера `kraken`, бэкап `~/crontab-backup-20260920-212155.txt`. `nightly` 01:00 + `discover` вс 09:00, логи в `/tmp/`. Первая проверка в бою — прогон в 01:00.
|
||||
- 🟡 **[2026-09-20] Логи крона в `/tmp/`** — теряются при перезагрузке. Перенести в постоянное место (`~/logs/` или на диск), если нужна история прогонов.
|
||||
- 🟡 **[2026-09-20] Удаление просмотренных фильмов при заполнении диска >90%** — требование Alex, механизм НЕ написан. См. [[family/plans/watchlist-cleanup]]. Замер 2026-09-20: диск **83.7%**, кандидатов на удаление **0** (пересечение `[x]` ∩ файлы Radarr пусто). Jellyfin **не отдаёт `DatePlayed`** (`None` у всех) — планировать без опоры на дату просмотра.
|
||||
- 🟡 **[2026-09-20] `sync-down` берёт всего 5 за прогон** — при 250 кандидатах разбор очереди займёт ~50 ночей. Рассмотреть увеличение `--batch` (сейчас `--batch 5` в `watchlist-nightly.sh`). Особенно актуально, раз фильтр `<6.0` уже отсеял 18.
|
||||
- 🟡 **[2026-09-20] Разобрать 5 застрявших закачек в очереди Radarr** со статусом `warning`: `Brokeback Mountain`, `Мортал Комбат 2`, `Sorry to Bother You`, `Город бога`, `День хомячка`. Висят давно, релиз не находится/не качается.
|
||||
- 🟡 **[2026-09-20] `Oficina do Diabo` / `Мастерская Сатаны` (2025)** — в Radarr, но релиз не найден. Ждёт RSS. Проверить через несколько дней.
|
||||
|
||||
Reference in new issue
Block a user