Files
lampac/AGENT.md
T

130 lines
14 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.
# AGENT.md — инструкции для ИИ-агентов
Работа с проектом: локальный Docker-развёртывание [Lampac NextGen](https://github.com/lampac-nextgen/lampac). Человек читает ответы **только на русском**.
## Источники правды (порядок приоритета)
1. **Официальная документация** — [docs.lampac.dev](https://docs.lampac.dev) (полный текст страниц: `https://docs.lampac.dev/llms-full.txt`, индекс: `llms.txt`). Не гадать по памяти — проверять в доках.
2. **Живой контейнер** — состояние модулей, манифестов и конфигов брать из контейнера:
```bash
docker exec lampac sh -c 'cat /lampac/module/<Имя>/manifest.json'
docker exec lampac cat /lampac/current.conf # merged-конфиг: base + init
```
3. **Логи контейнера** — `docker logs lampac`.
4. Локальные файлы проекта: `docker-compose.yaml`, `config/init.conf`, `mods/`.
## Ключевые правила
### 1. Никогда не правь файлы внутри контейнера/образа
Файлы в `/lampac/module/` (и любые другие в образе) **сгорают при обновлении** (`docker compose pull && up -d`). Включение встроенного модуля делается только пользовательской копией:
```bash
docker cp lampac:/lampac/module/<Имя> "mods/<Имя>"
# в mods/<Имя>/manifest.json -> "enable": true
# в docker-compose.yaml -> "- ./mods/<Имя>:/lampac/mods/<Имя>"
# docker compose up -d
```
См. также официальные шаги: [Включить модуль](https://docs.lampac.dev/modules/overview), [Пользовательские модули](https://docs.lampac.dev/maintenance/custom-modules).
### 2. Механика загрузки модуля (4 независимых фильтра)
Модуль грузится, только если выполнены **все**:
| Фильтр | Где |
|---|---|
| `"enable": true` | `manifest.json` модуля (копия в `mods/` для встроенных) |
| Имя **не** в `BaseModule.SkipModules` | `base.conf` (в образе) + `config/init.conf` |
| Имя попадает в `BaseModule.LoadModules` | если allowlist задан (у нас не задан — грузится всё остальное) |
| Runtime-флаг | секция модуля в `config/init.conf`, например `"gst": { "enable": true }` |
`SkipModules` имеет приоритет над `LoadModules` — модуль из обоих списков **не** грузится. Паттерны: точное имя, группа (`OnlineUKR`), regex (`LME.*`), `.*`.
### 3. `config/init.conf` — валидный JSON
JSON **без** trailing comma. Перед применением правок проверять:
```bash
python3 -m json.tool config/init.conf > /dev/null && echo OK
```
После правки конфига: `docker compose restart` (том смонтирован, `up -d` не нужен). После правки `manifest.json` в `mods/` с `dynamic: true` — тоже `restart` (или ждать hot-rebuild). После изменения томов в compose — `docker compose up -d`.
### 4. Клиентские плагины Lampa
- Встроенные плагины: флаги `LampaWeb.initPlugins` (`tracks`, `dlna`, `catalog`, `sync`, `backup`, ...).
- Дополнительные: `LampaWeb.customPlugins` — записи со `status: 1` добавляются как есть; поддерживается плейсхолдер `{localhost}` (подставляется реальный адрес сервера).
- Если плагин «не виден» в веб-клиенте — сначала проверить HTTP-статус его URL на сервере (`curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:9118/<плагин>.js`), а не лезть в клиент.
### 4.1 Каталог плагинов (store) `/extensions`
- Раздел «Плагины» веб-клиента грузит каталог с `/extensions` (при `LampaWeb.initPlugins.pirate_store: true`).
- Источник: `/lampac/module/LampaWeb/plugins/extensions.json` — переопределён mount из `./plugins/extensions.json`. Править хост-файл, в контейнер не залезать.
- `{localhost}` в ссылках store сервер заменяет своим адресом при выдаче.
- Статика: `/lampac/plugins/` **не раздаётся** (проверено: файл → 404), корень `wwwroot` — раздаётся. Все плагины каталога — **локальный mirror** в `./plugins/`, смонтирован **одним directory-mount** в `/lampac/wwwroot/plugins/` → ссылки store `{localhost}/plugins/<имя>.js`. Не монтировать каталог целиком в корень `wwwroot` — скроется веб-клиент `lampa-main`.
- Обновление плагина: исходный URL — в `plugins/sources.json`; скачать, перезаписать файл, перезапуск не нужен (статика).
- При проверке скачанного плагина отличать: (а) реальный код, (б) лоадер `putScriptAsync` (абсолютные URL — безопасен локально; host от currentScript — **требуется патч**, см. showy.js), (в) пустой stub/placeholder (мёртвый плагин, из каталога удалять).
- **Кеш-ловушка**: ответ `/extensions` (и других LampaWeb-маршрутов) кешируется на диск в `/lampac/cache/static/<bucket>/<id>.json` (named volume `lampac_cache`); кеш переживает `docker compose restart`. После правки store: `docker exec lampac rm -rf /lampac/cache/static/59` (bucket `/extensions`), перезапуск не нужен. Заголовок `X-StatiCache-Status: HIT/MISS` показывает состояние.
### 5. AdminPanel API из скриптов (root-авторизация)
- Root-пароль = содержимое `config/passwd`. Механизм: cookie `accspasswd=<пароль>` (таков штатный сценарий: страница входа `auth.html` сама кладёт пароль в эту cookie). Заголовок `lcrqpasswd` — для внутренних вызовов, на `/adminpanel/api/*` с ним уходит 302 на `/adminpanel/auth`.
- Не передавать root-пароль в query string (предупреждение доков).
- Сервер может отвечать 404 вместо 401/403, чтобы не раскрывать админский endpoint.
- Основные маршруты: `GET /adminpanel/api/init` (чтение), `POST /adminpanel/api/init` (полная запись), `POST /adminpanel/api/init/section/{key}` (секция), `GET /adminpanel/api/current` (merged-конфиг), `GET /adminpanel/api/users-json`.
- Правка секций через API пишется в `init.conf` — watcher подхватит без рестарта (runtime-параметры). `customPlugins` — runtime-параметр: плагин появляется в `/lampainit.js` через ~1 с.
### 6. Диагностика «модуль не найден»
Чек-лист (в этом порядке):
1. `curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:9118/<маршрут>` — 404 подтверждает, что модуль не загружен.
2. `docker logs lampac | grep -E "compilation|loaded module" | grep <Имя>` — скомпилирован ли и загружен ли.
3. Манифест: `enable: true`? (в `mods/` для встроенных)
4. Фильтры `SkipModules`/`LoadModules` в `config/init.conf`.
5. Runtime-секция модуля в `config/init.conf`.
6. В логе после старта ожидаются строки `compilation <Имя>`, `configure module: <Имя>` (если есть конфиг-секция), `loaded module: <Имя>`.
### 7. Команды эксплуатации
```bash
docker compose up -d # запуск / пересоздание (при изменении compose)
docker compose restart # после правки init.conf / mods
docker compose logs -f # логи
docker compose pull && docker compose up -d # обновление (сначала поменять тег в compose)
docker exec lampac sh -c '...' # осмотр состояния в контейнере
```
`container_name: lampac` — контейнер один; одновременный запуск нескольких compose-файлов с одним именем невозможен. `docker-compose.override.yml` (gitignore) живёт только на сервере Proxmox и не коммитится.
### 8. Чего не трогать
- `config/passwd`, `dlna/` — в .gitignore, не коммитить. `cache`/`database` — **named Docker volumes** (`lampac_cache`, `lampac_database`), в git не попадают. Ловушка `.gitignore`: паттерны без якоря (`cache/`) матчат каталоги на любой глубине и без учёта регистра — из-за этого `mods/Music/Services/Cache/` не попадал в git и ломала Roslyn-компицию на сервере (CS0103, crash-loop). Новые данные/каталоги проверять через `git status`/`git check-ignore -v`.
- В named volume данные принадлежат тому, кто их туда положил: после миграции/копии `chown -R 1000:1000` (процесс в контейнере — `lampac:1000`), иначе SQLite «attempt to write a readonly database».
Исключение: `cache/static/` (в volume `lampac_cache`) — одноразовый диск-кеш ответов LampaWeb; очистка (`docker exec lampac rm -rf /lampac/cache/static/<bucket>`) — штатное действие после правки store/статических маршрутов (см. 4.1).
- Тег образа в `docker-compose.yaml` закреплён **точным digest** (`1.68.0@sha256:752dafd8…`): тег 1.68.0 на ghcr mutable, его переиздавали, и новая сборка ломает Roslyn-компиляцию наших копий `mods/` (пример: `Music` → `CS0103 MusicMetadataCacheService`, crash-loop). Обновление образа = новый digest + пересборка копий `mods/` из нового образа. Не делать «просто» `docker compose pull` без фиксации digest.
- `LampaWeb.autoupdate` — веб-клиент Lampa сам обновляется из git (`yumata/lampa`), `wwwroot/lampa-main` в контейнере перезаписывается — туда не править.
### 9. После изменений в проекте
Обновлять `README.md` и `AGENT.md` в той же ревизии: структура, включённые модули, секции конфига, новые правила.
### 10. Безопасность (не публиковать)
`config/passwd`, cookie `accspasswd`, заголовок `lcrqpasswd`, `bot_token` в `TelegramBot`. Маршруты `/adminpanel`, `/weblog`, `Tracks`, `Catalog`, `DLNA`, proxy-модули — только для доверенной сети без WAF не открывать.
### 11. Tg-notify.bot (Telegram-бот)
- Механика: long polling по `TelegramBot.bot_token`; если токен пуст — polling не стартует (в логе `[TelegramBot] Установите bot_token…`, сервер работает). После правки секции: `docker compose restart lampac`.
- Три подсистемы: трекер серий (Trakt→TMDB), трекер озвучек (параллельно Mirage/Collaps/VideoHub через `lampac_host`: `/lite/mirage`, `/lite/collaps`, `/lite/cdnvideohub`), клиентский плагин `tg-notify.js` (вкладка «TG Подписки», перехват 🔔). Полный разбор — в README.md.
- Данные подписок: `database/tgnotify/{users.json,subscriptions.json}` (том `./database/`, в .gitignore). Не «чинить» вручную — это живые данные бота.
- Диагностика: `GET /tg-notify.js` (200 без авторизации), `GET /api/tg/voices` (200), `/api/tg/*` остальной — требует `user_uid`. Озвучки могут не работать, если балансеры недоступны (проверить `GET /lite/mirage` — тело `disable`/ошибка, `/lite/collaps` — 503); тогда уведомления приходят только о выходе серий.
- `kp_api_key` опционален: без него VideoHub резолвит `kinopoisk_id` только через мост `/externalids` (покрытие ~40%), иначе — молча пропускается, Mirage/Collaps работают.
### 12. TelegramAuth / TelegramAuthBot (вход через Telegram)
- Не путать с Tg-notify.bot (уведомления): эта пара — **аутентификация** (вход в Lampa через Telegram вместо пароля), группа Community, в образе выключена (`SkipModules` + `enable: false`).
- Гейт (`LampaWeb.telegramAuthGate`) активен только при `accsdb.enable: true` + `telegramAuthGate.enabled: true` + непустом `botUsername`, иначе тихий откат на `deny.js`. У нас `accsdb` не включён — связка неактуальна, включать только вместе с `accsdb`.
- `mutations_api_secret` одинаковый в обоих модулях, ненулевой в проде; `bot_token` — в `init.conf`, не коммитить (см. правило 10).