> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lampac.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# QRAuth: вход по QR-коду через Telegram

> QRAuth заменяет экран входа Lampac на страницу с QR-кодом и Telegram-ботом: вход на ТВ без пароля, заявки на доступ и управление пользователями из Telegram.

**QRAuth** — модуль Lampac NextGen из папки `Modules/Community/QRAuth`. Он заменяет стандартный экран входа на страницу с QR-кодом и подключает Telegram-бота. Пользователь сканирует QR телефоном, подтверждает вход в боте, и телевизор входит сам.

Модуль работает поверх `accsdb`. Он не заменяет авторизацию Lampac, а дописывает пользователей в общий `users.json`.

## Возможности

* **Вход по QR.** Экран входа показывает QR-код на `https://t.me/<бот>?start=qr_<сессия>`. После подтверждения в боте страница входит этим аккаунтом.
* **Заявки на доступ.** Новый пользователь нажимает **Запросить доступ**, админ одобряет одной кнопкой. Пароль приходит пользователю в личку.
* **Управление из Telegram.** Команда `/users`: список пользователей, карточки, бан и разбан, статистика.
* **Фон из постеров.** Сервер собирает стену из постеров TMDB в одну картинку, поэтому слабым ТВ почти нечего считать.

## Включение модуля

<Steps>
  <Step title="Включите в manifest.json">
    В файле `Modules/Community/QRAuth/manifest.json` установите `"enable": true`. По умолчанию в репозитории стоит `false`.
  </Step>

  <Step title="Проверьте SkipModules">
    Убедитесь, что `QRAuth` нет в `BaseModule.SkipModules` в `init.conf`.
  </Step>

  <Step title="Включите accsdb">
    Задайте `accsdb.enable: true` и длинный `shared_passwd`. Модуль работает только поверх `accsdb`.
  </Step>

  <Step title="Добавьте секции QRAuthBot и DenyPage">
    Скопируйте пример ниже в `init.conf`. Полный набор полей лежит в `Modules/Community/QRAuth/init.merge.example.json`.
  </Step>

  <Step title="Перезапустите сервер">
    Выполните `systemctl restart lampac` (Linux) или перезапустите контейнер (Docker).
  </Step>
</Steps>

Собирать модуль не нужно. Lampac компилирует `.cs` при запуске, а `Telegram.Bot.dll` уже лежит в `references/`.

<Note>
  Модуль с `"enable": false` в `manifest.json` пропускается молча, без записи в лог. Если в логе нет строк `compilation QRAuth` и `loaded module: QRAuth`, проверьте манифест.
</Note>

## Конфигурация

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "accsdb": {
    "enable": true,
    "shared_passwd": "длинный_случайный_пароль",
    "accounts": {},
    "users": []
  },
  "QRAuthBot": {
    "enable": true,
    "bot_token": "ТОКЕН_ОТ_BOTFATHER",
    "admin_ids": [123456789],
    "users_file_path": "users.json",
    "log_path": "tgbot.log"
  },
  "DenyPage": {
    "tg_target": "@YourQRAuthBot",
    "show_qr": true,
    "page_title": "Вход в Lampa",
    "page_subtitle": "Войдите через Telegram или по паролю.",
    "poster_wall": true,
    "poster_source": "trending"
  }
}
```

<Tip>
  Токен бота выдаёт [@BotFather](https://t.me/BotFather) по команде `/newbot`. Свой Telegram ID для `admin_ids` покажет [@userinfobot](https://t.me/userinfobot).
</Tip>

### QRAuthBot

| Поле | Тип | По умолчанию | Назначение |
| - | - | - | - |
| `enable` | `bool` | `true` | Включает бота. При `false` экран входа работает без QR. |
| `bot_token` | `string` | `""` | Токен от BotFather. Если пусто при `enable: true`, в консоль пишется предупреждение и бот не стартует. |
| `admin_ids` | `long[]` | `[]` | Telegram ID админов. Они получают заявки и видят `/users`. Если список пуст, бот отвечает на заявки «Администратор не настроен». |
| `users_file_path` | `string` | `"users.json"` | Файл пользователей. Должен совпадать с файлом, который читает `accsdb`. |
| `log_path` | `string` | `"tgbot.log"` | Собственный лог модуля: выдачи, отказы, ошибки. |

<Warning>
  Поле называется `admin_ids` и принимает массив. Вариант `"admin_id": 123` модуль молча игнорирует, и админов не будет.
</Warning>

### DenyPage

| Поле | Тип | Назначение |
| - | - | - |
| `tg_target` | `string` | Бот для QR и кнопки Telegram: `@username`, `https://t.me/…` или `tg://`. Должен указывать на бот из `QRAuthBot`. |
| `show_qr` | `bool` | QR показывается, только если задан `tg_target` и `show_qr: true`. |
| `page_title`, `page_subtitle` | `string` | Заголовок и подзаголовок экрана входа. |
| `step1_text`, `step2_text` | `string` | Строки подсказки под кнопками. Пустая строка не выводится. |
| `qr_subcaption` | `string` | Подпись под QR. |
| `tg_button_text` | `string` | Текст кнопки **Войти через Telegram**. На телефоне она заменяет QR, на ТВ её нет. |
| `poster_wall` | `bool` | Фон из постеров. По умолчанию `true`. |
| `poster_source` | `string` | Источник постеров TMDB: `trending` (по умолчанию), `popular`, `now_playing`, `top_rated`. |

Правки секции `DenyPage` подхватываются без перезапуска. Модуль перегенерирует `plugins/override/deny.js`.

<Warning>
  **Docker:** `users_file_path` и `log_path` — пути внутри контейнера, обычно `/lampac/...`. Путь хоста приведёт к тому, что бот пишет пользователей в файл, которого Lampac не видит.
</Warning>

## Совместная работа с Tg-notify

<Warning>
  QRAuth нужен **отдельный бот**. Если рядом стоит [Tg-notify](/modules/tg-notify) (секция `TelegramBot`), у `QRAuthBot` и `TelegramBot` должны быть разные `bot_token`.
</Warning>

Оба модуля сами опрашивают Telegram через long polling (`GetUpdates`). Общего обработчика событий нет. На одном токене возникают три проблемы:

1. **Конфликт опроса.** Telegram отвечает `409 Conflict: terminated by other getUpdates request`. Модули сбивают друг друга, лог забивается ошибками 409.
2. **Потерянные нажатия.** Каждое событие получает модуль, который первым забрал его из очереди. Нажатие **Выдать доступ** может уйти в Tg-notify, который такой кнопки не знает. Кнопки срабатывают через раз.
3. **Неподтверждённый вход.** Если `tg_target` указывает на бот Tg-notify, `/start` с номером сессии уйдёт туда, и вход не подтвердится.

Создайте в [@BotFather](https://t.me/BotFather) два бота: один для QRAuth, другой для Tg-notify.

<Note>
  До переименования QRAuth читал секцию `TelegramBot`, ту же, что и Tg-notify. Если вы обновляетесь со старой версии, переименуйте секцию QRAuth в `init.conf` в `QRAuthBot`. Иначе бот QRAuth не запустится.
</Note>

## Как работает вход по QR

<Steps>
  <Step title="Страница запрашивает сессию">
    Экран входа вызывает `GET /tgbot/qr/start` и получает `session`. QR ведёт на `https://t.me/<бот>?start=qr_<session>`.
  </Step>

  <Step title="Пользователь сканирует QR">
    В боте приходит `/start qr_<session>`. Если доступа нет, бот предлагает **Запросить доступ**.
  </Step>

  <Step title="Пользователь подтверждает вход">
    Бот показывает кнопку **Подтвердить вход**. Нажатие подтверждает сессию токеном пользователя.
  </Step>

  <Step title="Страница входит">
    Экран входа опрашивает `GET /tgbot/qr/status?session=…`, получает токен и входит через `/testaccsdb`, как при вводе пароля.
  </Step>
</Steps>

* Сессия живёт 3 минуты, хранится в памяти и одноразовая. По истечении страница сама берёт новый QR.
* У каждой загрузки страницы своя сессия, поэтому устройства друг другу не мешают.
* Перезапуск Lampac обнуляет активные сессии.

## Команды бота

| Команда или кнопка | Кто | Действие |
| - | - | - |
| `/start` | все | Новому пользователю — кнопка **Запросить доступ**, пользователю с доступом — его пароль. |
| **Выдать** / **Отклонить** | админы | Решение по заявке. Выдача дописывает `users.json` и присылает пользователю пароль. |
| `/users`, **Пользователи** | админы | Список пользователей, карточки, бан и разбан, статистика. |
| **Подтвердить вход** | пользователи с доступом | Появляется после сканирования QR. Телевизор входит сам. |

Повторная заявка от того же пользователя игнорируется 10 минут. У доступа нет срока действия, только бан и разбан.

## Связь с accsdb

Модуль и ядро Lampac не вызывают друг друга напрямую. Связь идёт через общий `users.json` и эндпоинт `/testaccsdb`.

* При выдаче доступа модуль генерирует токен и записывает его в поле `id`. Это и пароль пользователя.
* Ядро перечитывает `users.json` примерно раз в секунду. Между **Выдать** и возможностью войти бывает задержка до секунды.
* Бан ставит `ban: true` в существующей записи. Удалять строку нельзя: ядро не забывает удалённых пользователей до перезапуска.

Пример записи в `users.json`:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "987654321",
  "tg_id": 123456789,
  "group": 1,
  "expires": "2126-01-01T00:00:00Z",
  "comment": "@ivanov / Иван",
  "ban": false
}
```

## HTTP API

| Метод | Маршрут | Назначение |
| - | - | - |
| `GET` | `/tgbot/qr/start` | Создать QR-сессию |
| `GET` | `/tgbot/qr/status?session=` | Статус сессии; после подтверждения отдаёт токен один раз |
| `GET` | `/tgbot/qr/posters` | Состояние фона из постеров |
| `GET` | `/tgbot/qr/wall` | Готовая стена постеров; `?s=4k` для 4K |
| `GET` | `/tgbot/qr/poster/{n}` | Отдельный постер для мобильной версии |
| `POST` | `/tgbot/qr/login-ping?token=` | Уведомление админов о входе по паролю; всегда отвечает `200` |

Модуль сам пропускает `/tgbot/qr/*` для неавторизованных посетителей через `EventListener.Accsdb`. Добавлять `tgbot/qr` в `accsdb.whitepattern` не нужно.

## Диагностика

| Симптом | Что проверить |
| - | - |
| В логе нет `loaded module: QRAuth` | `"enable": true` в `manifest.json`, `QRAuth` нет в `SkipModules` |
| `bot_token пустой — проверьте секцию QRAuthBot` | Секция называется `QRAuthBot`, а не `TelegramBot` |
| `409 Conflict` в `tgbot.log` | Этот токен опрашивает второй процесс: другой Lampac или Tg-notify |
| Заявки никому не приходят | `admin_ids` задан массивом и содержит ваш Telegram ID |
| QR открывает не тот бот | `DenyPage.tg_target` указывает на бот из `QRAuthBot` |
| Фона из постеров нет | Поле `state` в ответе `/tgbot/qr/posters` |

Значения `state` у `/tgbot/qr/posters`:

| `state` | Значение |
| - | - |
| `pending` | Первая загрузка ещё не прошла. Она идёт через 15 секунд после старта. |
| `tmdb_unreachable` | Не ответили ни `/tmdb` Lampac, ни зеркала. Проверьте доступ сервера в интернет. |
| `tmdb_empty` | TMDB ответил, но постеров нет. |
| `images_failed` | Список получен, но картинки не скачались. |
| `disabled` | `poster_wall: false`. |

Подробности сбоев пишутся в `tgbot.log`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.