Меня зовут Андрей Устьянцев, я ведущий аналитик направления Big Data Лиги Цифровой Экономики, и в этой статье я расскажу, как писал чат-бот в Telegram на webhook. Если вы знаете, что это такое, и подготовка не вызывает интереса — можете сразу переходить к разделу «Очень кратко». С остальными поделюсь всеми необходимыми шагами.
Почему webhook
Чат-бот в Telegram может работать в одном из двух режимов.
Один из них называется polling — это когда код, непосредственно реализующий механику бота, опрашивает сервера Telegram с определенной периодичностью («не появилось ли чего новенького»). А если обнаружена активность в чате — реализуется определенная механика взаимодействия (общения).
Большинство материалов в интернете посвящено описанию того, как создавать ботов именно на этой механике, но мне (частное мнение без претензии на истину в последней инстанции) такой подход не очень нравится. Вот почему:
Python Telegram Бот На WebHook | Как Создать И Использовать Вебхуки Для Отправки Уведомлений
- не вижу смысла постоянно «дергать» сервера Telegram почем зря;
- таймаут, установленный для опроса всех чатов, в которых «общается» бот — это суть задержка в коммуникациях с человеком, который «общается» с ботом.
Второй режим работы ботов, webhook, подразумевает, что Telegram сам вызывает обработчик события/сообщения, когда в боте происходит какая-то активность. Другими словами, код, реализующий механику бота, срабатывает по инициативе человека, который «общается» с ботом. Самый главный плюс от такого режима работы — ответ бота на действие человека происходит мгновенно: человек написал что-то боту, Telegram тут же вызвал webhook, написанный код сразу «ответил» человеку.
Лирическое отступление: на тему «что лучше — polling или webhook» спорить можно бесконечно долго. Критерий истины: все зависит от решаемой задачи и от user-story.
Для задачи, которую решал я, лучше подходит режим webhook: заранее не известно, когда кто-то напишет боту, но тот должен в любой момент быть готовым поддержать диалог.
При чем тут «минимум» внешних библиотек?
Мое личное убеждение — использовать «чужие» библиотеки по минимуму при написании кода. Особенно в процессе изучения языка программирования. Это отнюдь не означает, что надо впадать в крайности и писать вообще все с нуля — везде возможен разумный компромисс.
Ниже я покажу, что можно написать аккуратный, короткий и читаемый код на Python и без использования специализированных библиотек именно для чат-ботов (особенно работающих в режиме webhook).
Пошаговая инструкция: как и с чего начать
Расскажу, как я писал код на Python, с какими трудностями столкнулся по пути и как их решал.
Ремарка: код написан в процессе изучения Python, поэтому некоторые моменты могут показаться неоптимальными — буду рад конструктивной критике и предложениям в комментариях к статье.
Итак, что необходимо для работы чат-бота в режиме webhook?
1. Создание Telegram бота с Webhook’ом на Python. Подготовка.
Ссылка на официальную документацию Telegam, где описана работа чат-ботов в режиме webhook: https://core.telegram.org/bots/api#setwebhook
1. Бот. Я не буду здесь подробно расписывать, как зарегистрировать бота — подробных мануалов достаточно и в интернете, и на этом портале.
2. Сервер для размещения кода, обрабатывающего механику бота — тот самый webhook, которого будет вызывать Telegram при активностях в боте.
Важные моменты (требования Telegram к таким серверам):
- Сервер должен работать круглосуточно. Telegram периодически проверяет служебными запросами наличие и работоспособность webhook.
- Важно, чтобы на сервере был установлен SSL-сертификат, обеспечивающий (подтверждающий) безопасное соединение с серверами Telegram.
Ну и где брать такой сервер?
Первое — создать свой сервер:
- настроить собственный компьютер под управлением Linux в режиме сервера,
- получить, купить «фирменный» SSL-сертификат или сформировать самостоятельно такой, который Telegram примет как достоверный.
Недостатки такого решения:
- Необходимы дополнительные компетенции по «поднятию» сервера (обычно это еще и на основе Linux) и созданию SSL-сертификата.
Хотя пошаговых инструкций и статей на эту тему достаточно.
- Нужен постоянный IP-адрес подключения к интернету.
Если компьютер подключен к интернету из домашней сети — скорее всего, у вас динамический IP-адрес, который точно не подойдет.
- Надо держать компьютер постоянно включенным в 220В.
Мне в рамках этой задачи круглосуточно гудящий под столом системный блок не нужен.
- Об этом редко пишут, но на поднятый на скорую руку сервер, на который может «постучаться» Telegram, точно будут «ломиться» разные люди, боты, сети в попытке использовать ваш сервер для своих (не всегда хороших) целей.
А это означает, что мало «поднять» сервер, его еще надо и защитить от потенциальных атак из внешних сетей — суровая дополнительная компетенция, скажу я вам.
С профессиональной точки зрения неплохо, конечно, прокачать дополнительные компетенции, но задача состоит в том, чтобы написать на Python код, реализующий механику бота. Причем в процессе изучения самого Python.
Поэтому я выбрал второе решение — облачное.
Идеальный вариант — виртуальный хостинг.
- Круглосуточно работающий сервер Apach, настроенный для запуска приложений на Python.
- Защита от ddos-атак и прочих «пакостей» извне.
- Автоматический выпуск качественного SSL-сертификата.
- Качественный url webhook, соответствующий требованиям Telegram.
- Удобный интерфейс для написания кода на Python прямо из браузера.
Итак, напишем простенького бота, который при любом взаимодействии с ним будет всегда писать в ответ «Ну привет, >»
Очень кратко
- Берем виртуальный хостинг.
- Регистрируем бота.
- Определяем URL-адрес, который сообщим Telegram — что это webhook, соответствующий нашему чат-боту.
- Пишем код на Python.
- «Сообщаем» Telegram адрес webhook нашего бота.
Важно! Рекомендую не менять местами последовательность действий из пунктов 5 и 4. В чем риск? Если Telegram решит проверить работоспособность адреса webhook, а там еще не отлажен код на Python, неправильный ответ Telegram на запрос может привести к блокировке webhook и бота. Снятие блокировки — отдельная неинтересная история.
Разберем код
(Исходный код – тут /home/c58504/t473test.na4u.ru/wsgi0.py )
Нам понадобятся следующие библиотеки:
- time — для работы с функциями даты и времени;
- JSON — для распарсивания JSON-строки, получаемой от Telegram;
- requests — для отправки сообщений в бот.
Примечание: в зависимости от настроек виртуальных серверов по умолчанию и инсталляций Python перечисленные библиотеки могут быть уже предустановлены. Если нет — необходимо их установить командой pip install.
Строка 5: Функция MainProtokol написана для логирования происходящего в коде. Задача этой функции — записывать в текстовый файл то, что в обычных условиях выводится на экран компьютера. Поскольку код выполняется по сути на сервере в момент вызова webhook Telegram, на экран ничего вывести нельзя, потому что экрана как такового нет. Так что текстовый файл — это замена вывода на экран ошибок (если они возникнут при выполнении кода), а также всего, что было бы полезно залогировать.
Строка 12: Функция application — основная у Python, которую вызывает сервер Apach при любом обращении к сайту. И при вызове webhook тоже.
Все данные, которые поступают при обращении к сайту (не важно, открывают ли его в браузере при прямом заходе по имени сайта, или происходит вызов webhook), сохраняются в переменной env (тип — словарь) — суть переменные окружения.
Строка 14: Переменная content в текущем коде — это «заглушка», потому что на экран ничего выводиться не должно. Можно в ней разместить HTML-код, который будет отображается в случае захода на сайт из браузера.
Строка 15: Переменная token — в ней хранится токен бота, полученный при его регистрации.
Строка 17: Проверяем, что вызывается именно webhook. В env[‘PATH_INFO’] хранится имя страницы, к которой было обращение. Я решил, что у меня страница для коммуникаций с ботами будет называться ‘tg_bot’. Настоятельно рекомендую придумывать страницу (адрес) webhook, а не сообщать Telegram просто имя домена – это защитит дополнительно ваш сайт от внешних атак.
Примечание: приведение значения переменной окружения к нижнему регистру функцией lower() — это, можно сказать, мой «пунктик»: так я еще больше уверен, что сравнение строк в одинаковом регистре произойдет корректно.
Строка 19: Получаем данные, переданные из Telegram («от бота») — они хранятся в переменной окружения «wsgi.input» в формате WSGI. Для его дальнейшей обработки применяем метод read().
Строки 24–27: Распарсиваем JSON-строку, полученную от бота.
И вот тут меня ждал подводный камень размерами с булыжник. Метод load библиотеки JSON выдавал ошибку «нарушение структуры JSON». Потратив значительное время и логируя в текстовый файл с использованием функции MainProtokol все, что только можно, я обнаружил следующее:
В JSON-строке, передаваемой из Telegram, совершенно непонятно зачем добавляется спецсимвол «n» (перевод строки). Причем только в одном месте.
Решение проблемы — перед распарсиванием JSON-строки принудительно заменить в ней «мешающий» спецсимвол на пробел: replace(‘n’,’ ‘).
Ремарка: по-хорошему надо было бы написать кусок кода или функцию, которая «убирает» из JSON-строки все известные спецсимволы. Но я СТОЛЬКО времени потратил на поиск проблемы, что сил на ее полномасштабное устранение со всеми возможными вариантами последствий впредь у меня уже не осталось.
Итого мы получили словарь в переменной json_string, содержащий все, что передал Telegram от бота. В общем-то, блок строк 17-30 — это то место, где необходимо реализовывать логику «общения» бота. Суть — анализировать полученный JSON и в зависимости от полученных данных программировать поведение бота.
Как разбираться с полученным JSON? По сути это объект message, полное описание которого можно найти в официальной документации вместе с описанием всех вложенных объектов типа chat, user и т. д.
Я пошел другим путем: писал в лог получаемые JSON по разным сценариям взаимодействия с ботом (отправка команды боту, отправка текста боту, отправка картинки), потом смотрел их структуру и реализовывал нужную мне логику.
Ремарка: Telegram передает в webhook только те поля, которые имеют значение. Покажу на примере.
(Исходный код – тут log1 с примерами JSON.txt)
Отправка команды «/start»
Отправка простого текста
Источник: temofeev.ru
Python-сообщество
- Начало
- » Python для новичков
- » Как написать webhook к боту telegram и разместить его потом на heroku
#1 Апрель 8, 2017 22:06:15
Как написать webhook к боту telegram и разместить его потом на heroku
Не могу написать вебхук к боту телеграмм, помогите люди добрые
Облазил интернет, вроде бы нашел подходящую тему, но все равно не получается
Вот мой код бота V
Скажите пожалуйста что нужно и куда добавить, если можно, прям в этот код написать
И потом стоит еще вопрос как его потом разместить на сервисе Heroku…
Если поможите могу отблагодарить денюшкой на киви(куда перевсти, ответите в личку или в теме)
Отредактировано leet896 (Апрель 8, 2017 22:12:40)
#2 Апрель 9, 2017 09:54:24
Как написать webhook к боту telegram и разместить его потом на heroku
у меня кириллица вызывает исключения, так что убрал русские слова из сообщений
возможно коде/декоде поможет
А на Heroku даже видео есть как чего установить, flask для примера
Думаю если на Heroku свои сертификаты стоят то просто установить там flask и юзать этот код из примера
Отредактировано Kasta_neda (Апрель 9, 2017 13:17:22)
#3 Апрель 10, 2017 15:46:48
Как написать webhook к боту telegram и разместить его потом на heroku
Kasta_neda
у меня кириллица вызывает исключения, так что убрал русские слова из сообщенийвозможно коде/декоде поможетУрок 4. ВебхукиПримерздесь обсуждалиА на Heroku даже видео есть как чего установить, flask для примераДумаю если на Heroku свои сертификаты стоят то просто установить там flask и юзать этот код из примера
Сделал по вашему сообщение, бот заработал , но все волишь на минуты 3 (отвечал на запросы), потом при написание чего-нибудь боту, он отвечает через часа 4-5 ,в логах ошибок нет.
Посмотрите пожалуйста, по ссылке, там все фаqлы и может что-то не так в коде где-то?
Ответьте прошу Вас
Если так, то можите исправить или сказать что нужно изменить и на что, и где, будьте добры пожалуйста
https://github.com/leet896/test9786
Отредактировано leet896 (Апрель 10, 2017 15:48:42)
#4 Апрель 10, 2017 20:42:13
Как написать webhook к боту telegram и разместить его потом на heroku
Kasta_neda
у меня кириллица вызывает исключения, так что убрал русские слова из сообщенийвозможно коде/декоде поможетУрок 4. ВебхукиПримерздесь обсуждалиА на Heroku даже видео есть как чего установить, flask для примераДумаю если на Heroku свои сертификаты стоят то просто установить там flask и юзать этот код из примера
а нет у меня ошибка в логах вот такая после запуска
2017-04-10T16:20:57.290131+00:00 heroku: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
2017-04-10T16:20:57.290228+00:00 heroku: Stopping process with SIGKILL
2017-04-10T16:20:57.428102+00:00 heroku: Process exited with status 137
2017-04-10T16:20:57.439610+00:00 heroku: State changed from starting to crashed
Скажите пожалуйста , вроде бы ругается на порт как я понял, скажите как его поставить или где что нужно добавить, откликнитесь пожалуйста
#5 Апрель 10, 2017 20:54:40
Как написать webhook к боту telegram и разместить его потом на heroku
Если вам нужен только бот, без вэбхука то этот код рабочий вариант
а вот вэбхук если вы читали действует малость по другому
Давайте для начала разберемся, как боты принимают сообщения. Первый и наиболее простой вариант заключается в периодическом опросе серверов Telegram на предмет наличия новой информации. Всё это осуществляется через т.н. Long Polling, т.е. открывается соединение на непродолжительное время и все обновления тут же прилетают боту. Просто, но не очень надежно.
Во-первых, серверы Telegram периодически начинают возвращать ошибку 504 (Gateway Timeout), из-за чего некоторые боты впадают в ступор. Даже pyTelegramBotAPI, используемый мной, не всегда может пережить такое.
Во-вторых, если одновременно запущено несколько ботов, вероятность столкнуться с ошибками возрастает. Это вдвойне обидно, если сами боты используются не очень часто.
Вебхуки работают несколько иначе. Устанавливая вебхук, вы как бы говорите серверам Telegram: “Слышь, если кто мне напишет, стукни сюда — (ссылка)”. Отпадает необходимость периодически самому опрашивать серверы, тем самым, исчезает неприятная причина падений ботов. Однако за это приходится платить необходимостью установки полноценного веб-сервера на ту машину, на которой планируется запускать ботов. Что ещё неприятно, надо иметь собственный SSL-сертификат, т.к. вебхуки в телеграме работают только по HTTPS
Источник: python.su
Serverless в Microsoft Azure или боты для telegram на Azure Functions и python
Это продолжение серий постов про «Бомжуем в Microsoft Azure» или как нам запускать сервисы в облаке и при этом не тратить много-много денег.
В Microsoft Azure есть такой сервис Azure Functions — это бессерверные вычисления. Суть его в том, что у вас есть какой-то код/функция, которая запустилась по какому-то триггеру, отработала, сделала что-то и спокойно умерла, ожидая, когда её вызовут еще раз. Такой Function as a Service. Вам не надо настраивать сервера, платформу или инфраструктуру, вы просто берёте свой код и запускаете где-то в облаке.
В Azure Functions существует несколько триггеров, с помощью которых вы можете запустить выполнение функции: HTTPTrigger, TimerTrigger, CosmosDBTrigger, BlobTrigger и т.д. Подробное описание всех триггеров есть в документации. Ажуровские функции поддерживают запуск кода на .net core, node.js, python, java и powershell core (preview) в Linux и Windows среде, включая собранные в docker-контейнерах.
Но почему я решил написать про Azure Functions. Знаете почему? Потому что выполнение функций стоит копейки. 1 миллион запусков в месяц обойдётся в 12,50 рублей. Да, да, двенадцать рублей и пятьдесят копеек.
И вот, в один прекрасный субботний вечер, я подумал, а что если запустить телеграмовского бота внутри ажурных функций, но перед тем, как окунуться в мир ажура, надо рассказать про нюансы.
Для telegram, как и для любой платформы существует несколько способов запуска ботов: polling и webhook. Polling не требует сертификатов и публикации вашего приложения, он просто раз в секунду, например, идёт в API мессенджера и спрашивает «Есть чо?», если есть, то в код прилетает целая пачка объектов JSON, с которыми вы уже развлекаетесь. Это просто, не очень быстро работает при больших нагрузках и мессенджеры не любят, когда вы их регулярно пинаете. Webhook же работает наоборот, вы сообщаете мессенджеру endpoint, где живёт ваш фронт и когда в мессенджере происходит какая-то активность, то он просто присылает вам сообщения, но есть нюансы, так как вам требуется публикация вашего приложения, SSL-сертификат и FQDN имя.
В Azure Functions есть Consumption Plan — это оплата за потребление, но у него есть стандартное ограничение на выполнение функции — 5 минут, его можно расширить, но главная идея в том, что мы не будет крутить постоянно запущенный код для бота внутри Azure Functions, мы скажем телеграму, чтобы он сам триггерил функцию на запуск (тот самый Webhook) и вся магия уже будет происходить внутри кода. Для этого будем использовать HTTPTrigger.
Для Azure Functions можно писать и тестировать всё локально в VScode, а уже только потом заливать всё в облако. Нам необходимо создать функцию для анонимного HTTP триггера.
В нашем проекте надо поправить несколько файлов. В requirements.txt добавляем pyTelegramBotAPI и requests.
host.json
Источник: masyan.ru