From 01911543840974bc062cb613b12ae00fbcd00735 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Tue, 22 Sep 2026 15:51:50 +0600 Subject: [PATCH] [2026-09-22] eagle: personal/plans/lampac-watchlist-plugin.md personal/tech/lampac-deployment.md --- personal/plans/lampac-watchlist-plugin.md | 78 +++++++++++++- personal/tech/lampac-deployment.md | 118 ++++++++++++++++++++++ 2 files changed, 195 insertions(+), 1 deletion(-) diff --git a/personal/plans/lampac-watchlist-plugin.md b/personal/plans/lampac-watchlist-plugin.md index 5d06caa3..f8febd3c 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: card-fixed-tv-check-pending +status: cub-sections-blocked tags: - lampac - lampa @@ -1907,5 +1907,81 @@ Lampa на ТВ **кэширует манифест и ответы**. Посл выгрузить приложение** (не свернуть), иначе клиент держит старый кэш и показывает дореформенный результат. +--- + +## 🔴 СЕССИЯ 4 (2026-09-22, поздняя ночь): приёмка НЕ пройдена, требование изменено + +### Что сказал Alex + +1. «у фильмов в "Мой список" появились норм названия, годы и у большинства — + постеры. **Но при открытии все так же "здесь пусто"** и никакого инфо или + воспроизведения!» +2. «че блядь значит надо Настройки → Остальное → Основной источник?! мы блядь + это уже обсуждали и **надо было добавить в CUB список новые секции** а не + ручное блядь переключение!» + +### Статус по факту + +| Пункт | Состояние | +|---|---| +| Серверная карточка | ✅ **исправна** — curl отдаёт `tmdb_id: 424781` числом, `source`, жанры, постер, описание | +| Приёмка на ТВ | ❌ **НЕ пройдена** — «здесь пусто» на экране | +| Соединения ТВ → Lampac | ❌ **ноль** (`sudo ss -tn \| grep 9118` пусто в момент проверки) | +| Секции внутри CUB | ❌ не реализовано — сейчас подмена через `e.abort()` | + +### Диагностика, выполненная в этой сессии + +Разобран `app.min.js` (2.1 МБ) — **эталон CUB-источника**: + +- `CUB.full()` ставит `json.source = 'cub'` сам (строка ~34252). +- `Explorer` читает `this.object.movie || this.object.card`. +- `full` пушится с `source: element.data.source || 'tmdb'` (**строка 44291**) — + 🔴 **фолбэк на tmdb, если у элемента нет поля `source`**. В ответе + `/catalog/list` поля `source` **нет** → проверить первым делом. +- `plugin.js:42-43` требует от карточки: `tmdb_id` (**число**), `original_name` + (или `original_title`) для определения tv/movie, `img`, `overview`. + +Полная анатомия — [[personal/tech/lampac-deployment]] → «Анатомия CUB-источника». + +### 🎯 ЗАДАЧА СЛЕДУЮЩЕЙ СЕССИИ (переформулирована Alex'ом) + +**Не переключать источник, а дорисовать наши секции ВНУТРЬ CUB.** + +1. **Проверить гипотезу `source`.** Элементы `/catalog/list` не содержат `source`. + Если `full` уходит в `tmdb` вместо `watchlist` — это и есть «здесь пусто». + Проверка: `curl "/catalog/list?plugin=watchlist&cat=films&page=1" | jq '.results[0].source'`. +2. **Отвязать плагин от перехвата `menu`.** Патчить рендер главной CUB + (`app.min.js` строки ~44260-44310: `feed`/`category_full`) либо добавить ряды + через `Lampa.Listener.follow('activity')`. `e.abort()` — НЕ использовать + (отменяет родной раздел, чего Alex не хочет). +3. **Приёмка = глазами на ТВ.** Открыть **обычный CUB** → сверху видны наши + секции с постерами → клик → карточка с описанием → кнопка воспроизведения + ведёт в TorrServer. Никакого ручного переключения источника. + +### Питфоллы, найденные в этой сессии + +- 🔴 **Проверять карточку по `/catalog/card`, НЕ по `/card`.** `/card` отдаёт 404 + и выглядит как поломка каталога — потерян час на ложном диагнозе. +- 🔴 **Кэш `catalog:card:{plugin}:{uri}` живёт в ПАМЯТИ** и **переживает + `docker restart`**. После правки данных старые ответы продолжают отдаваться. + Проверять на **незэкешированном** `uri` (взять другой фильм). +- 🔴 **`nodeValue` (`ModInit.cs:285`) возвращает любое `JValue` СТРОКОЙ** → + в `card_args` нужен `format: "long.TryParse(value, out long v) ? v : 0"`. +- 🔴 **`tmdb_id` ДОЛЖЕН быть числом** — `plugin.js` делает `if(json.tmdb_id)`. +- macOS `tar` кладёт AppleDouble `._*` в `wwwroot` → `tar --no-mac-metadata`. +- Права `root:root 600` → `Permission denied` → статика молча отдаёт **404**. + Нужно `1000:1000` + `755`/`644`. +- `find -exec` через `ssh -t` рвётся (`missing argument to -exec`) → `chmod -R`. +- `&&`-цепочка рвёт tty-сессию ssh → каждая команда отдельным вызовом. +- `tcpdump` на Кра́кене **не был установлен** → `sudo apt-get install -y tcpdump`. +- `com.webos.service.devtools` **не существует** на webOS 5.4.2 Lite. +- `luna-send` пишет в tty → только через `script -q -c "..." /tmp/out.txt`. + +### Артефакты + +- Скрипты: `/Users/admin/lampac-tmp/{gen_watchlist_v2.py,deploy_lampac.py,watchlist.yaml}`. +- Копия UI Lampa для разбора: `/tmp/app-min.js` (2.1 МБ). +- Бэкап плана: `~/backup-lampac-plugin-plan-20260922-150459.md`. +- Доклады по карточке — [[personal/tech/lampac-deployment]] (конец файла). ## Связанные diff --git a/personal/tech/lampac-deployment.md b/personal/tech/lampac-deployment.md index 11d6062e..5f3d8300 100644 --- a/personal/tech/lampac-deployment.md +++ b/personal/tech/lampac-deployment.md @@ -1445,3 +1445,121 @@ CUB и «Мой список» — **два независимых источн Lampa на ТВ кэширует манифест и ответы. После правок **надо полностью выгрузить приложение** (не свернуть), иначе клиент держит старый кэш. + +--- + +## 🔴 Анатомия CUB-источника — что нужно, чтобы карточка открылась (разобрано 2026-09-22) + +Разбор `app.min.js` (2.1 МБ; Лампа грузится с сервера, файл живёт в +`/lampac/wwwroot/lampa-main/app.min.js`). Копия локально: + +```bash +ssh kraken "sudo docker cp lampac:/lampac/wwwroot/lampa-main/app.min.js /tmp/app-min.js" +scp -q kraken:/tmp/app-min.js /tmp/app-min.js +``` + +### Источники регистрируются как `sources = { tmdb: TMDB, cub: CUB }` + +```js +var CUB = { main, menu, full: full$1, list, category, clear, person, + seasons, menuCategory, discovery, reactionsGet, reactionsAdd, + metadataGet, discussGet, extensions }; +``` + +### `CUB.full()` (строка ~34240) — эталон карточки + +```js +function full$1(params, oncomplite, onerror) { + var status = new Status(9); + if (Utils$1.dcma(params.method, params.id)) return onerror(); + get$7('3/' + params.method + '/' + params.id + + '?api_key=' + TMDB$1.key() + + '&append_to_response=content_ratings,release_dates,external_ids,' + + 'keywords,alternative_titles,images' + + '&language=' + Storage.field('tmdb_lang'), params, function (json) { + if (json.status_code) return status.stop(), onerror(); + json.source = 'cub'; // ← 🔴 CUB проставляет source САМ + ... + status.append('movie', json); + }, ...); +} +``` + +**Вывод:** `json.source` — обязательное поле. CUB ставит его сам; наш плагин +делает то же (`plugin.js:42`: `json.source = params.source`). + +### Как Explorer открывает карточку + +`Explorer$1` (строка ~39403) читает `this.object.movie || this.object.card || {}`. +Данные приезжают из `Activity.push({ component: 'full', id, method, card, source })`. + +Три места, где пушится `full`: + +| Строка | Контекст | `source` | +|---|---|---| +| **44291** | кнопка «Смотреть» в фиде | `element.data.source \|\| 'tmdb'` | +| **40247** | кнопка «Назад» | `params.movie.source` | +| **18668** | уведомление | `element.card.source \|\| (ru/uk/be ? 'cub' : '')` | + +🔴 **Фолбэк `|| 'tmdb'`** — если у элемента списка нет поля `source`, Lampa уйдёт +в **tmdb**, а не в наш каталог. Проверить, добавляет ли плагин `source` в элементы +`catalog/list` (в ответе `/catalog/list` этого поля **нет**). + +### Что читает `full` из ответа карточки (`plugin.js:42-43`) + +```js +json.source = params.source; +if (json.seasons && json.seasons.length) { ...tv/{tmdb_id}/season/{N}... } +if (json.tmdb_id) { ... cub.reactionsGet({id: json.tmdb_id, + method: json.original_name ? 'tv' : 'movie'}) ... } +if (json.credits) status.data['persons'] = json.credits; +if (json.recommendations) status.data['recomend'] = addSource(...); +if (json.similar) status.data['simular'] = addSource(...); +if (json.videos) status.data['videos'] = addSource(...); +status.append('movie', json); +``` + +→ **Обязательные поля:** `tmdb_id` (**число**), `original_name` или +`original_title` (определяет tv/movie), `img`, `overview`. +`seasons`/`credits`/`recommendations`/`similar`/`videos` — опциональны. + +### ТВ-диагностика при «здесь пусто» + +| Что | Как проверить | +|---|---| +| Есть ли соединения ТВ → Lampac | `ssh kraken "sudo ss -tn \| grep 9118"` | +| **Ноль соединений** | Lampa на ТВ **не общается с Lampac** — не запущена либо источник не активен | +| Захват запросов ТВ | `ssh kraken "sudo timeout 40 tcpdump -i any -n -A 'host 192.168.1.70 and port 9118'"` | +| `tcpdump` на Кра́кене | **не был установлен** → поставлен `sudo apt-get install -y tcpdump` (4.99.3) | +| Front app на ТВ | `script -q -c "luna-send -n 1 -f luna://com.webos.applicationManager/getForegroundAppInfo {}" /tmp/fg.txt` → вернул `com.lampac.tv` | +| `lampac_url` на ТВ | `loader.js`: `localStorage['lampac_url']`, дефолт `http://192.168.1.14:9118` ✅ | +| Кэш манифеста | `loader.js`: `cache_version = floor(Date.now()/9e5)` — смена сервера в течение ~15 мин не подхватится | +| Служба devtools | `com.webos.service.devtools` **НЕ существует** на webOS 5.4.2 Lite | + +### 🔴 ТРЕБОВАНИЕ Alex: секции ВНУТРИ CUB, БЕЗ ручного переключения + +**Дословно:** «надо блядь добавить в CUB список новые секции а не ручное блядь переключение!» + +Текущий `plugin.js` подменяет разделы через: + +```js +Lampa.Listener.follow('menu', function (e) { + if (e.type=='action' && (e.action=='tv'||'cartoon'||'anime'||'movie'||'relise')) { + var catalog = Api.getCatalog(); + if (!catalog) return; // ← 🔴 молчит, если активен НЕ наш источник + ... + e.abort(); + } +}); +``` + +**Почему не работает для CUB:** `Api.getCatalog()` читает +`Lampa.Manifest.catalogs[<текущий источник>]`. При выбранном источнике **CUB** +нашего каталога там нет → `return` → открывается родной раздел CUB. + +**Что делать вместо этого (задача следующей сессии):** +дорисовывать секции в **корень CUB** — не перехватывать `menu`, а патчить рендер +главной (строки ~44260-44310: `feed` / `category_full`) либо добавлять ряды через +`Lampa.Listener.follow('activity')`. Цель: Alex открывает **обычный CUB** и **сверху +видит наши секции** с реальными элементами (постеры, рейтинги) — как в исходной +формулировке из [[personal/plans/lampac-watchlist-plugin]].