[2026-09-22] eagle: personal/plans/lampac-watchlist-plugin.md personal/tech/lampac-deployment.md
This commit is contained in:
1 parent
9e1a06340f
commit
7a021b26c3
2 files changed
+192
-10
No files matched your search
@@ -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` на сервере — см. «ПРАВИЛО ДИАГНОСТИКИ» выше.
|
||||
|
||||
Reference in new issue
Block a user