[2026-09-22] eagle: personal/plans/lampac-watchlist-plugin.md personal/tech/lampac-deployment.md
This commit is contained in:
1 parent
7a021b26c3
commit
8441f3a4cb
2 files changed
+130
-9
No files matched your search
@@ -7,7 +7,7 @@ related:
|
||||
- '[[family/projects/watchlist-sync]]'
|
||||
- '[[family/projects/watchlist-automation]]'
|
||||
- '[[family/documents/movies-watchlist]]'
|
||||
status: accepted-in-ui-cub-sections-pending
|
||||
status: cub-sections-patched-awaiting-tv-restart
|
||||
tags:
|
||||
- lampac
|
||||
- lampa
|
||||
@@ -68,23 +68,41 @@ updated: '2026-09-22'
|
||||
> Залито, отдаётся в сборке `/catalog.js` (35566 Б). **Ожидает приёмки в UI.**
|
||||
> Механика — [[personal/tech/lampac-deployment]] раздел «Внедрение секций Watchlist в CUB-фид».
|
||||
>
|
||||
> **Обновление 2026-09-22 (шестая сессия): 🔴🔴 ПРИЧИНА «В CUB НИХУЯ НЕ ПОМЕНЯЛОСЬ» — `Manifest` НЕДОСТУПЕН В ОБЁРТКЕ.**
|
||||
> Alex: «Ты вообще нихуя не поменял!!». Проверка через **CDP-пробу на живом ТВ** подтвердила
|
||||
> его правоту: обёртка `Api.sources.cub.main` стояла (`__wl_injected: true`), но вызов
|
||||
> `cub.main({})` возвращал **4 родные секции** и **ни одной нашей**.
|
||||
> **Корень:** первая версия инжекта читала `Manifest.catalogs['watchlist']` напрямую, а
|
||||
> `Manifest` объявлен **локально в замыкании плагина** → `ReferenceError: Manifest is not defined`
|
||||
> → `catch` → молча отдавался родной фид. **Ошибки нет ни в UI, ни в логах.**
|
||||
> **Фикс:** `window.__wl_menu` (заполняется в `loadCatalogs`) + `wlEnsureMenu()` с фолбэком
|
||||
> на запрос `/catalog`. Переписан сборщик: **`build_plugin.py`** (детерминированный,
|
||||
> с инвариантами `INJECT=1`/`def=1`/`startPlugin=1`, `node --check` + баланс скобок),
|
||||
> вместо неидемпотентного `patch_cub_inject.py` (он вставлял INJECT дважды и ломал скобки).
|
||||
> Залито (сборка **35440 Б**), **ждёт перезапуска Lampa на ТВ** — `docker restart lampac`
|
||||
> НЕ перезагружает плагин в памяти ТВ.
|
||||
> Механика + CDP-пробы — [[personal/tech/lampac-deployment]] раздел
|
||||
> «🔴🔴 ШЕСТАЯ СЕССИЯ: ИСТИННАЯ ПРИЧИНА…».
|
||||
|
||||
> **Обновление 2026-09-22 (пятая сессия): ✅✅ ПРИЁМКА ALEX ПРОЙДЕНА — ФИЛЬМЫ ОТКРЫВАЮТСЯ И ПРОИГРЫВАЮТСЯ.**
|
||||
> Дословно: «фильмы из списка Watchlist теперь открываются и проигрываются».
|
||||
> Закрыт последний блокер — кириллический ключ плагина (`plugin: watchlist`).
|
||||
> Плюс устранён питфолл `Staticache` (кэш собранного `/catalog.js` переживал
|
||||
> заливку и выглядел как «патч не применяется» → `docker restart lampac`).
|
||||
>
|
||||
> **Осталось (2026-09-22, конец сессии):**
|
||||
> 1. **5 фильмов с Кинопоиск-ID** (`film/NNNNN/`) — «Рассекая волны: экспедиция „Лас Бальсас“»,
|
||||
> «Хамнет», «Цена вершины», «Астрал. Могильный ритуал 2», «О добре и зле».
|
||||
> **Осталось (2026-09-22, конец шестой сессии):**
|
||||
> 1. **Секции CUB в UI** — 🔴 инжект залит, но требовал **перезапуска Lampa на ТВ**
|
||||
> (причина «ничего не поменялось» — `Manifest` в обёртке, см. выше). После перезапуска
|
||||
> проверить через `probe_cub_main.py`: должно быть **8 секций** (4 родные CUB + 4 наши).
|
||||
> 2. **5 фильмов с Кинопоиск-ID** (`film/NNNNN/`) — «Рассекая волны: экспедиция „Лас Бальсас“»,
|
||||
> «Хамнет», «Эхопраксия», «Цена вершины», «Астрал. Могильный ритуал 2», «О добре и зле»,
|
||||
> WeWork (2024).
|
||||
> TMDB не нашёл (2025 год) → нет карточки и постера → клик даёт «здесь пусто».
|
||||
> **Нужен выбор Alex:** заглушка с кнопкой поиска торрента либо дорисовать `tmdb_id`.
|
||||
> 2. **~51 название без постера** — проблема ЗАПИСИ В СПИСКЕ, не скрипта:
|
||||
> 3. **~51 название без постера** — проблема ЗАПИСИ В СПИСКЕ, не скрипта:
|
||||
> `Плохие парни 1/2` (ДВА фильма одной строкой), `Солярис Тарковский` (уточнение
|
||||
> режиссёра), `Самолетом, поездом, машиной (1987)` (русский аналог).
|
||||
> Генератор такое угадать не может — **правится только список руками**.
|
||||
> 3. **Секции CUB в UI** — инжект залит, нужен перезапуск Lampa и визуальная проверка:
|
||||
> секции Watchlist должны появиться поверх родного фида CUB при активном источнике CUB.
|
||||
>
|
||||
> **Обновление 2026-09-22 (четвёртая сессия, ранее): ✅ ЧИСЛОВОЙ `tmdb_id` В КАРТОЧКАХ.**
|
||||
> 352 из 352 карточек отдают `tmdb_id` числом, `source`, `runtime`, `vote_average`, жанры.
|
||||
|
||||
@@ -1786,10 +1786,13 @@ else{Lampa.Listener.follow('app',function(e){if(e.type=='ready')patchCubMain();}
|
||||
| `runtime`, `vote_average` | тем же способом через `format` |
|
||||
| `displayname` | «Мой список» — надпись в UI |
|
||||
| **✅ Alex подтвердил в UI** | **фильмы Watchlist открываются и ПРОИГРЫВАЮТСЯ** |
|
||||
| Инжект секций в CUB-фид | залито, ожидает проверки в UI (перезапуск Lampa) |
|
||||
| Инжект секций в CUB-фид | ⚠️ залито (35440 Б) — **ждёт перезапуска Lampa на ТВ** |
|
||||
| Причина «секции не появились» | 🔴 `Manifest` не виден в обёртке → `ReferenceError` → фикс через `window.__wl_menu` |
|
||||
| Сборщик плагина | `build_plugin.py` (детерминированный, с инвариантами); `patch_cub_inject.py` **отменён** |
|
||||
|
||||
Скрипты: `/Users/admin/lampac-tmp/gen_watchlist_v2.py`, `deploy_lampac.py`
|
||||
(`--skip-plugin` для быстрого прогона), `patch_cub_inject.py`.
|
||||
(`--skip-plugin` для быстрого прогона), `build_plugin.py`, `deploy_cub.py`,
|
||||
`restart_lampa.sh`, `probe_tv.py`, `probe_cub_main.py`.
|
||||
Проверка в шаге 7 валидирует именно ключ `watchlist` и предупреждает,
|
||||
если в `/catalog` остался русский ключ.
|
||||
|
||||
@@ -1827,6 +1830,106 @@ else{Lampa.Listener.follow('app',function(e){if(e.type=='ready')patchCubMain();}
|
||||
Инжект залит (`plugin-cub.js`, 35566 Б в отдаваемой сборке). Нужен перезапуск
|
||||
Lampa на ТВ и проверка: секции Watchlist появляются **поверх родного фида CUB**.
|
||||
|
||||
### 🔴🔴 ШЕСТАЯ СЕССИЯ: ИСТИННАЯ ПРИЧИНА «СЕКЦИИ НЕ ПОЯВИЛИСЬ» — `Manifest` НЕДОСТУПЕН ВНУТРИ ОБЁРТКИ
|
||||
|
||||
Первая версия `injectWatchlistParts` читала `Manifest.catalogs['watchlist']` **напрямую**.
|
||||
Проба через CDP на живом ТВ показала:
|
||||
|
||||
```
|
||||
out.cubMainSrc = "function (params, oncomplite, onerror) { original(params, function (cub_data) {
|
||||
try { var wl = Manifest.catalogs['watchlist']; if (!..."
|
||||
out.err = "ReferenceError: Manifest is not defined"
|
||||
wlInjected: true ← обёртка СТОЯЛА
|
||||
вызов main({}) → len: 4, titles: ["Сейчас смотрят","Рекомендуем посмотреть","Последнее добавление","Огонь!"]
|
||||
← только родные CUB, НИ ОДНОЙ нашей
|
||||
```
|
||||
|
||||
**Корень:** `Manifest` объявлен **локально в замыкании плагина** (`/catalog.js`, IIFE).
|
||||
Обёртка вызывается из другого контекста → `ReferenceError` → `catch` → молча
|
||||
`oncomplite(cub_data)` с родными секциями. Ошибка **не видна в UI и не пишется в логи**.
|
||||
|
||||
**Фикс:** не полагаться на замыкание — сохранять `menu` в глобальный `window.__wl_menu`
|
||||
при `loadCatalogs()`, в обёртке читать оттуда, с фолбэком на прямой запрос `/catalog`:
|
||||
|
||||
```js
|
||||
// в loadCatalogs, ПОСЛЕ Manifest.catalogs=json;
|
||||
if(json['watchlist']&&json['watchlist'].menu)window.__wl_menu=json['watchlist'].menu;
|
||||
|
||||
function wlEnsureMenu(cb) {
|
||||
if (window.__wl_menu && Object.keys(window.__wl_menu).length) return cb(window.__wl_menu);
|
||||
network.silent(Utils.account(Manifest.api_host + '/catalog'), function (json) {
|
||||
var m = (json && json['watchlist'] && json['watchlist'].menu) || {};
|
||||
window.__wl_menu = m; cb(m);
|
||||
}, function () { cb(window.__wl_menu || {}); });
|
||||
}
|
||||
```
|
||||
`wlEnsureMenu` вызывается внутри обёртки вместо прямого `Manifest.catalogs['watchlist']`.
|
||||
|
||||
⚠️ **`Manifest.api_host` в `wlEnsureMenu` — тоже замыкание.** Фолбэк сработает только
|
||||
если `__wl_menu` уже заполнен `loadCatalogs`; в норме он заполнен. Если `__wl_menu`
|
||||
пуст И `Manifest` недоступен — вернётся `{}` и родной фид.
|
||||
|
||||
### Сборка плагина: `build_plugin.py` вместо `patch_cub_inject.py`
|
||||
|
||||
🔴 **`patch_cub_inject.py` отменён — он не идемпотентен.** Разрезание по первому
|
||||
`function startPlugin` + поиск `end` вставляло `INJECT` **дважды** и оставляло файл
|
||||
с нарушенным балансом скобок (`{`=123, `}`=122 → `node --check` → `SyntaxError`).
|
||||
|
||||
**Новый сборщик — `build_plugin.py`, детерминированный:**
|
||||
1. берёт базу `plugin-patched.js`;
|
||||
2. вставляет `window.__wl_menu` в `loadCatalogs`;
|
||||
3. вырезает ранее вставленный INJECT по маркеру `/* ==== WL-INJECT-START ==== */`;
|
||||
4. разбивает файл на `[до startPlugin]` + `[startPlugin…]` + `[хвост })();]`;
|
||||
5. собирает заново: `before` + `INJECT` + `NEW_START` + `tail`.
|
||||
|
||||
**Инварианты в конце скрипта** (падает с `[x] ИНВАРИАНТ НАРУШЕН`, если нарушено):
|
||||
- `WL-INJECT-START` = **1**
|
||||
- `function patchCubMain()` = **1**
|
||||
- `function startPlugin` = **1**
|
||||
|
||||
⚠️ `patchCubMain();` встречается **2 раза** (в `window.appready` и в `app:ready`-листенере) —
|
||||
это норма, в инвариант не входит (первая версия проверки ошибочно требовала 1).
|
||||
|
||||
Проверка: `node --check plugin-cub.js` + баланс скобок `{`/`}` = 0.
|
||||
Итог: **13054 Б**, сборка на сервере **35566 → 35440 Б** (зависит от длины `catalogs`-JSON).
|
||||
|
||||
### Перезапуск Lampa на ТВ — правильный `luna-send`
|
||||
|
||||
🔴 **`luna-send` через `ssh 'script -q -c "luna-send … -a \"{...}\""'` НЕ парсит аргументы** —
|
||||
печатает help. Кавычки в кавычках рвутся. Рабочая форма — **одинарные кавычки внутри
|
||||
`script -c`**, файлом (не inline):
|
||||
|
||||
```bash
|
||||
ssh $TV 'script -q -c "luna-send -n 1 -f luna://com.webos.applicationManager/close -a '"'"'{"id":"com.lampac.tv"}'"'"'" /dev/null'
|
||||
sleep 4
|
||||
ssh $TV 'script -q -c "luna-send -n 1 -f luna://com.webos.applicationManager/launch -a '"'"'{"id":"com.lampac.tv"}'"'"'" /dev/null'
|
||||
```
|
||||
Скрипт: `/Users/admin/lampac-tmp/restart_lampa.sh` (закрыть → пауза 4с → запустить → 20с → показать devtools).
|
||||
|
||||
⚠️ **`docker restart lampac` НЕ перезагружает плагин на ТВ.** После заливки `plugin.js`
|
||||
ТВ продолжает держать **старую версию в памяти** — `cubMainSrc` через CDP показывает
|
||||
старый код. Обязателен **перезапуск приложения на ТВ**.
|
||||
|
||||
### Диагностика рантайма Lampa через CDP (websocket-client)
|
||||
|
||||
⚠️ Модуля `ws` в Node нет, `websockets` в Python нет → использовать **`websocket-client`**
|
||||
(установлен). Скрипты `/Users/admin/lampac-tmp/probe_tv.py`, `probe_cub_main.py`.
|
||||
|
||||
```python
|
||||
WS=$(curl -s "http://192.168.1.70:9998/json/list" | jq -r '.[] | select(.title=="Lampac") | .webSocketDebuggerUrl' | head -1)
|
||||
python3 probe_cub_main.py "$WS"
|
||||
```
|
||||
`probe_cub_main.py` вызывает `Lampa.Api.sources.cub.main({}, cb)` и печатает
|
||||
`titles` секций — **единственный надёжный способ увидеть, что реально отдаёт обёртка**.
|
||||
Успех = 8 секций (4 родные CUB + 4 наши).
|
||||
|
||||
Полезные поля пробы `probe_tv.py`: `Lampa.Storage.field('source')`,
|
||||
`Object.keys(Lampa.Api.sources)`, `Lampa.Api.sources.cub.__wl_injected`,
|
||||
`typeof Lampa.Api.sources.cub.main`.
|
||||
|
||||
⚠️ `Manifest` внутри `Runtime.evaluate` **тоже не виден** (`ReferenceError: Manifest is not defined`) —
|
||||
он в замыкании плагина. Не использовать в пробах.
|
||||
|
||||
## Питфоллы проверки на ТВ (сводка)
|
||||
|
||||
1. **Lampa кэширует манифест и ответы.** После правок — **полностью выгрузить
|
||||
|
||||
Reference in new issue
Block a user