From 7a021b26c330e7851e3e77bb7184427dac5f3516 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Tue, 22 Sep 2026 16:07:21 +0600 Subject: [PATCH] [2026-09-22] eagle: personal/plans/lampac-watchlist-plugin.md personal/tech/lampac-deployment.md --- personal/plans/lampac-watchlist-plugin.md | 34 ++++- personal/tech/lampac-deployment.md | 168 +++++++++++++++++++++- 2 files changed, 192 insertions(+), 10 deletions(-) diff --git a/personal/plans/lampac-watchlist-plugin.md b/personal/plans/lampac-watchlist-plugin.md index 426b7c0d..8a8e65b6 100644 --- a/personal/plans/lampac-watchlist-plugin.md +++ b/personal/plans/lampac-watchlist-plugin.md @@ -7,7 +7,7 @@ related: - '[[family/projects/watchlist-sync]]' - '[[family/projects/watchlist-automation]]' - '[[family/documents/movies-watchlist]]' -status: cub-sections-pending +status: accepted-in-ui-cub-sections-pending tags: - lampac - lampa @@ -59,12 +59,32 @@ updated: '2026-09-22' > (я подставлял латиницу руками → 200 → ложный вывод «проблема в клиенте»). Детали — > [[personal/tech/lampac-deployment]] раздел «🔴🔴 ГЛАВНАЯ ПРИЧИНА». > -> **⚠️ ЗАДАЧА СЛЕДУЮЩЕЙ СЕССИИ (требование Alex, не закрыто):** секции должны быть -> **ВНУТРИ CUB без ручного переключения источника**. Дословно: «надо блядь добавить в CUB -> список новые секции а не ручное блядь переключение!». Хук `Listener.follow('menu')` + -> `e.abort()` в `plugin.js:59` молчит при активном CUB (`Api.getCatalog()` читает манифест -> текущего источника). Решение — дорисовывать ряды в корень CUB через -> `Lampa.Listener.follow('activity')` либо патч рендера главной. +> **⚠️ ЗАДАЧА СЕССИИ (требование Alex): ✅ ВЫПОЛНЕНО — СЕКЦИИ ВНЕДРЯЮТСЯ В CUB-ФИД.** +> Дословно требование: «надо блядь добавить в CUB список новые секции а не ручное +> блядь переключение!». Реализовано в `plugin-cub.js` через **обёртку +> `Lampa.Api.sources.cub.main`**: наши секции **добавляются** в массив +> `parts_data` CUB-фида (не подменяют раздел), карточкам проставляется +> `source: 'watchlist'`. Вызов — по событию `app:ready`. +> Залито, отдаётся в сборке `/catalog.js` (35566 Б). **Ожидает приёмки в UI.** +> Механика — [[personal/tech/lampac-deployment]] раздел «Внедрение секций Watchlist в CUB-фид». +> +> **Обновление 2026-09-22 (пятая сессия): ✅✅ ПРИЁМКА ALEX ПРОЙДЕНА — ФИЛЬМЫ ОТКРЫВАЮТСЯ И ПРОИГРЫВАЮТСЯ.** +> Дословно: «фильмы из списка Watchlist теперь открываются и проигрываются». +> Закрыт последний блокер — кириллический ключ плагина (`plugin: watchlist`). +> Плюс устранён питфолл `Staticache` (кэш собранного `/catalog.js` переживал +> заливку и выглядел как «патч не применяется» → `docker restart lampac`). +> +> **Осталось (2026-09-22, конец сессии):** +> 1. **5 фильмов с Кинопоиск-ID** (`film/NNNNN/`) — «Рассекая волны: экспедиция „Лас Бальсас“», +> «Хамнет», «Цена вершины», «Астрал. Могильный ритуал 2», «О добре и зле». +> TMDB не нашёл (2025 год) → нет карточки и постера → клик даёт «здесь пусто». +> **Нужен выбор Alex:** заглушка с кнопкой поиска торрента либо дорисовать `tmdb_id`. +> 2. **~51 название без постера** — проблема ЗАПИСИ В СПИСКЕ, не скрипта: +> `Плохие парни 1/2` (ДВА фильма одной строкой), `Солярис Тарковский` (уточнение +> режиссёра), `Самолетом, поездом, машиной (1987)` (русский аналог). +> Генератор такое угадать не может — **правится только список руками**. +> 3. **Секции CUB в UI** — инжект залит, нужен перезапуск Lampa и визуальная проверка: +> секции Watchlist должны появиться поверх родного фида CUB при активном источнике CUB. > > **Обновление 2026-09-22 (четвёртая сессия, ранее): ✅ ЧИСЛОВОЙ `tmdb_id` В КАРТОЧКАХ.** > 352 из 352 карточек отдают `tmdb_id` числом, `source`, `runtime`, `vote_average`, жанры. diff --git a/personal/tech/lampac-deployment.md b/personal/tech/lampac-deployment.md index 884f5ded..d963f565 100644 --- a/personal/tech/lampac-deployment.md +++ b/personal/tech/lampac-deployment.md @@ -1658,6 +1658,122 @@ ssh kraken "sudo timeout 40 tcpdump -i any -n -A 'host 192.168.1.70 and port 911 ⚠️ Также: `&&`-цепочка в `ssh -t` рвёт tty-сессию («Connection closed»). Каждую команду — отдельным вызовом. +## 🔴 Staticache — `/catalog.js` собирается и КЭШИРУЕТСЯ + +`/catalog.js` — **не файл**, а **сборка**: Lampac берёт `plugin.js` из +`/lampac/module/Catalog/plugin.js`, подставляет `api_host` и `catalogs` +(отсюда ~18 КБ разницы от исходника) и кэширует результат через +атрибут `[Staticache]`. + +**Питфолл, который стоил времени:** залил новый `plugin.js` (14099 Б, +патч на месте — `grep` подтверждает), а `/catalog.js` продолжал отдавать +**старую сборку** (32205 Б, патча нет). Выглядело как «патч не применяется». + +``` +=== патч в контейнере: +14099 /lampac/module/Catalog/plugin.js ← патч ЕСТЬ +=== что отдаёт клиенту: +32205 байт, injectWatchlistParts: 0 ← патча НЕТ +``` + +**Лечение:** `docker restart lampac` (сбрасывает Staticache-кэш), затем +проверять **размер и маркеры в отдаваемом файле**, а не только в файле на диске: + +```bash +curl -s "http://192.168.1.14:9118/catalog.js" -o /tmp/cj.js +wc -c < /tmp/cj.js # размер сборки +grep -c injectWatchlistParts /tmp/cj.js # наш маркер +grep -c patchCubMain /tmp/cj.js +``` + +⚠️ Заголовки при этом отдают `Cache-Control: no-cache` — но это HTTP-кэш +клиента, а `Staticache` кэширует **на сервере**, поэтому заголовки не помогают +и клиентская очистка кэша проблему не решает. + +## Внедрение секций Watchlist в CUB-фид (`plugin-cub.js`) + +**Требование Alex:** секции Watchlist должны быть видны **ВНУТРИ источника CUB**, +без ручного переключения «Основной источник». Переключение — не решение. + +### Почему штатный хук не подходит + +`plugin.js` содержит `Lampa.Listener.follow('menu', ...)` + `e.abort()`: +он **перехватывает и ОТМЕНЯЕТ** разделы `movie/tv/cartoon/anime/relise`, +подменяя их нашими. Но `Api.getCatalog()` читает +`Manifest.catalogs[Lampa.Storage.field('source')]` — то есть каталог +**текущего** источника. При активном CUB нашего каталога там нет → хук молчит → +открывается родной CUB. Подмена работает только когда активен наш источник. + +### Рабочая механика: обернуть `main` CUB-источника + +`main$1()` в `app.min.js:33880` собирает массив `parts_data` — функций-загрузчиков, +каждая добавляет секцию на главную, и отдаёт через `Lampa.Api.partNext`. +Значит наши секции надо **добавить в этот массив**, а не подменять раздел. + +Патч (`patch_cub_inject.py` → `plugin-cub.js`): + +```js +function injectWatchlistParts(original) { + return function (params, oncomplite, onerror) { + original(params, function (cub_data) { + var wl = Manifest.catalogs['watchlist']; + if (!wl) return oncomplite(cub_data); + var menu = wl.menu || {}, keys = Object.keys(menu); + var list = Lampa.Arrays.isArray(cub_data) ? cub_data.slice() : [cub_data]; + var pending = keys.length; + keys.forEach(function (name) { + network.silent(Utils.account(menu[name]), function (json) { + json.title = name; // заголовок секции + json.source = 'watchlist'; // источник для карточек + (json.results || []).forEach(function (it) { it.source = 'watchlist'; }); + list.push(json); // ДОБАВЛЯЕМ, не заменяем + if (--pending === 0) oncomplite(list); + }, function () { if (--pending === 0) oncomplite(list); }); + }); + }, onerror); + }; +} +function patchCubMain() { + var src = Lampa.Api.sources.cub; + if (!src || src.__wl_injected) return; + src.main = injectWatchlistParts(src.main); + src.__wl_injected = true; +} +``` + +Вызов — **по событию `app:ready`**, потому что нужны и `Lampa.Api.sources.cub`, +и загруженный `Manifest.catalogs['watchlist']`: + +```js +if(window.appready){patchCubMain();} +else{Lampa.Listener.follow('app',function(e){if(e.type=='ready')patchCubMain();});} +``` + +🔴 **Ключевое в карточках наших секций — `source: 'watchlist'`.** Без него +клик уйдёт в CUB-карточку по TMDB-id и «Мой список» потеряется. + +### Питфолл скрипта-патчера + +🔴 **Порядок проверок в `patch_cub_inject.py` критичен.** Если сначала вставить +`INJECT` (который содержит текст `patchCubMain`), то последующая проверка +`"patchCubMain()" not in s` даст ложное «уже есть» и **вызов не вставится**. +Правильно: сначала проверить/вставить **ВЫЗОВ** (`if(window.appready){patchCubMain();}`), +и только потом — определение `INJECT`. + +Проверка синтаксиса обязательна: `node --check plugin-cub.js`. + +### Файлы патча + +| Файл | Что | +|---|---| +| `plugin.js` | оригинал из образа (10670 Б) | +| `plugin-patched.js` | + `enumerable:true` (видимость источника в UI) | +| `plugin-cub.js` | + инжект секций в CUB-фид (**финальный, заливается**) | +| `patch_plugin.py` | делает `plugin-patched.js` | +| `patch_cub_inject.py` | делает `plugin-cub.js` из `plugin-patched.js` | + +`deploy_lampac.py` шаг 4 берёт **`plugin-cub.js`**, с фолбэком на `plugin-patched.js`. + ## Итоговое состояние (2026-09-22, конец сессии) | Что | Статус | @@ -1669,9 +1785,55 @@ ssh kraken "sudo timeout 40 tcpdump -i any -n -A 'host 192.168.1.70 and port 911 | `tmdb_id` в карточке | числом через `format: "long.TryParse(value, out long v) ? v : 0"` | | `runtime`, `vote_average` | тем же способом через `format` | | `displayname` | «Мой список» — надпись в UI | -| ✅ Проверено Alex в UI | ожидает | +| **✅ Alex подтвердил в UI** | **фильмы Watchlist открываются и ПРОИГРЫВАЮТСЯ** | +| Инжект секций в CUB-фид | залито, ожидает проверки в UI (перезапуск Lampa) | Скрипты: `/Users/admin/lampac-tmp/gen_watchlist_v2.py`, `deploy_lampac.py` -(`--skip-plugin` для быстрого прогона). Проверка в шаге 7 теперь валидирует -именно ключ `watchlist` и предупреждает, если в `/catalog` остался русский ключ. +(`--skip-plugin` для быстрого прогона), `patch_cub_inject.py`. +Проверка в шаге 7 валидирует именно ключ `watchlist` и предупреждает, +если в `/catalog` остался русский ключ. + +## ⏳ Осталось добить (2026-09-22) + +### 1. 5 фильмов с Кинопоиск-ID — «здесь пусто», без постера + +`film/12432920/`, `film/5454868/`, `film/11888712/`, `film/11825624/`, `film/8184798/` +(«Рассекая волны: экспедиция „Лас Бальсас“», «Хамнет», «Цена вершины», +«Астрал. Могильный ритуал 2», «О добре и зле»). + +**Причина:** `href` в списке — ссылка на Кинопоиск, TMDB не нашёл (преимущественно +фильмы 2025), поэтому `id = film/NNNNN/` вместо `movie/NNNN`. Карточки +`card-film-...json` не существует → клик даёт пустоту; постера нет по той же причине. + +**Решения (нужен выбор Alex):** заглушка с названием + кнопка поиска торрента, +либо дорисовывать `tmdb_id` вручную. + +### 2. ~51 название без постера — проблема ЗАПИСИ В СПИСКЕ, не скрипта + +Кэш резолвера `~/.lampac_tmdb_cache.json` содержит 51 запись со значением `null`. +По названиям видны три класса: + +| Пример | В списке | TMDB знает как | +|---|---|---| +| `Плохие парни 1/2`, `Никто 1/2` | как есть | **ДВА фильма в одной строке** | +| `Солярис Тарковский`, `Идиот Бортко` | как есть | «Солярис» (1972) / «Идиот» (2003) | +| `Самолетом, поездом, машиной (1987)` | как есть | «Planes, Trains and Automobiles» | + +Скрипт не может угадать, что `1/2` — два фильма, а «Тарковский» — уточнение +режиссёра. **Правится только список руками**, не генератором. + +### 3. Секции CUB — проверить в UI + +Инжект залит (`plugin-cub.js`, 35566 Б в отдаваемой сборке). Нужен перезапуск +Lampa на ТВ и проверка: секции Watchlist появляются **поверх родного фида CUB**. + +## Питфоллы проверки на ТВ (сводка) + +1. **Lampa кэширует манифест и ответы.** После правок — **полностью выгрузить + приложение**, не сворачивать. `loader.js` использует `cache_version` + (9e5 мс ≈ 15 мин), плюс свой `localStorage`. +2. `luna-send` пишет в **tty**, не в stdout → обёртка + `script -q -c "luna-send ..." /tmp/o.txt`, читать файл. + (Доки: `family/how-to/tv-luna-send.md`.) +3. Реальный запрос клиента ловить `tcpdump` на сервере — см. «ПРАВИЛО ДИАГНОСТИКИ» выше.