[2026-09-22] eagle: personal/plans/watchlist-tmdb-missing-marker.md personal/tech/lampac-deployment.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-22 18:24:10 +06:00
1 parent d10bc1a5d0
commit a334332c5b
2 files changed
+382 -6

No files matched your search

+219 -3
View File
@@ -2,8 +2,8 @@
# Watchlist — автопоиск TMDB + маркер «нет в базе» (без ручных правок)
**Дата:** 2026-09-22
**Статус:** Шаги 1, 1.3, 2, 3 ВЫПОЛНЕНЫ И ПРОВЕРЕНЫ, оба репо запушены.
Осталось только: деплой на Кра́кен + имя в карточке из TMDB/КП.
**Статус:** ✅ Шаги 1, 1.3, 2, 3 ВЫПОЛНЕНЫ, ЗАДЕПЛОЕНЫ НА КРА́КЕН И ПРИНЯТЫ В UI.
Осталось: коммит правок в `lampac-scripts`, имя в карточке из TMDB/КП, порядок категорий в ленте.
**Связано:** [[personal/plans/lampac-watchlist-plugin]], [[family/projects/watchlist-automation]], [[family/projects/watchlist-sync]], [[personal/tech/lampac-deployment]]
---
@@ -257,6 +257,218 @@ Alex: *«В developer. Пуш на gitea.»* Репо на gitea (private, HTTP
---
## ✅ ПОСТ-ДЕПЛОЙНАЯ ИТЕРАЦИЯ (2026-09-22, поздний вечер)
### 🔴 Генератор НЕ ЧИСТИЛ кэш промахов — исправлено
Alex спросил прямо: *«че блядь значит чистка кэша обязательна?! скрипт блядь её делает?!»* —
и был прав: **не делал**.
```python
key = f"{title.lower().strip()}|{year or ''}"
if key in cache:
return tuple(v) if v else None # промах вернулся, в сеть не пошли
```
Инвалидации не было. Промах (`None`) писался **навсегда** → правка названия, не
меняющая ключ кэша (регистр, пробел, порядок слов), `❓` не снимала.
**Фикс:** `clear_failed_cache()` — вызывается в `main()` сразу после `load_cache()`.
Удаляет **все `None`**, успешные резолвы (~350) не трогает. Промахи (~50)
перезапрашиваются на каждом прогоне.
Залито на Кра́кен, сумма `c556c52b8cf4714686add4083c4afc09` (совпала с локальной).
Патч: `~/lampac-tmp/patch_autoclear_cache.py`, бэкап `.bak-cacheclear`.
⚠️ **Ручная чистка `clear_cache_kraken.py` больше не нужна** — это часть прогона.
Подробности: [[personal/tech/lampac-deployment]], раздел «Кэш промахов».
### Правки Alex в `.md`: он делает их САМ, скрипт подхватывает
Alex уточнил три названия — **добавил год, снял `❓` и подсказки-подбуллеты**:
| Было | Стало |
|---|---|
| `❓ Everything Everywhere All at Once 2021` + 2 подбуллета | `Everything Everywhere All at Once 2022` |
| `❓ Духless` + 2 подбуллета | `Духless 2012` |
| `❓ Бумбараш` + 2 подбуллета | `Бумбараш 1972` |
🔴 **Синк vault — почасовой.** Alex правит в Obsidian на Mac, на Кра́кен уезжает
через `sync-vault.sh` (крон `0 * * * *`). Дифф `.md` до синка **пустой** — прогонять
«после правок» нужно ПОСЛЕ синка, иначе генератор увидит старую версию.
Правки вручную гоняются: `ssh kraken 'bash ~/scripts/sync-vault.sh'`.
### Ответы на вопросы Alex (проверено `crontab -l` и кодом)
1. **Порядок в ленте — БАГ, не задумано.** `watchlist.yaml`: `displayindex: 1` —
самый низкий из всех (`rezka 10`, `kinobase 15`, `filmix 20`, `vokino 30`,
`eneyida 35`, `kinoukr 40`, `getstv 45`, `aniliberty 60`). «Мой список» должен
быть ПЕРВЫМ, но оказался ниже «Сейчас Смотрят» и «Рекомендуем посмотреть».
Эти два блока — **встроенные каталоги Lampa, не из `sites/`**, поэтому
`displayindex` их не сдвигает. `watchlist.yaml` в этой сессии НЕ правился.
Требует отдельного разбора.
2. **Маркеры — да, так.** `❓` = резолв не нашёл, не в каталоге. `🗓️` = не вышел,
не в каталоге. Без маркера = вышел и найден → в каталоге.
3. **Прогон после правок сработает** — при условии, что синк прошёл и кэш промахов
очищен (теперь автоматически).
4. **Radarr и лимит — это РАЗНЫЕ лимиты, не один.**
- `batch=2` (снижен с 5 после инцидента 2026-09-21, диск 100%) — сколько позиций
**уходит в Radarr на закачку** за прогон. Плюс `_free_gb()` — стоп при нехватке места.
- **Выдача в Lampa лимита НЕ имеет** — отдаётся весь `watchlist.json`.
- Каталог строится из `.md` → `watchlist.json`; **Radarr в отображении не участвует**.
- «Один скрипт в кроне» — неверно, их **пять** (см. таблицу ниже).
### Осталось
1. **Коммит в `lampac-scripts`** — на gitea лежит `1765c05`; **не закоммичены**:
фикс `.env`-пути, `clear_failed_cache()`, переделанный `mark_missing.py`.
Это единственный реально висящий технический долг.
2. **Имя в карточке из TMDB/КП** — «отображать как в tmdb/kp, ничего не укорачивать».
Сейчас генератор пишет `it["name"]` = название из `.md`.
3. **Порядок категорий в ленте** — разобраться со встроенными блоками Lampa.
4. **Доки** — обновлены (этот файл + [[personal/tech/lampac-deployment]]).
---
## ✅ ДЕПЛОЙ НА КРА́КЕН ВЫПОЛНЕН (2026-09-22, вечер)
### 🔴🔴 Главная находка деплоя: генератор на Кра́кене НИКОГДА не резолвил
`load_env()` искал `.env` **только по Mac-пути**:
```python
for p in (Path("/Users/admin/Developer/watchlist-sync/.env"),):
```
На Кра́кене такого пути нет → `TMDB_KEY` не найден → `[ERR] нет TMDB_KEY в .env` →
**каталог собирался на одних Кинопоиск-ссылках, без TMDB-ID и постеров.**
Это объясняет, почему до сессии в JSON не было TMDB-ID у половины позиций: дело было
не в слабом резолве, а в том, что резолв **вообще не запускался**.
**Фикс:** `load_env()` перебирает 5 мест (последний найденный по ключу побеждает),
печатает, какие файлы прочитаны:
```python
candidates = [
os.environ.get("WATCHLIST_ENV", ""),
"/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/watchlist-sync/.env",
"/srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/watchlist-sync/.env",
str(Path.home() / "Developer" / "watchlist-sync" / ".env"),
str(Path.home() / ".config" / "watchlist-sync" / ".env"),
]
```
Скрипт патча: `~/lampac-tmp/patch_envpath.py`. Бэкап: `.bak-envpath`.
### Боевой прогон на реальном `.md` (не тест)
```bash
ssh kraken "cd $H && python3 $H/scripts/gen_watchlist.py $W $H/wwwroot/watchlist.json"
```
| Метрика | Значение |
|---|---|
| позиций в каталоге | **373** |
| без TMDB-ID | **0** |
| films / new / cartoons / anime | 331 / 32 / 3 / 7 |
| постеров | 327 / 32 / 3 / 7 |
| `missing.json` | **30** |
| источники | Radarr 9, TMDB 343, автопоиск **2b: 17**, **2c: 4**, miss 30 |
Размеры: `watchlist.json` 102 456 Б, `missing.json` 1 239 Б.
### Что задеплоено на Кра́кен
| Что | Путь | Права | Сумма |
|---|---|---|---|
| генератор | `$H/scripts/gen_watchlist.py` | `kraken:kraken 600` | `3c7d4df3…` |
| маркер | `$H/scripts/mark_missing.py` | `kraken:kraken 600` | `43b3bb15…` |
| крон-скрипт | `~/scripts/watchlist-catalog.sh` | `root:root 755` | `17672d62…` |
| бэкап генератора | `$H/scripts/gen_watchlist.py.bak-20260922-175754` | | |
`$H` = `/srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/lampac`
Суммы сверены `md5` локально и на Кра́кене — **совпали**. `py_compile` + `bash -n` — OK.
🔴 **Права критичны:** установка только через
`sudo install -o kraken -g kraken -m 600` — каталог `$H/scripts/` принадлежит
`kraken:kraken`, но `~/scripts/` — `root:root 755`. `cp` без sudo падает на
`Permission denied` (грабля: бэкап крона-скрипта из-за этого не сделался с первого раза).
### `watchlist-catalog.sh` — обновлён
Добавлен блок маркера между генерацией и перезапуском lampac:
```bash
python3 "$GEN" "$WATCHLIST" "$OUT" 2>&1 | tail -12 || { log "ERR: генерация упала"; exit 1; }
if [ -f "$MISSING" ] && [ -f "$MARK" ]; then
log "Простановка ❓ по missing.json"
python3 "$MARK" --missing "$MISSING" "$WATCHLIST" --apply 2>&1 | tail -8 \
|| log "WARN: маркер не проставился (не фатально)"
fi
docker restart lampac # сброс кэша Catalog
```
`MISSING=$LAMPAC/wwwroot/missing.json`. Нефатально для маркера — генерация важнее.
### Крон на Кра́кене — полная картина (проверено `crontab -l`)
```
0 1 * * * watchlist-nightly.sh process-thumbs → resolve → sync-down → sync-up
0 9 * * 0 watchlist-discover.sh новинки из KP (воскресенье)
0 2 * * * watchlist-cleanup.sh удаление просмотренного при диске >90%
30 2 * * * watchlist-catalog.sh JSON-каталог для Lampa ← ОБНОВЛЁН
0 * * * * sync-vault.sh синк vault
0 * * * * pgs-to-srt.sh (новая загрузка) — не watchlist
0 3 * * * pgs-to-srt.sh (вся библиотека) — не watchlist
```
⚠️ **«Один скрипт в кроне» — неверно, их пять по watchlist.** Разделение ролей:
`discover` **только пишет в `.md`**, в закачку не отправляет. Закачку отправляет
`sync-down` через **Radarr** (`radarr_add()` + `radarr_search()`, `sync_down.py:155,158`).
**Лимит есть:** batch снижен `5 → 2` после инцидента 2026-09-21 (диск 100%),
плюс проверка свободного места `_free_gb()`.
### Осталось открытым
1. **Коммит в `lampac-scripts`** — `mark_missing.py` (переделка) и фикс `.env`-пути
**ещё не закоммичены**. В gitea лежит `1765c05`, там `mark_missing.py` старой версии.
2. **Имя в карточке из TMDB/КП** — требование Alex «отображать как в tmdb/kp,
ничего не укорачивать». Сейчас генератор пишет `it["name"]` = название из `.md`.
3. **Порядок в ленте Lampa** — «Мой список» (`displayindex: 1`, самый низкий из всех)
оказался **ниже** встроенных блоков «Сейчас Смотрят» и «Рекомендуем посмотреть».
Встроенные каталоги Lampa не из `sites/`, поэтому `displayindex` их не сдвигает.
Требует отдельного разбора — правился ли `watchlist.yaml` в этой сессии: НЕТ.
### Приёмка Alex (частично)
Alex подтвердил: *«вижу фильмы в ленте, работают»* — то есть каталог в UI **виден
и играет**. Это закрывает приёмку пунктов 1–3 из плана.
Осталось: **имя в карточке** и **порядок категорий**.
### Порядок резолва — финальная реализация в коде
```python
# 1) Radarr по названию
# 2) TMDB по названию как есть
# 2c) kp_id_from_url(it["kp_href"]) -> kp_search_by_id() -> _docs_to_tmdb()
# 2b) tmdb_via_kp() с KP_SIM_THRESHOLD
# 3) miss -> missing.json
```
Функции: `kp_id_from_url()`, `kp_search_by_id()`, `_docs_to_tmdb()`, `tmdb_via_kp_id()`,
`tmdb_via_kp()`, `kp_search()`, `title_sim()`. Константы: `KP_BASE`, `UA`,
`KP_SIM_THRESHOLD = 0.75`, `KP_ID_IN_URL`.
`_docs_to_tmdb()` — общая логика для 2b и 2c. Параметр `_by_id` на документе
отключает проверку порога: **если фильм пришёл по kp_id, близость названия не важна —
id и есть доказательство.**
---
## Требование Alex (дословно)
> «Нет блядь, нахуя мне в плеере заглушки?! Нормальный автопоиск! Никаких БЛЯДЬ ручных
@@ -534,7 +746,11 @@ def tmdb_via_kp(title, year, tmdb_key, kp_key, cache):
| `~/Developer/lampac-scripts/scripts/mark_missing.py` | маркер ❓ по `missing.json` (переделан, `--missing`) |
| `~/Developer/lampac-scripts/tests/accept_step1*.py` | приёмки автопоиска (3/3) |
| `~/lampac-tmp/` | рабочая свалка + все патч-скрипты сессии (НЕ git) |
| Кра́кен: `lampac/scripts/gen_watchlist.py` | **ЗАДЕПЛОЕННАЯ старая версия** — ждёт обновления |
| Кра́кен: `lampac/scripts/gen_watchlist.py` | **ЗАДЕПЛОЕНА НОВАЯ ВЕРСИЯ** (`3c7d4df3…`, `kraken:kraken 600`), бэкап старой `.bak-20260922-175754` |
| Кра́кен: `lampac/scripts/mark_missing.py` | задеплоен (`43b3bb15…`), ставит `❓` по `missing.json` |
| Кра́кен: `~/scripts/watchlist-catalog.sh` | обновлён (`17672d62…`) — генерация → маркер → restart lampac |
| Кра́кен: `lampac/wwwroot/missing.json` | снимок нерезолвленных (30 позиций) |
| `~/lampac-tmp/patch_envpath.py` | фикс `load_env()` — путь `.env` для Кра́кена (КРИТИЧНО) |
| `~/Developer/watchlist-sync/watchlist_sync/resolver.py` | ЭТАЛОН cross-reference |
| `~/Developer/watchlist-sync/watchlist_sync/discover.py` | TMDB-фильтр (Шаг 3, `_resolvable()`) |
| `~/Developer/watchlist-sync/watchlist_sync/cli.py` | `discover` передаёт `TMDB_KEY` |