# Lampac NextGen — локальный Docker-развёртывание Локальное развёртывание [Lampac NextGen](https://github.com/lampac-nextgen/lampac) — самохостируемого бекенда для Lampa — в Docker. Официальная документация: [docs.lampac.dev](https://docs.lampac.dev). ## Быстрый старт ```bash docker compose up -d # первый запуск docker compose logs -f # логи (строки compilation / configure module / loaded module) docker compose restart # после правки config/init.conf или манифестов в mods/ ``` - Веб-клиент Lampa: **http://localhost:9118** - Админ-панель: **http://localhost:9118/adminpanel** (root-пароль из `config/passwd`) - TorrServer-прокси: `http://localhost:9118/ts/*` (порт TorrServer — 9085) По умолчанию сервер слушает порт **9118**; если порт занят — меняй `listen.port` в `config/init.conf` до первого запуска. ## Структура проекта | Путь | Назначение | |---|---| | `docker-compose.yaml` | Основной сервис (образ закреплён на `ghcr.io/lampac-nextgen/lampac:1.68.0`) | | `config/init.conf` | Конфигурация сервера (JSON, монтируется в `/lampac/init.conf`) | | `config/passwd` | Пароль root для `/adminpanel` и `/weblog` (не в git) | | `cache/` | Кеш (`/lampac/cache`) | | `database/` | SQLite-базы Sync, TimeCode, Music, tg-notify (`/lampac/database`) | | `dlna/` | Локальные медиа для DLNA (`/lampac/data/dlna`) | | `plugins/extensions.json` | Каталог плагинов для веб-клиента (раздел «Плагины»), отдаётся через `/extensions` | | `mods/<Имя>/` | Пользовательские копии встроенных модулей с `enable: true` | > `docker-compose.override.yml` (в .gitignore) — серверное override для Proxmox (том DLNA -> `/mnt/torrents`), живёт только на сервере. ## Включённые модули из `mods/` Встроенные модули с `"enable": false` в `manifest.json` внутри образа **нельзя включать правкой файла в контейнере** — файлы пропадут при обновлении. Механика по официальной документации ([модули Lampac](https://docs.lampac.dev/modules/overview), [пользовательские модули](https://docs.lampac.dev/maintenance/custom-modules)): 1. Скопировать модуль из образа в `mods/<Имя>/` на хосте: ```bash docker cp lampac:/lampac/module/<Имя> "mods/<Имя>" ``` 2. В `mods/<Имя>/manifest.json` поставить `"enable": true`. 3. Добавить том в `docker-compose.yaml`: ```yaml - ./mods/<Имя>:/lampac/mods/<Имя> ``` 4. При необходимости добавить секцию модуля в `config/init.conf` (runtime-флаг). 5. `docker compose up -d` (при добавлении тома) или `restart` (при правке манифеста с `dynamic: true`). ### Сейчас подключены | Модуль | Что даёт | Секция в init.conf | |---|---|---| | `Tracks` | `/tracks.js`, `/ffprobe` — субтитры и дорожки | `"Tracks": { "enable": true }` | | `AdminPanel` | `/adminpanel` — редактор init.conf, current.conf, users.json | `"AdminPanel": { "enable": true }` | | `Music` | `/music.js`, `/music/*` — музыкальный каталог, плейлисты, стримы | секция `"Music"` (базовые дефолты) | | `Tg-notify.bot` | `/tg-notify.js`, `/api/tg/*` — уведомления о новых сериях в Telegram | секция `"TelegramBot"` | Клиентские плагины `music.js` и `tg-notify.js` зарегистрированы в `LampaWeb.customPlugins`; `{localhost}` в URL автоматически подставляется сервером. ### Ещё можно включить тем же способом В образе выключены также: `DatabaseEditor`, `ExternalBind`, `LogUserRequest-Lite`, `Transcoding`, `WatchTogether`, `TelegramAuth`, `TelegramAuthBot`. ## Конфигурация - `config/init.conf` — JSON. После правки: `docker compose restart`. Следи за валидностью JSON (лишняя запятая ломает парсинг). - `BaseModule.SkipModules` / `BaseModule.LoadModules` — фильтры загрузки модулей (имя, группа, regex). `SkipModules` имеет приоритет над `LoadModules`. - `LampaWeb.initPlugins` — флаги встроенных плагинов веб-клиента; `LampaWeb.customPlugins` — дополнительные плагины (`status: 1`). - `LampaWeb.autoupdate: true` — Lampa Web-клиент автообновляется из `yumata/lampa` (раз в 90 минут). ## Установка плагинов по ссылке через веб (AdminPanel) Список плагинов, который сервер раздаёт всем клиентам через `/lampainit.js` и `/on.js`, собирается по `LampaWeb.initPlugins` + `LampaWeb.customPlugins`. Watcher перечитывает `init.conf` без перезапуска (интервал ~1 с, runtime-параметры применяются на лету). 1. Открой **http://localhost:9118/adminpanel**, введи root-пароль (содержимое `config/passwd`) — пароль сохраняется в cookie `accspasswd` (штатный механизм root-авторизации). 2. В редакторе `init.conf` открой секцию **`LampaWeb`** → **`customPlugins`** и добавь запись: ```json { "url": "https://example.com/plugin.js", "status": 1, "name": "ИмяПлагина" } ``` Поддерживается плейсхолдер `{localhost}` — сервер подставит свой адрес. 3. Сохрани — перезапуск не нужен. Проверка: `curl -s http://localhost:9118/lampainit.js | grep <имя>`. Нюансы: - `status: 1` — активная запись. - Family-dedup: `name.js` и `name/js/{token}` считаются одним плагином; если в registry клиента уже есть один вариант, второй из серверного списка не добавляется. - Внешние URL должны быть доступны из браузеров клиентов и отдавать CORS-заголовки. - Альтернатива без сервера: вставить ссылку напрямую в веб-клиенте Lampa (настройки → «Плагины») — тогда плагин живёт только в localStorage этого браузера и грузится браузером напрямую. API (для скриптов): `GET/POST /adminpanel/api/init`, `POST /adminpanel/api/init/section/{key}` с cookie `accspasswd=`. ## Каталог плагинов (раздел «Плагины» в веб-клиенте) В веб-клиенте Lampa раздел «Плагины» грузит каталог (store) с маршрута **`/extensions`** (включается при `LampaWeb.initPlugins.pirate_store: true`). Содержимое берётся из файла `LampaWeb/plugins/extensions.json` модуля — у нас он переопределён файловым mount из `./plugins/extensions.json` (см. `docker-compose.yaml`). Плейсхолдер `{localhost}` в ссылках сервер заменяет своим адресом. **Все плагины каталога размещены локально** (mirror): `.js`-файлы лежат в `./plugins/`, каталог целиком смонтирован в `/lampac/wwwroot/plugins/` (одна строка в compose) и ссылки в каталоге ведут на `{localhost}/plugins/<имя>.js`. (Целиком в корень `wwwroot` монтировать нельзя — перекроется веб-клиент `lampa-main`.) Сами файлы плагинов всегда локальные; исключение — плагин-лоадеры, подгружающие основной код с внешнего хоста: «Клубничка 18+» (rc.bwa.ad) и Showy (showy.online/online.js — файл локально патчен под абсолютный URL, иначе он бы подгружал `/online.js` с нашего сервера). Остальные скачаны целиком (для pubtorr / torrentmanager / td скачано тело, а не лоадер). - `plugins/sources.json` — карта «локальный файл → исходный URL». Для обновления плагина: скачать файл по исходному URL, перезаписать локальный, перезапуск не нужен. - `plugins/modss.js` — локальная patched-копия MODS's (заменён вызов `Lampa.Utils.isPWA()`), раздаётся как `/plugins/modss.js`, но из каталога исключена (upstream мёртв: загрузчик отвечает stub-ошибкой «Используйте: lampa.mx»). Вернуть карточку можно, добавив запись с `link: "{localhost}/plugins/modss.js"`. Удалены из каталога (мёртвы upstream, проверено по факту выдачи): - «MODS's» (`lampa.stream/modss`) — загрузчик отвечает stub-ошибкой; - «Отзывы и рецензии» (`lampaplugins.github.io/store/o.js`) — файл заменён автором на пустой stub; - «Вторая кнопка Торренты», «Поиск локального TorrServer», «Горячие кнопки», «Золотая Тема», «Тип управления», «Старый стиль», «Мультфильмы» — публичных копий нет; - «Телевидение by Skaz» / «ТВ by skaz» / «ТВ by skaz 2.0» — файлы заменены placeholder-заглушками; - «Импорт/Экспорт закладок, истории» (`skaz.tv/export.js`) — 404. Важный нюанс — **диск-кеш ответа**: маршруты LampaWeb кешируют ответы в `cache/static//.json` (том `./cache`), кеш переживает рестарт контейнера. После правки `extensions.json` для мгновенного применения удалить закешированную запись: ```bash rm -rf cache/static/59 # bucket /extensions; либо rm -rf cache/static ``` Перезапуск контейнера при этом **не требуется** (маршрут читает файл при каждом запросе, если нет кеш-записи). ## Tg-notify.bot: Telegram-бот уведомлений о новых сериях Фоновый Telegram-бот (long polling): пользователь подписывается на сериал прямо из карточки Lampa, бот отслеживает выход новых эпизодов и появление выбранной озвучки и шлёт в Telegram уведомление с обложкой, номером серии и описанием из TMDB. Модуль объединяет три подсистемы: 1. **Трекер новых серий** — Trakt API (если задан `trakt_client_id`), иначе TMDB. 2. **Трекер озвучек** — параллельный опрос встроенных балансиров **Mirage**, **Collaps** и **VideoHub** через `lampac_host` (`/lite/mirage`, `/lite/collaps`, `/lite/cdnvideohub`); берётся максимальный эпизод из всех источников. 3. **Клиентский плагин** `tg-notify.js` — вкладка «TG Подписки», перехват кнопки 🔔 в карточке, меню выбора озвучки. ### Как это работает (поток) 1. **Привязка аккаунта** — во вкладке «TG Подписки» в Lampa выдаётся deep-link `/start link_{uid}` (для UID вида email — `/start link64_{base64url(uid)}`). После `/start` бот сохраняет связку `chat_id ↔ lampac_uid` в `database/tgnotify/users.json`; подписки становятся общими для всех устройств этого аккаунта. 2. **Подписка** — в карточке сериала кнопка 🔔 перехватывается плагином, показывается меню озвучек (`GET /api/tg/voices`), выбор уходит на `POST /api/tg/subscribe` и сохраняется в `subscriptions.json`. 3. **Фоновый цикл `CheckAll`** — раз в `check_interval_minutes` (первый прогон — через 2 минуты после старта, вручную — `/check`): новые серии через Trakt→TMDB; если выбрана конкретная озвучка — параллельно Mirage + Collaps + VideoHub. 4. **Уведомление** — сообщение вида: ``` 🎬 Название 🎙 Озвучка 📺 S05E08 — Название эпизода Описание (до 300 символов) ``` с обложкой кадра из TMDB (`still_path`), если есть. ### Конфигурация (секция `TelegramBot` в `config/init.conf`) | Поле | Назначение | |---|---| | `bot_token` | Токен от [@BotFather](https://t.me/BotFather). **Обязателен** — без него long polling не стартует (в логе предупреждение, сервер работает) | | `tmdb_api_key` | Ключ TMDB v3: обложки, описания эпизодов, определение актуального сезона | | `trakt_client_id` | Client ID Trakt; основной источник новых серий (если пуст — только TMDB) | | `lampac_host` | Базовый URL Lampac для запросов к балансерам; в Docker — `http://127.0.0.1:9118` | | `lampac_token` | Токен `accsdb`; обязателен, если включена защита (иначе балансеры вернут ошибку входа) | | `kp_api_key` | Ключ kinopoiskapiunofficial.tech — резолвинг `tmdb_id → kinopoisk_id` по названию для VideoHub (опционально; без него покрытие ~40% через мост `/externalids`) | | `check_interval_minutes` | Период фоновой проверки (дефолт 60) | | `tmdb_lang` | Язык метаданных TMDB (дефолт `ru-RU`, фоллбэк `en-US`) | | `data_dir` | Каталог `users.json`/`subscriptions.json` (дефолт `database/tgnotify` — у нас это том `./database/`, переживает рестарты) | ### Быстрый старт 1. [@BotFather](https://t.me/BotFather) → `/newbot` → получить токен. 2. `config/init.conf` → `TelegramBot.bot_token` = токен. 3. `docker compose restart lampac` (по желанию — заполнить `tmdb_api_key` и `trakt_client_id`). 4. В Lampa (http://localhost:9118) вкладка «TG Подписки» → deep-link → `/start` у бота. 5. В карточке сериала — 🔔, выбрать озвучку (или «без озвучки» — уведомление о самом факте выхода серии). ### Команды бота | Команда | Действие | |---|---| | `/start` | Приветствие; `/start link_{uid}` — привязка аккаунта | | `/list` | Список активных подписок | | `/check` | Принудительная проверка в фоне | | `/help` | Справка | | `/unlink` | Отвязать аккаунт | ### HTTP API | Метод | Маршрут | Назначение | |---|---|---| | `GET` | `/tg-notify.js` | Раздача клиентского плагина (AllowAnonymous) | | `POST` | `/api/tg/subscribe` | Подписка на сериал/озвучку | | `POST` | `/api/tg/unsubscribe` | Отписка | | `GET` | `/api/tg/status?tmdb_id=` | Статус подписки текущего пользователя | | `GET` | `/api/tg/voices?title=&year=&season=&tmdb_id=` | Доступные озвучки (Mirage + Collaps + VideoHub) | | `GET` | `/api/tg/link` | Deep-link для привязки бота | | `GET` | `/api/tg/subscriptions` | Все подписки пользователя с метаданными | Все маршруты, кроме `/tg-notify.js` и `/api/tg/voices`, требуют `requestInfo.user_uid` (вход в аккаунт). ### Состояние на нашем инстансе - Модуль загружен, `/tg-notify.js` → 200, плагин уже в `LampaWeb.customPlugins`, вкладка «TG Подписки» видна. - `bot_token` **пуст** → long polling не работает (лог: `[TelegramBot] Установите bot_token…`); уведомления придут только после заполнения токена. - Трекинг озвучек зависит от балансиров: на текущий момент `GET /lite/mirage` → тело `disable`, `GET /lite/collaps` → `503` — до тех пор, пока они не будут доступны (или не включится `lampac_token` при защите), бот будет уведомлять только о выходе серий (TMDB/Trakt). ## Обновление Lampac ```bash docker compose pull docker compose up -d ``` Перед обновлением проверить, что в `docker-compose.yaml` раскомментированы нужные тома. Данные сохраняются в примонтированных томах: `config/`, `cache/`, `database/`, `dlna/`, `mods/`. Изображение закреплено на конкретном теге — при обновлении поменяй тег в `docker-compose.yaml`. ## Безопасность По предупреждению официальной документации: - Не публикуй в интернет без аутентификации, WAF и ограничения сети: `/adminpanel`, `/weblog`, `/database-editor`, `Tracks`, `Transcoding`, `Catalog`, `DLNA`, proxy-модули. - Нигде не раскрывай `config/passwd`, cookie `accspasswd`, заголовок `lcrqpasswd`. - Для публикации за reverse proxy: [deployment/reverse-proxy](https://docs.lampac.dev/deployment/reverse-proxy) (HTTPS в ответах, реальный IP клиента, WebSocket, SSE, streaming). - `shm_size: 4096mb` — рекомендованный минимум для Playwright/Chromium.