Привет, Хабр!
Если вас заинтересовал заголовок, то вы, скорее всего, уже знакомы с разработкой Telegram- или Discord-ботов. И что также вероятно: для получения обновлений вы используете обычный polling. Сегодня же я вам предлагаю ознакомиться с другим способом получения обновлений - через webhook.
Итак, в этой статье мы узнаем:
Что такое webhook, зачем он нужен?
Чем он лучше того же
pollingи в чем он ему уступает?Как подключить Webhook в Telegram и Discord (Он концептуально отличается для сервисов, если интересует Webhook в Discord, сразу переходите во вторую половину статьи).
Дополнительно развернем простейшего бота в Telegram с использованием Webhook.
Что такое Telegram Webhook
Начнём издалека и с Telegram: зачем вообще нужен polling или webhook подход? Чтобы ответить на этот вопрос, нужно хотя бы примерно понимать, как работает бот.
К счастью, тут все не очень сложно. Нулевым действием бот должен получить обновления от Telegram: новые сообщения, действия пользователей, вообще любые события, а потом уже как-то работать с этой полученной информацией.
Отличия Polling от Webhook
Теперь важно понимать, чем эти способы отличаются.
Представьте, что у вас есть какой-то сервер, который стоит где-то в интернете - не важно где. Telegram должен каким-то образом достучаться до него или, наоборот, вы (ваш сервер) должен регулярно спрашивать Telegram, есть ли что-то новое.
Именно так и работают эти два механизма:
polling- режим опроса Telegram. Каждое N количество времени, ваш бот спрашивает у Telegram с помощью специального эндпоинтаgetUpdates, нет ли каких-либо обновлений;webhook- режим, когда Telegram сам доставляет все обновления на специальный, подготовленный заранее домен с эндпоинтом, который вы указали в методеsetWebhook.
Отсюда же можно вынести несколько плюсов и минусов в сторону webhook (мы же все-таки его обозреваем).
Плюсы:
Возможность масштабировать сервер - один из главных плюсов вебхуков. Из-за того, что BotAPI принимает
getUpdatesтолько от одного инстанса бота, просто технически невозможно горизонтальное масштабирование проекта при использовании polling - Telegram будет циклически возвращать 409. С использованием Webhook эта боль пропадает. Вы фактически можете развернуть неограниченное количество реплик приложения за балансировщиком.Мгновенное получение обновлений. Как только происходит что-то новое, Telegram собирает это в пакет и отправляет на специальный эндпоинт (далее будет говорить проще - на вебхук), который вы подготовили ранее.
Меньше нагрузка на сервер. То, что вам не нужно постоянно обращаться к API Telegram для получения обновлений заметно облегчает работу всей программы.
Минусы (?):
Необходимость наличия собственного публичного домена и SSL-сертификата на нем (HTTP Telegram просто не примет).
Сервер должен быть постоянно доступен и всегда возвращать
200 OK.
И вот здесь у многих возникает вполне логичный вопрос: а что, если я не хочу или по каким-то причинам не могу настроить VPS, приобрести домен, настраивать Nginx, SSL и т.д.?
И тут все тоже просто: от проблемы с настройкой и необходимостью собственного домена можно избавиться. Например, можно использовать облачные сервисы для развертывания приложений, которые сразу дают публичный HTTPS-домен. Один из таких вариантов - Amvera.
Что это нам дает:
Не нужно покупать домен отдельно - Amvera предоставит публичный домен совершенно бесплатно;
Не нужно вручную настраивать SSL;
Развернуть бота можно буквально за 2-3 минуты, а после регистрации сервис бесплатно предоставляет 111 рублей* на баланс для тестирования;
Webhook можно подключить буквально через минуту после развертывания.
Таким образом этот минус webhook с HTTPS на практике получается очень незначительным.
Сравнение Webhook и Polling
Здесь я просто хочу в паре абзацев рассказать, когда достаточно использования Polling, а когда уже следует пересесть на Webhook.
Итак, Polling лучше:
Когда бот тестируется локально;
Нет публичного сервера;
Простая логика;
Стабильно небольшая нагрузка на сервер.
Когда же уже необходимо использовать Webhook:
Продакшен;
Высокая нагрузка (горизонтальное масштабирование - вопрос времени)
Нужны минимальные задержки.
Если коротко: Polling - это не что-то плохое, просто он имеет свою зону применения, которая не очень идет для продакшена.
Кратко про ограничения
Нельзя использовать
getUpdates, пока включена работа через Webhook.Если сертификат самоподписанный (self-signed), то нужно загрузить публичный сертификат параметром
certificateвsetWebhookПорты ограничены: разрешены только 443, 80, 88, 8443.
Все это описано в официальной документации в блоке Notes: https://core.telegram.org/bots/api#setwebhook
Помимо этого, очень важно отметить про безопасность: в setWebhook можно указать secret_token, и Telegram будет присылать его вам вместе со всем обновлениями в заголовке X-Telegram-Bot-Api-Secret-Token. Это один из способов навсегда избавиться от злоумышленников, пытающихся прислать фейковые данные через вебхук.
А что c Webhook в Discord?
Хотелось бы, чтобы Discord Webhook был ровно тем же, что Telegram Webhook, однако нет, это немного другое.
В Telegram вебхуки используются именно для получения обновлений - его нельзя использовать для отправки сообщений или любой публикации других событий, тогда как в Discord все наоборот: классический webhook используется для отправки сообщений в канал.
Казалось бы: зачем вебхук, если это просто отправка сообщений? Но на практике это очень удобный механизм.
Что такое Discord Webhook
Discord Webhook - это специальный URL от самого Discord, привязанный к конкретному каналу сервера. Любой, у кого есть этот URL, может отправить в канал сообщение через обычный HTTP POST-запрос.
То есть если Telegram Webhook - это про получение обновлений, то Discord Webhook используется для отправки сообщений.
При создании вебхука в Discord (описано здесь) вы создаете специального webhook-пользователя, от лица которого вы будете писать через вебхук в определенный канал, выбранный при создании вебхука.
Чаще всего это используется для:
логов действий;
аудита;
сообщений от CI/CD (на примере GitHub Bot рассказано в инструкции выше);
интеграций с внешними сервисами.
Как создать Discord Webhook
Создается он буквально за минуту.
Открываем сервер.
Переходим в настройки нужного канала.
Раздел Integrations -> Webhooks.
Нажимаем Create Webhook.
Настраиваем имя бота, аватарку и канал и копируем полученный URL.

Webhook URL - СЕКРЕТ. Кто угодно с URL может отправить совершенно любое сообщение в канал.
А как тогда получать обновления в Discord?
Если вы рассматриваете полноценного Discord-бота, то это не про вебхук. Здесь для получения событий используется другой механизм:
либо подключение к WebSocket Gateway;
либо настройка Interaction Endpoint (для /команд);
либо можно использовать любые библиотеки, в которых это все преднастроенно, где требуется только токен вашего бота и не париться.
Практика: создание бота на Telegram Webhook
Развернём простого бота на Webhook. Это самый обычный и простой бот, который в ответ на каждое сообщение будет возвращать его же - Echo bot.
Главная цель этого блока - показать, как легко и быстро можно развернуть бота и подключить Webhook, потратив минимальное количество времени, нервов и денег.
Подготовка кода
Прежде всего, понятное дело, нужно подготовить сурсы. В состав всего приложения входит всего 3 файла:
bot.py- файл, содержащий весь код;requirements.txt- файл, содержащий названия библиотек, необходимых для запуска проекта;amvera.yml- файл, содержащий инструкции для запуска и сборки приложения. Сгенерируется автоматически.
Вот содержимое двух файлов:
bot.py:
import os from aiogram import Bot, Dispatcher, F from aiogram.types import Message from aiogram.webhook.aiohttp_server import SimpleRequestHandler from aiohttp import web TOKEN = os.environ["BOT_TOKEN"] WEBHOOK_URL = os.environ["WEBHOOK_URL"] WEBHOOK_PATH = "/webhook" PORT = int(os.environ.get("PORT", 8080)) bot = Bot(TOKEN) dp = Dispatcher() @dp.message(F.text) async def echo(message: Message): await message.answer(message.text) async def on_startup(): await bot.set_webhook( url=WEBHOOK_URL + WEBHOOK_PATH, drop_pending_updates=True # Убьет все старые и неактуальные обновления ) async def on_shutdown(): await bot.delete_webhook() app = web.Application() SimpleRequestHandler(dispatcher=dp, bot=bot).register(app, path=WEBHOOK_PATH) app.on_startup.append(lambda _: on_startup()) app.on_shutdown.append(lambda _: on_shutdown()) if __name__ == "__main__": web.run_app(app, host="0.0.0.0", port=PORT)
Здесь мы принимаем 3 переменные окружения:
BOT_TOKEN- токен бота;WEBHOOK_URL- публичный HTTPS-домен, который мы скоро создадим совершенно бесплатно;PORT- порт, на котором будет запущено веб-приложение.
Самое интересное: установка Webhook при запуске.
async def on_startup(): await bot.set_webhook( url=WEBHOOK_URL + WEBHOOK_PATH, drop_pending_updates=True # Убьет все старые и неактуальные обновления ) app.on_startup.append(lambda _: on_startup())
Здесь при старте приложения вызывается setWebhook с url = полный адрес до эндпоинта и с drop_pending_updates=True.
HTTP-сервер, где aiohttp создает обычное веб-приложение, а SimpleRequestHandler связывает HTTP-запросы с Dispatcher от aiogram:
app = web.Application() SimpleRequestHandler(dispatcher=dp, bot=bot).register(app, path=WEBHOOK_PATH)
requirements.txt:
aiogram>=3.0,<4.0 aiohttp
Создание проекта в Amvera
Теперь, когда у нас есть весь необходимый код, мы можем создать проект. Предварительно регистрируемся по ссылке, создаем проект на главной странице проектов с любым названием и тарифом, загружаем bot.py и requirements.txt.
На этапе создания вы можете сразу указать переменные окружения. Я же рекомендую создать переменные уже после создания домена.
На этапе "Конфигурация" у вас будет автоматически сгенерированная конфигурация, поэтому следует обратить внимание на настройки. В параметре scriptName действительно должен быть путь до файла, который отвечает за запуск приложения, а в параметре requirementsPath - путь до requirements.txt.

Жмём кнопку "Завершить" и сразу открываем проект из списка приложений.
Давайте убедимся, что сервис сгенерировал нам amvera.yml - ту самую конфигурацию, которая настраивалась при создании проекта. Для этого открываем вкладку "Репозиторий" и проверяем наличие файла в Code.

Если все на месте, то мы уже можем создавать домен. Для этого переходим в одноименную вкладку и жмём кнопку в правом верху экрана - "Создать доменное имя".
В настройках выбираем:
Тип подключения: HTTPS,
Тип домена: Бесплатный домен Амвера.
Нажимаем "Применить" - и все, домен готов! Копируем его и переходим во вкладку "Переменные" для последнего этапа настройки проекта.
Здесь нам нужно просто создать необходимые переменные (в том числе WEBHOOK_URL, в значение которой добавить скопированный домен) для этапа запуска.

Вся настройка выполнена, осталось только собрать проект и ожидать его запуска. Для этого во вкладке "Конфигурация" есть кнопка "Собрать".
Проверка работы бота
Если вы все сделали корректно, статус приложения сменитс�� на "Приложение работает", а бот будет отвечать теми же сообщениями, что вы отправили ему:

Итог
Итак, мы вместе разобрали:
Что такое Telegram Webhook и чем он лучше Polling;
Что такое Discord Webhook и как с ним работать;
Создали бота на Telegram Webhook.
Я надеюсь, что статья была для вас полезна и вы узнали что-то новое!
