Бот проверки подписки на канал: кнопка ещё ничего не доказала

У кнопки «Подписался» есть один врождённый недостаток — она верит человеку на слово. Нажать её можно, не вступая в канал, вступив с другого аккаунта или выйдя через минуту после получения файла. На экране всё выглядит торжественно — палец коснулся кнопки, бот задумался, доступ открыт. В доказательной базе, однако, пока имеется только палец.

Я бы назвал это кнопочным алиби. Интерфейс как будто подтверждает подписку, хотя само нажатие сообщает лишь о действии конкретного пользователя внутри бота. Чтобы не приписывать существующему демо лишних функций, оговорюсь сразу — реплики «Подписался» и «Проверить ещё раз» в этой статье придуманы как макет интерфейса, а не взяты из готового сценария на сайте.

Рабочая проверка начинается после нажатия. Бот берёт идентификатор нажавшего пользователя и спрашивает Telegram о его текущем положении в нужном чате методом getChatMember. У метода два главных адреса — `chat_id` указывает канал, `user_id` указывает человека, причём первый для публичного канала может выглядеть как `@username`, а второй передаётся числом. Не именем, не подписью под аватаркой и не тем публичным адресом, который пользователь завтра поменяет.

Здесь появляется первая неприятная, но полезная подробность. Telegram Bot API гарантирует работу метода для других пользователей только тогда, когда бот назначен администратором чата. Формула осторожная — не «иногда желательно дать права», а «гарантируется при администраторе». Поэтому сценарий, где владелец добавил бота в канал обычным участником, а затем требует безошибочно распознавать всех подписчиков, начинается с неверной настройки. Красивый экран её не вылечит.

Ответ Telegram — не булева табличка с двумя лампочками «да» и «нет». В описании ChatMember перечислены шесть типов участника. Статусы `creator`, `administrator` и `member` означают, что человек находится в чате. `left` сообщает, что он сейчас не участник, а `kicked` — что он заблокирован. Есть ещё `restricted`; этот объект Telegram Bot API относит к супергруппам, и там надо смотреть отдельное поле `is_member`. Получилась маленькая нозография членства — одного слова `restricted` недостаточно, требуется ещё один диагноз.

Для канала обычная логика проще, но обработчик всё равно лучше писать по точным статусам, а не по принципу «всё, что не left, считаем подпиской». Иначе новый вариант ответа или неверно понятый статус однажды откроет дверь именно потому, что программист решил проявить оптимизм. Я в таких местах оптимизму не доверяю. Доступ выдаётся после явно положительного ответа, остальные случаи получают понятное сообщение и возможность повторить проверку.

Именно так я понимаю задачу «бот проверки подписки на канал» — кнопка запускает запрос о текущем статусе, а не заменяет его. Предлагаемый маршрут может выглядеть так. Бот показывает ссылку на канал и кнопку «Проверить подписку». После нажатия он либо открывает следующий шаг, либо отвечает: «Telegram пока не видит подписку. Вступите в канал и нажмите проверить ещё раз». Формулировку можно менять; технический смысл менять нельзя.

Сохранять результат при первом `/start` и потом верить ему до конца разговора я бы тоже не стал. Между запуском бота, переходом в канал и возвратом к кнопке пользователь успевает изменить статус, поэтому запрос нужен в момент, когда решается вопрос о доступе; иначе Telegram уже знает одно, а локальная отметка бота продолжает изображать другое. Кэш хорош для скорости. Для привратника — только если понятен срок его памяти.

Слово «текущий» здесь важнее всей кнопочной мишуры. Проверка отвечает на вопрос в момент запроса. Она не обещает, что человек останется подписчиком завтра, вечером или хотя бы после следующего движения большого пальца. Пользователь способен вступить, пройти ворота, скачать материал и выйти. Повторный запрос позже покажет `left`, но уже скачанный PDF от этого не испарится. Бот не располагает дистанционным ластиком для чужого телефона.

Отсюда следует не трагедия, а нормальное проектирование. До разработки нужно решить, что именно охраняется. Если бот один раз выдаёт файл, проверка регулирует момент выдачи, но не дальнейшую жизнь копии. Если материал остаётся внутри бот-сценария, статус можно запрашивать перед каждым защищённым действием. Если открывается внешний кабинет, проверку придётся связать с его собственной авторизацией и правилами доступа. Одно слово «материалы» скрывает три совершенно разных замка.

Есть и второй способ знать об изменениях — получать событие `chat_member`, когда статус участника меняется. В объекте Update Telegram Bot API ставит два условия — бот должен быть администратором, а тип `chat_member` надо явно добавить в `allowed_updates`. По умолчанию пустой список не включает такие события. Можно написать превосходный обработчик выхода из канала и никогда не вызвать его просто потому, что доставку этого типа обновлений не заказали.

События Telegram полезны для учёта, но я бы не превращал их в единственного привратника. Бот мог быть временно выключен, настройки получения обновлений могли измениться, старое событие могло остаться вне локальной базы, тогда как запрос текущего статуса перед выдачей задаёт Telegram прямой вопрос именно в тот момент, когда нужен ответ. Событие говорит, что когда-то произошёл переход. Это родственники, а не близнецы.

Принимать такую работу тоже стоит не одной счастливой кнопкой. Нужны разные состояния — участник канала, человек вне канала, вышедший после первой успешной проверки и заблокированный пользователь. Затем стоит снять у бота административный статус и посмотреть, не маскирует ли интерфейс техническую ошибку сообщением «вы не подписаны». Отказ Telegram Bot API и отрицательный статус — разные новости. В первой чинят настройку бота, во второй человеку предлагают вступить.

Я не знаю, какой именно материал и на какой срок нужно закрыть в конкретном проекте. Поэтому на сайте проверка подписки названа среди возможных задач для ботов групп и каналов, но из этой строки не следует готовая политика доступа для любого бизнеса. Её надо договорить — когда проверять, что выдавать, можно ли получить повторно, что происходит после выхода. Эту схему можно описать своими словами; длинное техническое задание для первого разговора не требуется.

Кнопку «Подписался» при этом можно оставить. Только снять с неё должность нотариуса. Пусть она делает свою настоящую работу — звонит привратнику и просит проверить документы.

Оцените статью

Комментарии

Загружаю комментарии…

Написать комментарий

Комментарии публикуются сразу после автоматической проверки на спам и рекламу. Ссылки в комментариях не кликабельны.