Бот доступа к стрим-сервису: вход по коду из Telegram
собственный бот для Переговорки (ToshaStream): вход по коду, заявки, роли
Telegram-бот управления аккаунтами стрим-сервиса: привязка к Telegram, вход на сайт по одноразовому коду, одобрение заявок и роли из чата. Python, aiogram 3, без своей базы, связь с сервисом через frp-туннель.
Задача
У сервиса чата, голосовой связи и эфира для своей команды (это Переговорка, она же ToshaStream, отдельный кейс) регистрация была открыта любому, кому переслали ссылку. Владелец узнавал о новом аккаунте постфактум. Заявки терялись, а любая мелочь вроде смены имени или пароля требовала прийти к владельцу или зайти в веб-админку.
Нужно было привязать каждый аккаунт сервиса к живому человеку в Telegram. Участнику: вход без пароля по одноразовому коду, смена пароля и имени без участия владельца. Владельцу: заявки на одобрение, список аккаунтов и уведомления о событиях сервиса. Исходное задание оформлено в репозитории как отдельный документ технического задания.
Решение
Stream Bot — собственный Telegram-бот управления аккаунтами. Реализовано в версии 1.2.0:
Участнику
- Привязка аккаунта.
/link: бот спрашивает логин (ищется и по логину, и по отображаемому имени) и выдаёт код для ввода на сайте. - Вход без пароля.
/loginприсылает одноразовый код для входа на сайт. - Профиль и имя.
/meпоказывает профиль,/nameменяет отображаемое имя; без аргумента бот спрашивает имя отдельным сообщением. - Аватарка.
/avatarберёт аватарку сервиса из фото профиля Telegram. - Пароль.
/passwordвыдаёт новый пароль веб-входа; сообщение с ним бот удаляет через 120 секунд. - Выход везде.
/logoutзакрывает все веб-сессии. - Уведомления.
/notify— личные настройки оповещений об эфире и рассылках владельца.
Владельцу (только Telegram-ID из настройки):
/users— список аккаунтов постранично;/pending— заявки с кнопками «Одобрить» и «Отклонить»;/approve,/deny,/role,/kick,/sessions <логин>./stats— кто сейчас на сервисе: зрители и голосовые каналы./broadcast— рассылка любого сообщения (текст, картинка, голосовое) тем, кто не отключил рассылки, с подтверждением./announce— общий выключатель оповещений о начале эфира./version— скрытая команда: версия запущенного экземпляра.
Постоянное меню на кнопках строится по роли: непривязанному человеку видна одна кнопка привязки, владельцу добавляется ряд «Аккаунты», «Заявки», «Кто на сервисе».
Как это устроено
Вход на сайт по коду из Telegram
Аккаунт сервиса привязывается к Telegram один раз через /link. После этого код для входа выдаётся по /login, а подтверждения привязки и входа бот присылает самому человеку. Код — это одноразовый набор символов: его вводят на сайте вместо пароля. Вход по логину и паролю остаётся отдельным способом, поэтому остановка бота не закрывает сервис.
Бот без своей базы: внутренний API с общим секретом
Бот не хранит аккаунты и не читает базу сервиса напрямую. Он обращается по HTTP во внутренний API сервиса (API — набор адресов, через которые одна программа просит другую что-то сделать), а каждый запрос подписан общим секретом в заголовке. Владелец данных один, поэтому расхождений между ботом и сервисом нет. Даже настройки уведомлений хранит сервис: в его таблице настроек лежат поля для оповещений об эфире и рассылок.
События сервиса: опрос очереди раз в 20 секунд
Бот раз в 20 секунд запрашивает у сервиса очередь событий. Владельцу приходят заявки на регистрацию, вход с нового адреса, серия неудачных входов, начало и конец эфира. Человеку приходят подтверждение привязки и вход по коду. Если туннель оборвался, бот отвечает «Сервис чата сейчас не отвечает», а после восстановления дочитывает очередь с прежнего курсора. При старте бота хвост очереди пропускается, чтобы не пересылать старые события.
frp-туннель между сервером сервиса и ботом
Сервис стоит на российском сервере, откуда Telegram недоступен. Поэтому бот работает на зарубежной машине в отдельном проекте Docker Compose. Связь строит frp — программа обратного туннеля: клиент на стороне сервиса сам, исходящим соединением, подключается к серверу на стороне бота и отдаёт внутренний API через TLS. Управляющий порт на стороне бота открыт только для адреса сервера сервиса. Более ранний вариант — обратный SSH-туннель — оставлен в репозитории как запасной.
Long polling: бот без открытого порта
Бот получает сообщения методом long polling: сам держит запрос к Telegram и ждёт ответа. Поэтому ему не нужны ни публичный адрес, ни сертификат, ни webhook. Состояния диалогов (например, «бот ждёт имя») хранятся в памяти, и перезапуск обрывает незавершённые диалоги.
Скрытые команды владельца
Команды владельца не показываются в меню. Для чужого Telegram-ID на /users или /version бот отвечает так, как отвечал бы на несуществующую команду. Права определяются переменной с ID владельца: без неё команды владельца и уведомления выключены.
Что ещё лежит в репозитории
Кроме самого бота в каталоге deploy/ хранятся патчи и новые файлы сервиса чата (Go и JS), которыми он дорабатывался на боевом сервере: эмоции, ответы и реакции, поиск по истории, удаление сообщений, вложения, показ экрана, монитор качества связи, записи эфиров, сторож и ночные бэкапы. Там же конфигурация туннеля. Полного исходного кода сервиса в репозитории нет.
Результат
- Аккаунт привязан к живому человеку в Telegram, а вход без пароля работает по одноразовому коду.
- Заявки на регистрацию приходят владельцу в чат и решаются кнопками или командами.
- Смена имени, пароля, выход из всех сессий и права доступа выполняются из чата, без веб-админки.
- У бота нет собственной базы: аккаунты хранятся в одном месте, в сервисе.
- Остановка бота не останавливает сайт, чат, голосовую и эфир.
- Бот работает в Docker от пользователя без root, версия пишется в лог при старте.
Технологии: что и зачем
- Python 3.12 и aiogram 3.15 — асинхронный Telegram-бот, диалоги на конечных автоматах состояний.
- aiohttp — клиент внутреннего API сервиса и long polling.
- Внутренний API сервиса с общим секретом — единственный источник данных об аккаунтах.
- frp — туннель между российским сервером сервиса и зарубежным сервером бота, через TLS.
- Docker — образ python:3.12-slim, процесс без root, TZ=Europe/Moscow.
Статус
Собственный продукт, часть стенда Переговорки (ToshaStream). Текущая версия 1.2.0 от 10 сентября 2026 года добавила /notify, /broadcast, /announce и привязку по отображаемому имени. С 14 сентября в коде без повышения версии: команда /avatar и доработки самого сервиса чата в deploy/.
Ограничения: автоматических тестов нет, проверка ручная; состояния диалогов не переживают перезапуск. Не выяснено по коду: включена ли на боевом сервере обязательная привязка Telegram для входа в голосовую. В планах отдельных пунктов нет.
Вопросы по проекту
Как сделать вход на сайт по коду из Telegram без пароля?
Как владельцу одобрять новые аккаунты стрим-сервиса из Telegram?
Где бот хранит аккаунты и пароли?
Что видит и может обычный пользователь, а что только владелец?
Что будет с сайтом и голосовой, если бот остановится?
Как бот связан с сервером, если Telegram с него недоступен?
Ещё по этому направлению
Финансовый ассистент: учёт денег из PDF-выписок в Telegram
собственный продукт: бот и веб-дашборд, выписки четырёх банков, Gemini
Тикет-система для IT-отдела в Telegram
для музейного комплекса в Москве: заявки, учёт техники, база знаний и аналитика
Tech Poly VPN: биллинг VPN-подписок в Telegram
собственный продукт: оплата по СБП, выдача ключей в Marzban, резервный бот во ВКонтакте
Нужно похожее?
Расскажите о задаче — покажем, как решали такое, и прикинем объём работ.