Files
obsidian-vault/personal/plans/lampac-watchlist-plugin.md
T

1035 lines
60 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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: rework
tags:
- lampac
- lampa
- watchlist
- catalog
- webos
- plugin
- kraken
- radarr
title: Watchlist в UI Lampa — каталог из списка
type: plan
updated: '2026-09-22'
---
# Watchlist в UI Lampa — каталог из списка
> Реализовано 2026-09-22. План был переписан после разведки кода модуля Catalog.
> Базовое развёртывание — [[personal/plans/lampac-kraken]] (шаги 1–6 закрыты).
>
> 🔴 **АРХИТЕКТУРА ПРИЗНАНА НЕВЕРНОЙ 2026-09-22 — переписывается.**
> Сделано `menu` (подмена родных разделов) вместо `main` (секции СВЕРХУ).
> Плюс источник данных — парсинг текстового `.md` вместо **Radarr API**, где уже
> есть TMDB ID и постеры. Alex: «Я предполагал что будет отображаться то что и раньше
> (список cub) но В НЕГО будет сверху добавлено несколько секций в которых будут
> РЕАЛЬНЫЕ ЭЛЕМЕНТЫ - а не сгенерируют пустые заглушки!»
> См. «🔴 АРХИТЕКТУРНАЯ ОШИБКА» — читать ПЕРВЫМ.
>
> **Итог одной строкой:** серверная часть каталога работает (4 категории, 360/33/3/7),
> но реализована не по замыслу: подменяет каталог вместо добавления секций,
> и не использует Radarr как источник постеров/ID.
>
> **Обновление 2026-09-22 (вечер):** Alex лично нашёл источник в UI
> («остальное → основной источник → Мой список»), увидел результат и подтвердил
> диагноз: секции подменяют CUB, нет превью, элементы — сырые строки файла.
> Затем сам сформулировал целевую схему (Radarr = источник метаданных **без автоскачки**,
> просмотр через TorrServer, файлы на HDD не пишутся) → записано в **«ПЕРЕДЕЛКА 2»**.
> План работ на апруве, **ничего не выполнено**.
>
> **Аудит «как это реализуемо» — ✅ ЗАВЕРШЁН 2026-09-22.** Проверено всё:
> TorrServer **на диск не пишет** (`UseDisk: false`, RAM-кэш 96 МБ) — главный вопрос закрыт;
> поиск торрентов работает через **Jackett-API самого Lampac** (отдельный Jackett не нужен);
> найдены **оба** виновника автоскачки — Radarr (45 monitored, очередь 6) и
> **Sonarr** (13 monitored, очередь 19). См. «✅ ПРОВЕРКА "как это реализуемо"».
> ⚠️ Порядок работ теперь включает Sonarr — раньше он в плане не учитывался.
## 🔴 АРХИТЕКТУРНАЯ ОШИБКА 2026-09-22 — почему каталог «не работает»
**Что хотел Alex (дословно):**
> «Я предполагал что будет отображаться то что и раньше (список cub) но В НЕГО будет
> сверху добавлено несколько секций в которых будут РЕАЛЬНЫЕ ЭЛЕМЕНТЫ — а не сгенерируют
> пустые заглушки! Нахуя это надо то?! Чё блядь значит оно так и должно быть?!»
**Что сделано вместо этого — две независимые ошибки:**
### Ошибка 1 — структура: `menu` вместо `main`
Модуль Catalog умеет **два независимых блока**, и они делают РАЗНОЕ:
| Блок YAML | Что делает | Поведение |
|---|---|---|
| **`menu`** | **подменяет** родные разделы Lampa (Фильмы/Сериалы/Аниме) | ❌ заполнен → родной каталог исчезает |
| **`main`** | **добавляет секции на главную СВЕРХУ** | ✅ родной каталог остаётся |
Реализация заполнила **оба** (`menu` и `main`) → при выборе источника «Мой список»
исчез весь CUB-контент.
**Симптом по словам Alex:** «при его выборе исчезло все что было до этого из списка CUB
во всех разделах. Нет превью.»
**Фикс:** в `sites/watchlist.yaml` **убрать блок `menu`**, оставить только `main`.
Тогда родной каталог (CUB/tmdb) работает как раньше, а твои секции идут рядами сверху.
Код: `plugin.js` → `function menu()` собирает из `catalog.menu`; если ключа нет —
`menu` не подменяется (вернётся пустой, Lampa использует родные). `main()` строит
`parts_data` из `catalog.main` и подмешивает их в `Lampa.Api.partNext`.
### Ошибка 2 — источник данных: парсинг `.md` вместо Radarr API
Генератор читал `movies-watchlist.md` — **текстовый список названий**. В нём
**нет ни TMDB ID, ни постеров**. Результат:
| Метрика | Значение |
|---|---|
| Всего позиций (films) | 360 |
| Из них с постером (`img != null`) | **0** |
| Из них с реальным ID (`film/...`) | **18** |
Остальные 342 отдавались с `id` = **ссылка на поиск Кинопоиска**
(`index.php?kp_query=...`). Отсюда жалоба «при открытии элемента пишет *здесь пусто*»:
Lampa идёт по ссылке, получает страницу поиска, а не фильм.
**Замер 2026-09-22 (доказательство, воспроизводимо):**
```bash
curl -s "http://192.168.1.14:9118/catalog/list?plugin=watchlist&cat=films" \
| jq '[.results[] | select(.img == null)] | length' # → 360
curl -s "..." | jq '.results | length' # → 360
curl -s "..." | jq '[.results[] | select(.id | startswith("film/"))] | length' # → 18
```
То есть **постеров 0 из 360**, рабочих карточек 18 из 360.
**Почему «девять» с маленькой буквы и `Gods don't give gifts`** — это не баг каталога,
а буквально строки файла (проверено `grep -n`):
```
56: - [ ] Gods don't give gifts
64: - [ ] ❓ девять
```
Каталог отдаёт строки как есть. Обе — в секции `## Новинки` (отступ 2 пробела, подсписок).
Alex: «Отображаются элементы типа "девять"(с маленькой буквы), Gods don't give gifts —
который вообще ещё не вышел — короче не реальные фильмы а буквально пункты списка.»
**Правильный источник — Radarr API.** Alex: «Они уже резолвятся же блядь!! Оно же
добавлялось в arr!» — TMDB ID и постеры уже есть там, потому что фильмы добавлялись
в Radarr.
```bash
# API-ключ Radarr
grep -oE "<ApiKey>[^<]+</ApiKey>" /srv/dev-disk-by-uuid-6194539b-.../docker/radarr/config.xml
# → cbcb8ec320104359920c0f611d503c7b
# ⚠️ ВАЖНО: -L обязателен! Без него Radarr отдаёт 307, тело пустое
curl -sL "http://localhost:7878/api/v3/movie?apikey=$KEY" | jq length
# → 50
```
**Форма ответа Radarr (то, что нужно было брать с самого начала):**
```json
{
"tmdbId": 1292695,
"title": "They Will Kill You",
"year": 2026,
"hasFile": true,
"images": [{"coverType":"poster",
"remoteUrl":"https://image.tmdb.org/t/p/original/6oI4oQKTWMVUlr8Ivqydp28R"}]
}
```
Есть **всё**: TMDB ID → рабочий `href`, `remoteUrl` → постер, `title`/`year` → название,
`hasFile` → скачан или нет. Плюс постеры локально: `/config/MediaCover/` (46 каталогов).
⚠️ **Покрытие:** в Radarr **50 фильмов**, в `.md` — **360**. Разница (310) — то, что
в список записано, но в Radarr не заказано. Что с ними делать — **решение Alex
не получено**, открытый вопрос №1 ниже.
### Что НЕ надо было делать (записано, чтобы не повторять)
- Парсить текст вместо API, где данные уже резолвлены
- Складывать `menu` + `main` одновременно
- Считать «список названий» готовым каталогом для UI с постерами
### Alex: корневая претензия к процессу
> «А нахуя ты это так реализовал?? Подумать блядь вообще не твое!»
Разбор: задача звучала как «покажи список в UI» — и была прочитана буквально
(«отдать строки файла»). **Надо было сначала выяснить, откуда брать постеры и ID**
(а ответ — Radarr, куда фильмы и добавлялись), а не начинать с парсера текста.
## Задача
Показывать список фильмов Alex (`family/documents/movies-watchlist.md`) **в UI Lampa на ТВ** — каталогом.
Не локальный плейбэк. Формулировка Alex: «отображение фильмов из списка».
**Уточнение от 2026-09-22 (важное!):** каталог **добавляется СЕКЦИЯМИ СВЕРХУ** к родному
каталогу Lampa. Родной CUB-контент **не подменяется и не исчезает**. Элементы — **реальные**
фильмы с постерами и карточками, а не пустые заглушки (см. «🔴 АРХИТЕКТУРНАЯ ОШИБКА»).
⚠️ **Что НЕ спрашивать повторно.** Задача — **отображение**, не воспроизведение.
Список — это перечень, а не источник видео. Вопрос «а что играть по клику?» —
**выдумка сверх постановки**, 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 падает изолированно.
## Что осталось — ПЕРЕДЕЛКА (после признания архитектуры неверной)
| # | Шаг | Статус |
|---|---|---|
| 1 | Генератор берёт данные **из Radarr API** (`localhost:7878/api/v3/movie`), а не парсит текст | ⏳ ждёт апрува |
| 2 | Подставлять в `id` → `tmdbId`, в `img` → `images[].remoteUrl` (постер), `year` → `year` | ⏳ |
| 3 | Из `sites/watchlist.yaml` **убрать блок `menu`**, оставить `main` → родной CUB остаётся | ⏳ |
| 4 | Постеры кэшировать локально (Radarr `MediaCover/` или проксировать через `tmdbproxy`) | ⏳ |
| 5 | Фикс `plugin.js` (`enumerable:true`) — **отдельная независимая правка**, см. ниже | ⏳ ждёт апрува |
**Порядок:** шаги 1–4 закрывают жалобу «пустые заглушки + исчез CUB».
Шаг 5 — про то, что источника вообще не видно в списке выбора.
Приёмка (формулировка Alex): **родной список CUB на месте, сверху добавлены ряды
с реальными фильмами из списка, у элементов есть постеры и рабочие карточки.**
## Диагностический скрипт для ТВ (`/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) — решить при реализации.
## 🎯 ПЕРЕДЕЛКА 2 — Radarr как источник метаданных без автоскачки (план Alex, 2026-09-22)
### Логика Alex (дословно)
> «Мы блядь убираем автоскачку на диск так?! При этом ты оставляешь radarr/sonarr
> источником, так?? И в него из списка добавляется скриптом, но не грузит автоматом так?
> Сейчас ты отменяешь текущие загрузки, так??»
**Расшифровка:**
| # | Что | Как |
|---|---|---|
| 1 | **Автоскачка на HDD — выключить** | Radarr/Sonarr ничего не качают сами |
| 2 | **Radarr/Sonarr остаются источником** | TMDB ID + постеры для каталога Lampa |
| 3 | **Скрипт добавляет в них из списка** | `.md` → Radarr API, фильм получает метаданные |
| 4 | **Но не грузит автоматом** | Добавление ≠ загрузка |
| 5 | **Текущие загрузки — отменить** | 6 записей в очереди |
### Как это в Radarr технически (проверено 2026-09-22)
⚠️ **Важно для понимания:** в Radarr «добавить, но не качать» = **`monitored: false`**.
Отдельного состояния «источник, но не грузить» нет. При добавлении через API Radarr
**сам ходит в TMDB** и тянет метаданные (постер, год, описание) — даже при `monitored: false`.
Это и есть решение задачи №2+№3+№4.
### Доступ к Radarr API (проверено 2026-09-22, воспроизводимо)
```bash
# API-ключ лежит в config.xml (не в БД)
ssh kraken 'grep -oE "<ApiKey>[^<]+</ApiKey>" \
/srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/docker/radarr/config/config.xml' \
| sed 's/<[^>]*>//g' # → cbcb8ec320104359920c0f611d503c7b
```
🔴 **ПИТФОЛЛ: `-L` обязателен.** Без него Radarr отдаёт **307 с пустым телом** и `jq length` падает:
```bash
curl -s "http://localhost:7878/api/v3/movie?apikey=$KEY" | jq length # → пустой вывод, 0 байт
curl -sL "http://localhost:7878/api/v3/movie?apikey=$KEY" | jq length # → 200, 50
```
**Конфиг Radarr (замер):**
```bash
curl -sL ".../api/v3/config/indexer?apikey=$KEY" | jq .rssSyncInterval # → 30 (мин)
```
`rssSyncInterval: 30` = Radarr **каждые 30 минут** сам ходит в RSS-фиды и качает новое.
Это вторая причина автоскачки помимо `monitored: true`. **Выключать надо оба.**
### Окружение Radarr на Кра́кене (для будущих сессий)
| Параметр | Значение |
|---|---|
| Порт | `7878` (`0.0.0.0`) |
| Контейнер | `radarr`, образ `lscr.io/linuxserver/radarr:latest` |
| Конфиг на HDD | `/srv/...6194539b.../docker/radarr/config/` |
| БД | `radarr.db` (+ `-shm`, `-wal`) |
| Постеры | `/config/MediaCover/` — **46 каталогов** |
| `sqlite3` в контейнере | ❌ **нет** (на хосте Кра́кена — **есть**, `/usr/bin/sqlite3`) |
| Соседи | `sonarr:8989`, `prowlarr:9696`, `transmission` |
⚠️ В контейнерах `sqlite3` отсутствует (см. профиль Alex) — БД читать через `strings`
или вытаскивать файл наружу и смотреть хостовым `sqlite3`.
### Текущее состояние Radarr (замер 2026-09-22)
| Метрика | Значение |
|---|---|
| Фильмов всего | 50 |
| `monitored: true` | **45** ← активны, ищут и качают |
| `hasFile: true` | 24 (уже на диске) |
| `rssSyncInterval` | **30** мин ← Radarr ходит в RSS каждые полчаса |
| Очередь | **6 записей** (все `warning`, ничего не качается активно) |
| Transmission | простаивает (1% CPU) |
Очередь (id для отмены):
```
598407147 Brokeback Mountain.mkv
1092005446 Гладиатор (2000) (DTS X) DV.mkv
914899324 Sorry.to.Bother.You.BDRemux.1080p.NNMClub.pk.mkv
1671545331 Мортал Комбат 2 (DTS-HD MA).mkv
1486734395 Gorod.boga.2002.BDRemux.1080p.mkv
139445264 День хомячка (2003)
```
## ✅ ПРОВЕРКА «как это реализуемо» — полный аудит 2026-09-22 (вечер)
Alex: «Мне надо чтоб lampa источники видела и играла фильмы из списка и cub.
При этом мы перестаем качать торренты на диск! Как это реализуемо??
Проверь блядь все чтобы ты опять не обосрался».
Проверено всё, что может качать или мешать. **Ничего не менялось — только чтение.**
### 🎯 Главная находка: TorrServer на диск НЕ пишет
Ключевой факт, снимающий главный вопрос Alex («при этом фильмы не будут
скачиваться на hdd я правильно понимаю?!»). Конфиг TorrServer внутри Lampac:
```bash
ssh kraken 'docker exec lampac cat /lampac/data/ts/settings.json' | jq .
```
```jsonc
{
"BitTorr": {
"CacheSize": 100663296, // 96 МБ — RAM-кэш
"UseDisk": false, // 🔴 НА ДИСК НЕ ПИШЕТ
"TorrentsSavePath": "", // путь сохранения пуст
"TorrentDisconnectTimeout": 180, // раздача живёт 3 мин после остановки
"PreloadCache": 0,
"ReaderReadAHead": 83
}
}
```
**`UseDisk: false`** — TorrServer держит всё в RAM (96 МБ) и **на диск не пишет ничего**.
Это ровно то, что нужно Alex. Настраивать не надо, уже так.
### TorrServer жив и работает (проверено)
```bash
curl -s "http://192.168.1.14:9118/ts/echo" # → MatriX.135 (версия, живой)
curl -s "http://192.168.1.14:9118/ts/torrents" # → 404 (это не тот эндпоинт)
curl -s -X POST "http://192.168.1.14:9118/ts/torrents" \
-H 'Content-Type: application/json' -d '{"action":"list"}' # → [] пусто, ничего не висит
```
Кэш Lampac: `/lampac/cache/` = 31 МБ (SQLite, Playwright, gstreamer-registry) —
**не фильмы**. `/lampac/data/` = 44 МБ (ts/settings.json, dlna/thumbs). Диск не забит.
### Поиск торрентов — Jackett внутри Lampac, отдельный НЕ нужен
🔴 **ПИТФОЛЛ-ЛОВУШКА: в `lampainit.js` стоит `parser_torrent_type = 'jackett'`,
но отдельного контейнера Jackett НЕТ.** Это не ошибка — Lampac **сам отдаёт
Jackett-совместимый API**.
```bash
# что прописывает Lampac клиенту:
curl -s "http://192.168.1.14:9118/lampainit.js" | grep -oE "Lampa.Storage.set\('[^']+', ?'[^']*'\)"
# Lampa.Storage.set('jackett_url', '192.168.1.14:9118')
# Lampa.Storage.set('jackett_key', '1')
# Lampa.Storage.set('parser_torrent_type', 'jackett')
# Lampa.Storage.set('parser_use', 'true')
```
`jackett_url` указывает **на сам Lampac**, а не на сторонний сервис. Проверка API:
```bash
# ⚠️ работает БЕЗ префикса /jackett — на корне
curl -s "http://192.168.1.14:9118/api/v2.0/indexers/all/results?apikey=1&Query=matrix"
# → 200, реальные результаты: rutor, магнит-ссылки, Size, Seeders, ffprobe
curl -s -o /dev/null -w "%{http_code}" "http://192.168.1.14:9118/jackett/api/v2.0/..." # → 404
curl -s -o /dev/null -w "%{http_code}" "http://192.168.1.14:9118/api/v2.0/..." # → 200 ✅
```
**Вывод:** поиск торрентов работает штатно, ничего поднимать не надо.
### Кто качает на диск — полный реестр (единственные виновники)
```bash
ssh kraken 'docker ps --format "{{.Names}}\t{{.Image}}"'
```
| Сервис | Качает? | Замер | Нужен для задачи? |
|---|---|---|---|
| **Radarr** | ✅ да | 50 фильмов, **45 monitored**, очередь **6**, RSS 30 мин | ❌ мешает |
| **Sonarr** | ✅ да | 13 сериалов, **13 monitored**, очередь **19** | ❌ мешает |
| **Transmission** | ⚠️ исполнитель | **257** `.torrent`, CPU 0.76% (простаивает), NetIO 290G/26.7G | ⚠️ движок Radarr/Sonarr |
| **TorrServer** | ❌ НЕТ | `UseDisk: false`, список торрентов `[]` | ✅ **вот чем играет Lampa** |
Полный список контейнеров Кра́кена:
`lampac · radarr · jellyfin · transmission · portainer · flaresolverr ·
prowlarr · sonarr · watchtower · rclone · xray-reverse-bridge · hermes-kraken · cloudflared`
**Sonarr API** (для будущей работы, по аналогии с Radarr):
```bash
# ключ: /srv/.../docker/sonarr/config/config.xml → 15fbec32f1cb4b05b1c2b229ce27359b
curl -sL "http://localhost:8989/api/v3/series?apikey=$SONARR_KEY" | jq 'length' # → 13
curl -sL "http://localhost:8989/api/v3/queue?apikey=$SONARR_KEY" | jq '.totalRecords' # → 19
```
⚠️ Sonarr — **тоже источник автоскачки**, не только Radarr. Alex упомянул его не зря.
Отключать надо оба, иначе Sonarr продолжит качать сериалы.
### Transmission — настройки (замер)
```bash
ssh kraken 'docker exec transmission cat /config/settings.json' > /tmp/trans-settings.json
```
```json
{"download-dir": "/downloads", "rpc-port": 9091,
"speed-limit-down-enabled": false, "peer-port": 51413,
"alt-speed-enabled": false}
```
`/config/torrents/*.torrent` = **257 файлов** — это накопленный список раздач,
**не признак активной качки** (CPU 0.76%). Файлы на диске не трогаем.
### Кто чем играет в Lampa (подтверждено)
```bash
curl -s "http://192.168.1.14:9118/lampainit.js" | grep -iE "torrents_use|source"
# lampa_settings.torrents_use = true ← кнопка торрентов включена
# Lampa.Storage.set('source', 'cub') ← CUB — основной источник ✅
# Lampa.Storage.set('proxy_tmdb', 'true')
```
В `plugins_add` (серверные плагины Lampac, не список Lampa):
`tmdbproxy.js · cubproxy.js · online.js · catalog.js · sisi.js · startpage.js ·
timecode.js · ts.js` — все `status: 1`.
### Итоговая схема (что получится после переделки)
```
ТВ: Lampa (com.lampac.tv)
├── источник CUB ── онлайн, работает как раньше ✅
└── источник «Мой список» ── секции СВЕРХУ, постеры из Radarr
│
▼ клик по фильму
поиск торрента через Lampac (Jackett-API на :9118)
│
▼
TorrServer (UseDisk: false) → RAM-кэш 96 МБ → на HDD НЕ ПИШЕТ ✅
Radarr/Sonarr после переделки = ЧИСТЫЙ СПРАВОЧНИК МЕТАДАННЫХ
(monitored: false + rssSyncInterval: 0) — не ищут, не качают
```
### ⚠️ Порядок работ (обновлён с учётом Sonarr)
| # | Действие | Сервис | Статус |
|---|---|---|---|
| 0 | Бэкап `radarr.db` + `config.xml` (+ то же для Sonarr) | оба | ⏳ |
| 1 | Отменить очередь: 6 записей Radarr + **19 Sonarr** | оба | ⏳ |
| 2 | `monitored: false` — 45 Radarr + **13 Sonarr** | оба | ⏳ |
| 3 | `rssSyncInterval: 0` | оба | ⏳ |
| 4 | Проверка: monitored 0, очередь 0, RSS 0, Transmission тих | оба | ⏳ |
| 5 | Генератор каталога → данные из **Radarr API** (TMDB ID + постер) | — | ⏳ |
| 6 | В `sites/watchlist.yaml` убрать `menu`, оставить `main` | — | ⏳ |
| 7 | Фикс `plugin.js` (`enumerable:true`) | — | ⏳ |
| 8 | Добавление 310 фильмов из `.md` в Radarr с `monitored: false` | Radarr | ⏳ |
**Не трогаем:** Prowlarr, Transmission, 24 файла на диске, Jellyfin, остальные контейнеры.
### ❓ Открытый вопрос к Alex
Radarr/Sonarr нужны **как справочник** (тогда постеры сохраняются) или
**выключаются совсем** (тогда каталог Lampa теряет постеры — их брать неоткуда)?
Ответа нет.
### План работ (на апруве Alex)
**Шаг 0 — бэкап (обязательно, до всего)**
```bash
ssh kraken 'cp /srv/.../docker/radarr/config/radarr.db /srv/.../radarr.db.bak-$(date +%Y%m%d-%H%M%S)'
ssh kraken 'cp /srv/.../docker/radarr/config/config.xml /srv/.../config.xml.bak-$(date +%Y%m%d-%H%M%S)'
```
Причина: `radarr.db` — боевая база, содержит всю библиотеку.
**Шаг 1 — отменить текущие загрузки (6 шт)**
```bash
curl -sL -X DELETE "http://localhost:7878/api/v3/queue/<id>?removeFromClient=true&blocklist=false&apikey=$KEY"
```
⚠️ **Не** использовать `blocklist=true` — иначе релизы попадут в чёрный список и
не найдутся при ручной загрузке. Файлы на диске **не трогаются**.
**Шаг 2 — снять `monitored` со всех фильмов**
```bash
curl -sL -X PUT "http://localhost:7878/api/v3/movie/editor?apikey=$KEY" \
-H "Content-Type: application/json" \
-d '{"movieIds":[<все 50>],"monitored":false}'
```
Результат: Radarr не ищет и не качает. Фильмы в базе с метаданными остаются.
**Шаг 3 — выключить авто-поиск по RSS**
```bash
curl -sL -X PUT "http://localhost:7878/api/v3/config/indexer?apikey=$KEY" \
-H "Content-Type: application/json" \
-d '{"rssSyncInterval":0,"id":1, ...остальные поля как есть}'
```
0 = Radarr не ходит в RSS. Ничего не находит сам.
**Шаг 4 — проверить**
```bash
jq '[.[] | select(.monitored==true)] | length' # → 0
jq '.rssSyncInterval' # → 0
jq '.totalRecords' # очередь → 0
```
**Что НЕ трогаем:** Prowlarr, Transmission, библиотеку на диске (24 файла), Sonarr
(отдельная проверка ниже).
### ⚠️ Незакрытые вопросы к плану
1. **Sonarr** — Alex упомянул его вместе с Radarr. Проверить его настройки отдельно
(сериалы в списке есть?). Это отдельная задача. **Вопрос задан Alex, ответа нет.**
2. **Ручная загрузка после отключения** — если Alex захочет скачать фильм вручную,
нужно временно включить `monitored` или искать вручную через Interactive Search.
Работает, но не автоматически.
3. **310 фильмов, которых нет в Radarr** — скрипт будет добавлять их с `monitored: false`,
Radarr сам подтянет постеры из TMDB. Но часть названий найдётся криво («девять»).
### ✅ Подтверждено Alex 2026-09-22 (семантика задачи — не переспрашивать)
Alex сам сформулировал схему и подтвердил её понимание ассистентом:
> «При этом фильмы не будут скачиваться на hdd я правильно понимаю?! Играть будет
> через torrserver так?» → ответ: **да, правильно**.
**Разделение обязанностей (запомнить, чтобы не путать):**
| Слой | Роль | Куда пишет |
|---|---|---|
| **Radarr/Sonarr + Transmission** | библиотека, автоскачка релизов | на HDD (библиотека) |
| **Lampac TorrServer** | стриминг по требованию из UI Lampa | **ничего не сохраняет** — только временный кэш кусков |
| **«Мой список» (Catalog)** | только показ секций с постерами | ничего не качает |
То есть после выключения автоскачки в Radarr: **фильмы, которые Alex смотрит через Lampa,
на HDD не попадают вообще** — TorrServer отдаёт поток и выбрасывает буфер. Файлы на диске
остаются только у 24 уже скачанных (нужны Jellyfin).
⚠️ **`transmission` НЕ связан с Lampa.** Radarr качает через него релизы в свою библиотеку —
это отдельный контур. Вопрос «через что играет TorrServer» и «что качает Radarr» —
**разные вещи**, не смешивать в объяснениях.
### 🔴 Правка `plugin.js` (`enumerable:true`) — всё ещё НЕ применена
Независимая от ПЕРЕДЕЛКИ 2 правка. Файл лежит локально `/tmp/catalog-plugin.js`
(10738 байт, `node --check` чистый, 2 вхождения исправлены), бэкап
`/tmp/catalog-plugin.js.bak-20260922-121452`. На Кра́кене и в образе — **оригинал**.
Нужен volume `./catalog/plugin.js:/lampac/module/Catalog/plugin.js:ro` в compose.
Подробности — раздел «🔴 ГЛАВНЫЙ ПИТФОЛЛ» выше.
**Порядок:** правку `plugin.js` имеет смысл применять **вместе с ПЕРЕДЕЛКОЙ 2**,
чтобы не пересоздавать контейнер дважды.
### Откат
```bash
# вернуть monitored (одним запросом)
curl -sL -X PUT ".../api/v3/movie/editor" -d '{"movieIds":[...],"monitored":true}'
# вернуть RSS
curl -sL -X PUT ".../api/v3/config/indexer" -d '{"rssSyncInterval":30,"id":1}'
# восстановить базу при необходимости
cp radarr.db.bak-<дата> radarr.db && docker restart radarr
```
**Статус: план на апруве. Ничего не выполнено.**
## Открытые вопросы — БЛОКИРУЮЩИЕ (2026-09-22, ждут решения Alex)
1. **Что делать с 310 фильмами, которых нет в Radarr?**
В `.md` — 360, в Radarr — 50. У 310 нет TMDB ID и постера.
Варианты: (а) показывать только 50 из Radarr; (б) добирать остальные через TMDB-search
(часть названий найдётся криво: «девять» → не то); (в) показывать заглушкой без постера.
**Без решения шаг 1 переделки не начать.**
2. **Нужны 4 секции или одна?** Секции «Фильмы / Новинки / Мультфильмы / Аниме»
или одна «Мой список» сверху. Вопрос задан, ответа нет.
## Открытые вопросы (не блокируют)
1. **Постеры** — тянуть через TMDB-кэш Lampac, через Radarr `MediaCover/`, или `remoteUrl` CDN?
2. **Карточка** — `card_parse` не настроен. С реальным TMDB ID карточка должна
подтянуться штатным механизмом Lampa — проверить после переделки.
3. **`🗓️` upcoming** — показывать или прятать? Сейчас показываем.
4. **`❓` ambiguous** — сейчас показываем с названием как есть.
## ⚠️ Отменённые/ошибочные указания (не повторять)
- ❌ **«Настройки → Источник»** — такого пункта в Lampa **не существует**. Выдумано,
Alex не нашёл. Источник переключается в разделе «остальное → основной источник»
(Alex нашёл сам 2026-09-22).
- ❌ **«влево → панель источников»** — тоже не подтверждено.
- ❌ **`plugins_add` в `lampainit.js`** — это серверные плагины Lampac
(`tmdbproxy.js`, `cubproxy.js`, `online.js`, `catalog.js`…), а **не** список плагинов Lampa.
`catalog.js` там есть при `"catalog": true` в init.conf.
## Связанные
- [[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]] — источник данных