Files
lampac/README.md
T

247 lines
22 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.
# 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) |
| volume `lampac_cache` | Кеш (`/lampac/cache`) — Docker named volume, не файловый том |
| volume `lampac_database` | SQLite-базы Sync, TimeCode, Music, tg-notify (`/lampac/database`) — Docker named volume |
| `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=<root-пароль>`.
## Каталог плагинов (раздел «Плагины» в веб-клиенте)
В веб-клиенте 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 кешируют ответы в `/lampac/cache/static/<bucket>/<id>.json` (named volume `lampac_cache`), кеш переживает рестарт контейнера. После правки `extensions.json` для мгновенного применения удалить закешированную запись:
```bash
docker exec lampac rm -rf /lampac/cache/static/59 # bucket /extensions; либо весь /lampac/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).
## TelegramAuth + TelegramAuthBot: вход в Lampa через Telegram
Пара модулей из группы **Community** — замена пароля аккаунта подтверждением в Telegram (сценарий: ТВ, где вводить пароль неудобно). Не путать с Tg-notify.bot — тот только уведомляет о сериях.
- **`TelegramAuth`** — серверная часть: хранение пользователей/устройств, HTTP API `/tg/auth/*`, синхронизация UID в `accsdb`; **Telegram Auth Gate** — вместо экрана `deny.js` (модалка пароля) показывает fullscreen-оверлей с UID, кнопкой «Открыть Telegram» и QR-кодом на крупных экранах.
- **`TelegramAuthBot`** — long-polling бот: пользователь открывает бота (`/start link_{uid}` или отправляет UID), бот сам вызывает `POST /tg/auth/bind/complete`; есть админ-команды. HTTP UI нет.
Активация гейта — только при трёх условиях сразу: `accsdb.enable: true` + `LampaWeb.telegramAuthGate.enabled: true` + непустой `botUsername`. Иначе тихий откат на `deny.js`.
Конфиг (по образцу `init.merge.example.json` модулей):
```json
"TelegramAuth": {
"enable": true,
"mutations_api_secret": "SECRET"
},
"TelegramAuthBot": {
"enable": true,
"bot_token": "ТОКЕН_ОТ_BOTFATHER",
"mutations_api_secret": "SECRET"
},
"LampaWeb": {
"telegramAuthGate": {
"enabled": true,
"botUsername": "имя_бота_без_@",
"serviceName": "lampa"
}
}
```
`mutations_api_secret` должен совпадать в обоих модулях и быть ненулевым — защищает `bind/complete` и бот-админку; вместе с `bot_token` не публиковать. Оба модуля выключены в `base.conf` (`SkipModules`) и в манифестах (`enable: false`).
**Состояние у нас:** выключены, `accsdb` в `init.conf` не включён → гейт неактивен, используем беззащитный доступ + root-пароль AdminPanel. Включать связку имеет смысл вместе с `accsdb` (защита сервера учётными записями).
## Обновление Lampac
```bash
docker compose pull
docker compose up -d
```
Перед обновлением проверить, что в `docker-compose.yaml` раскомментированы нужные тома. Данные сохраняются в примонтированных томах: `config/`, `cache/`, `database/`, `dlna/`, `mods/`.
**Образ закреплён точным digest** (`1.68.0@sha256:752dafd8…`): тег `1.68.0` на ghcr — mutable, его переиздавали, и в новой сборке `mods/Music` (копия из старой сборки) не компилируется (`MusicMetadataCacheService` не найден) — сервер уходит в crash-loop. Чтобы обновить образ: взять новый digest, пересобрать копии модулей в `mods/` из нового образа (иначе Roslyn-компиляция упадёт) и заменить digest в `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.