Лайфхаки

Маленькие, полезные хитрости

Написание телеграм-бота на Python. Почему webhook

13.10.2023 в 06:15

Написание телеграм-бота на Python. Почему webhook

Чат‑бот в Telegram может работать в одном из двух режимов.

Один из них называется polling  — это когда код, непосредственно реализующий механику бота, опрашивает сервера Telegram с определенной периодичностью («не появилось ли чего новенького»). А если обнаружена активность в чате — реализуется определенная механика взаимодействия (общения).

Большинство материалов в интернете посвящено описанию того, как создавать ботов именно на этой механике, но мне (частное мнение без претензии на истину в последней инстанции) такой подход не очень нравится. Вот почему:

    не вижу смысла постоянно «дергать» сервера Telegram почем зря;

    таймаут, установленный для опроса всех чатов, в которых «общается» бот — это суть задержка в коммуникациях с человеком, который «общается» с ботом.

Второй режим работы ботов, webhook , подразумевает, что Telegram сам вызывает обработчик события/сообщения, когда в боте происходит какая‑то активность. Другими словами, код, реализующий механику бота, срабатывает по инициативе человека, который «общается» с ботом. Самый главный плюс от такого режима работы — ответ бота на действие человека происходит мгновенно: человек написал что‑то боту, Telegram тут же вызвал webhook, написанный код сразу «ответил» человеку.

Лирическое отступление: на тему «что лучше — polling или webhook» спорить можно бесконечно долго. Критерий истины: все зависит от решаемой задачи и от user‑story.

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

Готовый телеграм бот на питоне. python-telegram-bot-template

This repository serves as a template to create newapplications, their python wrapper over the Telegram API is amazing and enables very smooth programming for bots. It doesn't however provide defaults for persistence, state management and other shortcuts that are necessary for a maintainable and growable software architecture.

This template is mostly meant for projects that start with quite a bit of complexity and whose requirements are going to evolve as time passes.

The documentation from this point forward may be incorrect, I did some refactoring for a few wrapper and edited a few typings as my new LSP gave me a lot of errors (went from Pycharm to Pyright). I will update this documentation in the future.

I made this template to provide an implementation for a few things that I always ended up implementing in my telegram bot projects, customApplicationContextforcontext.bot_data, context.chat_data, context.user_datatyping, decorators/wrappers for handlers to cut down on a bit of boilerplate and implement common behaviours. This will take the mind off technicalities and instead help put your focus where it belongs, on the project.

On a sidenote: the code inside ofencoders.pyforjsonable_encoderis from

  1. Run:poetry install
  2. Run:poetry run python -m src.main

Make sure the following environment variables are set:

    MONGODB_CONNECTION_URLneeded to conntect to your database, feel free to swap out the persistence layer with anything you prefer or to remove it entirely, MongoDB together with their atlas-cloud database is a nice way to get started prototyping your small projects. In hindsight I should have just used SQLite with SQLAlchemy, this would allow anyone that pulls the template to just start it up with a bot token. MONGODB_DATABASEname of your database BOT_TOKENyou can get one from Botfather

This project comes with a barebone CI pipeline.

  1. It tests your code using pytest, the same as it would locally withpython -m pytest
  2. It builds the Docker image
  3. It pushes the Docker image to a repository, just open upci.ymland fill out the secrets in your own repository

The app gets its configuration from environment variables that are defined in the classes extendingpydantic.BaseSettingsinsettings.py

from pydantic import BaseSettings class DBSettings ( BaseSettings ): MONGODB_CONNECTION_URL : str MONGODB_DB : str class TelegramSettings ( BaseSettings ): BOT_TOKEN : str class Settings ( TelegramSettings , DBSettings ): pass settings = Settings ()

For the persistence layer of the project I created two main template classes to extend,MongoEntityandBaseDao, both live indb.core.

Телеграм бот Python с базой данных. Взаимодействие между Телеграмом и функцией

Сначала давайте разберёмся в том, что происходит, после того, как пользователь совершает какое-либо действие с ботом.

Когда боту приходит любое сообщение или команда, Телеграм отправляет запрос с содержимым согласно вебхуку, который мы настроили командойsetWebhookв первой статье . В нашем случае Телеграм оповещает о событии API шлюз Яндекс Облака. API шлюз в свою очередь запускает функцию и передаёт ей на вход данные запроса от Телеграма.

При созданиимы настроили входную точку в python код - python-функцияhandlerв файлеindex.py. Запрос от Телеграма передаётся вhandlerаргументом под названиемevent.

Так как аргументы входной python-функции в шаблоне залогированы, после отправки команды боту во вкладкеЛогифункции можно посмотреть, какие именно запросы поступают - достаточно отфильтровать логи по уровню логированияDEBUGи тексту лога.

Тело запроса передаётся для обработки предварительно созданному объекту класса, который для простоты будем далее называть просто “бот”.

message = telebot.types.Update.de_json(event) bot.process_new_updates()

В процессе обработки сообщений бот совершает действия, которые подразумевает его реализация, после этого функция возвращает ответ API шлюзу и засыпает.

Верхнеуровневая логика обработки сообщений функцией полностью реализована в файлеindex.py:

import os import telebot from bot.structure import create_bot from database.ydb_settings import get_ydb_pool from logs import logger YDB_ENDPOINT = os.getenv("YDB_ENDPOINT") YDB_DATABASE = os.getenv("YDB_DATABASE") BOT_TOKEN = os.getenv("BOT_TOKEN") def handler(event, _): logger.debug(f"New event: {event}") pool = get_ydb_pool(YDB_ENDPOINT, YDB_DATABASE) bot = create_bot(BOT_TOKEN, pool) message = telebot.types.Update.de_json(event) bot.process_new_updates() return { "statusCode": 200, "body": "!", }

Инициализацию бота из файлаbot/structure.pyи подключение в базе данных изdatabase/ydb_settings.pyподробно разберём далее.

Python-telegram-bot примеры. Ша. Пишем основу бота


Создаём папку Bot, в которой потом создаём файл bot.py. Здесь будет код нашего бота.Открываем консоль и переходим в директорию с файлом, устанавливаем python-telegram-bot .

pip install python-telegram-bot --upgrade

После установки мы уже можем написать «основу», которая пока что будет просто отвечать однотипными сообщениями. Импортируем необходимые модули и прописываем наш токен API:

Код настроек и импорта

# Настройки from telegram.ext import Updater, CommandHandler, MessageHandler, Filters updater = Updater(token='ВАШ API КЛЮЧ') # Токен API к Telegram dispatcher = updater.dispatcher

Далее напишем 2 обработчика команд. Это callback-функции, которые будут вызываться тогда, когда будет получено обновление. Напишем две таких функции для команды /start и для обычного любого текстового сообщения. В качестве аргументов туда передаются два параметра: bot и update . Bot содержит необходимые методы для взаимодействия с API, а update содержит данные о пришедшем сообщении.

Создание телеграм бота Python aiogram. Telegram-бот на Python за полчаса с aiogram

Напишем простой Telegram-бот на Python с использованием aiogram, Docker и AWS, предварительно ознакомившись с нужными инструментами.

Напишем простой диалоговый Telegram-бот на Python, который в дальнейшем можно дополнить различными функциями, и задеплоим его.

ПримечаниеВы читаете улучшенную версию некогда выпущенной нами статьи.

    Настройка

    Откройте Telegram, найдите @BotFather и начните беседу. Отправьте команду/newbotи следуйте инструкциям. Вы получите:

  • свой токен;
  • адрес Telegram API (https://api.telegram.org/bot);
  • ссылку на документацию.

Обязательно сохраните токен, так как это ключ для взаимодействия с ботом.

ПримечаниеХранение токена должно быть локальным: ни в коем случае не выгружайте его в общий доступ, например в GitHub-репозиторий .

Далее начните беседу. Введите в поисковой строке имя бота и нажмите/start. Отправьте любое сообщение: оно станет первым обновлением, которое получит Телеграм бот.

Установка Python

Для написания Telegram-бота на Python, нужно установить сам язык. Если вы пользуетесь Windows, скачать Python можно. Версия важна. Нам подойдет Python не ниже версии 3.7. Если же у вас Linux или macOS, то, скорее всего, у вас стоит Python 3.6. Как обновиться, можете почитать.

Тем, кто только начал изучение этого языка, будет также полезна.

Установка pip

Это менеджер пакетов. В версиях выше Python 2.7.9 и Python 3.4, а также на macOS/Linux он уже есть. Проверить это можно командойpip --versionв терминале. Если же по каким-то причинам он отсутствует, установить его можно при помощи команды:

$ sudo apt-get install python-pip

Установка aiogram

Установить данный фреймворк для Telegram Bot API с помощью pip:

pip install aiogram

Hello, bot!

Давайте напишем простенькую программу приветствия. Для начала следует импортировать библиотеки и создать экземпляры Телеграм бота и диспетчера:

from aiogram import Bot, types from aiogram.dispatcher import Dispatcher from aiogram.utils import executor TOKEN = "ваш токен от бота здесь" bot = Bot(token=TOKEN) dp = Dispatcher(bot)

Теперь напишем обработчик текстовых сообщений, который будет обрабатывать входящие команды/startи/help:

@dp.message_handler(commands=) async def send_welcome(msg: types.Message): await msg.reply_to_message(f‘Я бот. Приятно познакомиться, {msg.from_user.first_name}’)

Добавим ещё один обработчик для получения текстовых сообщений. Если бот получит «Привет», он также поздоровается. Все остальные сообщения будут определены, как нераспознанные:

@dp.message_handler(content_types=) async def get_text_messages(msg: types.Message): if msg.text.lower() == 'привет': await msg.answer('Привет!') else: await msg.answer('Не понимаю, что это значит.')

Запускаем Telegram бота, написанного на Python, следующим образом:

if __name__ == '__main__': executor.start_polling(dp)

ПримечаниеТак мы задаём боту непрерывное отслеживание новых сообщений. Если бот упадёт, а сообщения продолжат поступать, они будут накапливаться в течение 24 часов на серверах Telegram, и в случае восстановления бота прилетят ему все сразу.

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

Docker

Сейчас мало кто не слышал про Docker, но если вдруг не слышали —. Для нашего проекта потребуется самый простой Dockerfile:

FROM python:3.8 # set work directory WORKDIR /usr/src/app/ # copy project COPY . /usr/src/app/ # install dependencies RUN pip install --user aiogram # run app CMD

Каталог проекта должны при этом содержать следующие файлы:

  • bot.py;
  • Dockerfile.

Для локальных тестов достаточно установить Docker (,,), после чего в папке проекта собрать и запустить контейнер с помощью команд:

docker build -t my_app docker run -d my_app

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

-d— специальный флаг, который запускает контейнер в фоне и позволяет дальше работать в терминале. Это называется detached mode .

Деплой на AWS

Прежде всего нам понадобится аккаунт на. Это аналог GitHub, только не с исходниками кода, а с уже созданными контейнерами. Работа с Docker Hub выглядит достаточно просто:

  1. Локально или с помощью пайплайнов собрали контейнер.
  2. Загрузили его на докер хаб.
  3. Пройдёмся по этим шагам. Везде, где указано, надо вставлять свой юзернейм, использованный при регистрации на докерхабе. Если это ваша первая публикация на докерхаб, для начала потребуется залогиниться с помощью docker login.