[2026-09-25] eagle: personal/plans/lampac-watchlist-plugin.md
This commit is contained in:
1 parent
a0d298568c
commit
aed8c42aa3
1 file changed
+162
-18
@@ -8,7 +8,7 @@ related:
|
||||
- '[[family/projects/watchlist-automation]]'
|
||||
- '[[family/documents/movies-watchlist]]'
|
||||
- '[[personal/plans/lampac-watched-to-watchlist]]'
|
||||
status: investigation-2026-09-25-all-screens-feed-and-latency
|
||||
status: main-screen-filter-implemented-2026-09-25-awaiting-tv-acceptance
|
||||
tags:
|
||||
- lampac
|
||||
- lampa
|
||||
@@ -26,6 +26,7 @@ tags:
|
||||
- matcher-parity
|
||||
- partnext
|
||||
- latency
|
||||
- wlonmain
|
||||
title: Watchlist в UI Lampa — каталог из списка
|
||||
type: plan
|
||||
updated: '2026-09-25'
|
||||
@@ -41,14 +42,82 @@ updated: '2026-09-25'
|
||||
прогружается относительно основного CUB списка, почему он не моментально проявляется,
|
||||
он же статичный».
|
||||
|
||||
**Статус: расследование завершено, причина установлена, фикс НЕ применён (ждёт апрува).**
|
||||
**Статус: ✅ ФИКС ПРИМЕНЁН И ЗАЛИТ 2026-09-25. Ждёт только перезапуска Lampa на ТВ
|
||||
(ТВ `192.168.1.70` был выключен — ни ping, ни CDP-порт 9998 не отвечали).**
|
||||
|
||||
### Причина 1 — фид на всех экранах: в `plugin-cub.js` НЕТ фильтра по экрану
|
||||
### ✅ РЕШЕНИЕ: `wlOnMain()` — строгий белый список по активному activity
|
||||
|
||||
Файл: `/Users/admin/lampac-tmp/plugin-cub.js` (196 строк, сборка `build_plugin.py`;
|
||||
Alex: «В смысле всё кроме? **Только главный экран!**» — предикат сделан ЖЁСТКИМ
|
||||
(`=== 'main'`), не «всё кроме списка исключений». Любое незнакомое имя activity
|
||||
обязано по умолчанию секции НЕ получать.
|
||||
|
||||
```js
|
||||
function wlOnMain() {
|
||||
try {
|
||||
var a = (window.Lampa && Lampa.Activity && Lampa.Activity.active)
|
||||
? Lampa.Activity.active() : null;
|
||||
var act = (a && a.activity && a.activity.url) ? a.activity.url : '';
|
||||
if (act === 'main') return true;
|
||||
console.log('[watchlist] не главная (' + (act || '?') + ') — секции пропущены');
|
||||
return false;
|
||||
} catch (e) {
|
||||
console.log('[watchlist] wlOnMain error', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Гард в перехватчике (`plugin-cub.js:193`):
|
||||
```js
|
||||
if (wlOnMain() && Lampa.Arrays.isArray(parts) && !parts.__wl_done) { ... wlInject(parts, menu); }
|
||||
```
|
||||
|
||||
🔴 **Второе, неочевидное изменение:** `parts.__wl_done = true` теперь ставится ТОЛЬКО
|
||||
внутри ветки фактической вставки. Раньше флаг мог выставиться до готовности
|
||||
`window.__wl_menu` — и тогда вставка была бы закрыта НАВСЕГДА, главная осталась бы без
|
||||
секций после возврата из категории.
|
||||
|
||||
**Файлы:**
|
||||
- `/Users/admin/lampac-tmp/plugin-cub.js` — рабочая сборка (бэкап
|
||||
`plugin-cub.js.bak-before-filter-<ts>`)
|
||||
- `/Users/admin/lampac-tmp/build_plugin.py` — тот же текст в константе `INJECT`
|
||||
(сборщик детерминированный; `plugin-cub.js` руками не правим) + **2 новых инварианта**:
|
||||
`wlOnMain def` и `wlOnMain guard` — сборка падает, если фильтр пропал
|
||||
|
||||
**Проверки перед заливкой (все пройдены):**
|
||||
```
|
||||
python3 build_plugin.py → 10/10 инвариантов, 17241 байт
|
||||
node --check plugin-cub.js → SYNTAX OK
|
||||
```
|
||||
|
||||
**Деплой (выполнен):**
|
||||
1. бэкап боевого — `catalog/plugin.js.bak-before-mainfilter-20260925-220809` (17476 Б)
|
||||
2. `scp plugin-cub.js kraken:...6194539b.../lampac/catalog/plugin.js` → 19576 Б,
|
||||
md5 `53ccdc306cf6a14f343eaeb67a8a29c3`
|
||||
3. bind-mount проверен: `docker exec lampac grep -c wlOnMain
|
||||
/lampac/module/Catalog/plugin.js` → **3**
|
||||
4. по HTTP тоже отдаётся: `curl http://127.0.0.1:9118/catalog.js` → 41050 Б, `wlOnMain` ×3
|
||||
|
||||
**Осталось — перезапуск Lampa на ТВ** (webOS кэширует `catalog.js`, `docker restart
|
||||
lampac` его НЕ сбрасывает):
|
||||
```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'
|
||||
```
|
||||
|
||||
**Приёмка = видно в UI** (не «API отвечает»): главная — 4 секции Watchlist сверху;
|
||||
Фильмы → документальные — секций НЕТ. Если фид вылезет ещё где-то — в логе ТВ будет
|
||||
строка `[watchlist] не главная (<имя>)`, по ней добавить имя в разбор.
|
||||
|
||||
**Что НЕ трогалось:** `window.__wl_menu`, `wlGet`/`wlAbs`/`wlHost`, `unshift`,
|
||||
`watchlist.yaml`, `sync_down.py`, nightly-пайплайн.
|
||||
|
||||
### Причина 1 (диагноз) — в `plugin-cub.js` НЕ БЫЛО фильтра по экрану
|
||||
|
||||
Файл: `/Users/admin/lampac-tmp/plugin-cub.js` (сборка `build_plugin.py`;
|
||||
это тот же файл, что залит в Lampac как `module/Catalog/plugin.js`).
|
||||
|
||||
`wlPatchPartNext()` (строки 155–193) — перехват глобального `Lampa.Api.partNext`:
|
||||
`wlPatchPartNext()` — перехват глобального `Lampa.Api.partNext` — до фикса выглядел так:
|
||||
|
||||
```js
|
||||
Lampa.Api.partNext = function (parts, parts_limit, partLoaded, partEmpty) {
|
||||
@@ -61,18 +130,16 @@ Lampa.Api.partNext = function (parts, parts_limit, partLoaded, partEmpty) {
|
||||
}
|
||||
```
|
||||
|
||||
**Ни одного обращения к активному экрану** — нет проверки `Lampa.Activity.active()`,
|
||||
`activity.url`, `Lampa.Storage.field('source')` или чего-либо подобного.
|
||||
|
||||
Механика: `partNext` — глобальный API, через него строят страницу ВСЕ источники.
|
||||
`plugin.js:30` (`main()`) и `plugin.js:36` (`category()`) **оба** вызывают
|
||||
**Ни одного обращения к активному экрану** — это не регресс, а исходное отсутствие
|
||||
проверки. Механика: `partNext` — глобальный API, через него строят страницу ВСЕ
|
||||
источники. `plugin.js:30` (`main()`) и `plugin.js:36` (`category()`) **оба** вызывают
|
||||
`Lampa.Api.partNext(parts_data, parts_limit, ...)`. Отсюда:
|
||||
- CUB рисует главную → перехват срабатывает → наши 4 секции сверху;
|
||||
- вход в категорию («документальные» внутри Фильмов) → Lampa перестраивает страницу
|
||||
через **тот же** `partNext` → перехват срабатывает снова → фид снова сверху.
|
||||
|
||||
`wlInject()` (строки 121–127) кладёт секции через `unshift` в **начало** пула, поэтому
|
||||
они рисуются поверх содержимого любой категории — ровно то, на что жалуется Alex.
|
||||
`wlInject()` кладёт секции через `unshift` в **начало** пула, поэтому они рисуются
|
||||
поверх содержимого любой категории — ровно то, на что жаловался Alex.
|
||||
|
||||
### Причина 2 — «долго грузится»: замеры (не догадки)
|
||||
|
||||
@@ -134,16 +201,25 @@ Lampa.Api.partNext = function (parts, parts_limit, partLoaded, partEmpty) {
|
||||
|
||||
### Открытые шаги (для следующей сессии)
|
||||
|
||||
1. **Фикс «фид на всех экранах»:** добавить в `wlPatchPartNext` проверку активного экрана —
|
||||
инжектить только когда `Lampa.Activity.active()` указывает на главную, иначе
|
||||
пропускать. Точный предикат определить CDP-пробой на живом ТВ (`probe_ui.py`):
|
||||
прочитать `Lampa.Activity.active()` на главной и внутри категории, сравнить.
|
||||
1. ✅ **ЗАКРЫТО 2026-09-25** — фикс «фид на всех экранах»: `wlOnMain()` + гард в
|
||||
`wlPatchPartNext`, залито на Кра́кен. Осталась приёмка на ТВ (перезапуск Lampa +
|
||||
визуальная проверка главной и «Фильмы → документальные»).
|
||||
2. **Диагностировать 66 с на карточке** — `docker logs lampac` + трейс `CardController`.
|
||||
Единственный замеренный источник ощущения «не моментально», который НЕ объясняется
|
||||
холодным `hybridCache` (2.25 с). Запрос:
|
||||
`GET /catalog/card?plugin=watchlist&uri=movie%2F424781&type=movie` → 66 118 мс, 939 Б.
|
||||
3. **Matcher-parity** (главный блокер с 2026-09-24, см. ниже) — всё ещё не закрыт.
|
||||
|
||||
**Правило диагностики этой сессии:** не читать `%{size_download}` как «размер фида»
|
||||
(это gzip). И — `ifconfig` на Кра́кене отсутствует, ssh-команды через `bash -c` иначе
|
||||
падают шумом.
|
||||
(это gzip) — брать `ls -la` или `Accept-Encoding: identity`. И — `ifconfig` на Кра́кене
|
||||
отсутствует: каждая ssh-команда печатает `bash: line 1: ifconfig: command not found`
|
||||
безвредным шумом, это НЕ ошибка команды.
|
||||
|
||||
**🔴 Питфолл инструментов этой сессии:** `execute_code` падал на `import`
|
||||
(`No module named 'psutil'`) — расследование и правки сделаны через `terminal` +
|
||||
`read_file` + `patch`, БЕЗ python-скриптов. `scp` файла `wwwroot/catalog.js` не нашёл:
|
||||
такого пути НЕТ, `plugin.js` живёт в `lampac/catalog/plugin.js` и монтируется в
|
||||
`/lampac/module/Catalog/plugin.js`.
|
||||
|
||||
---
|
||||
|
||||
@@ -492,6 +568,74 @@ Alex уточнил требование: «это же чистая дораб
|
||||
|
||||
---
|
||||
|
||||
## 🟢 ВОСЬМАЯ СЕССИЯ 2026-09-25: ФИЛЬТР «СЕКЦИИ ТОЛЬКО НА ГЛАВНОЙ» (PLAN)
|
||||
|
||||
**Задача Alex:** «watchlist фид отображается не только на главной, но даже когда я
|
||||
выбираю категорию например "документальные" в разделе Фильмы» + «он как будто долго
|
||||
прогружается относительно основного CUB списка». Требование: **ТОЛЬКО ГЛАВНЫЙ ЭКРАН**
|
||||
(белый список, не чёрный — Alex: «В смысле всё кроме? Только главный экран!»).
|
||||
|
||||
### Диагноз (по коду, замеры)
|
||||
|
||||
1. **Причина «на любом экране».** `plugin-cub.js:164` — `wlPatchPartNext` вставляет
|
||||
секции БЕЗУСЛОВНО:
|
||||
```js
|
||||
if (Lampa.Arrays.isArray(parts) && !parts.__wl_done) {
|
||||
var menu = window.__wl_menu;
|
||||
if (menu && Object.keys(menu).length) { parts.__wl_done = true; wlInject(parts, menu); }
|
||||
```
|
||||
`Lampa.Api.partNext` — глобальный: через него строят страницу И `main()`
|
||||
(`plugin.js:30`), И `category()` (`plugin.js:36`). Никакой проверки активного
|
||||
экрана нет → `unshift` кладёт секции в голову пула на КАЖДОМ экране.
|
||||
Фильтра по activity в коде НЕ БЫЛО — это не регресс, а исходное отсутствие.
|
||||
|
||||
2. **Замеры скорости (Kraken, `127.0.0.1:9118`):**
|
||||
- `catalog/list?cat=films` прогретый кэш — **4 мс**; первый холодный — **2 250 мс**
|
||||
(`hybridCache` модуля Catalog парсит JSON целиком при первом запросе)
|
||||
- `watchlist-films.json` (чистая статика) — 1 мс
|
||||
- 🔴 `catalog/card?uri=movie/424781` — **66 118 мс (66 сек!)** на 939 байт.
|
||||
Это НЕ диск и не фид: `card_parse.initUrl` исполняется как C# и ждёт внутри
|
||||
CardController. Отдельный баг, в эту правку не входит.
|
||||
- ⚠️ `curl -w %{size_download}` показывает размер **после** распаковки gzip —
|
||||
на этом легко обмануться: `watchlist-films.json` = 88 КБ несжатых при 347
|
||||
позициях, а `cards.json` = **548 КБ**. Реальный объём фида в разы больше «видимого».
|
||||
|
||||
### Решение
|
||||
|
||||
Белый список по активному activity Lampa:
|
||||
```js
|
||||
function wlOnMain() {
|
||||
try {
|
||||
var a = Lampa.Activity && Lampa.Activity.active && Lampa.Activity.active();
|
||||
var act = (a && a.activity && a.activity.url) ? a.activity.url : '';
|
||||
return act === 'main'; // ТОЛЬКО главная
|
||||
} catch (e) { return false; }
|
||||
}
|
||||
```
|
||||
Плюс `parts.__wl_done = true` ставить ТОЛЬКО при фактической вставке (иначе после
|
||||
возврата из категории на главную секции не доберутся). `console.log` при пропуске —
|
||||
для отладки на живом ТВ.
|
||||
|
||||
### Шаги
|
||||
|
||||
1. правка `plugin-cub.js` + `build_plugin.py` (INJECT + новый инвариант `wlOnMain`)
|
||||
2. `python3 build_plugin.py && node --check plugin-cub.js`
|
||||
3. бэкап боевого `catalog/plugin.js` → `scp` нового
|
||||
4. **перезапуск Lampa на ТВ обязателен** (`tv_restart.sh` через `luna-send`;
|
||||
`docker restart lampac` кэш webOS не сбрасывает)
|
||||
5. 🔴 приёмка = **видно в UI**: главная — 4 секции сверху; Фильмы → документальные —
|
||||
секций НЕТ. CDP-проба читает `Lampa.Activity.active().activity.url` на обоих экранах.
|
||||
|
||||
### Питфоллы, найденные при расследовании (не повторять)
|
||||
|
||||
- `ssh kraken` на каждом вызове печатает `bash: line 1: ifconfig: command not found` —
|
||||
это безвредный шум из `~/.bashrc`, НЕ ошибка команды.
|
||||
- 🔴 `execute_code` в этой сессии падает на `import` (`No module named 'psutil'`) —
|
||||
работаем через `terminal` + `read_file` + `jq`, БЕЗ python.
|
||||
- Обрыв `scp` из-за не найденного пути: `wwwroot/catalog.js` НЕ существует (в wwwroot
|
||||
лежат только JSON фида) — `plugin.js` живёт в `lampac/catalog/plugin.js` и
|
||||
монтируется в `/lampac/module/Catalog/plugin.js`.
|
||||
|
||||
## 🔴🔴 СЕДЬМАЯ СЕССИЯ: РАБОЧИЙ МЕХАНИЗМ НАЙДЕН — ПЕРЕХВАТ `Lampa.Api.partNext`
|
||||
|
||||
**Статус: ✅ секции Watchlist рендерятся ВНУТРИ главной CUB. Проверено на живом ТВ через CDP.**
|
||||
|
||||
Reference in new issue
Block a user