Telegram Webhook
Всем мир! Сегодня я вам на практике покажу, как с 0 написать несложного Telegram бота.
Для начала придумаем тестовое задание.
У меня есть сервер Counter Strike 1.6 на котором я временами играю с друзьями. Заходить в игру, чтобы проверить наличие там игроков, лень. Напишем бота, который будет доставать для нас информацию о сервере и список игроков со счетом и выводить в удобном формате.

Для того, чтобы проследить за действиями, достаточно базовых знаний linux, web и python.
Постановка задачи
Для работы телеграм бот, который крутится на нашей машине, должен получать обновления от сервера Telegram. Это можно сделать двумя методами:
- Long polling. Метод, когда ваша программа в определенный промежуток времени опрашивает сервер об обновлениях.
- Web hook. Тут вы поднимаете веб сервер, на который телеграм бот шлет обновления, если они есть.
Второй метод популярнее и считается надежнее, поэтому остановимся на нем.
Писать будем на Python с использованием Flask. В роли веб сервера используем nginx. В работе с сервером CS нам поможет чудесный модуль python-valve
Выбор сервера для хостинга нашего бота роли не играет, я буду работать с Digital Ocean.
Сам бот будет довольно простым: одна кнопка Обновить, нажатие на которую, как и любое сообщение, будет обновлять информацию о карте и игроках.
Регистрация бота
Первым делом нам надо зарегистрировать своего бота у @BotFather. Он отвечает за управление информацией о боте и получение и обновление токенов для работы с ними. От него мы получим такую строку

Это ключ по которому сервера телеграм будут знать, что вы владельцы этого бота. Если вы его потеряете, вы можете получить новый у того же @BotFather.
Первый шаг сделали. Мы уже сейчас можем найти нашего бота в ТГ и писать ему, но это пока только оболочка и отвечать вам не будет. Ему нужен код/призрак.
Аренда выделенного сервера на DO
Как и любой сайт и серверсайд программа, наш код должен быть запущен на машине с белым ip и выходом в интернет. Для такого случая мы арендуем машину у Ditial Ocean
Показывать пошаговую регистрацию на сайте я не буду, покажу только как получить и настроить сам сервер. Кстати, если вы студент, можете попробовать получить 50$ на хостинг бесплатно.
Нажимаем на большую копку Create droplet.

Выбираем желаемую ОС. Я буду работать с Ubuntu.
Дальше можно выбрать самый дешевый сервер за 5 баксов в месяц или 0.007 в час. С выбором региона чуть тяжелее. Для телеграм бота особой разницы нет, но если будете хостить игры тут, следует подумать о пингах. Тут можно сравнивать состояние от вас, до разных регионов DO. http://speedtest-sfo1.digitalocean.com/
Больше нам ничего менять тут не надо, нажимаем Create.
В течении пары минут мы получим ip адрес и root пароль от сервера на нашу почту. Все, машина работает. Можем коннектиться к ней по ssh.
Вводим пароль и получаем полный контроль над сервером. Возможно вас попросят сменить пароль, поставьте посложнее.
Первым делом нам сразу надо создать нового пользователя и входить на сервер из под него, чтобы не стать легкой мишенью для хакеров.
Теперь необходимо перезайти на сервер под новым пользователем
Установка нужных сервисов
Первая команда обновит локальные репозитории, чтобы не было проблем с поиском нужных пакетов. Вторая поставит PIP (систему управления пакетами python), веб сервер nginx и dev пакет python. Третья команда запустит веб сервер.
Если вы сейчас введете ip адрес вашего сервера в браузере любого компьютера подключенного к сети интернет, вы получите страницу приветствия nginx.

Выключим на пока наш веб сервер и займемся python.
Python и virtualenv
По хорошему, нам надо создавать окружения для каждого из наших python проектов, чтобы их зависимости не начали конфликтовать между собой. Для этого воспользуемся virtualenv.
Создаем папку проекта и стартуем в ней новое изолированное окружение.
Теперь у нас есть локальная копия python, pip и все python модули установленные внутри останутся в этом окружении.
Устанавливем Flask и UWSGI
Бота будем писать на микрофреймворке flask, который позволит нам сократит время на разработку. Для перенаправления запросов с nginx на flask будем пользоваться uwsgi.
Для начала запустим простую страничку в Flask и попробуем достучаться к ней через nginx.
В папке с проектом создадим наш главный файл в котором будет хранится код.
Так же напишем скрипт, который будет запускать наше Flask приложение.
Оба файла находятся в папке с проектом.
Запускам uwsgi командой:
Если все прошло успешно, вы, перейдя в своем браузере по адресу вашего сервера и порт 5000 должны увидеть It’s working.

Теперь напишем конфиг файл, чтобы Flask приложение поднималось само, даже если сервер перезагрузится. Сначала выйдем из нашего окружения.
Потом создадим .ini конфиг для uwsgi в папке с ботом. Конфиг задает количество процессов, имя сокета, права и файл для логирования.
Так же создадим папку для логов и сделаем ее владельцем себя.
Создадим так же systemd unit файл, для атвоматизации запуска нашего бота.
и сам файл
Теперь после ввода команды, мы должны увидеть сокет файл в нашей папке проекта.
Мы так же можем проверить работу с помощью просмотра логов в папке и статуса сервиса.
Настройка nginx
Дальше нам необходимо настроить веб сервер, чтобы свои запросы он направлял в сокет uwsgi.
Теперь нам надо сделать ссылку на конфиг, в папке sites-enabled
Мы можем проверить наши конфиг файлы с помощью nginx.
Если он сказал, что все ОК, перезапускаем веб сервер.
Теперь по ip адресу нашего сервера в браузере вы должны получить выдачу Flask приложения.
Включаем https
Телеграм бот не станет работать по обычному протоколу http т.к. это ставит под угрозу переписку. У нас нет домена на сервере, будем работать с самоподписным сертификатом.
Сначала генерируем наш сертификат и ключ с помощью openssl.
На последней команде openssl задаст вам несколько вопросов. Можно игнорировать все, кроме Common Name (FQDN). В нем следует указать ip вашего сервера.
Следующей командой мы получим сертификат из сгененрированного выше приватного ключа.
Так-с, серты сгенерировали. Идем к настройке nginx.
Открываем конфиги нашего сайта в nginx:
Указвыаем новый порт взамен 80. Указвыаем ключи и сертификаты и протоколы, которые мы можем хендлить.
Проверяем конфиги и перезапускаем веб сервер
Теперь в браузере по https://ваш_ип, вы должны увидеть вашу страницу flask приложения. Браузер будет ругаться на сертификат, игнорируйте.
Пишем код для бота
Дошли до самого интересного.
Сначала установим модуль для работы с Telegram — python-telegram-bot
Теперь напишем код бота, который всегда отвечает словом hello на любое наше сообщение.
Разберем код.
В начале мы импортируем нужные модули flask, request, telegram. Дальше мы создаем наше приложение, включаем режим отладки (надо присвоить False, когда закончим разработку).
После мы задаем наш token полученный при создании бота в самом начале, адрес сервера и создаем бота.
У нас есть два главных метода:
*set_webhook — отвечает за создание вебхука с сервером Telegram и вызывается один раз.
*webhook_handler — слушает на /HOOK и занимается обработкой сообщений с серверов телеграма.
В хендлере мы получаем данные в Post запросе, достаем нужную информацию и исходя из этого делаем какие-то действия и шлем сообщение юзеру методом bot.send_message.
Перезапускаем бота и заходим на https://ваш_ип/set_webhook. Если в ответе вы получили webhook setup ok, можно пойти тестить бота.

Давайте чуть усложним его и добавим кнопку «Обновить».
Для начала импортируем ReplyKeyboardMarkup для создания клавиатуры и после отправим его в сообщении параметром reply_markup.

Немного функционала
Напишем функцию, которая будет опрашивать наш CS сервер и выдавать информацию по нему.
Для начала установим наш модуль для работы с valve серверами. Не забудьте перейти в окружение перед установкой.
Теперь в коде определим новую функцию, которая будет генерить строку ответ и возвращать ее нам, для отправки пользователю.
Код сам по себе не сложен, но давайте разберем. Сначала задаем адрес и порт сервера и создаем объект.
В функции достаем общую информацию и инфу об игроках. Заносим данные в строку answer и проходимся по массиву пользователей добавляя в новую строку данные о солдатах с количеством очков и временем проведенным на сервере. Возвращаем строку ответ. Названия полей (player_count, max_players и остальные можно посмотреть в коде модуля на github https://github.com/Holiverh/python-valve/blob/master/valve/source/a2s.py)
Осталось отправлять полученную строку сообщение пользователю. Для этого правим строку bot.send_message
Перезапускаем нашего бота.

Логи
В случае ошибок мы можем узнать что не так благодаря двум логам:
- Логи веб сервера находятся в /var/log/nginx/
- Логи нашего приложения и uwsgi в /var/log/uwsgi/
Код бота можно найти тут: https://github.com/mrZizik/CSBot Написать ему можно тут: @csinfobot
Telegram Webhook — это технология, позволяющая отслеживать в чате события в реальном времени и отправлять информацию о нем на указанный адрес. Если вы создали бот, то метод необходим, чтобы система могла реагировать на сообщения и действия пользователей. Получая информацию о них, сервер отправляет ее программе бота, в алгоритм которой заложена обработка.

Что нужно для рабочего коннекта Webhook
- Адрес (URL) страницы с программным кодом;
- Поддержка IPv4;
- Возможность сервера обрабатывать HTTPS трафик;
- Наличие SSL сертификата.
Команды работы с методом описаны в Telegram Webhook Bot API. К ним относятся:
- setWebhook — установка соединения. При этом необходимо передать адрес, на который будут отправляться сообщения из чата;
- deleteWebhook — удаление соединения. Указание предыдущей команды без параметров также удалит его;
- getWebhookInfo — получение текущего статуса соединения;
- WebhookInfo — объект с информацией о статусе.
Активация Webhook Telegram
Чтобы использовать метод постоянного коннекта сервера и бота, следует запустить программный код, в котором выполняется команда API для Телеграм.
Для официального сертификата SSL:
Для самоподписанного сертификата:
Какая команда будет использоваться для отправки сообщения в мессенджер зависит от языка программирования.
Например, для PHP это будет curl_exec(), а для Python — requests.get().
Для установки сертификата на сервера чаще всего используется криптографический пакет с открытым исходным кодом OpenSSL. Его можно скачать с официального сайта. Настройка зависит от операционной системы и сервера.

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