Как привязать webhook telegram
Перейти к содержимому

Как привязать webhook telegram

  • автор:

Telegram бот через webhook

Я тогда давно написал статью про создание Telegram бота, и обещал дополнить её описанием настройки работы через webhook, но так и не дополнил. Вот только сейчас дошли руки.

Telegram bot webhook

Что это такое

Как пишут в документации, общаться с серверами Telegram бот может двумя способами:

  1. getUpdates — pull: ваш бот постоянно дёргает сервер Telegram и проверяет есть ли новые сообщения;
  2. setWebhook — push: по мере поступления новых сообщений сервер Telegram отправляет их вашему боту.

Разницу можно изобразить следующим образом:

Telegram bot, getUpdates vs setWebhook

Очевидно, что второй способ ( setWebhook ) рациональнее для всех участников процесса. Однако в нём присутствует неявная сложность: кто-то должен принимать сообщения от Telegram на стороне бота, то есть необходим веб-сервер или его эквивалент.

Как настроить

Что нужно сделать:

  1. Заиметь доменное имя для сервера и получить на него сертификат (например, от Let’s Encrypt). Документация также говорит, что в случае самоподписанного сертификата можно обойтись и просто IP адресом, но этого я не пробовал;
  2. Запилить серверную часть на стороне бота (куда будет ломиться Telegram);
  3. Зарегистрировать адрес серверной части в Telegram (зацепить webhook на endpoint), чтобы Telegram знал, куда ломиться с сообщениями.

Сертификат

С доменом и сертификатом просто. Домен у меня уже был, а сертификат я получил по этой инструкции.

Вариант с самоподписанным сертификатом на прямой IP адрес я оставляю вам на самостоятельное изучение.

Серверная часть

Серверная часть чуть посложнее. Я переделал текущую реализацию бота на pyTelegramBotAPI, используя пример для AIOHTTP.

Ставим необходимые пакеты:

pip install pyTelegramBotAPI pip install aiohttp pip install cchardet pip install aiodns

И сокращённо код бота теперь такой:

import config import telebot from aiohttp import web import ssl  WEBHOOK_LISTEN = "0.0.0.0" WEBHOOK_PORT = 8443  WEBHOOK_SSL_CERT = "/etc/letsencrypt/live/YOUR.DOMAIN/fullchain.pem" WEBHOOK_SSL_PRIV = "/etc/letsencrypt/live/YOUR.DOMAIN/privkey.pem"  API_TOKEN = config.token bot = telebot.TeleBot(API_TOKEN)  app = web.Application()  # process only requests with correct bot token async def handle(request):  if request.match_info.get("token") == bot.token:  request_body_dict = await request.json()  update = telebot.types.Update.de_json(request_body_dict)  bot.process_new_updates([update])  return web.Response()  else:  return web.Response(status=403)  app.router.add_post("/ /", handle)  help_string = [] help_string.append("*Some bot* - just a bot.\n\n") help_string.append("/start - greetings\n") help_string.append("/help - shows this help")  # - - - messages  @bot.message_handler(commands=["start"]) def send_welcome(message):  bot.send_message(message.chat.id, "Ololo, I am a bot")  @bot.message_handler(commands=["help"]) def send_help(message):  bot.send_message(message.chat.id, "".join(help_string), parse_mode="Markdown")  # - - -  context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.load_cert_chain(WEBHOOK_SSL_CERT, WEBHOOK_SSL_PRIV)  # start aiohttp server (our bot) web.run_app(  app,  host=WEBHOOK_LISTEN,  port=WEBHOOK_PORT,  ssl_context=context, )

Что здесь происходит: мы запускаем мини-веб-сервер, который слушает порт 8443 и отвечает на запросы через определённый endpoint, который образован токеном бота. Токен используется здесь как достаточно уникальный идентификатор, чтобы какой-нибудь мимокрокодил из интернета не навызывал бота и не натворил дел. Полный адрес endpoint’а будет выглядеть вот так: https://YOUR.DOMAIN:8443/YOUR-TOKEN/ .

Обратите также внимание на отличия от стандартного примера из репозитория:

  • в качестве файла сертификата указан fullchain.pem , а не cert.pem ;
  • удалён код снятия и установки webhook’а.

Так как бота я запускаю не из-под root’а, сервис начал валиться с такой ошибкой:

python-bot[1824]: Traceback (most recent call last): python-bot[1824]: File "/usr/local/bin/bot/bot.py", line 142, in python-bot[1824]: context.load_cert_chain(WEBHOOK_SSL_CERT, WEBHOOK_SSL_PRIV) python-bot[1824]: PermissionError: [Errno 13] Permission denied systemd[1]: telegram-bot.service: Main process exited, code=exited, status=1/FAILURE systemd[1]: telegram-bot.service: Failed with result 'exit-code'.

То есть, у пользователя, из-под которого выполняется скрипт, нет доступа к /etc/letsencrypt/ , чтобы открыть файл сертификата. Я попытался дать доступ к каталогу для новой группы, включив в неё этого пользователя:

groupadd letsencrypt usermod -a -G letsencrypt userforbot chgrp -R letsencrypt /etc/letsencrypt/

Но он один фиг не мог открыть файлы оттуда, даже простой ls выдавал ошибку доступа. В общем, или мои познания Linux полный отстой, или одно из двух. Пришлось тупо назначить его владельцем:

chown -R userforbot:letsencrypt /etc/letsencrypt/

Тогда сервис запустился нормально.

Регистрация

Теперь осталось самое, как оказалось, сложное — зарегистрировать endpoint бота в Telegram. Сложности возникли потому, что я сначала неправильно понял принцип составления endpoint’а, а также из-за проблем с проверкой сертификата.

Для установки/регистрации webhook’а нужно выполнить следующий HTTP запрос (можно просто открыть этот URL в браузере):

https://api.telegram.org/botYOUR-TOKEN/setWebhook?url=https://YOUR.DOMAIN:8443/YOUR-TOKEN/

Пока я экспериментировал и разбирался с форматом endpoint’а, Telegram возвращал мне нормальный результат:

  "description": "Webhook was set",  "ok": true,  "result": true >

Но потом я его видимо задолбал, и он стал возвращать мне следующее:

  "ok": false,  "error_code": 504,  "description": "Gateway Timeout" >

Но оказалось, что это ни на что не влияет, и webhook нормально устанавливается, так что можно даже не дожидаться таймаута, а просто отменять запрос через пару секунд.

Проверить статус webhook’а можно таким запросом:

https://api.telegram.org/botYOUR-TOKEN/getWebhookInfo

Если всё нормально, должно вернуть такое:

  "ok": true,  "result":   "url": "https://YOUR.DOMAIN:8443/YOUR-TOKEN/",  "has_custom_certificate": false,  "pending_update_count": 0,  "max_connections": 40  > >

Как видим, в поле url стоит наш endpoint.

Однако, мне оно сейчас возвращает такое:

  "ok": true,  "result":   "url": "https://YOUR.DOMAIN:8443/YOUR-TOKEN/",  "has_custom_certificate": false,  "pending_update_count": 0,  "last_error_date": 1543762687,  "last_error_message": "SSL error ",  "max_connections": 40  > >

Что указывает на некие проблемы с сертификатом. При этом бот работает нормально, то есть эта ошибка ни на что не влияет. Однако, если вместо fullchain.pem оставить cert.pem (как было указано в примере), то бот работать перестанет.

Стоит также отметить, что если вы установили webhook, то опрос Telegram через getUpdates работать больше будет. Чтобы снять webhook, надо отправить тот же самый запрос, что и для установки, но на этот раз без параметра url :

https://api.telegram.org/botYOUR-TOKEN/setWebhook
  "ok": true,  "result": true,  "description": "Webhook was deleted" >

Ну и всё, не так уж и сложно. Если бы в документации (и сторонних манулах из интернетов) была указана такая простая вещь, что для webhook’а всего-то нужен лишь веб-сервер на стороне бота, я бы это сделал уже сто лет назад. Конечно, продвинутым чувакам это скорее всего было очевидно сразу, но мнe — нет.

Telegram Webhook

Telegram Webhook – это технология, позволяющая отслеживать в чате события в реальном времени и отправлять информацию о нем на указанный адрес. Если вы создали бот, то метод необходим, чтобы система могла реагировать на сообщения и действия пользователей. Получая информацию о них, сервер отправляет ее программе бота, в алгоритм которой заложена обработка.

Что нужно для рабочего коннекта Webhook

  • Адрес (URL) страницы с программным кодом;
  • Поддержка IPv4, но рекомендуем поддержка IPv6 из-за частой блокировки телеграмма по IPv4;
  • Возможность сервера обрабатывать HTTPS трафик;
  • Наличие SSL сертификата.

Команды работы с методом описаны в Telegram Webhook Bot API. К ним относятся:

  • setWebhook – установка соединения . При этом необходимо передать адрес, на который будут отправляться сообщения из чата;
  • deleteWebhook – удаление соединения . Указание предыдущей команды без параметров также удалит его;
  • getWebhookInfo – получение текущего статуса соединения.

Активация Webhook Telegram

Чтобы использовать метод постоянного коннекта сервера и бота, следует запустить программный код, в котором выполняется команда API для Телеграм.

Для официального сертификата SSL :

https://api.telegram.org/botТОКЕН/setWebhook?url=ВАША_ССЫЛКА

Для самоподписанного сертификата :

https://api.telegram.org/botТОКЕН/setWebhook?url=ВАША_ССЫЛКА&certificate=ФАЙЛ_СЕРТИФИКАТА

ВАША_ССЫЛКА — это ссылка на скрипт, обрабатывающий запросы от сервера Telegram, например сообщения или команды для вашего бота.

Какая команда будет использоваться для отправки сообщения в мессенджер зависит от языка программирования.

Например, для PHP это будет curl_exec(), а для Python — requests.get().

Для установки сертификата на сервера чаще всего используется криптографический пакет с открытым исходным кодом OpenSSL . Его можно скачать с официального сайта. Настройка зависит от операционной системы и сервера.

Официальные цифровые подписи устанавливаются на хостинге провайдером. Эта одна из услуг большинства компаний.

Прежде чем использовать Webhooks убедитесь, что вам доступен этот функционал.

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

Регистрируем бот у @BotFather, устанавливаем WebHook

Переходим к сотрудничеству с Telegram. Зарегистрируем своего бота у @BotFather, получим токен для работы с API. Установим WebHook для взаимодействия нашего сервера с Bots API.

Name — Название бота
About — Что умеет этот бот? (выводится при открытии бота по середине экрана)
Description — Описание (доступно при просмотре профиля бота)
Botpic — Картинка — логотип бота
Commands — набор команд (доступно при вызове в диалоге с ботом командой / )

Обратите внимание, что поменять имя бота (@) в настройках возможности нет.

Методы взаимодействия с Bot API

Есть два взаимоисключающих способа получения обновлений для бота — getUpdates и webHook . Входящие обновления хранятся на сервере Telegram до тех пор, пока бот не получит их, но они не будут храниться дольше, чем 24 часа.

Независимо от того, какой вариант вы выбрали, вы получите в результате JSON-сериализованные объекты (WIKI).

В случае с getUpdates вам необходимо будет настроить периодическое снятие (например, 1 раз в секунду) с сервера Telegram обновлений (данных полученных от взаимодействия пользователя с ботом — сообщения, картинки . ).

В случае с webHook обновления вам будут доставляться Bot API по указанному адресу сразу же как только они появятся. Если в ответ API получит статус обработки его запроса не 200 OK, а другой, например, 500 (ошибка сервера) то обновления подвиснут и будут периодически к вам стучатся, и успокоятся только в случае получения в ответ статуса 200 ОК.

Для себя я выбрал WebHook, потому что не придется нагружать сервер постоянной проверкой обновлений, они сами придут, останется только их обработать и отправить в ответ запланированную реакцию. Если решите остановиться на getUpdates, то прочитайте статью про хороший инструмент.

Устанавливаем WebHook

Для установки WebHook есть специальный метод setWebHook . Нам просто необходимо в параметре url передать web-адрес где будут обрабатываться данные отправленные Telegram Bot API. Допустим, что у вас такой же хостинг как у меня, и за работу бота будет отвечать файл index.php , который лежит в директории bots в корне сайта.

public_html |__cgi-bin |__bots |__index.php 

Если структура файлов у вас совпадает, и у вас есть доменное имя, а также установленный SSL сертификат, тогда назначаем webHook используя вот этот URL:

https://api.telegram.org/botВАШ_ТОКЕН/setwebhook?url=https://ВАШ_ДОМЕН/bots/index.php

Вставляем его в адресную строку браузера и переходим, в случае если все прошло без ошибок, на экране у вас выведется вот такая информация:

Это означает, что все прошло хорошо и WebHook установлен. Теперь можно спокойно начать работать над реализацией бота.

Дополнительные настройки WebHook

Также вместе с параметром url в методе setWebHook можно передать:

max_connections - максимальное разрешенное количество одновременных HTTPS-подключений к webhook для доставки обновления, 1-100. По умолчанию 40.

allowed_updates - можно передать типы обновлений, которые будет получать бот. По умолчанию подписка идет на все обновления.

certificate - сертификат открытого ключа, чтобы проверить используемый корневой сертификат, если у вас например самописный сертификат.

В случае если будет необходимо переназначить webHook, то нужно вызвать метод setWebHook еще раз и указать в качестве значения параметра url новый адрес обработчика данных от Bot API.

Для удаления webHook и перехода к getUpdates используйте метод deleteWebhook , параметры передавать не требуется.

Для получения, текущего состояние webHook используйте метод getWebhookInfo , параметры передавать не требуется.

Методы вызываются при помощи:

https://api.telegram.org/botВАШ_ТОКЕН/METHOD_NAME

Как создать Telegram-бота на облачных функциях

С помощью ботов можно упростить себе задачу коммуникации с пользователями, создав для них умного помощника. Боты понимают текстовые команды и могут обращаться к API вашего вебсайта, сервиса или быть самостоятельным продуктом с уникальными услугами. Обычно, для создания бота требуется сервер, но в этой статье мы разберем подход, позволяющий обойтись без него. Он идеален при резких колебаниях количества запросов и прекрасно выдерживает пиковые нагрузки.
Настроить Telegram-бота на Облачных функциях, используя официальный API и заготовленный нами пример, можно в 3 этапа:

  1. Запрограммировать логику работы Telegram-бота.
  2. Зарегистрировать нового бота в Telegram.
  3. Связать бота и его логику воедино.

Запрограммировать логику работы Telegram-бота

Чтобы упростить задачу, мы написали пример такого бота. Его исходный код доступен по ссылке github.com/selectel/cloud-telegram-bot. Он понимает команды:

/start 

с приветственным сообщением;

/sticker 

с ответом в виде стикера;

/getwebhook 

чтобы вы могли получить информацию о настройках вашего бота;

/setwebhook

для настройки вашего бота, но об этом позже.

Пройдите следующие шаги с нашим примером бота, чтобы освоиться:

  • Скачайте исходный код как архив («Clone or download» → «Download ZIP») и распакуйте его.
  • Внутри должно быть:
    • «setup.py» с минимальным кодом, чтобы Python-окружение приняло содержимое папки за модуль для установки;
    • «requirements.txt» с описанием зависимостей;
    • «bot» — папка с исходным кодом нашего бота.

    Теперь у нас есть API, реализующее логику ответов бота. Следующим этапом мы зарегистрируем его в Telegram.

    Зарегистрировать нового бота в Telegram

    Чтобы Telegram знал о существовании нашего бота, его нужно зарегистрировать. Для этого существует только один способ:

    • Найдите бота @BotFather в Телеграм. Это официальный бот, созданный специально для управления ботами.
    • Отправьте ему команду:
    /newbot
    • @BotFather спросит вас, как вы назовёте вашего бота. Следующим сообщением отправьте его название, заканчивающееся на «_bot».
    • Запишите полученный токен от @BotFather — это ключ для работы с Telegram API.

    Теперь у нас API, регистрация бота в Telegram и его токен. Осталось связать это вместе.

    Связать бота и его логику воедино

    На этом этапе надо сделать так, чтобы бот знал токен пользователя, а Telegram знал, где его API:

    • Найдите переменную окружения «TOKEN» в настройках функции. Мы оставили её пустой на первом этапе.
    • Укажите в этой переменной токен вашего бота, который получили от @BotFather.
    • Нажмите Сохранить и развернуть.

    Далее нужно направить сообщения, которые пользователи отправляют в Telegram, нашему боту — в то API, которое для него создали.

    Через бота @SelectelServerless_bot

    • Найдите бота @SelectelServerless_bot в Телеграме.
    • Введите команду:

    /setwebhook

    • Бот ответит тем, что получит из Telegram API. Если все хорошо, это будет «true».
    • Чтобы удостовериться в том, что все корректно, отправьте команду:
    /getwebhook
    • В ответ должна прийти информация о webhook, в том числе указанный вами URL.

    Заключение

    Готов для работы бот, доступный в Telegram, отвечающий на команды и способный автоматически масштабироваться под нагрузкой и без сервера.

    Зарегистрируйтесь в панели управления

    И уже через пару минут сможете арендовать сервер, развернуть базы данных или обеспечить быструю доставку контента.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *