Files
lampac/AGENT.md
T
prodik b6acef01ef TelegramAuth + TelegramAuthBot + WatchTogether; README/AGENT
- mods/TelegramAuth, mods/TelegramAuthBot, mods/WatchTogether: копии из
  образа с enable: true (правило 1), секции в config/init.conf
- TelegramAuth в API-режиме (enable: false -> accsdb/гейт не поднимается),
  TelegramAuthBot: бот @GatusMonBot, long polling
- WatchTogether: customPlugins watchtogether.js, relay /wt/c/
- README: секция про SQLite/volume (первый запуск), таблица модулей,
  состояние Tg-notify и TelegramAuth, раздел WatchTogether
- AGENT: правило 10 дополнено секретами init.conf, §12 переписан,
  добавлен §13 WatchTogether, список mods/ в §1
- в git bot_token и mutations_api_secret оставлены пустыми (правило 10),
  реальные значения только в рабочем файле на сервере
2026-10-04 15:03:00 +00:00

18 KiB
Raw Blame History

AGENT.md — инструкции для ИИ-агентов

Работа с проектом: локальный Docker-развёртывание Lampac NextGen. Человек читает ответы только на русском.

Источники правды (порядок приоритета)

  1. Официальная документация — docs.lampac.dev (полный текст страниц: https://docs.lampac.dev/llms-full.txt, индекс: llms.txt). Не гадать по памяти — проверять в доках.
  2. Живой контейнер — состояние модулей, манифестов и конфигов брать из контейнера:
    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). Включение встроенного модуля делается только пользовательской копией:

docker cp lampac:/lampac/module/<Имя> "mods/<Имя>"
# в mods/<Имя>/manifest.json -> "enable": true
# в docker-compose.yaml -> "- ./mods/<Имя>:/lampac/mods/<Имя>"
# docker compose up -d

См. также официальные шаги: Включить модуль, Пользовательские модули.

Сейчас в mods/: AdminPanel, Tracks, Tg-notify.bot, TelegramAuth, TelegramAuthBot, WatchTogether. mods/Music удалён (remote-коммит remove Music): в образе у Music manifest.enable: false, поэтому модуль не грузится, /music.js → 404, секция "Music" и плагин убраны из init.conf.

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. Перед применением правок проверять:

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. Команды эксплуатации

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, bot_token в TelegramAuthBot, mutations_api_secret. Маршруты /adminpanel, /weblog, Tracks, Catalog, DLNA, proxy-модули — только для доверенной сети без WAF не открывать.

Секреты в git не попадают: в закоммиченном config/init.conf токены и секрет должны быть пустыми (так делает и remote — коммит remove), реальные значения живут только в рабочем файле на сервере (копия до мержа — /root/init.conf.local). Перед git add config/init.conf: git diff config/init.conf | grep -E ":[0-9]{8,}:AA|\"mutations_api_secret\": \"[a-f0-9]{16}" → должно быть пусто.

11. Tg-notify.bot (Telegram-бот)

  • Механика: long polling по TelegramBot.bot_token; если токен пуст — polling не стартует (в логе [TelegramBot] Установите bot_token…, сервер работает). После правки секции: docker compose restart lampac.
  • Токен только локально: в git поле пустое (правило 10). На сервере в init.conf вставлен @KlinkerZabbixBot — после git pull/переписывания конфига проверять, что polling снова стартовал ([TelegramBot] @KlinkerZabbixBot запущен!). Второй экземпляр на том же токене даёт Conflict: terminated by other getUpdates request.
  • Три подсистемы: трекер серий (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. Копии в mods/TelegramAuth/ и mods/TelegramAuthBot/, манифесты enable: true, из SkipModules убраны (у нас SkipModules: []).
  • Сейчас: API-режим. TelegramAuth.enable: false → accsdb не поднимается, гейт неактивен, доступ не режется; работают привязки, /tg/auth/*, админ-API. TelegramAuthBot — бот @GatusMonBot, long polling идёт (Telegram API OK).
  • Гейт (LampaWeb.telegramAuthGate) активен только при accsdb.enable: true + telegramAuthGate.enabled: true + непустом botUsername, иначе тихий откат на deny.js. Включать только вместе с accsdb, и сначала связать свои устройства через бота — иначе текущие UID получат отказ.
  • mutations_api_secret одинаковый в обоих модулях, ненулевой; bot_token — в init.conf, не коммитить (правило 10): в git оба поля пустые.
  • owner_telegram_ids: [143672] → владелец создаётся как admin при старте. auto_provision_users: true + auto_provision_activate_immediately: false → новые привязки ждут одобрения (/users в боте, кнопки Принять/Отклонить).
  • Данные: database/tgauth/{users.json,admins.json,user_langs.json} (том lampac_database, владелец 1000:1000). Живые данные — не «чинить» руками.
  • Проверка: GET /tg/auth/status?uid=x → 200; GET /tg/auth/admin/users → 401 без заголовка, 200 с X-TelegramAuth-Mutations-Secret.

13. WatchTogether (комнаты синхронного просмотра)

  • Копия в mods/WatchTogether/ (enable: true), секция WatchTogether в init.conf (enable, allow_anonymous: true, relay_max_channels: 500, relay_max_clients_per_channel: 32, gc_empty_timeout_minutes: 30, gc_max_lifetime_hours: 12).
  • Клиентский плагин зарегистрирован в LampaWeb.customPlugins: {localhost}/watchtogether.js.
  • Роуты: GET /watchtogether.js → 200, GET /watch_together/ → 200, WS /wt/c/{channel} → 400 на обычном GET (нужен WebSocket upgrade — это штатно, handshake даёт 101).
  • Lampac пассивно хранит состояние комнаты и становится хостом-«тенью» (ShadowHost.cs), если создатель отключился; роль возвращается ему при переподключении. Лаг ≤ 2 с.
  • При появлении reverse proxy: на /wt/c/ обязателен WebSocket upgrade, отключённый buffering и таймаут больше длительности просмотра.