12 KiB
created, namespace, related, status, tags, title, type, updated
| created | namespace | related | status | tags | title | type | updated | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2026-09-22 | personal |
|
proposed |
|
Watchlist в UI Lampa — каталог из списка | plan | 2026-09-22 |
Watchlist в UI Lampa — каталог из списка (план)
Составлен 2026-09-22, переписан после разведки кода Catalog. Ждёт подтверждения Alex. Базовое развёртывание — personal/plans/lampac-kraken (шаги 1–6 закрыты).
Задача
Показывать список фильмов Alex (family/documents/movies-watchlist.md) в UI Lampa на ТВ — каталогом.
Не локальный плейбэк. Формулировка Alex: «отображение фильмов из списка».
✅ Затык снят: чем это делается
В образе 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
if (!url.StartsWith("http"))
url = $"{init.host}/{url}"; // ListController.cs:87
host из YAML сканируется по HTTP (Http.Get / Playwright / RCH).
Локальные файлы напрямую Catalog читать не умеет — только HTTP-ответ.
Два режима парсинга
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)
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 правки
// 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 отдаёт его сам, без новых сущностей.
Что показывать в каталоге
Секции берём из самого файла: ## Фильмы, ## Мультфильмы, ## Аниме → три категории меню.
Поля: name (название), year, href (ссылка на Кинопоиск — уже есть в файле как [название](https://www.kinopoisk.ru/film/NNN/)),
image — постер (можно взять через TMDB-кэш Lampac, tmdbproxy).
⚠️ href в файле — ссылка Кинопоиска, а Lampa ждёт карточку. Отрисовку карточки решает card_parse
(в vokino он ходит по {host}/view/{uri}). Для нашего случая возможен режим только список, без карточки —
проверить на этапе реализации.
Обновление каталога
- Генератор дёргать после
watchlist-nightly.sh(уже кроном 01:00 на Кра́кене) — догенерировать JSON - ⚠️
watchlist-nightly.shв~/scripts/— root:root, правка толькоsudo install -m 755 - Партия данных меняется (
⬇️,[x], 👍→перенос) — JSON пересобирать после каждого прогона
Шаги (черновик, уточняется на этапе реализации)
- Включить модуль Catalog:
SkipModules+catalog: true, закрепитьinit.confvolume. - Смонтировать
module/Catalog/(или толькоsites/+override/) на HDD — чтобы каталоги не терялись. - Написать генератор
movies-watchlist.md→ JSON (переиспользоватьparser.pyиз watchlist-sync). - Положить JSON туда, откуда Lampac отдаёт статику.
- Написать
sites/watchlist.yamlпо образцуvokino.yaml. - Подключить на ТВ: Lampa → Настройки → Плагины →
http://192.168.1.14:9118/catalog.js. - Приёмка: категории видны в UI Lampa на ТВ, названия совпадают со списком.
Откат
catalog: false + вернуть Catalog в SkipModules. Ничего в Lampac не патчится.
Правила отбора и сортировки (утверждено Alex 2026-09-22)
Фильтрация
| Правило | Действие |
|---|---|
[ ] непросмотренные |
показывать |
[x] просмотренные |
❌ скрыть |
👎 |
❌ скрыть |
🗓️ upcoming |
показывать (решить при реализации — есть в файле) |
❓ ambiguous |
показывать (название как есть) |
Сортировка внутри списка — трёхключевая
⭐(U+2B50) — первыми- Рейтинг — по убыванию (IMDb/KP из строки файла; строки
[название](kp) (год) IMDb N.N KP N.N) - Ужасы (
🧟♀️, TMDB genre_id=27) — последними
⚠️ Только ⭐ (U+2B50) — как в sync-down (см. family/projects/watchlist-automation).
✭ (U+272D) приоритетом не является.
Порядок секций
- Главный список — первым. Это
## Фильмы - Дальше — остальные по порядку в файле:
## Новинки - 👍/👎,## Мультфильмы,## Аниме, …
⚠️ ## Новинки👎 — не показывать (это скрытая секция отказов).
⚠️ Секция ## Новинки содержит 👍/👎; 👎-строки прячем, 👍 показываем.
Источник рейтинга
В строках со ссылками Кинопоиска рейтинг уже в тексте: IMDb 7.6 KP 8.2.
Для строк без рейтинга (например - [ ] Gods don't give gifts) — сортировать как 0, в конец группы.
Опционально: добирать через TMDB (кэш tmdbproxy в Lampac) — решить при реализации.
Открытые вопросы
- Нужна ли карточка (описание/рейтинг внутри Lampa), или достаточно списка названий с постерами?
- Постеры — тянуть через TMDB-кэш Lampac или не тянуть вовсе?
🗓️upcoming — показывать или прятать? (сейчас по умолчанию показываем)
Связанные
- personal/plans/lampac-kraken — базовое развёртывание
- personal/tech/lampac-deployment — эксплуатация, порты, питфоллы
- family/projects/watchlist-sync — парсер списка, CLI
- family/projects/watchlist-automation — форматы маркеров, cron
- family/documents/movies-watchlist — источник данных