[2026-09-22] eagle: family/how-to/tv-lampac-plugin.md personal/plans/lampac-watchlist-plugin.md personal/tech/lampac-deployment.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-22 12:48:55 +06:00
1 parent 1aeb42f4b8
commit 38b803d4fd
3 files changed
+305 -50

No files matched your search

+46 -16
View File
@@ -58,10 +58,9 @@ Lampa в webOS использует `localStorage`, который Chromium хр
⚠️ Мой предыдущий вариант («влево на ряду → панель источников») **не подтверждён**.
⚠️ **При выборе «Мой список» исчезает родной каталог CUB** — это **не баг Lampa**,
а следствие архитектурной ошибки в нашей конфигурации (заполнен блок `menu`).
Разбор и фикс — раздел «🔴 Архитектура: `menu` подменяет каталог» ниже.
а следствие перехвата кликов в `plugin.js` (см. раздел «🔴 Что на самом деле подменяет CUB»).
## 🔴 Архитектура: `menu` подменяет каталог, `main` добавляет сверху
## 🔴 Что на самом деле подменяет CUB — `plugin.js`, а не YAML (проверено 2026-09-22)
**Что хотел Alex:**
@@ -69,17 +68,36 @@ Lampa в webOS использует `localStorage`, который Chromium хр
> сверху добавлено несколько секций в которых будут РЕАЛЬНЫЕ ЭЛЕМЕНТЫ — а не сгенерируют
> пустые заглушки!»
| Блок YAML | Поведение |
⚠️ **Гипотеза «`menu` подменяет / `main` добавляет» — ОПРОВЕРГНУТА на живом сервере.**
Её здесь не повторять. Факты:
| Гипотеза | Факт |
|---|---|
| **`menu`** | ❌ **подменяет** родные разделы (Фильмы/Сериалы/Аниме) — родной каталог **исчезает** |
| **`main`** | ✅ **добавляет секции на главную сверху** — родной каталог **остаётся** |
| `menu` подменяет родные разделы | ❌ `menu` **регистрирует канал**. Без него сайт отбрасывается: `ApiController.cs:70` → `if (init == null \|\| !init.enable \|\| init.menu == null \|\| init.hide) continue;` |
| `main` добавляет секции сверху | ❌ блока `main` **в YAML не существует** — YamlDotNet давится неизвестным полем, `goInit` → null, сайт молча пропадает |
| «Убрать `menu` из watchlist.yaml» | ❌ **сломало канал**: «Мой список» исчез из `/catalog`, список пустой. Три раунда правок, три рестарта |
Наша конфигурация заполнила **оба** → при выборе источника «Мой список» пропал весь CUB.
**Настоящий виновник — `plugin.js`** (он же `/catalog.js`):
**Фикс:** в `catalog/sites/watchlist.yaml` **убрать `menu`**, оставить только `main`.
```js
Lampa.Listener.follow('menu', function(e){
if (e.type=='action' && (e.action=='tv'||'cartoon'||'anime'||'movie'||'relise')) {
var catalog = Api.getCatalog();
if (!catalog) return;
...
Lampa.Router.call('category', {...});
e.abort(); // ← перехват клика по родному разделу
}
});
```
Механика в `plugin.js`: `function menu()` собирает из `catalog.menu`;
`function main()` строит `parts_data` из `catalog.main` и подмешивает в `Lampa.Api.partNext`.
**Перехват работает ТОЛЬКО когда выбран источник «Мой список».** Родной CUB/tmdb не
трогается, пока источник не переключён на наш.
**Вывод про «CUB + мой список одновременно»:** родной CUB и «Мой список» — **два источника
Lampa** (переключаются в «остальное → основной источник»). Показать одновременно нельзя
без своего плагина. Варианты — [[personal/tech/lampac-deployment]], раздел
«🎯 Как добиться „CUB + мой список сверху“».
## 🟡 «Здесь пусто» и нет постеров — потому что данные не из Radarr
@@ -304,14 +322,26 @@ var plugins_add = [
- ❌ В панели выбора источника его **нет** — `plugin.js` регистрирует свойство
без `enumerable: true`. **Баг в Lampac, не в нашей настройке.**
**Что переделывается (2026-09-22, после разбора с Alex):**
**Что переделывается (обновлено 2026-09-22 ночь):**
1. Убрать блок `menu` из `watchlist.yaml` → вернуть родной каталог CUB, оставить только `main`
2. Переключить источник данных с парсинга `.md` на **Radarr API** → постеры + TMDB ID
3. Смонтировать поправленный `plugin.js` (`enumerable: true`)
1. ❌ ~~Убрать блок `menu` из `watchlist.yaml`, оставить `main`~~ — **ОТМЕНЕНО, невозможно.**
`main` в YAML ломает парсинг (сайт исчезает из `/catalog`), `menu` обязателен для
регистрации канала. Подмену делает `plugin.js`. См. раздел выше.
2. ⏳ Переключить источник данных с парсинга `.md` на **`resolver.py`** (TMDB + Кинопоиск)
→ постеры + TMDB ID для всех 360. *(Radarr API даёт только 50 — в нём нет остальных 310.)*
3. ⏳ Смонтировать поправленный `plugin.js` (`enumerable: true`)
4. ✅ **Выключена автоскачка на HDD** — Radarr (45→0 monitored, очередь 6→0, RSS 30→0),
Sonarr (13→0, 19→0, 15→0). Бэкапы `20260922-123404`. Метаданные целы: 50 фильмов,
46 с постерами, 24 файла на диске не тронуты.
**Ждёт апрува Alex.** Полный разбор — [[personal/plans/lampac-watchlist-plugin]],
раздел «🔴 АРХИТЕКТУРНАЯ ОШИБКА».
**Текущее состояние каталога: РАБОЧИЙ.** «Мой список» на месте в `/catalog`, 4 категории
(360/33/3/7). `watchlist.yaml` откачен к проверенной форме.
**Открытое решение Alex:** родной CUB и «Мой список» одновременно показать нельзя —
нужен свой плагин. Варианты (оставить как есть / патч `plugin.js` / свой плагин) —
[[personal/tech/lampac-deployment]], раздел «🎯 Как добиться „CUB + мой список сверху“».
Полный разбор — [[personal/plans/lampac-watchlist-plugin]].
**Скрипт-автоматизация по-прежнему не создана** — и, вероятно, не нужна: источник
переключается через **Настройки → «остальное» → основной источник** (Alex сделал сам).
+148 -27
View File
@@ -53,9 +53,27 @@ updated: '2026-09-22'
> RSS 30→**0**) и Sonarr (13→**0**, 19→**0**, 15→**0**). Метаданные целы — 50 фильмов,
> **46 с постерами**, 24 файла на диске не тронуты. Проверено: Transmission не сдвинулся
> ни на байт за 45 с, логи Radarr пусты. Бэкапы `radarr.db`/`sonarr.db`/`config.xml` — метка
> `20260922-123404`. Осталось 4 правки (шаги 5–8): постеры через `resolver.py`, убрать
> `menu` из YAML, фикс `plugin.js`, фикс `arr.py`. См. «✅ Порядок работ» и
> «🔴 Питфоллы выполнения». **Всё на апруве, ничего сверх не трогалось.**
> `20260922-123404`. См. «✅ Порядок работ» и «🔴 Питфоллы выполнения».
>
> **Обновление 2026-09-22 (ночь): 🔴 ПОПЫТКА УБРАТЬ `menu` ПРОВАЛЕНА — ГИПОТЕЗА БЫЛА НЕВЕРНА.**
> Попытка «оставить `main`, убрать `menu`» **сломала канал**: «Мой список» исчез из `/catalog`,
> `catalog/list?plugin=watchlist` отдавал пустоту. Три раунда правок YAML, три рестарта.
> **Установлено тестом:**
> - **`menu` ОБЯЗАТЕЛЕН** — он регистрирует канал, а не подменяет разделы
> (`ApiController.cs:70`: без `menu` сайт отбрасывается). Убрать нельзя.
> - **блок `main` в YAML НЕ СУЩЕСТВУЕТ** — любые формы (список/словарь) ломают парсинг,
> `goInit` → null, сайт молча пропадает. **Errors в логах нет.**
> - **`main` Catalog генерирует САМ** из `menu` — в JSON-ответе `/catalog` есть оба ключа
> с одинаковым содержимым.
> - **Подмену разделов делает `plugin.js`**, не YAML (`Listener.follow('menu')` + `e.abort()`),
> срабатывает только при выбранном источнике «Мой список».
> - **`host` + `uri` СКЛЕИВАЮТСЯ** (`ListController.cs:53`) → `uri` обязан быть относительным.
> Также найден питфолл: **явный `format` в `menu` перезагружает страницу** при выборе раздела.
>
> **Текущее состояние:** каталог **рабочий** (waтchlist.yaml откачен к рабочей форме,
> «Мой список» на месте, 4 категории 360/33/3/7). Правки 5–8 (постеры через `resolver.py`,
> `plugin.js`, `arr.py`) **не начаты** — ждут решения Alex по вопросу
> «CUB и Мой список одновременно». См. **«🔴 ПИТФОЛЛ YAML: `main` ЗАПРЕЩЁН»**.
>
> **Аудит «как это реализуемо» — ✅ ЗАВЕРШЁН 2026-09-22.** Проверено всё:
> TorrServer **на диск не пишет** (`UseDisk: false`, RAM-кэш 96 МБ) — главный вопрос закрыт;
@@ -74,27 +92,11 @@ updated: '2026-09-22'
**Что сделано вместо этого — две независимые ошибки:**
### Ошибка 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`.
> ⚠️ **ОПРОВЕРГНУТО ТЕСТОМ 2026-09-22 (поздний вечер).** Раздел ниже описывает
> **неверную гипотезу** («`menu` подменяет / `main` добавляет»). Проверка на живом
> сервере показала: **блока `main` в YAML не существует** — он ломает парсинг.
> Подмену разделов делает **`plugin.js`**, а не YAML. Читать раздел
> **«🔴 ПИТФОЛЛ YAML: `main` ЗАПРЕЩЁН»** ниже — там правильная механика.
### Ошибка 2 — источник данных: парсинг `.md` вместо Radarr API
@@ -326,7 +328,7 @@ Cron: `30 2 * * *` → лог `~/logs/watchlist-catalog.log`.
|---|---|---|
| 1 | Генератор берёт данные **из Radarr API** (`localhost:7878/api/v3/movie`), а не парсит текст | ⏳ ждёт апрува |
| 2 | Подставлять в `id` → `tmdbId`, в `img` → `images[].remoteUrl` (постер), `year` → `year` | ⏳ |
| 3 | Из `sites/watchlist.yaml` **убрать блок `menu`**, оставить `main` → родной CUB остаётся | ⏳ |
| 3 | ~~Из `sites/watchlist.yaml` убрать блок `menu`, оставить `main`~~ ❌ **НЕВОЗМОЖНО** — `main` в YAML ломает парсинг, `menu` обязателен. Подмену делает `plugin.js`. См. «🔴 ПИТФОЛЛ YAML» | ❌ опровергнуто |
| 4 | Постеры кэшировать локально (Radarr `MediaCover/` или проксировать через `tmdbproxy`) | ⏳ |
| 5 | Фикс `plugin.js` (`enumerable:true`) — **отдельная независимая правка**, см. ниже | ⏳ ждёт апрува |
@@ -653,6 +655,125 @@ ssh kraken 'sed -i "s/\"catalog\": true/\"catalog\": false/" \
Для строк без рейтинга (например `- [ ] Gods don't give gifts`) — сортировать как `0`, в конец группы.
Опционально: добирать через TMDB (кэш `tmdbproxy` в Lampac) — решить при реализации.
## 🔴 ГЛАВНЫЙ ПИТФОЛЛ YAML: `main` ЗАПРЕЩЁН, он генерируется сам (2026-09-22)
**Симптом:** добавил блок `main:` в `sites/watchlist.yaml` → «Мой список» **полностью
исчез** из `/catalog` (остались только Eneyida, FilmixApp, KinoUkr, Kinobase, Rezka, VoKino).
Запрос `catalog/list?plugin=watchlist` отдавал **пустоту**. В логах Lampac — **тишина**,
ошибка не пишется, сайт просто отбрасывается.
**Причина:** `CatalogSettings` **не имеет поля `main`** для входного YAML. YamlDotNet
давится неизвестным полем → `ModInit.goInit(site)` возвращает **null** →
`ApiController.cs:70` отбрасывает сайт:
```csharp
if (init == null || !init.enable || init.menu == null || init.hide)
continue;
```
⚠️ Проверено обе формы — **обе ломают**:
```yaml
main: # список — НЕ работает
- categories:
Фильмы: films
```
```yaml
main: # словарь — НЕ работает
Фильмы: http://...
```
**Как на самом деле:** Catalog **сам генерирует `main`** в JSON-ответе `/catalog`,
выводя его из блока `menu`. Проверено — в ответе есть **и `menu`, и `main`** с одинаковым
содержимым:
```json
"menu": { "Фильмы": "/catalog/list?plugin=watchlist&cat=films", ... },
"main": { "Фильмы": "/catalog/list?plugin=watchlist&cat=films", ... }
```
**Писать `main` в YAML не нужно и нельзя.** Достаточно `menu`.
### Правильная форма YAML (проверенная, рабочая)
```yaml
enable: true
jsonPath: true
displayindex: 1
displayname: Мой список
host: http://127.0.0.1:9118
menu: # ← ЕДИНСТВЕННЫЙ обязательный блок категорий
- categories:
Фильмы: films
Новинки: new
Мультфильмы: cartoons
Аниме: anime
format:
"-": |
return $"http://127.0.0.1:9118/watchlist-{cat}.json";
search:
uri: watchlist.json
list:
uri: watchlist-films.json
firstpage: watchlist-films.json
total_pages: 1
content:
nodes: "$.items[*]"
name: { attribute: name }
original_name: { attribute: original }
year: { attribute: year }
href: { attribute: href }
image: { attribute: image }
args:
- { name_arg: rating, attribute: rating }
```
### Сопутствующие питфоллы (все проверены на живом сервере)
1. 🔴 **`menu` ОБЯЗАТЕЛЕН.** Не «подменяет разделы», а **регистрирует канал**.
`ApiController.cs:70`: без `menu` сайт отбрасывается. Убирать нельзя.
2. 🔴 **`host` + `uri` СКЛЕИВАЮТСЯ.** `ListController.cs:53`:
```csharp
string url = $"{init.host}/{(page==1 && init.list?.firstpage != null
? init.list?.firstpage : init.list?.uri)}";
```
Значит `uri`/`firstpage` должны быть **относительными** (`watchlist-films.json`).
Полный URL даёт двойной префикс → пусто:
`http://127.0.0.1:9118/http://127.0.0.1:9118/watchlist-films.json`
3. 🔴 **Явно указанный `format` в `menu` вызывает перезагрузку страницы при каждом
выборе категории.** Если не нужен — убрать `format` из `menu`, оставить только
`categories`. (Наблюдение Alex: «перезагружает прогрузку страницы при каждом выборе
раздела».)
### Кто на самом деле подменял родные разделы Lampa
**НЕ YAML.** Это `plugin.js` (он же `/catalog.js`):
```js
Lampa.Listener.follow('menu', function(e){
if (e.type=='action' && (e.action=='tv'||'cartoon'||'anime'||'movie'||'relise')) {
var catalog = Api.getCatalog();
if (!catalog) return;
...
Lampa.Router.call('category', {...});
e.abort(); // ← перехват клика по родному разделу
}
});
```
**Перехват срабатывает ТОЛЬКО когда выбран источник «Мой список».**
Родной CUB/tmdb не трогается, пока источник не переключён на наш.
### Как реально добиться «CUB + мой список сверху»
| Путь | Реализуемость |
|---|---|
| Блок `main` в YAML | ❌ **невозможно** — ломает парсинг |
| Оставить `menu` | ⚠️ источник работает, но разделы подменяются, пока он выбран |
| Патч `plugin.js` | ⚠️ возможно: убрать `Listener.follow('menu')` — перехвата не будет, но и секции сверху не появятся |
**Открытый вопрос для Alex:** родной CUB и «Мой список» — это **два источника Lampa**,
переключаются в «остальное → основной источник». Одновременно показывать нельзя без
патча `plugin.js`. Решение за Alex.
## ✅ РЕШЕНИЕ НАЙДЕНО 2026-09-22 — полная архитектура (проверено)
### Что уже есть в системе (нашёл, проверено)
@@ -774,7 +895,7 @@ family/documents/movies-watchlist.md ← источник (360 филь
| # | Файл | Правка | Зачем |
|---|---|---|---|
| 1 | `watchlist_sync/arr.py` | `searchForMovie: True` → **`False`** (+ у дочки то же для сериалов) | добавление без скачки |
| 2 | `catalog/sites/watchlist.yaml` | убрать блок `menu`, оставить `main` | родной CUB не подменяется |
| 2 | ~~`catalog/sites/watchlist.yaml` — убрать блок `menu`, оставить `main`~~ ❌ **НЕВОЗМОЖНО** (опровергнуто тестом). Вместо этого — выбрать путь из трёх: оставить как есть / патч `plugin.js` / свой плагин. Решение Alex | ❌ отменено |
| 3 | генератор каталога | брать постер/ID через `resolver` | реальные элементы вместо заглушек |
⚠️ Правка №1 **может уже не понадобиться**: шаги 1–3 (unmonitor + RSS 0) закрыли скачку
@@ -1024,7 +1145,7 @@ Radarr/Sonarr после переделки = ЧИСТЫЙ СПРАВОЧНИК
| 3 | `rssSyncInterval: 0` | оба | ✅ **сделано** (оба 0) |
| 4 | Проверка: monitored 0, очередь 0, RSS 0, Transmission тих | оба | ✅ **сделано** |
| 5 | Генератор каталога → постеры/ID через **`resolver.py`** | — | ⏳ ждёт апрува |
| 6 | В `sites/watchlist.yaml` убрать `menu`, оставить `main` | — | ⏳ ждёт апрува |
| 6 | ~~В `sites/watchlist.yaml` убрать `menu`, оставить `main`~~ ❌ **ОТМЕНЕНО** — невозможно, см. «🔴 ПИТФОЛЛ YAML» | — | ❌ опровергнуто |
| 7 | Фикс `plugin.js` (`enumerable:true`) | — | ⏳ ждёт апрува |
| 8 | Фикс `arr.py`: `searchForMovie` → `False` | — | ⏳ ждёт апрува |
+111 -7
View File
@@ -203,16 +203,120 @@ Configure complete ← HTTP начинает отвечать
берутся парсингом `.md` вместо **Radarr API** (в `.md` нет TMDB ID и постеров).
Разбор ошибки — [[personal/plans/lampac-watchlist-plugin]], секция «🔴 АРХИТЕКТУРНАЯ ОШИБКА».
### 🔴 `menu` vs `main` — принципиальная разница
### 🔴 Рабочая форма `sites/watchlist.yaml` (проверена 2026-09-22, откат после провала)
| Блок YAML | Что делает |
```yaml
enable: true
jsonPath: true
displayindex: 1
displayname: Мой список
host: http://127.0.0.1:9118
menu: # ← ОБЯЗАТЕЛЕН (регистрирует канал), единственный блок категорий
- categories:
Фильмы: films
Новинки: new
Мультфильмы: cartoons
Аниме: anime
format:
"-": |
return $"http://127.0.0.1:9118/watchlist-{cat}.json";
search:
uri: watchlist.json
list:
uri: watchlist-films.json
firstpage: watchlist-films.json
total_pages: 1
content:
nodes: "$.items[*]"
name: { attribute: name }
original_name: { attribute: original }
year: { attribute: year }
href: { attribute: href }
image: { attribute: image }
args:
- { name_arg: rating, attribute: rating }
```
### 🔴 `main` в YAML ЗАПРЕЩЁН — ломает канал (опровергнуто 2026-09-22)
**Раздел ниже (гипотеза «`menu` подменяет / `main` добавляет») — НЕВЕРЕН.** Проверено
на живом сервере: попытка добавить блок `main` в YAML → **«Мой список» исчез из `/catalog`**,
`catalog/list?plugin=watchlist` отдавал пустоту. **Три раунда правок, три рестарта.**
| Гипотеза (неверна) | Факт (проверено) |
|---|---|
| `menu` | **подменяет** родные разделы Lampa (Фильмы/Сериалы/Аниме) → родной каталог исчезает |
| `main` | **добавляет секции на главную СВЕРХУ** → родной каталог остаётся |
| `menu` подменяет родные разделы | ❌ `menu` **регистрирует канал**. `ApiController.cs:70`: `if (init == null \|\| !init.enable \|\| init.menu == null \|\| init.hide) continue;` — без `menu` сайт **отбрасывается** |
| `main` добавляет секции сверху | ❌ блока `main` **не существует** во входном YAML. YamlDotNet давится неизвестным полем → `ModInit.goInit(site)` → **null** → сайт молча пропадает |
| Заполнять нужно только `main` | ❌ `main` Catalog **генерирует САМ** из `menu`. В JSON-ответе `/catalog` есть **оба** ключа с одинаковым содержимым |
Заполнять нужно **только `main`**, если задача — «добавить ряды к родному каталогу».
`plugin.js` → `function menu()` собирает из `catalog.menu`; `function main()` строит
`parts_data` из `catalog.main` и подмешивает в `Lampa.Api.partNext`.
⚠️ **Обе формы `main` ломают одинаково** — и список, и словарь:
```yaml
main: # вариант 1 — список: НЕ работает
- categories:
Фильмы: films
```
```yaml
main: # вариант 2 — словарь: НЕ работает
Фильмы: http://...
```
⚠️ **Ошибка не логируется.** В логах Lampac — тишина (`docker logs lampac | grep -i yaml`
пусто). Сайт просто не появляется в `/catalog`. Диагностика только перебором YAML.
**Кто на самом деле подменяет родные разделы — `plugin.js`, а не YAML:**
```js
Lampa.Listener.follow('menu', function(e){
if (e.type=='action' && (e.action=='tv'||'cartoon'||'anime'||'movie'||'relise')) {
var catalog = Api.getCatalog();
if (!catalog) return;
...
Lampa.Router.call('category', {...});
e.abort(); // ← перехват клика по родному разделу
}
});
```
**Перехват срабатывает ТОЛЬКО когда выбран источник «Мой список».** Родной CUB/tmdb
не трогается, пока источник не переключён на наш.
### 🔴 `host` + `uri` СКЛЕИВАЮТСЯ — `uri` обязан быть относительным
`ListController.cs:53`:
```csharp
string url = $"{init.host}/{(page==1 && init.list?.firstpage != null
? init.list?.firstpage : init.list?.uri)}";
```
Полный URL в `uri`/`firstpage` даёт **двойной префикс** → пусто:
```
http://127.0.0.1:9118/http://127.0.0.1:9118/watchlist-films.json
```
Правильно: только `watchlist-films.json`, `host` приклеится сам. Так же устроены
родные YAML (`vokino.yaml` → `uri: search?name={search}`).
### ⚠️ Питфолл: явный `format` в `menu` перезагружает страницу
С `format`-блоком в `menu` Lampa **перезагружает прогрузку страницы при каждом выборе
раздела** (наблюдение Alex). Если перезагрузка не нужна — убрать `format` из `menu`,
оставить только `categories`.
### 🎯 Как добиться «CUB + мой список сверху» — варианты (решение Alex, не принято)
Родной CUB и «Мой список» — это **два источника Lampa**, переключаются в
«остальное → основной источник». Одновременно показать нельзя без вмешательства:
| Путь | Реализуемость |
|---|---|
| Блок `main` в YAML | ❌ **невозможно** — ломает парсинг |
| Оставить `menu` как есть | ⚠️ источник работает, но разделы подменяются, пока он выбран |
| Патч `plugin.js` | ⚠️ убрать `Listener.follow('menu')` → перехвата нет, но и секции сверху **не появятся** |
| Написать свой плагин | ✅ единственный путь для «сверху», объём работы |
### ⚠️ Баг Lampac: источник не виден в списке выбора