518 lines
29 KiB
Markdown
518 lines
29 KiB
Markdown
---
|
||
created: '2026-09-22'
|
||
namespace: personal
|
||
related:
|
||
- '[[personal/plans/lampac-kraken]]'
|
||
- '[[personal/tech/lampac-deployment]]'
|
||
- '[[family/projects/watchlist-sync]]'
|
||
- '[[family/projects/watchlist-automation]]'
|
||
- '[[family/documents/movies-watchlist]]'
|
||
status: active
|
||
tags:
|
||
- lampac
|
||
- lampa
|
||
- watchlist
|
||
- catalog
|
||
- webos
|
||
- plugin
|
||
- kraken
|
||
title: Watchlist в UI Lampa — каталог из списка
|
||
type: plan
|
||
updated: '2026-09-22'
|
||
---
|
||
|
||
# Watchlist в UI Lampa — каталог из списка
|
||
|
||
> Реализовано 2026-09-22. План был переписан после разведки кода модуля Catalog.
|
||
> Базовое развёртывание — [[personal/plans/lampac-kraken]] (шаги 1–6 закрыты).
|
||
>
|
||
> **Итог одной строкой:** Lampac отдаёт `movies-watchlist.md` как каталог Lampa
|
||
> через модуль `Catalog` → 4 категории (360/33/3/7 позиций), автообновление кроном 02:30.
|
||
> Серверная часть полностью рабочая. **Осталось одно:** в `plugin.js` Lampac баг
|
||
> (`defineProperty` без `enumerable:true`) — из-за него источник «Мой список» не виден
|
||
> в списке выбора Lampa на ТВ. Фикс готов, ждёт апрува Alex (2026-09-22).
|
||
> См. «🔴 ГЛАВНЫЙ ПИТФОЛЛ».
|
||
|
||
## Задача
|
||
|
||
Показывать список фильмов Alex (`family/documents/movies-watchlist.md`) **в UI Lampa на ТВ** — каталогом.
|
||
Не локальный плейбэк. Формулировка Alex: «отображение фильмов из списка».
|
||
|
||
⚠️ **Что НЕ спрашивать повторно.** Задача — **отображение**, не воспроизведение.
|
||
Список — это перечень, а не источник видео. Вопрос «а что играть по клику?» —
|
||
**выдумка сверх постановки**, Alex на него реагировал раздражением («я чё тебе сказал в постановке задачи»).
|
||
Штатное воспроизведение Lampa (торренты/онлайн) работает само, отдельно решать нечего.
|
||
|
||
## ✅ Затык снят: чем это делается
|
||
|
||
В образе Lampac уже есть модуль **`Catalog`** — YAML-каталоги → плагин Lampa `/catalog.js`.
|
||
Сейчас **выключен**. Писать плагин с нуля **не нужно**.
|
||
|
||
## Как работает Catalog (разобрано по коду 2026-09-22)
|
||
|
||
**Файлы в контейнере:** `/lampac/module/Catalog/` — `Controllers/`, `plugin.js`, `README.md`,
|
||
`sites/*.yaml` (10 готовых примеров: `vokino`, `rezka`, `kinopub`, `anime`, …).
|
||
|
||
### Механика
|
||
|
||
| Что | Как |
|
||
|---|---|
|
||
| Данные | `sites/<site>.yaml` — описание сайта: `host`, `menu`, `search`, `list`, `content` |
|
||
| Подстановки | `override/<site>.yaml` и `override/_.yaml` — переопределения поверх базового |
|
||
| Роуты | `/catalog.js` (плагин), `/catalog` (JSON каналов), `/catalog/list`, `/catalog/card` |
|
||
| WAF | `^/catalog/` → **10 запросов/сек** |
|
||
| Имя файла | только `[a-z0-9-]`; есть fallback-поиск по `displayname` |
|
||
|
||
### Ключевое: обязателен HTTP
|
||
|
||
```csharp
|
||
if (!url.StartsWith("http"))
|
||
url = $"{init.host}/{url}"; // ListController.cs:87
|
||
```
|
||
`host` из YAML сканируется **по HTTP** (`Http.Get` / Playwright / RCH).
|
||
**Локальные файлы напрямую Catalog читать не умеет** — только HTTP-ответ.
|
||
|
||
### Два режима парсинга
|
||
|
||
```csharp
|
||
bool? jsonPath = contentParse.jsonPath ?? init.jsonPath;
|
||
|
||
if (jsonPath == true) json = JToken.Parse(html); // JSON-режим
|
||
else doc.LoadHtml(html); // HTML-режим
|
||
```
|
||
|
||
- `jsonPath: true` → ответ парсится как **JSON**, элементы берутся по `nodes` (`$.channels[*].details`)
|
||
- иначе → HTML через HtmlAgilityPack
|
||
|
||
🔴 **Это и есть рычаг:** любой **свой HTTP-эндпоинт, отдающий JSON нужной формы**, подойдёт как `host`.
|
||
Тогда задача сводится к генерации JSON + YAML-обёртки, без правки кода Lampac.
|
||
|
||
### Форма элемента (`content` в YAML)
|
||
|
||
```yaml
|
||
content:
|
||
nodes: "$.channels[*].details" # jsonPath-выражение (JSON) или CSS/XPath (HTML)
|
||
name: { attribute: name }
|
||
original_name:{ attribute: originalname }
|
||
href: { attribute: ident }
|
||
image: { attribute: poster }
|
||
year: { attribute: released }
|
||
serial_key: { attribute: type, format: | return value is "serial" ? value : null; }
|
||
args:
|
||
- { name_arg: vote_average, attribute: rating_kp }
|
||
```
|
||
|
||
Карточка — отдельная секция `card_parse` + `card_args` (описание, рейтинги, жанры, страна).
|
||
Полный живой пример — `sites/vokino.yaml` (копия в [[personal/tech/lampac-deployment]], раздел Catalog).
|
||
|
||
## Включение модуля — 2 правки
|
||
|
||
```jsonc
|
||
// current.conf (внутри контейнера /lampac/current.conf)
|
||
"SkipModules": [ "Tracks", "Transcoding", ... ] // ← убрать "Catalog" (строка ~277)
|
||
"plugins": { ..., "catalog": true } // ← было false (строка ~1653)
|
||
```
|
||
|
||
🔴 **ПИТФОЛЛ — `init.conf` НЕ смонтирован.** В нашем `docker-compose.yml` нет volume на `/lampac/init.conf`,
|
||
файл живёт в образе. Правки через `docker exec` **исчезнут при пересоздании контейнера**
|
||
(`docker compose up`, watchtower-обновление образа). Варианты:
|
||
- (а) добавить volume `./config/init.conf:/lampac/init.conf:ro` — надёжно, но нужен первичный `docker cp`
|
||
- (б) править через **AdminPanel** `/adminpanel` (модуль, правит `init.conf` + `current.conf`)
|
||
- (в) `docker cp` + commit — плохо
|
||
|
||
**Рекомендация: (а)** — конфиг на HDD, переживает пересоздание.
|
||
|
||
## Архитектура решения
|
||
|
||
```
|
||
family/documents/movies-watchlist.md ← источник (vault, git-синхрон)
|
||
│ существующий парсер: watchlist-sync/parser.py
|
||
▼
|
||
генератор (Python, на Кра́кене)
|
||
│ пишет JSON нужной формы
|
||
▼
|
||
/lampac/... JSON-эндпоинт, доступный по HTTP с Lampac
|
||
│
|
||
▼
|
||
sites/watchlist.yaml ← Catalog-описание, host=<наш JSON URL>
|
||
menu: Фильмы / Мультфильмы / Аниме (по секциям .md)
|
||
│
|
||
▼
|
||
Lampa на ТВ: плагин http://192.168.1.14:9118/catalog.js
|
||
```
|
||
|
||
**Откуда отдавать JSON — варианты (выбрать на этапе реализации):**
|
||
|
||
| # | Где | Плюс | Минус |
|
||
|---|---|---|---|
|
||
| 1 | **статика в `/lampac/wwwroot/`** | ничего не поднимать, Lampac сам отдаёт | только чтение, обновление = перезапись файла |
|
||
| 2 | **отдельный лёгкий HTTP-сервер** на Кра́кене | есть API/логика | ещё один контейнер |
|
||
| 3 | `file://` | — | ❌ не поддерживается (только http) |
|
||
|
||
**Склоняюсь к (1)** — генерировать `wwwroot/watchlist.json`, Lampac отдаёт его сам, без новых сущностей.
|
||
|
||
## Обновление каталога — реализовано
|
||
|
||
Скрипт `~/scripts/watchlist-catalog.sh` (root:root, ставить только `sudo install -m 755`):
|
||
|
||
1. `python3 $LAMPAC/scripts/gen_watchlist.py <watchlist.md> $LAMPAC/wwwroot/watchlist.json`
|
||
2. `docker restart lampac` — **обязательно**, сбрасывает кэш Catalog (см. питфолл 3)
|
||
|
||
Cron: `30 2 * * *` → лог `~/logs/watchlist-catalog.log`.
|
||
Время выбрано после `watchlist-nightly` (01:00) и `watchlist-cleanup` (02:00).
|
||
|
||
Бэкап crontab перед установкой: `~/crontab-backup-20260922-112915.txt`.
|
||
|
||
⚠️ **`watchlist-catalog.sh` сделан отдельной задачей, а не врезан в `watchlist-nightly.sh`.**
|
||
Причина: `nightly` — рабочий боевой скрипт, его падение остановило бы весь пайплайн списка.
|
||
Отдельный cron падает изолированно.
|
||
|
||
## Что осталось (единственное незакрытое)
|
||
|
||
**Не шаг Alex, а правка сервера.** Плагин на ТВ уже добавлен и **источник уже выбран**
|
||
(`Storage.field('source') = 'Мой список'`). Проблема — баг в `plugin.js` Lampac
|
||
(см. «🔴 ГЛАВНЫЙ ПИТФОЛЛ»): источник не виден в UI из-за `enumerable: false`.
|
||
|
||
**Ждёт апрува Alex** (2026-09-22): смонтировать поправленный `plugin.js` через compose.
|
||
|
||
Путь на ТВ, который раньше писался («влево → панель → выбрать источник») — **не сработает**,
|
||
пока баг не исправлен: в панели источника просто нет.
|
||
|
||
Приёмка = категории видны в UI Lampa, названия совпадают с `movies-watchlist.md`.
|
||
|
||
## Диагностический скрипт для ТВ (`/tmp/lampa_probe.py`)
|
||
|
||
Правки в UI Lampa по SSH напрямую не сделать, но **состояние читается** через DevTools:
|
||
|
||
```python
|
||
pages = json.load(urllib.request.urlopen("http://192.168.1.70:9998/json", timeout=8))
|
||
target = next(p for p in pages if "com.lampac.tv" in p.get("url",""))
|
||
ws = websocket.create_connection(target["webSocketDebuggerUrl"], timeout=10)
|
||
# Runtime.evaluate:
|
||
# Lampa.Storage.field('source')
|
||
# Object.keys(Lampa.Api.sources).join('|')
|
||
# Object.getOwnPropertyDescriptor(Lampa.Api.sources,'Мой список')
|
||
# Lampa.Api.sources['Мой список'].getCatalog()
|
||
```
|
||
|
||
Требует `pip3 install websocket-client` (стоит). См. [[family/how-to/tv-lampac-plugin]].
|
||
|
||
## Известные ограничения
|
||
|
||
| Ограничение | Детали |
|
||
|---|---|
|
||
| **Постеров нет** | `image` пустой. Опционально — тянуть через TMDB-кэш Lampac (`tmdbproxy`) |
|
||
| **Карточки нет** | Только список названий. `card_parse` не настроен — Lampa может показывать пустую карточку |
|
||
| **`🗓️` upcoming показываются** | Не прячем. Решение Alex не запрашивалось |
|
||
| **Перезапуск контейнера** | Каждое обновление каталога = `docker restart lampac` (~30 сек простоя). Кэш не инвалидируется иначе |
|
||
|
||
## ⚠️ Что проверено, а что нет
|
||
|
||
**Проверено по HTTP (серверная часть):**
|
||
|
||
| Проверка | Результат |
|
||
|---|---|
|
||
| `/catalog.js` по IP | 200, ~32 КБ, `api_host:'http://192.168.1.14:9118'` |
|
||
| Каталог в `/catalog` | **7 ключей**, «Мой список» первым (Rezka, Kinobase, FilmixApp, VoKino, Eneyida, KinoUkr, Мой список) |
|
||
| JSON-файлы | `watchlist.json` + `watchlist-{films,new,cartoons,anime}.json` — все 200 |
|
||
| Выдача по категориям | films 360 · new **33** · cartoons 3 · anime 7 (после фикса сирот 2026-09-22) |
|
||
| Формат ответа `/catalog/list` | `{page, results, total_pages}`, `total_pages: 1` для films |
|
||
| Сортировка | ⭐ → рейтинг ↓ → ужасы |
|
||
| Чистота названий | эмодзи-маркеров 0 |
|
||
| Сирота «Конец света» | ❌ отсутствует во всех 4 категориях |
|
||
|
||
**НЕ проверено:**
|
||
|
||
- ✅ **UI Lampa на ТВ — ПРИЧИНА НАЙДЕНА 2026-09-22** (см. ниже «🔴 ГЛАВНЫЙ ПИТФОЛЛ»).
|
||
Диагностика через Chrome DevTools ТВ (`http://192.168.1.70:9998/json`):
|
||
- ТВ **физически достаёт** Кра́кен — `curl` с ТВ отдаёт `/catalog` 200 за 0.26 с.
|
||
- Lampa **работает и ходит на сервер** — соединение `192.168.1.70 → 192.168.1.14:9118` ESTABLISHED.
|
||
- `Storage.field('source')` = **`'Мой список'`** — источник уже выбран!
|
||
- `Lampa.Api.sources['Мой список']` **существует** и отдаёт каталог
|
||
(`getCatalog()` → `search, search_lazy, movie, cartoons, anime, menu, main`).
|
||
- ❌ НО: `Object.keys(Lampa.Api.sources)` = `'tmdb|cub'` — **источника нет в перечислении**.
|
||
- Причина: `defineProperty(..., {get: ..., enumerable:false, configurable:false})`.
|
||
- **Диагноз: баг в `plugin.js` самого Lampac, а не в нашей настройке.** UI Lampa строит
|
||
список источников через `Object.keys()` — «Мой список» из него выпадает, поэтому в UI
|
||
источник не видно и выбрать его нельзя.
|
||
- ❌ Боевой прогон крона в 02:30 (скрипт отработал вручную успешно).
|
||
- ❌ Карточка/постеры в UI.
|
||
|
||
## 🔴 ГЛАВНЫЙ ПИТФОЛЛ: источник не виден в UI Lampa (`enumerable: false`)
|
||
|
||
**Симптом.** Alex: «Ни на главной ни в Фильмах нет! Там только Сейчас смотрят, рекомендуем итд».
|
||
Плагин добавлен, серверная часть отдаёт всё корректно, а в UI источника нет.
|
||
|
||
**Диагностика (по возрастанию точности):**
|
||
|
||
1. `ssh kraken 'sudo ss -tn | grep ":9118"'` — сначала показал **0 соединений** (ложный вывод:
|
||
замер сделан в момент старта Lampa). Через 30 с на ТВ:
|
||
`netstat -tn | grep 9118` → **1 ESTABLISHED + 6 TIME_WAIT** — Lampa скачала все файлы.
|
||
2. Foreground-приложение: `luna-send -n 1 -f luna://com.webos.applicationManager/getForegroundAppInfo {}`
|
||
→ `com.lampac.tv`. Запускать надо `launch` с **экранированным JSON в кавычках**,
|
||
иначе `errorCode: 2 invalid parameters`.
|
||
3. Доступ к отладчику ТВ: **`curl http://192.168.1.70:9998/json`** — webOS отдаёт Chrome
|
||
DevTools Protocol на порту 9998 (у `WebAppMgr` в аргументах `--remote-debugging-port=9998`).
|
||
Через `websocket` + `Runtime.evaluate` читаются переменные живой Lampa.
|
||
4. Ключевой замер: `JSON.stringify(Object.getOwnPropertyDescriptor(Lampa.Api.sources,'Мой список'))`
|
||
→ `{"enumerable":false,"configurable":false}`.
|
||
|
||
**Корень.** В `/lampac/module/Catalog/plugin.js` (строка 59, `loadCatalogs()`, **два вхождения**):
|
||
|
||
```js
|
||
Object.defineProperty(Lampa.Api.sources, key, { get: function(){ return Api; } });
|
||
```
|
||
|
||
Свойство создаётся не-enumerable → `Object.keys()` его не видит → Lampa не рисует источник
|
||
в панели выбора. При этом `Api.sources['Мой список']` доступен напрямую и каталог отдаёт.
|
||
|
||
**Фикс** (одна правка, два вхождения):
|
||
|
||
```js
|
||
Object.defineProperty(Lampa.Api.sources, key,
|
||
{ get: function(){ return Api; }, enumerable: true, configurable: true });
|
||
```
|
||
|
||
**Как применять — `plugin.js` живёт в образе, не на HDD!** (проверено:
|
||
`docker inspect` не показывает монтирования на `module/Catalog`, монтируются только
|
||
`catalog/sites` и `catalog/override`). Правка через `docker exec` **исчезнет при обновлении образа**.
|
||
|
||
Предложенный путь (на апруве у Alex, 2026-09-22):
|
||
|
||
```yaml
|
||
# docker-compose.yml
|
||
volumes:
|
||
- ./catalog/plugin.js:/lampac/module/Catalog/plugin.js:ro
|
||
```
|
||
|
||
```bash
|
||
# 1. забрать, поправить локально (sed/grep по файлу не применять — только patch)
|
||
ssh kraken 'docker exec lampac cat /lampac/module/Catalog/plugin.js' > /tmp/catalog-plugin.js
|
||
# 2. бэкап
|
||
cp /tmp/catalog-plugin.js /tmp/catalog-plugin.js.bak-$(date +%Y%m%d-%H%M%S)
|
||
# 3. правка двух вхождений defineProperty → +enumerable:true,configurable:true
|
||
# 4. проверка синтаксиса ПЕРЕД заливкой
|
||
node --check /tmp/catalog-plugin.js
|
||
# 5. на HDD, добавить volume, пересоздать
|
||
scp /tmp/catalog-plugin.js kraken:/srv/.../lampac/catalog/plugin.js
|
||
ssh kraken 'cd /srv/.../lampac && docker compose up -d'
|
||
# 6. проверка на ТВ: Object.keys(Lampa.Api.sources) должен стать 'tmdb|cub|Мой список'
|
||
```
|
||
|
||
**Откат:** убрать строку volume из compose → `docker compose up -d`. Плюс бэкап файла в `/tmp`.
|
||
|
||
**Статус: правка НЕ применена** — ждёт апрува Alex (2026-09-22).
|
||
|
||
## Готовые команды диагностики ТВ (переиспользовать)
|
||
|
||
```bash
|
||
# 1. Что запущено на ТВ (luna-send пишет в tty → нужен script -q -c)
|
||
ssh root@192.168.1.70 'script -q -c "luna-send -n 1 -f \
|
||
luna://com.webos.applicationManager/getForegroundAppInfo {}" /dev/null'
|
||
|
||
# 2. Запустить приложение (JSON экранирован И обёрнут в кавычки)
|
||
ssh root@192.168.1.70 'script -q -c "luna-send -n 1 -f \
|
||
luna://com.webos.applicationManager/launch \"{\\\"id\\\":\\\"com.lampac.tv\\\"}\"" /dev/null'
|
||
|
||
# 3. Достаёт ли ТВ Кра́кен
|
||
ssh root@192.168.1.70 'curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" \
|
||
--max-time 8 http://192.168.1.14:9118/catalog'
|
||
|
||
# 4. Живые соединения с Lampac (на ТВ, не на сервере!)
|
||
ssh root@192.168.1.70 'netstat -tn 2>/dev/null | grep 9118'
|
||
|
||
# 5. DevTools-цель Lampa на ТВ
|
||
curl -s --max-time 8 "http://192.168.1.70:9998/json" | /usr/bin/jq -r '.[] | "\(.type): \(.url)"'
|
||
```
|
||
|
||
Скрипты-пробы DevTools: `/tmp/lampa_probe.py` (состояние источника),
|
||
`/tmp/lampa_probe3.py` (асинхронный вызов `menu()` каталога).
|
||
|
||
⚠️ `tcpdump` на Кра́кене **нет** — для съёма трафика ставить не стали, использован
|
||
DevTools-подход (дал больше: видно состояние JS, а не только пакеты).
|
||
|
||
⚠️ `luna://com.webos.service.capture/takeScreenShot` на этом ТВ **не существует**
|
||
(`Unknown method`) — скриншот так не снять.
|
||
|
||
## Файлы реализации (на HDD Кра́кена)
|
||
|
||
Корень: `/srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/lampac/`
|
||
|
||
| Путь | Роль |
|
||
|---|---|
|
||
| `config-module/init.conf` | включает Catalog → `/lampac/init.conf:ro` |
|
||
| `catalog/sites/watchlist.yaml` | описание каталога |
|
||
| `catalog/override/` | переопределения (пусто) |
|
||
| `wwwroot/watchlist.json` | все секции |
|
||
| `wwwroot/watchlist-<code>.json` | по файлу на категорию |
|
||
| `scripts/gen_watchlist.py` | генератор |
|
||
| `docker-compose.yml` | 7 монтирований; бэкапы `.bak-*` |
|
||
|
||
На хосте: `~/scripts/watchlist-catalog.sh`, лог `~/logs/watchlist-catalog.log`.
|
||
|
||
## Откат
|
||
|
||
```bash
|
||
# выключить каталог
|
||
ssh kraken 'sed -i "s/\"catalog\": true/\"catalog\": false/" \
|
||
/srv/.../lampac/config-module/init.conf && docker restart lampac'
|
||
# в Lampa убрать плагин catalog.js
|
||
# cron: crontab -l | grep -v watchlist-catalog | crontab -
|
||
```
|
||
|
||
Ничего в коде Lampac не патчилось — только конфиг и данные.
|
||
|
||
## Статус: ✅ РЕАЛИЗОВАНО 2026-09-22
|
||
|
||
Каталог «Мой список» работает, отдаётся в Lampa через `/catalog.js`.
|
||
|
||
### Что сделано
|
||
|
||
| # | Шаг | Результат |
|
||
|---|---|---|
|
||
| 1 | Включён модуль Catalog | `SkipModules` без Catalog + `catalog: true` → `/catalog.js` 200 |
|
||
| 2 | `init.conf` смонтирован | `./config-module/init.conf:/lampac/init.conf:ro` — правится на HDD, не теряется |
|
||
| 3 | `sites/` + `override/` смонтированы | `./catalog/sites`, `./catalog/override` |
|
||
| 4 | `wwwroot` смонтирован | `./wwwroot` — Lampac сам отдаёт JSON по HTTP |
|
||
| 5 | Генератор написан | `lampac/scripts/gen_watchlist.py` |
|
||
| 6 | `sites/watchlist.yaml` создан | `lampac/catalog/sites/watchlist.yaml` |
|
||
| 7 | Автообновление в cron | `30 2 * * *` → `~/scripts/watchlist-catalog.sh` |
|
||
| 8 | Проверка | 4 категории: films 360, new 34, cartoons 3, anime 7 |
|
||
|
||
### Архитектура (финальная)
|
||
|
||
```
|
||
family/documents/movies-watchlist.md ← источник
|
||
│ gen_watchlist.py (свой парсер, ~200 строк)
|
||
▼
|
||
lampac/wwwroot/watchlist.json ← все секции
|
||
lampac/wwwroot/watchlist-<code>.json ← по файлу на категорию
|
||
│ Lampac отдаёт wwwroot по HTTP сам
|
||
▼
|
||
lampac/catalog/sites/watchlist.yaml ← описание для Catalog
|
||
│ plugin=watchlist, jsonPath: true, nodes: $.items[*]
|
||
▼
|
||
Lampa на ТВ: плагин http://192.168.1.14:9118/catalog.js
|
||
```
|
||
|
||
### 🔴 Питфоллы, найденные по ходу (не повторять)
|
||
|
||
1. **Catalog ВЫБРАСЫВАЕТ элемент с пустым `href`.**
|
||
`ListController.cs`: `if (!IsNullOrWhiteSpace(name) && !IsNullOrWhiteSpace(href))`.
|
||
Симптом: из 404 позиций отдалось 52 — ровно те, у кого есть ссылка Кинопоиска.
|
||
**Фикс:** генератор подставляет fallback-href
|
||
`https://www.kinopoisk.ru/index.php?kp_query=<название>`.
|
||
|
||
2. **Catalog НЕ подставляет `{cat}` в `nodes`.**
|
||
JSONPath статичен, отфильтровать секцию внутри одного файла нечем.
|
||
Симптом: все категории отдавали весь список (404 вместо 360/34/3/7).
|
||
**Фикс:** генератор пишет отдельный плоский файл на категорию
|
||
(`watchlist-films.json` и т.д.), `nodes: "$.items[*]"` одинаков для всех.
|
||
|
||
3. **Кэш Catalog без версии данных.**
|
||
Ключ `catalog:{plugin}:{search}:{sort}:{cat}:{page}` — не зависит от содержимого.
|
||
Симптом: после перегенерации JSON выдача не менялась.
|
||
**Фикс:** `docker restart lampac` в скрипте обновления.
|
||
|
||
4. **`init.conf` не был смонтирован.**
|
||
Файл живёт в образе; правки через `docker exec` теряются при пересоздании.
|
||
Правки шли в `current.conf` (сгенерированный) — неверная цель.
|
||
**Фикс:** volume `:ro` + свой минимальный `init.conf` (перекрывает `base.conf`).
|
||
|
||
5. **`api_host` подставляется из запроса** (`{localhost}` → хост, по которому пришли).
|
||
По IP `192.168.1.14` отдаёт правильный адрес — специально ничего настраивать не нужно.
|
||
|
||
6. **Кириллица в inline-jq внутри `ssh '...'`** ломает команду (tirith + quoting).
|
||
Выносить в файл или убирать строки с кириллицей.
|
||
|
||
7. **Осиротевшие строки в `## Новинки` давали дубли в каталоге.**
|
||
Строки без `👍`/`👎` (например `- [ ] ⬇️ Название`) `process-thumbs` не трогал —
|
||
они висели в Новинках навсегда. Если фильм уже `[x]` в главном списке — получался дубль:
|
||
непросмотренный «Конец света» при просмотренном оригинале.
|
||
**Фикс в `watchlist-sync/parser.py`** (удаление сирот + флаг `_patch_dropped`) и `cli.py`.
|
||
Разбор: [[family/projects/watchlist-automation]], секция «ОСИРОТЕВШИЕ СТРОКИ».
|
||
|
||
8. **Двойное экранирование при правке `parser.py` скриптами.**
|
||
`r'\1'` превращался в байт `\x01`, `r'\b'` — в `\x08`. Синтаксис валиден, регекспы молчат.
|
||
**Проверять файл на `chr(1)` и `chr(8)` после патча.**
|
||
|
||
### Управление
|
||
|
||
```bash
|
||
ssh kraken
|
||
cd /srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/lampac
|
||
|
||
# перегенерировать каталог + сбросить кэш
|
||
bash ~/scripts/watchlist-catalog.sh
|
||
|
||
# логи
|
||
tail -f ~/logs/watchlist-catalog.log
|
||
|
||
# только генератор (без перезапуска)
|
||
python3 scripts/gen_watchlist.py \
|
||
/home/kraken/obsidian/family/documents/movies-watchlist.md \
|
||
wwwroot/watchlist.json
|
||
```
|
||
|
||
### Откат
|
||
|
||
```bash
|
||
# выключить каталог
|
||
ssh kraken 'sed -i "s/\"catalog\": true/\"catalog\": false/" \
|
||
/srv/.../lampac/config-module/init.conf && docker restart lampac'
|
||
# в Lampa убрать плагин catalog.js
|
||
```
|
||
|
||
## Правила отбора и сортировки (утверждено Alex 2026-09-22)
|
||
### Фильтрация
|
||
|
||
| Правило | Действие |
|
||
|---|---|
|
||
| `[ ]` непросмотренные | **показывать** |
|
||
| `[x]` просмотренные | ❌ скрыть |
|
||
| `👎` | ❌ скрыть |
|
||
| `🗓️` upcoming | показывать (решить при реализации — есть в файле) |
|
||
| `❓` ambiguous | показывать (название как есть) |
|
||
|
||
### Сортировка внутри списка — трёхключевая
|
||
|
||
1. **`⭐` (U+2B50) — первыми**
|
||
2. **Рейтинг — по убыванию** (IMDb/KP из строки файла; строки `[название](kp) (год) IMDb N.N KP N.N`)
|
||
3. **Ужасы (`🧟♀️`, TMDB genre_id=27) — последними**
|
||
|
||
⚠️ **Только `⭐` (U+2B50)** — как в `sync-down` (см. [[family/projects/watchlist-automation]]).
|
||
`✭` (U+272D) приоритетом **не является**.
|
||
|
||
### Порядок секций
|
||
|
||
1. **Главный список — первым.** Это `## Фильмы`
|
||
2. Дальше — **остальные по порядку в файле**: `## Новинки - 👍/👎`, `## Мультфильмы`, `## Аниме`, …
|
||
|
||
⚠️ `## Новинки👎` — **не показывать** (это скрытая секция отказов).
|
||
⚠️ Секция `## Новинки` содержит `👍`/`👎`; `👎`-строки прячем, `👍` показываем.
|
||
|
||
### Источник рейтинга
|
||
|
||
В строках со ссылками Кинопоиска рейтинг **уже в тексте**: `IMDb 7.6 KP 8.2`.
|
||
Для строк без рейтинга (например `- [ ] Gods don't give gifts`) — сортировать как `0`, в конец группы.
|
||
Опционально: добирать через TMDB (кэш `tmdbproxy` в Lampac) — решить при реализации.
|
||
|
||
## Открытые вопросы (не блокируют, решение Alex не запрошено)
|
||
|
||
1. **Постеры** — тянуть через TMDB-кэш Lampac или не тянуть вовсе? Сейчас пустые.
|
||
2. **Карточка** — нужна ли (описание/рейтинг внутри Lampa), или достаточно списка названий?
|
||
3. **`🗓️` upcoming** — показывать или прятать? Сейчас показываем.
|
||
4. **`❓` ambiguous** — сейчас показываем с названием как есть.
|
||
|
||
Ни один из них **не мешает работе** — каталог отдаётся, категории на месте.
|
||
Спрашивать только если Alex сам затронет тему.
|
||
|
||
## Связанные
|
||
|
||
- [[personal/plans/lampac-kraken]] — базовое развёртывание (шаги 1–6 сделаны)
|
||
- [[personal/tech/lampac-deployment]] — эксплуатация Lampac, модуль Catalog
|
||
- [[family/how-to/tv-lampac-plugin]] — подключение плагина на ТВ
|
||
- [[family/projects/watchlist-sync]] — парсер списка, CLI
|
||
- [[family/projects/watchlist-automation]] — форматы маркеров, cron
|
||
- [[family/documents/movies-watchlist]] — источник данных
|