diff --git a/personal/plans/lampac-watchlist-plugin.md b/personal/plans/lampac-watchlist-plugin.md index 315614fd..5d06caa3 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-done-tv-check-pending +status: card-fixed-tv-check-pending tags: - lampac - lampa @@ -40,10 +40,16 @@ updated: '2026-09-22' > См. «🔴 АРХИТЕКТУРНАЯ ОШИБКА» — читать ПЕРВЫМ. > > **Итог одной строкой:** серверная часть каталога работает полностью — «Мой список» -> первым в `/catalog`, 4 категории (403 позиции, 348 постеров, 352 рабочих карточки), -> карточка по клику отдаёт **HTTP 200** (339/339). Родной CUB не тронут. +> первым в `/catalog`, 4 категории (403 позиции, 348 постеров), **карточка по клику +> отдаёт все поля: 352/352 с числовым `tmdb_id`**. Родной CUB не тронут. > Осталась приёмка глазами на ТВ. > +> **Обновление 2026-09-22 (третья сессия): ✅ КАРТОЧКА ПОЧИНЕНА ОКОНЧАТЕЛЬНО.** +> «Здесь пусто» давало отсутствие **числового** `tmdb_id`: `plugin.js` делает +> `if(json.tmdb_id)`, а `ModInit.cs:285` возвращает любое `JValue` СТРОКОЙ. +> Фикс — `format: "long.TryParse(...)"` в `card_args`. Плюс кэш `catalog:card:*` +> в ПАМЯТИ переживал `docker restart` и отдавал старое. См. «🔴 ФИНАЛЬНЫЙ ФИКС». +> > **Обновление 2026-09-22 (вечер):** Alex лично нашёл источник в UI > («остальное → основной источник → Мой список»), увидел результат и подтвердил > диагноз: секции подменяют CUB, нет превью, элементы — сырые строки файла. @@ -1807,4 +1813,99 @@ Cron: генератор в **02:30**, после `watchlist-nightly` (01:00). 310 фильмов из списка, которых нет в Radarr — пока показываются через фолбэк Кинопоиска (51 без постера). Решить судьбу отдельно. +--- + +## 🔴 ФИНАЛЬНЫЙ ФИКС: карточка = «здесь пусто» без ЧИСЛОВОГО `tmdb_id` + +**2026-09-22, третья сессия. Карточка заработала: 352/352 отдают `tmdb_id`.** + +Alex после первого «готово»: «при открытии все так же "здесь пусто" и никакого инфо +или воспроизведения». Сервер отдавал `HTTP 200` с title/img/overview — значит +дело было **не в запросе, а в полноте ответа**. + +### Причина — одна, но скрытая за двумя масками + +`plugin.js` при клике (`full()`): + +```js +if(json.tmdb_id){ status.need++; + Lampa.Api.sources.cub.reactionsGet( + {id: json.tmdb_id, method: json.original_name ? 'tv' : 'movie'}, ...); } +``` + +**Без `tmdb_id` Lampa считает карточку неполной → пустой экран.** Причём нужен +**числовой** `tmdb_id`, не строка. + +Два бага в цепочке `card_args`: + +1. **`ModInit.cs:285` — `nodeValue` возвращает ЛЮБОЕ `JValue` как строку.** + ```csharp + string value = valueToken switch { + JValue jValue => jValue.Value?.ToString(), // ← число 424781 → "424781" + ... }; + ``` + Поэтому `tmdb_id` из JSON-файла приходил строкой, и `if(json.tmdb_id)` не + давала числа. **Никакой конфиг это не обходит — только `format`.** + +2. **Кэш `catalog:card:{plugin}:{uri}` живёт в ПАМЯТИ процесса и переживает + `docker restart`.** После правки данных старые ответы продолжали отдаваться. + Именно поэтому `movie/424781` (**первый элемент «Фильмов»**, по нему Alex и + кликал) упорно оставался `null`, хотя исправленный файл уже лежал на диске. + **Проверять фикс только на НЕзакэшированном `uri`.** + +### Фикс — `format` в `card_args` (исполняется как C#, возвращает настоящий тип) + +```yaml +card_args: + - name_arg: tmdb_id + attribute: tmdb_id + format: "long.TryParse(value, out long v) ? v : 0" + - name_arg: source + attribute: media_type + - name_arg: overview + attribute: overview + - name_arg: genres + attribute: genres + - name_arg: runtime + attribute: runtime + format: "long.TryParse(value, out long v) ? v : 0" + - name_arg: vote_average + attribute: vote_average + format: "double.TryParse(value, out double v) ? v : 0" + - name_arg: rating + attribute: rating # остаётся строкой — Lampa показывает в бейдже +``` + +`format` вызывается как `CSharpEval.Execute(nd.format, +new CatalogNodeValue(value, host), options)` (`ModInit.cs:255` и `:317`) — +`value` это уже строка, поэтому нужен `TryParse`. + +### Эталонный рабочий ответ + +```json +{ "id": "movie/424781", "title": "Простите за беспокойство", + "original_title": "Простите за беспокойство", "tmdb_id": 424781, + "source": "movie", "runtime": 111, "rating": "6.8", "vote_average": 68, + "genres": [{"name":"фэнтези"},{"name":"фантастика"},{"name":"комедия"}], + "overview": "...", "img": "http://192.168.1.14:9118/proxyimg:210:0/..." } +``` + +### Итог проверки + +**352 из 352** карточек (все, у кого есть TMDB ID) отдают числовой `tmdb_id`, +`source`, `runtime`, рейтинг и жанры. Ошибок — 0. + +### 🔴 CUB: «вижу только фильмы из списка» + +CUB **не пропал** — это **два независимых источника Lampa**, одновременно +показать нельзя. Переключение: **Настройки → Остальное → Основной источник**. +Пункта «Источник» в настройках НЕ существует. + +### Питфолл приёмки на ТВ + +Lampa на ТВ **кэширует манифест и ответы**. После правок надо **полностью +выгрузить приложение** (не свернуть), иначе клиент держит старый кэш и +показывает дореформенный результат. + + ## Связанные diff --git a/personal/tech/lampac-deployment.md b/personal/tech/lampac-deployment.md index eb1105aa..11d6062e 100644 --- a/personal/tech/lampac-deployment.md +++ b/personal/tech/lampac-deployment.md @@ -1371,3 +1371,77 @@ python3 deploy_lampac.py /tmp/wl-out --skip-plugin вызовом (`&&`-цепочка рвёт tty). ### Связанные + +## 🔴 ПОЧЕМУ КАРТОЧКА = «ЗДЕСЬ ПУСТО» (найдено 2026-09-22, вечер) + +**Симптом:** данные в карточку приходят (title, img, overview), но в UI «здесь пусто», +нет кнопки воспроизведения. + +**Причина:** `plugin.js` при клике: + +```js +if(json.tmdb_id){ status.need++; Lampa.Api.sources.cub.reactionsGet( + {id: json.tmdb_id, method: json.original_name ? 'tv' : 'movie'}, ...); } +``` + +Без `tmdb_id` (**числа**, не строки!) Lampa считает карточку неполной → пустой экран. + +### Два бага в цепочке, оба надо было починить + +1. **`ModInit.cs:285` — `nodeValue` возвращает ЛЮБОЕ значение как строку.** + ```csharp + string value = valueToken switch { + JValue jValue => jValue.Value?.ToString(), // ← число → "424781" + ... }; + ``` + Поэтому `tmdb_id` из JSON приходил строкой, и `if(json.tmdb_id)` давала не число. + +2. **Кэш в памяти процесса переживает `docker restart`.** + `hybridCache` ключ `catalog:card:{plugin}:{uri}` живёт в памяти. При правке + данных старые ответы продолжают отдаваться. **Обязательно `docker restart lampac` + и проверять на НЕзакэшированном uri.** + +### Фикс — `format` в `card_args` + +`format` исполняется как C# (`CSharpEval`, объект `CatalogNodeValue(value, host)`) +и может вернуть настоящий тип, а не строку: + +```yaml +card_args: + - name_arg: tmdb_id + attribute: tmdb_id + format: "long.TryParse(value, out long v) ? v : 0" + - name_arg: source + attribute: media_type + - name_arg: runtime + attribute: runtime + format: "long.TryParse(value, out long v) ? v : 0" + - name_arg: vote_average + attribute: vote_average + format: "double.TryParse(value, out double v) ? v : 0" + - name_arg: rating + attribute: rating # строкой — Lampa показывает в бейдже +``` + +### Рабочий ответ карточки (эталон) + +```json +{ "id": "movie/424781", "title": "Простите за беспокойство", + "original_title": "Простите за беспокойство", "tmdb_id": 424781, + "source": "movie", "runtime": 111, "rating": "6.8", "vote_average": 68, + "genres": [{"name":"фэнтези"},{"name":"фантастика"},{"name":"комедия"}], + "overview": "...", "img": "http://192.168.1.14:9118/proxyimg:210:0/..." } +``` + +**Результат: 352 из 352 карточек отдают числовой `tmdb_id`.** + +### Про `CUB` — почему «только фильмы из списка» + +CUB и «Мой список» — **два независимых источника Lampa**, одновременно показать +нельзя. Переключение: **Настройки → Остальное → Основной источник**. +Пункта «Источник» в настройках НЕ существует. + +### Питфолл проверки на ТВ + +Lampa на ТВ кэширует манифест и ответы. После правок **надо полностью +выгрузить приложение** (не свернуть), иначе клиент держит старый кэш.