Telegram webhook php: Пишем простого чат-бота для Telegram на PHP / Блог компании Нетология / Хабр
Telegram-бот, webhook и 50 строк кода / Хабр
Как, опять? Ещё один туториал, пережёвывающий официальную документацию от Telegram, подумали вы? Да, но нет! Это скорее рассуждения на тему того, как построить функциональный бот-сервис используя Python3.5+, asyncio и aiohttp. Тем интереснее, что заголовок на самом деле лукавит…
Так в чём же лукавство заголовка? Во-первых, кода не 50 строк, а всего 39, а во-вторых, и бот не такой сложный, просто эхо-бот. Но, как мне кажется, этого достаточно, чтобы поверить в то, что сделать свой собственный бот-сервис не столь сложно, как может показаться.Telegram-bot в 39 строк кода
import asyncio
import aiohttp
from aiohttp import web
import json
TOKEN = '111111111:AAHKeYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
API_URL = 'https://api.telegram.org/bot%s/sendMessage' % TOKEN
async def handler(request):
data = await request.json()
headers = {
'Content-Type': 'application/json'
}
message = {
'chat_id': data['message']['chat']['id'],
'text': data['message']['text']
}
async with aiohttp.ClientSession(loop=loop) as session:
async with session.post(API_URL,
data=json.dumps(message),
headers=headers) as resp:
try:
assert resp.status == 200
except:
return web.Response(status=500)
return web.Response(status=200)
async def init_app(loop):
app = web.Application(loop=loop, middlewares=[])
app.router.add_post('/api/v1', handler)
return app
if __name__ == '__main__':
loop = asyncio.get_event_loop()
try:
app = loop.run_until_complete(init_app(loop))
web.run_app(app, host='0.0.0.0', port=23456)
except Exception as e:
print('Error create server: %r' % e)
finally:
pass
loop.close()
Далее, в нескольких словах, что для чего и как сделать лучше из того, что уже есть.
Содержание:
- Что используем
- Как используем
- Что можно улучшить
- Реальный мир
1. Что используем
- во-первых, Python 3.5+. Почему именно 3.5+, потому что asyncio [2] и потому что сахарные async, await etc;
- во-вторых, aiohttp. Так как сервис на вебхуках, то он одновременно и HTTP-сервер и HTTP-клиент, а что для этого использовать, как не aiohttp [3];
- в-третьих, почему webhook, а не long polling? Если не планируется изначально бот-рассыльщик, то интерактивность является его основной функцией. Выскажу своё мнение, что для этой задачи, бот в роли HTTP-сервера подходит лучше, чем в роли клиента. Да, и отдадим часть работы (доставку сообщений) сервисам Telegram.
И ещё, у вас должно быть подконтрольное доменное имя, валидный или самоподписанный сертификат. Доступ к серверу на который указывает доменное имя для настройки реверс-прокси на адрес сервиса.
К содержанию
2. Как используем
Сервер
Состояние библиотеки aiohttp на текущий момент таково, что с её использованием можно построить полноценный web-сервер в Джанго-стиле [4].
Для standalone-сервиса вся мощь не пригодится, поэтому создание сервера ограничивается несколькими строками.
Инициализируем веб-приложение:
async def init_app(loop):
app = web.Application(loop=loop, middlewares=[])
app.router.add_post('/api/v1', handler)
return app
N.B. Обратите внимание, что здесь мы определяем роутинг и задаём обработчик входящих сообщений handler.
И стартуем веб-сервер:
app = loop.run_until_complete(init_app(loop))
web.run_app(app, host='0.0.0.0', port=23456)
Клиент
Для отправки сообщения используем метод sendMessage из Telegram API, для этого необходимо отправить на оформленный должным образом URL POST-запрос с параметрами в виде JSON-объекта. И это мы делаем с помощью aiohttp:
TOKEN = '111111111:AAHKeYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
API_URL = 'https://api.telegram.org/bot%s/sendMessage' % TOKEN
...
async def handler(request):
data = await request.json()
headers = {
'Content-Type': 'application/json'
}
message = {
'chat_id': data['message']['chat']['id'],
'text': data['message']['text']
}
async with aiohttp.ClientSession(loop=loop) as session:
async with session.post(API_URL,
data=json.dumps(message),
headers=headers) as resp:
try:
assert resp.status == 200
except:
return web.Response(status=500)
return web.Response(status=200)
N.B. Обратите внимание, что в случае успешной обработки входящего сообщения и удачной отправки «эха», обработчик возвращает пустой ответ со статусом HTTP 200. Если этого не сделать, сервисы Telegram продолжат в течение какого-то времени «дёргать» запросами хук, либо пока не получат в ответ 200, либо пока не истечёт определённое для сообщения время.
К содержанию
3. Что можно улучшить
Совершенству нет предела, пара идей, как сделать сервис функциональней.
Используем middleware
Допустим, возникла необходимость фильтровать входящие сообщения. Препроцессинг сообщений можно сделать на специальных веб-обработчиках, в терминах aiohtttp — это middlewares [5].
Пример, определяем мидлварь для игнора сообщений от пользователей из черного списка:
async def middleware_factory(app, handler):
async def middleware_handler(request):
data = await request.json()
if data['message']['from']['id'] in black_list:
return web.Response(status=200)
return await handler(request)
return middleware_handler
И добавляем обработчик при инициализации web-приложения:
async def init_app(loop):
app = web.Application(loop=loop, middlewares=[])
app.router.add_post('/api/v1', handler)
app.middlewares.append(middleware_factory)
return app
Мысли по поводу обработки входящих сообщений
Если бот будет сложнее, чем репитер-попугай, то можно предложить следующую иерархию объектов Api → Conversation → CustomConversation.
Псевдокод:
class Api(object):
URL = 'https://api.telegram.org/bot%s/%s'
def __init__(self, token, loop):
self._token = token
self._loop = loop
async def _request(self, method, message):
headers = {
'Content-Type': 'application/json'
}
async with aiohttp.ClientSession(loop=self._loop) as session:
async with session.post(self.URL % (self._token, method),
data=json.dumps(message),
headers=headers) as resp:
try:
assert resp.status == 200
except:
pass
async def sendMessage(self, chatId, text):
message = {
'chat_id': chatId,
'text': text
}
await self._request('sendMessage', message)
class Conversation(Api):
def __init__(self, token, loop):
super().__init__(token, loop)
async def _handler(self, message):
pass
async def handler(self, request):
message = await request.json()
asyncio.ensure_future(self._handler(message['message']))
return aiohttp.web.Response(status=200)
class EchoConversation(Conversation):
def __init__(self, token, loop):
super().__init__(token, loop)
async def _handler(self, message):
await self.sendMessage(message['chat']['id'],
message['text'])
Наследуя от Conversation и переопределяя _handler получаем кастомные обработчики, в зависимости от функциональности бота — погодный, финансовый etc.
И наш сервис превращается в ферму:
echobot = EchoConversation(TOKEN1, loop)
weatherbot = WeatherConversation(TOKEN2, loop)
finbot = FinanceConversation(TOKEN3, loop)
...
app.router.add_post('/api/v1/echo', echobot.handler)
app.router.add_post('/api/v1/weather', weatherbot.handler)
app.router.add_post('/api/v1/finance', finbot.handler)
К содержанию
4. Реальный мир
Регистрация webhook
Создаём data.json:
{
"url": "https://bots.domain.tld/api/v1/echo"
}
И вызываем соответствующий метод API любым доступным способом, например:
curl -X POST -d @data.json -H "Content-Type: application/json" "https://api.telegram.org/botYOURBOTTOKEN/setWebhook"
N.B. Ваш домен, хук на который вы устанавливаете, должен резолвится, иначе метод setWebhook не отработает.
Используем прокси-сервер
Как говорит документация: ports currently supported for Webhooks: 443, 80, 88, 8443.
Как же быть в случае self-hosted, когда необходимые порты уже скорее всего заняты веб-сервером, да и соединение по HTTPS мы в нашем сервисе не настроили?
Ответ простой, запуск сервиса на любом доступном локальном интерфейсе и использование реверс-прокси, и лучше nginx здесь сложно найти что-то другое, пусть он возьмёт на себя задачу организации HTTPS-соединения и переадресацию запросов нашему сервису.
К содержанию
Заключение
Надеюсь, что работа с ботом через вебхуки не показалась сильно сложнее long polling, как по мне так даже проще, гибче и прозрачнее. Дополнительные расходы на организацию сервера не должны пугать настоящего ботовода.
Пусть ваши идеи находят достойный инструмент для реализации.
Полезное:
- Telegram Bot API
- 18.5. asyncio — Asynchronous I/O, event loop, coroutines and tasks
- aiohttp: Asynchronous HTTP Client/Server
- aiohttp: Server Tutorial
- aiohttp: Server Usage — Middlewares
Регистрируем бот у @BotFather, устанавливаем WebHook
Регистрация бота проходит без каких-либо необходимых навыков, путем взаимодействия в Отцом Ботов @BotFather.
Последовательность действий для создания любого бота одинаковая:
- Открываем @BotFather и запускаем его (Старт/Start).
- В списке предложенных команд выбираем:
/newbot - create a new bot
, нажимаем на эту команду, или вводим ее вручную в поле для ввода сообщений. - Вам предложат указать как будут звать бота, в дальнейшем название бота можно будет поменять. Вводите название в поле для ввода сообщений.
- Далее вам предложат указать имя, по которому бот будет доступен для пользователей. Имя пишите, используя латинский алфавит, цифры и нижнее подчеркивание. Еще одно важное условие — имя должно оканчиваться на «bot». Можно также с большой буквы «Bot», или «_bot» или «_Bot».
Если все прошло без замечаний со стороны @BotFather, то по итогу вам выведется на экран Token API, если вы его сразу использовать не будете, то можно его куда-нибудь записать. Также его можно запросить снова если вы его забыли или потеряли. Редактировать бота можно у @BotFather, для этого запросите список ваших ботов /mybots
, выберите из списка нужного бота и далее при необходимости вы можете отредактировать его информацию, для этого в меню бота выберите Edit Bot
:
- 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 <-- файл обработчик
|__index.html
Если структура файлов у вас совпадает, и у вас есть доменное имя, а также установленный SSL сертификат, тогда назначаем webHook используя вот этот URL:
https://api.telegram.org/botВАШ_ТОКЕН/setwebhook?url=https://ВАШ_ДОМЕН/bots/index.php
Вставляем его в адресную строку браузера и переходим, в случае если все прошло без ошибок, на экране у вас выведется вот такая информация:
{"ok":true,"result":true,"description":"Webhook was set"}
Это означает, что все прошло хорошо и 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, чтобы оставить комментарий.
Откройте бот @SiteAuthBot,
нажмите кнопку Старт/Start. Следуйте инструкциям бота.
Внимание!
Убедитесь, что эта страница
открыта в браузере, а не в приложении Telegram. В противном случае авторизация пройдет только в
приложении Telegram.
Телеграм Вебхук – правила создания и принцип работы бота для Telegram на Webhooks
Боты «Телеграма» быстро вошли в обиход абонентов. Их создание на Webhooks предпочтительней, нежели используемый ранее метод getUpdates. Это объясняется, прежде всего, наличием постоянного соединения. Способ имеет разные пути реализации, легок в понимании, надежен.
Зачем нужны боты
Роботы – небольшие программы с рядом возможностей, которые значительно упрощают жизнь пользователей мессенджера. Диапазон применения обширен. Они могут получать новости, искать аудио, видео, торговать ценными бумагами, отслеживать курс валют.
Основная задача bota api – отвечать на поступившую команду путем имитации действий живого человека.
Как ими пользоваться
Алгоритм работы бота Webhooks прост в понимании.
Телеграм Webhook.
Процесс взаимодействия между человеком и роботом производится через ряд последовательных команд:
- Абонент пишет команду.
- Робот обрабатывает и отправляет ее на сервер.
- Команда обрабатывается и отправляется обратно в виде ответа.
- Bot выводит ее на экран.
Такая последовательность повторяется при каждом контакте с телеграм-ботом.
Категории ботов
Используемые в Telegram боты имеют общий вид. Их единственное отличие от обычных профилей – наличие приставки «bot» в конце имени.
Существующие помощники делятся на следующие виды:
- Игровые.
- Ассистенты.
- Чат-боты.
- Информаторы.
Что такое WebHooks
Webhooks – метод отслеживания отдельно взятых событий в реальном времени. Работает на системе eSputnik. «Вебхук» доставляет данные обо всех активностях контактов без дополнительных запросов с вашей стороны. Получаемая информация регулярно поступает на указанный URL POST.
Как настроить
Настройка Telegram Webhook – сложный процесс.
Он выполняется в следующей последовательности:
- Устанавливаем программу Node.js, создаем новый проект.
- Для создания нужных файлов и зависимостей необходимо прописать команду: https://ibb.co/Zgx0FM2.
- Если все верно, то каталог setWebhook будет иметь вид: https://ibb.co/sVHcttC.
- В файле index.js пишем: https://ibb.co/V2Y9kch.
- В файл index.js прописываем: https://ibb.co/VJJnvq6.
- Создаем проверку Вебхук. Добавляем следующий код: https://ibb.co/2hsrk8m.
Данный код дает возможность «Вебхук» пройти проверку на мессенджер-платформе, которая подтверждает работоспособность и подлинность Webhook Telegram bot.
Как прописать бот на Вебхук
Создание помощника для Telegram на Webhooks несколько отличается от процесса создания обычного робота. Его настройка выполняется путем использования самоподписанных сертификатов.
Правильный ключ и самоподписанный сертификат.
Операции имеют определенную последовательность:
- Устанавливаем пакет openSSl.
- Генерируем правильный ключ и самоподписанный сертификат.
- При предложении ввести Common Name необходимо ввести адрес сервера: https://ibb.co/GpDF2dy.
- Перемещаемся в каталог сертификатов, создаем bot.py и config.py.
- Во втором каталоге прописываем переменную токен бота.
- Открываем bot.py, выполняем импорт двух библиотек.
- Создаем следующий экземпляр робота: https://ibb.co/zJQ9Jb0.
- Реализуем веб сервер: https://ibb.co/k578dNR.
- Отправляем полученный ранее самоподписанный сертификат и обратный адрес на сервер: https://ibb.co/qCfc4vR.
- Указываем его настройки, производим запуск: https://ibb.co/rsntJMR.
- Запускаем bot Telegram setWebhook, активируем его, отправляем несколько сообщений: https://ibb.co/dKQ6HpQ.
- Смотрим открывшееся окно. Если код статуса равен 200, значит все хорошо, помощник получил сообщение и он работоспособный.
Что делать, если бот не работает
Малознающие пользователи, создавшие робота по примеру или существующему алгоритму, часто сталкиваются с ситуацией, когда помощник перестает работать.
При каких-либо неполадках Webhook Python на Telegram или на других языках программирования следует придерживаться рекомендаций:
- Пропишите роботу команду @Botfather. Она позволит избавиться от имеющихся технологических проблем. При необходимости будет создан новый исправленный бот.
- Для активации чата напишите /setprivacy. Укажите адрес своего робота, дождитесь ответа. Он подготовит список имеющихся ошибок, укажет пути их исправления.
- В случае, если вы заметили, что bot работает, а чат не отвечает – обратитесь в службу поддержки.
- Если вышел из строя созданный вами помощник – ищите ошибку в коде.
Выводы
Как видим, создание бота для Telegram на методе Webhooks не сложный, но скрупулезный процесс, требующий предельной внимательности. Указанные выше инструкции помогут вам разобраться в данном вопросе. Процесс создания собственного помощника займет около получаса времени и не вызовет затруднений.
Детальная инструкция видна на видео:
настройка и активация 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=ФАЙЛ_СЕРТИФИКАТА
Какая команда будет использоваться для отправки сообщения в мессенджер зависит от языка программирования.
Например, для PHP это будет curl_exec(), а для Python — requests.get().
Для установки сертификата на сервера чаще всего используется криптографический пакет с открытым исходным кодом OpenSSL. Его можно скачать с официального сайта. Настройка зависит от операционной системы и сервера.
Официальные цифровые подписи устанавливаются на хостинге провайдером. Эта одна из услуг большинства компаний.
Прежде чем использовать Webhooks убедитесь, что вам доступен этот функционал.
Создание бота для Telegram на Webhooks предпочтительнее, чем использования метода getUpdates. Во втором случае приходится закладывать в код постоянное обращение этой команды к боту. Это делается в циклическом режиме. В конце концов начинаются баги, и он подвисает. Webhook же держит постоянное соединение, но запросы отправляются только когда произошло событие, например, пользователь ввел сообщение.
php — Как установить веб-перехватчик бота Telegram?
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
.
php — Как протестировать веб-перехватчик телеграмм-бота на локальной машине?
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
.
php — Как создать сервер Webhook, например Telegram Webhook
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
Загрузка…
- Авторизоваться
зарегистрироваться текущее сообщество
.