From 7dbfead569b85e0e3d741d58825ce88134ab0e11 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Fri, 25 Sep 2026 22:15:59 +0600 Subject: [PATCH] [2026-09-25] eagle: personal/plans/lampac-watchlist-plugin.md personal/tech/lampac-deployment.md --- personal/plans/lampac-watchlist-plugin.md | 134 ++++++++++++++++++++-- personal/tech/lampac-deployment.md | 87 +++++++++++++- 2 files changed, 208 insertions(+), 13 deletions(-) diff --git a/personal/plans/lampac-watchlist-plugin.md b/personal/plans/lampac-watchlist-plugin.md index 93b23ab2..3a712063 100644 --- a/personal/plans/lampac-watchlist-plugin.md +++ b/personal/plans/lampac-watchlist-plugin.md @@ -8,7 +8,7 @@ related: - '[[family/projects/watchlist-automation]]' - '[[family/documents/movies-watchlist]]' - '[[personal/plans/lampac-watched-to-watchlist]]' -status: main-screen-filter-implemented-2026-09-25-awaiting-tv-acceptance +status: main-screen-filter-fix-regressed-then-fixed-2026-09-25-acceptance-blocked-on-empty-catalog tags: - lampac - lampa @@ -42,16 +42,21 @@ updated: '2026-09-25' прогружается относительно основного CUB списка, почему он не моментально проявляется, он же статичный». -**Статус: ✅ ФИКС ПРИМЕНЁН И ЗАЛИТ 2026-09-25. Ждёт только перезапуска Lampa на ТВ -(ТВ `192.168.1.70` был выключен — ни ping, ни CDP-порт 9998 не отвечали).** +**Статус: ⚠️ ФИКС ПРИМЕНЁН И ЗАЛИТ 2026-09-25, НО ПРИЁМКА ПРОВАЛЕНА — секции на +главной исчезли. См. «РЕГРЕСС И ВТОРОЙ ФИКС» ниже — там актуальная версия `wlOnMain`.** -### ✅ РЕШЕНИЕ: `wlOnMain()` — строгий белый список по активному activity +### ✅ РЕШЕНИЕ: `wlOnMain()` — белый список по активному activity -Alex: «В смысле всё кроме? **Только главный экран!**» — предикат сделан ЖЁСТКИМ +Alex: «В смысле всё кроме? **Только главный экран!**» — предикат сделан строгим (`=== 'main'`), не «всё кроме списка исключений». Любое незнакомое имя activity обязано по умолчанию секции НЕ получать. +⚠️ **ПЕРВАЯ ВЕРСИЯ (ниже) НЕРАБОЧАЯ — оставлена как история ошибки.** Она читала +`a.activity.url`; правильный уровень — `a.url` (измерено на ТВ, см. «РЕГРЕСС И ВТОРОЙ +ФИКС»). Актуальный текст — `wlUrl()` + `wlOnMain()` в разделе регресса. + ```js +// ❌ НЕРАБОЧАЯ ПЕРВАЯ ВЕРСИЯ — оставлена как история ошибки, НЕ КОПИРОВАТЬ function wlOnMain() { try { var a = (window.Lampa && Lampa.Activity && Lampa.Activity.active) @@ -199,15 +204,117 @@ Lampa.Api.partNext = function (parts, parts_limit, partLoaded, partEmpty) { категории. На 2026-09-25 `watchlist-catalog.sh` уже убран в `.bak-removed-20260924-181942`, отдельной строки крона `30 2 * * *` в crontab **нет** (п.2 из списка незакрытого — закрыт). +### 🔴 РЕГРЕСС И ВТОРОЙ ФИКС 2026-09-25 (после первой заливки) + +**Alex после перезапуска Lampa:** «Нету теперь списка на главной. Смотри логи.» +Секции исчезли ПОЛНОСТЬЮ — первая версия фильтра оказалась нерабочей. + +**Логи сняты с живой Lampa через CDP** (ТВ `192.168.1.70:9998`, скрипт +`/Users/admin/lampac-tmp/wl_console.py` + `/tmp/wl_probe*.py`; `websocket-client`, +`Runtime.enable` + `Log.enable`): + +``` +act = undefined ← фильтр сравнивал с 'main', получал пустое +comp = [object Object] +wl_menu_type = undefined ← window.__wl_menu НЕ создан +catalog_all = NOMANIFEST ← Lampa.Manifest.catalogs вообще пуст +patch = true ← перехватчик стоял, фильтр работал +src = cub +``` + +**🔴 КОРНЕВАЯ ПРИЧИНА №1 — `url` лежит НА ВЕРХНЕМ уровне activity, а не во вложенном.** +Измерено на живом ТВ (`/tmp/wl_probe5.py`, вывод дословно): + +``` +Lampa.Activity.active() → {url, title, component, source, page, params, activity} +Lampa.Activity.active().activity → {component, object, slide, body, is_stopped, is_started} + ↑ url ЗДЕСЬ НЕТ +``` + +Первая версия читала `active().activity.url` → **всегда `undefined`** → `=== 'main'` +всегда `false` → секции пропускались на главной ВСЕГДА. Фильтр не «слишком строгий» — +он смотрел не туда. **Проверять форму объекта ЗАМЕРОМ, а не по памяти: в доках +сессии 7 форма не была зафиксирована.** + +**🔴 КОРНЕВАЯ ПРИЧИНА №2 — `Manifest.catalogs` пуст** → `loadCatalogs()` не получил +`/catalog` от Lampac → `window.__wl_menu` не создан → **вставлять нечего**, даже если +фильтр пропускает. Строгая первая версия заодно отсекала ЕДИНСТВЕННЫЙ вызов `wlMenu()`, +который дозагружает меню повторным запросом. То есть фильтр не только не пропускал — +он снял путь восстановления. + +**Фикс (залит 2026-09-25 22:14):** новая функция `wlUrl(a)` читает **оба уровня**, +верхний первым, вложенный — фолбэк; плюс смягчающая ветка «пустой `url` + пустой +`catalogs` = инициализация главной → пропустить»: + +```js +function wlUrl(a) { + if (!a) return ''; + if (a.url) return a.url; // ← ПРАВИЛЬНЫЙ уровень + if (a.activity && a.activity.url) return a.activity.url; // фолбэк + return ''; +} + +function wlOnMain() { + var a = (window.Lampa && Lampa.Activity && Lampa.Activity.active) + ? Lampa.Activity.active() : null; + var act = wlUrl(a); + if (act === 'main') return true; + if (!act) { // главная ещё инициализируется + var c = (window.Lampa && Lampa.Manifest && Lampa.Manifest.catalogs) || {}; + if (!Object.keys(c).length) return true; + } + console.log('[watchlist] не главная (' + (act || '?') + ') — секции пропущены'); + return false; +} +``` + +Ложная вставка на чужом экране при этом невозможна: без `__wl_menu` вставлять нечего. + +**Сборка и деплой (все инварианты пройдены):** +``` +python3 build_plugin.py → 12/12, 18281 байт +node --check plugin-cub.js → SYNTAX OK +``` +Новые инварианты сборщика: `wlUrl def`, `wlUrl верхний уровень` +(`if (a.url) return a.url;`) — сборка падает, если чтение уровня откатится назад. +Бэкап: `catalog/plugin.js.bak-before-fixurl-`. Залито → 20934 Б, +`docker exec lampac grep -n "function wlUrl" -A4 /lampac/module/Catalog/plugin.js` → на месте. + +**⚠️ НА МОМЕНТ ЗАПИСИ ФИКС НЕ ПРИЁМКОВАН.** Замер после заливки: `url = ""` +на ОБОИХ уровнях, `hasCats = false`, `menu = 0`. То есть Lampa стоит на главной давно +(URL страницы `component=main&source=cub`), но `Activity.active().url` пуст — это НЕ +стадия инициализации. Пока `/catalog` не отвечает, `__wl_menu` пуст и секции взять +неоткуда: **перезапуск Lampa без починенного `/catalog` ничего не даст.** + +**Следующий шаг (обязательный, не сделан):** проверить боевой запрос Lampa → Lampac +`/catalog` — отвечает ли он с ТВ, отвечает ли с Кра́кена, не сломан ли он вообще. + +### Инструменты диагностики ТВ, написанные в этой сессии (переиспользовать) + +| Скрипт | Что делает | +|---|---| +| `/Users/admin/lampac-tmp/wl_console.py` | CDP-клиент: сбор `console`-логов Lampa за 12 с + снимок состояния (`act`, `patch`, `menu`, `pending`, `src`) | +| `/tmp/wl_probe2..5.py` | точечные пробы структуры `Activity.active()` (ключи, типы, значения) | + +🔴 **Питфоллы CDP-проб, найденные на живом ТВ:** +- `JSON.stringify(Lampa.Activity.active())` → **`TypeError: Converting circular structure + to JSON`**. Возвращать поля по одному или собирать строку вручную. +- Обращаться к отсутствующему полю в `Runtime.evaluate` **без** обёртки — CDP отвечает + без `result.value`, и выглядит это как «все пробы пустые» (первый прогон дал девять + `` подряд). Каждую пробу оборачивать в `String(...)` / `typeof ...` и проверять + `subtype == "error"`. +- `Log.enable` + `Runtime.enable` дают **0 строк** лога, если Lampa уже загрузилась — + консольные сообщения, напечатанные до подключения, не отдаются. Логи читать СРАЗУ + после перезапуска приложения, либо подтверждать состояние пробами, а не логами. + ### Открытые шаги (для следующей сессии) -1. ✅ **ЗАКРЫТО 2026-09-25** — фикс «фид на всех экранах»: `wlOnMain()` + гард в - `wlPatchPartNext`, залито на Кра́кен. Осталась приёмка на ТВ (перезапуск Lampa + - визуальная проверка главной и «Фильмы → документальные»). +1. 🔴 **ПРИЁМКА НЕ ПРОЙДЕНА** — фикс `wlUrl` залит, но секции на главной не появились. + **Корень — пустой `Manifest.catalogs`: `/catalog` не отвечает Lampa.** Без этого + фильтр не при чём. Проверить боевой `/catalog` (с ТВ и с Кра́кена) — ПЕРВЫМ делом. 2. **Диагностировать 66 с на карточке** — `docker logs lampac` + трейс `CardController`. - Единственный замеренный источник ощущения «не моментально», который НЕ объясняется - холодным `hybridCache` (2.25 с). Запрос: - `GET /catalog/card?plugin=watchlist&uri=movie%2F424781&type=movie` → 66 118 мс, 939 Б. + Запрос: `GET /catalog/card?plugin=watchlist&uri=movie%2F424781&type=movie` + → 66 118 мс, 939 Б. 3. **Matcher-parity** (главный блокер с 2026-09-24, см. ниже) — всё ещё не закрыт. **Правило диагностики этой сессии:** не читать `%{size_download}` как «размер фида» @@ -219,7 +326,10 @@ Lampa.Api.partNext = function (parts, parts_limit, partLoaded, partEmpty) { (`No module named 'psutil'`) — расследование и правки сделаны через `terminal` + `read_file` + `patch`, БЕЗ python-скриптов. `scp` файла `wwwroot/catalog.js` не нашёл: такого пути НЕТ, `plugin.js` живёт в `lampac/catalog/plugin.js` и монтируется в -`/lampac/module/Catalog/plugin.js`. +`/lampac/module/Catalog/plugin.js`. Alex отдельно и дважды требовал результат +расследования (не план, не вопрос): «задача блядь поставлена», «хули ты творишь. ты +блядь не можешь в код проекта посмотреть и в доки и все выяснить?» — **сначала читать +код проекта и доки, потом отвечать.** --- diff --git a/personal/tech/lampac-deployment.md b/personal/tech/lampac-deployment.md index 24d0992e..1f19aa86 100644 --- a/personal/tech/lampac-deployment.md +++ b/personal/tech/lampac-deployment.md @@ -1,7 +1,7 @@ --- title: Lampac — развёртывание и эксплуатация (Кра́кен) created: '2026-09-22' -updated: '2026-09-24' +updated: '2026-09-25' type: tech namespace: personal tags: @@ -28,6 +28,91 @@ related: > Технический справочник. Развёрнуто 2026-09-22. План и статус шагов — [[personal/plans/lampac-kraken]]. +## 🔴 2026-09-25: деплой `plugin.js` модуля Catalog — контракт и подводные камни + +Правки фида Watchlist в UI Lampa живут НЕ в YAML, а в `plugin.js` модуля Catalog +(патч `enumerable:true` + инжект секций через перехват `Lampa.Api.partNext`). +Полный план и статус — [[personal/plans/lampac-watchlist-plugin]]. + +### Где лежит файл (три разных места — не путать) + +| Слой | Путь | Примечание | +|---|---|---| +| Mac, исходник | `/Users/admin/lampac-tmp/plugin-cub.js` | результат `build_plugin.py` | +| Mac, сборщик | `/Users/admin/lampac-tmp/build_plugin.py` | 🔴 `plugin-cub.js` РУКАМИ не правим | +| Кра́кен, хост | `/srv/dev-disk-by-uuid-6194539b-.../lampac/catalog/plugin.js` | bind-mount | +| В контейнере | `/lampac/module/Catalog/plugin.js` | `:ro` по compose | +| По HTTP | `http://192.168.1.14:9118/catalog.js` | что реально грузит ТВ | + +🔴 **`wwwroot/catalog.js` НЕ существует.** `wwwroot/` содержит только JSON фида +(`watchlist.json`, `watchlist-.json`, `cards.json`, `cards/`, `missing.json`). +Попытка `scp` оттуда падает с «No such file or directory» — это не сбой сети. + +### Порядок деплоя (боевой конфиг — коммит ДО, правка, заливка, ПРОВЕРКА, коммит ПОСЛЕ) + +```bash +cd /Users/admin/lampac-tmp +python3 build_plugin.py # инварианты: сборка падает при нарушении +node --check plugin-cub.js # SYNTAX OK обязателен +# бэкап боевого +ssh kraken 'cp .../lampac/catalog/plugin.js .../catalog/plugin.js.bak-<что>-$(date +%Y%m%d-%H%M%S)' +scp plugin-cub.js kraken:.../lampac/catalog/plugin.js +# проверка, что файл виден в контейнере (bind-mount) +ssh kraken 'docker exec lampac grep -c "<маркер>" /lampac/module/Catalog/plugin.js' +``` + +### 🔴 Перезапуск Lampa на ТВ обязателен + +`docker restart lampac` **НЕ сбрасывает** кэш `catalog.js` в браузере webOS — ТВ +продолжит исполнять старую версию плагина. Нужен рестарт приложения на ТВ: + +```bash +scp /Users/admin/lampac-tmp/tv_restart.sh root@192.168.1.70:/tmp/ \ + && ssh root@192.168.1.70 'sh /tmp/tv_restart.sh' +``` + +⚠️ `luna-send` через `ssh 'script -q -c "luna-send ... -a {\"id\":...}"'` ломается на +экранировании JSON (luna-send печатает help) — поэтому скрипт кладётся файлом на ТВ. + +### 🔴 Форма `Lampa.Activity.active()` — ИЗМЕРЕНО на живом ТВ 2026-09-25 + +``` +Lampa.Activity.active() → {url, title, component, source, page, params, activity} +Lampa.Activity.active().activity → {component, object, slide, body, is_stopped, is_started} + ↑ url ЗДЕСЬ НЕТ +``` + +**`url` лежит на ВЕРХНЕМ уровне.** Обращение к `.activity.url` всегда даёт `undefined` — +на этом была потеряна приёмка 2026-09-25 (фильтр «только главная» смотрел не туда и +секции исчезли полностью). Читать оба уровня, верхний первым. + +### 🔴 CDP-диагностика ТВ (порт 9998) — питфоллы + +```bash +curl -s "http://192.168.1.70:9998/json/list" | jq -r '.[] | select(.title=="Lampac") | .webSocketDebuggerUrl' +``` +Клиент — `websocket-client` (модуля `websockets` на Mac НЕТ). Готовый скрипт: +`/Users/admin/lampac-tmp/wl_console.py`. + +- `JSON.stringify(Lampa.Activity.active())` → **`TypeError: Converting circular structure + to JSON`**. Возвращать поля по одному. +- Обращение к отсутствующему полю в `Runtime.evaluate` без обёртки → ответ без + `result.value`, выглядит как «все пробы вернули ``». Оборачивать в + `String(...)` / `typeof ...`, проверять `subtype == "error"`. +- `Runtime.enable` + `Log.enable` дают **0 строк**, если Lampa уже загрузилась: + сообщения, напечатанные до подключения, не отдаются. Логи читать сразу после + рестарта приложения либо подтверждать состояние пробами. +- 🔴 `URL страницы ТВ — надёжный индикатор экрана`: `...index.html?title=Главная%20-%20CUB + &component=main&source=cub` = главная CUB. + +### 🔴 `Manifest.catalogs` пуст = фид вставлять некуда + +Если `/catalog` от Lampac не ответил, `loadCatalogs()` не отработал → +`window.__wl_menu` не создан → **секции Watchlist не появятся ни на одном экране**, +независимо от фильтров. Наблюдалось 2026-09-25: `catalog_all = NOMANIFEST`, +`wl_menu = undefined`, при этом `patch = true`. Диагностировать это ПЕРВЫМ, до +разбора логики фильтра. + ## 🔴 2026-09-24 (вечер): «Мастерская сатаны» — один источник, торренты пусты. План диагностики **Вопрос Alex:** *«для Мастерская сатаны например в lampac в источниках есть только