Класс dispatcher фреймворка aiogram

Класс dispatcher aiogram

В библиотеке Aiogram, Dispatcher — это класс, который играет центральную роль в управлении и обработке входящих событий (например, текстовых сообщений, команд, фотографий и т.д.) в Telegram ботах. Он является основной частью библиотеки для работы с асинхронными Telegram ботами на платформе Python.

Примеры, приведенные в этой статье работают на версии aiogram 2x

Основные методы и атрибуты класса Dispatcher

Методы

  1. register_message_handler(handler, *custom_filters): Регистрирует обработчик сообщений. handler — это функция или корутина, которая будет вызвана, когда пользователь отправит сообщение. `custom_filters` — дополнительные пользовательские фильтры для сообщений (опционально).
  2. register_callback_query_handler(handler, *custom_filters): Регистрирует обработчик для inline-кнопок (callback query). handler — это функция или корутина, которая будет вызвана, когда пользователь нажмет на inline-кнопку. custom_filters — дополнительные пользовательские фильтры для callback query (опционально).
  3. register_inline_handler(handler): Регистрирует обработчик для inline-режима. handler — это функция или корутина, которая будет вызвана, когда пользователь начнет вводить запрос в строку поиска в inline-режиме.
  4. register_chosen_inline_handler(handler): Регистрирует обработчик для выбранных результатов inline-режима. handler — это функция или корутина, которая будет вызвана, когда пользователь выберет один из результатов inline-режима.
  5. register_pre_checkout_query_handler(handler): Регистрирует обработчик для предварительных запросов на оформление платежа. handler — это функция или корутина, которая будет вызвана, когда пользователь запрашивает предварительное оформление платежа.
  6. register_shipping_query_handler(handler): Регистрирует обработчик для запросов на доставку. handler — это функция или корутина, которая будет вызвана, когда пользователь запрашивает информацию о доставке.
  7. register_errors_handler(handler): Регистрирует обработчик для обработки ошибок, которые могут возникнуть при обработке входящих событий.
  8. process_update(update): Обрабатывает входящее обновление Telegram API, вызывая соответствующие зарегистрированные обработчики.

Методы register* в классе Dispatcher не предназначены для использования напрямую. Вместо этого в библиотеке Aiogram для регистрации обработчиков событий рекомендуется использовать декораторы, которые предоставляют более простой и удобный способ определения обработчиков.

Каждый метод register* соответствует определенному типу события, например, register_message_handler используется для регистрации обработчиков текстовых сообщений, register_callback_query_handler — для inline-кнопок и так далее.

Декораторы для обработчиков событий в Aiogram имеют следующий синтаксис:

@dispatcher.message_handler(commands=['start'])
async def on_start(message: types.Message):
# Ваш код обработчика для команды /start
pass

@dispatcher.callback_query_handler(lambda c: c.data == 'button_pressed')
async def on_button_pressed(callback_query: types.CallbackQuery):
# Ваш код обработчика для нажатия на inline-кнопку с data='button_pressed'
pass

Обратите внимание на использование декоратора @dispatcher.message_handler и @dispatcher.callback_query_handler, которые связывают функцию on_start и on_button_pressed с соответствующими событиями.

Использование декораторов делает код более читабельным и позволяет определять обработчики событий в естественной структуре кода, что упрощает поддержку и расширение. Поэтому рекомендуется использовать декораторы для регистрации обработчиков событий в Aiogram.

Атрибуты

1. middlewares: Список промежуточных слоев (middlewares), которые позволяют выполнять определенные действия до и после обработки каждого обновления.

2. loop: Экземпляр цикла asyncio, используемый ботом для асинхронной обработки событий.

Назначение класса Dispatcher

Класс Dispatcher предоставляет удобный интерфейс для регистрации обработчиков различных событий и их последующей обработки. Когда приходит новое обновление от Telegram, Dispatcher проверяет тип события и вызывает соответствующий зарегистрированный обработчик.

from aiogram import Bot, Dispatcher, types
from aiogram.contrib.middlewares.logging import LoggingMiddleware
import asyncio

API_TOKEN = 'your_api_token'
bot = Bot(token=API_TOKEN)
dispatcher = Dispatcher(bot)
dispatcher.middleware.setup(LoggingMiddleware())

@dispatcher.message_handler(commands=['start'])
async def on_start(message: types.Message):
    await message.reply("Привет! Я бот.")

@dispatcher.message_handler()
async def on_message(message: types.Message):
    await message.reply("Вы написали мне сообщение!")

async def main():
# Запуск бота
await dispatcher.start_polling()

if __name__ == '__main__':
    asyncio.run(main())

В приведенном примере мы создаем бота с помощью токена Telegram, регистрируем обработчики команды /start и всех остальных сообщений, и запускаем бота с помощью start_polling(). Когда пользователь отправляет команду /start или любое другое сообщение, бот отвечает соответствующим образом. Обратите внимание, что это простой пример, и реальные боты могут иметь более сложную логику обработки событий.

Метод start_polling()

Метод start_polling() в классе Dispatcher из библиотеки Aiogram используется для запуска асинхронного процесса, который начинает опрос Telegram API на предмет новых обновлений для вашего бота. Когда новые обновления доступны, библиотека обрабатывает их и вызывает соответствующие зарегистрированные обработчики событий.

В ботах Telegram существует два способа получения обновлений:

1. Поддержка вебхуков (webhooks): В этом случае, вы должны настроить веб-сервер, который будет принимать обновления от Telegram и передавать их боту для обработки. Этот способ более предпочтителен для производственных ботов, так как он позволяет получать обновления в режиме реального времени.

2. Поддержка Long Polling: Это альтернативный способ, который использует метод getUpdates Telegram API для периодического опроса сервера на предмет новых обновлений. Когда бот вызывает метод start_polling(), он начинает циклически отправлять запросы на сервер Telegram для получения новых обновлений.

Метод start_polling() работает в асинхронном режиме, что позволяет боту обрабатывать несколько обновлений одновременно и не блокироваться при выполнении долгих операций.

Пример использования start_polling():

from aiogram import Bot, Dispatcher, types
import asyncio

API_TOKEN = 'your_api_token'
bot = Bot(token=API_TOKEN)
dispatcher = Dispatcher(bot)

# Регистрация обработчиков событий
@dispatcher.message_handler(commands=['start'])
async def on_start(message: types.Message):
    await message.reply("Привет! Я бот.")

@dispatcher.message_handler()
async def on_message(message: types.Message):
    await message.reply("Вы написали мне сообщение!")

async def main():
# Запуск бота с помощью метода start_polling()
    await dispatcher.start_polling()

if __name__ == '__main__':
    asyncio.run(main())

В этом примере метод start_polling() запускает бота, и он начнет принимать и обрабатывать обновления от пользователей, вызывая соответствующие обработчики, когда пользователи отправляют команду /start или любое другое сообщение.

Вебхуки

Вебхуки (Webhooks) — это механизм, который позволяет веб-серверу автоматически получать уведомления и данные от другого веб-сервера (в данном контексте — от Telegram) в режиме реального времени. Этот механизм используется для получения обновлений от API или сервиса, когда они становятся доступными, без необходимости постоянно опрашивать их для проверки новых данных.

В контексте Telegram ботов, вебхуки позволяют вашему боту получать обновления (например, сообщения, inline-кнопки, запросы на оформление платежей и т.д.) немедленно, как только они становятся доступными, что делает их предпочтительным способом для получения обновлений, особенно для ботов, которые должны обрабатывать события в реальном времени.

Вебхуки работают следующим образом:

1. Веб-сервер вашего бота устанавливает URL-адрес, который будет использоваться Telegram для отправки обновлений. Этот URL-адрес может быть определен как HTTPS (для обеспечения безопасности) или HTTP (менее безопасный).

2. Когда происходит событие в Telegram, например, когда пользователь отправляет сообщение боту, Telegram формирует JSON-объект с данными об обновлении.

3. Telegram отправляет этот JSON-объект на предварительно указанный URL-адрес (вебхук) вашего бота в виде POST-запроса.

4. Веб-сервер вашего бота принимает POST-запрос, извлекает данные из JSON-объекта и обрабатывает соответствующее событие.

Преимущества использования вебхуков:

— Получение обновлений в реальном времени.
— Эффективное использование ресурсов, так как нет необходимости постоянно опрашивать API на предмет новых обновлений.
— Меньшая задержка между возникновением события и его обработкой.
— Более подходящий вариант для производственных ботов с высокой нагрузкой и требованиями к быстрому отклику.

Однако для использования вебхуков необходимо наличие публичного IP-адреса и настройка HTTPS для обеспечения безопасности передачи данных. В свою очередь, при использовании Long Polling (другого способа получения обновлений) вам не нужно заботиться о настройке вебхуков, но обработка обновлений может занимать немного больше времени.

Пример реализации обработки вебхуков с помощью вебсервера на базе flask

Реализация механизма обработки обновлений с помощью вебхуков в Python связана с созданием веб-сервера, который будет принимать POST-запросы от Telegram с данными об обновлениях. Для этого вы можете использовать различные фреймворки для веб-разработки. В примере ниже я покажу, как это можно сделать с помощью Flask — популярного микрофреймворка для веб-приложений.

Шаги для реализации механизма обработки обновлений с помощью вебхуков:

  • Установите Flask, если у вас его ещё нет, используя pip:
pip install flask
  • Создайте файл с вашим кодом для веб-сервера. Ниже приведен пример кода для простейшего веб-сервера с использованием Flask:
from flask import Flask, request, jsonify
import json

app = Flask(__name__)

# Эндпоинт для обработки обновлений от Telegram
@app.route('/webhook', methods=['POST'])
def webhook():
    if request.method == 'POST':
        data = json.loads(request.data)
# Обработайте данные обновления, вызывая соответствующие обработчики
# Ваш код обработки обновлений здесь

return jsonify({"status": "ok"})

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8443, ssl_context='adhoc')
  • Получите публичный IP-адрес и настройте доменное имя для вашего сервера (вы можете использовать DDNS, если у вас нет статического IP-адреса).
  • Установите ваш публичный IP-адрес и порт (по умолчанию для HTTPS — 443) в качестве вебхука с помощью Telegram Bot API:
from aiogram import Bot
import requests

API_TOKEN = 'your_api_token'
WEBHOOK_URL = 'https://your_domain.com/webhook'

bot = Bot(token=API_TOKEN)
bot.set_webhook(WEBHOOK_URL)

Обратите внимание, что в примере выше используется adhoc контекст SSL для простоты, но в производственной среде рекомендуется использовать настоящий сертификат SSL.

  • Теперь ваш сервер на Flask готов принимать обновления от Telegram через вебхуки. Когда происходит событие в Telegram, оно будет отправлено на указанный URL-адрес вашего сервера, где Flask-приложение обработает данные и выполнит соответствующие действия.

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

Атрибут middlewares

В библиотеке Aiogram атрибут middlewares — это список промежуточных слоев (middlewares), которые позволяют вам внедрять дополнительные функции и обработку перед и после обработки каждого входящего события (например, сообщения, inline-запросы, команды и т.д.) в вашем Telegram боте. Middlewares представляют собой мощный механизм для модификации запросов и ответов, внедрения дополнительных действий и управления логикой обработки.

  • Каждый middleware — это асинхронная функция, которая принимает два аргумента: event и data, и возвращает data. Где:
    event — это объект события, такой как types.Message, types.CallbackQuery, и т.д., который содержит информацию о входящем событии.
    data — это словарь, который представляет информацию о текущей обработке события, и его можно изменить или расширить.

Примеры использования middlewares:

  • Логирование:
from aiogram.dispatcher.middlewares import BaseMiddleware
import logging

class LoggingMiddleware(BaseMiddleware):
async def on_pre_process_message(self, message, data):
    user = message.from_user
    logging.info(f"Received message from {user.full_name}: {message.text}")
    return data

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

  • Подсчет количества запросов:
from aiogram.dispatcher.middlewares import BaseMiddleware

class RequestCounterMiddleware(BaseMiddleware):
async def on_pre_process(self, event, data):
    if 'request_count' not in data:
        data['request_count'] = 1
    else:
        data['request_count'] += 1
    return data

В этом примере мы создаем middleware, который подсчитывает количество запросов к боту и сохраняет его в data.

  • Аутентификация:
from aiogram.dispatcher.middlewares import BaseMiddleware
from aiogram.types import Message
import config

class AuthMiddleware(BaseMiddleware):
async def on_pre_process_message(self, message: Message, data):
    if message.from_user.id not in config.ALLOWED_USERS:
        raise PermissionError("You are not authorized to use this bot.")
    return data

В этом примере мы создаем middleware, который проверяет, принадлежит ли пользователь, отправивший сообщение, к разрешенным пользователям (список ALLOWED_USERS определен в файле config). Если пользователь не авторизован, middleware вызывает исключение PermissionError.

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

Для того чтобы занести пользователей, которым разрешен доступ, в файл config.py, вы можете определить переменную, которая будет представлять список идентификаторов (ID) пользователей. Например:

ALLOWED_USERS = [123456789, 987654321]

В этом примере список ALLOWED_USERS содержит два идентификатора пользователей (123456789 и 987654321), которым разрешен доступ к боту.

Примечание: Для использования middlewares в Aiogram, вы должны зарегистрировать их в экземпляре Dispatcher, чтобы они были применены к соответствующим событиям. Это можно сделать с помощью метода dispatcher.middleware.setup():

from aiogram import Bot, Dispatcher
from aiogram.dispatcher.middlewares import BaseMiddleware

bot = Bot(token='your_token')
dispatcher = Dispatcher(bot)

# Регистрация middlewares
dispatcher.middleware.setup(LoggingMiddleware())
dispatcher.middleware.setup(RequestCounterMiddleware())
dispatcher.middleware.setup(AuthMiddleware())

Здесь мы регистрируем все три созданных ранее middlewares, чтобы они применялись при обработке всех входящих событий.

Примеры работы с обработкой обновлений

Обработка сообщений.

from aiogram import Bot, Dispatcher, types
import asyncio

API_TOKEN = 'your_api_token'
bot = Bot(token=API_TOKEN)
dispatcher = Dispatcher(bot)

@dispatcher.message_handler(content_types=types.ContentTypes.TEXT)
async def handle_text_message(message: types.Message):
    # Обработка текстового сообщения
    await message.reply(f"Вы написали: {message.text}")

async def main():
    # Запуск бота
    await dispatcher.start_polling()

if __name__ == '__main__':
    asyncio.run(main())

В этом примере мы определяем функцию handle_text_message, которая будет обрабатывать текстовые сообщения. Мы используем декоратор @dispatcher.message_handler для связи этой функции с событием прихода текстового сообщения. Декоратору передается аргумент content_types, который определяет типы контента, которые должны обрабатываться этим обработчиком. В данном случае мы указываем types.ContentTypes.TEXT, чтобы обработчик реагировал только на текстовые сообщения.

Когда пользователь отправляет текстовое сообщение боту, Aiogram вызывает функцию handle_text_message, и бот отправляет ответ с текстом, который он получил от пользователя.

Обработка inline кнопок.

from aiogram import Bot, Dispatcher, types
import asyncio

API_TOKEN = 'your_api_token'
bot = Bot(token=API_TOKEN)
dispatcher = Dispatcher(bot)

# Функция для создания инлайн-кнопок
def create_inline_keyboard():
    keyboard = types.InlineKeyboardMarkup()
    buttons = [
        types.InlineKeyboardButton(text="Кнопка 1", callback_data="button_1"),
        types.InlineKeyboardButton(text="Кнопка 2", callback_data="button_2"),
        types.InlineKeyboardButton(text="Кнопка 3", callback_data="button_3"),
    ]
    keyboard.add(*buttons)
    return keyboard

@dispatcher.callback_query_handler(lambda c: c.data.startswith('button_'))
async def handle_inline_button(callback_query: types.CallbackQuery):
    button_data = callback_query.data
    await callback_query.answer(f"Вы нажали на кнопку с данными: {button_data}")

async def main():
    # Создание инлайн-кнопок и отправка сообщения с ними
    inline_keyboard = create_inline_keyboard()
    await bot.send_message(chat_id='your_chat_id', text='Выберите кнопку:', reply_markup=inline_keyboard)

    # Запуск бота
    await dispatcher.start_polling()

if __name__ == '__main__':
    asyncio.run(main())

В этом примере мы определяем функцию create_inline_keyboard, которая создает инлайн-клавиатуру с тремя кнопками («Кнопка 1», «Кнопка 2» и «Кнопка 3»). Затем мы используем декоратор @dispatcher.callback_query_handler для связи функции handle_inline_button с событием нажатия на инлайн-кнопку.

При запуске бота, он отправляет сообщение с инлайн-клавиатурой на указанный chat_id. Когда пользователь нажимает на одну из кнопок, бот вызывает функцию handle_inline_button и отправляет ответ с данными кнопки.

Обратите внимание, что в этом примере мы используем your_chat_id в методе bot.send_message() для указания идентификатора чата, куда отправлять сообщение. Вы должны заменить его на реальный идентификатор чата, чтобы сообщения отправлялись в нужный чат.

Обработчик взаимодействия с ботом в режиме inline

Обработчик в режиме inline (Inline Query Handler) — это функция, которая обрабатывает запросы в режиме inline от пользователей. Режим inline позволяет пользователям отправлять запросы прямо из строки ввода чата, и бот отвечает на эти запросы с помощью специально сформированных сообщений или результатов.

Когда пользователь начинает вводить @ваш_бот текст в строке чата, Telegram отправляет запрос в режиме inline вашему боту с текстом запроса. Ваш бот должен ответить на этот запрос с помощью inline-режима ответа.

Вот пример реализации обработчика в режиме inline в библиотеке Aiogram:

from aiogram import Bot, Dispatcher, types
import asyncio

API_TOKEN = 'your_api_token'
bot = Bot(token=API_TOKEN)
dispatcher = Dispatcher(bot)

@dispatcher.inline_handler()
async def handle_inline_query(inline_query: types.InlineQuery):
    query = inline_query.query
    results = []
    # Здесь вы можете обработать запрос и сформировать ответы в режиме inline

    # Пример ответа с результатами
    results.append(types.InlineQueryResultArticle(
        id='1',
        title='Результат 1',
        input_message_content=types.InputTextMessageContent(message_text='Вы выбрали результат 1.')
    ))

    results.append(types.InlineQueryResultArticle(
        id='2',
        title='Результат 2',
        input_message_content=types.InputTextMessageContent(message_text='Вы выбрали результат 2.')
    ))

    # Отправляем ответ с результатами inline-режима
    await bot.answer_inline_query(inline_query.id, results=results, cache_time=1)

async def main():
    # Запуск бота
    await dispatcher.start_polling()

if __name__ == '__main__':
    asyncio.run(main())

В этом примере мы определяем функцию handle_inline_query, которая обрабатывает запросы в режиме inline. В этой функции мы можем получить текст запроса с помощью inline_query.query, обработать запрос и сформировать результаты ответа в режиме inline.

В нашем примере мы просто формируем два варианта ответов (Результат 1 и Результат 2) и отправляем их обратно с помощью метода bot.answer_inline_query(). Каждый результат представлен объектом types.InlineQueryResultArticle, который содержит информацию о результате inline-запроса.

Важно отметить, что в реальных ботах вы можете обрабатывать запросы в режиме inline более сложным образом, например, выполнять поиск в базе данных или интегрироваться с внешними API для получения результатов. В примере выше результаты ответов были заданы статически, но обычно они формируются динамически в зависимости от запроса пользователя.

Как работать в inline режиме?

Для использования примера обработчика в режиме inline, вы можете запустить бота на выполнение и отправить запрос в режиме inline, начиная с символа «@» в строке чата.

Вам не обязательно вводить запрос в чат с ботом. Вы можете ввести запрос в любой чат, где ваш бот также присутствует, и начать его имя с символа «@». Например, если имя вашего бота — «my_super_bot», то запрос должен начинаться с «@my_super_bot».

После ввода запроса с символом «@» и начала имени бота, Telegram будет автоматически определять это как inline-запрос и отправлять его боту для обработки. Затем ваш обработчик в режиме inline будет вызван, и ваш бот сможет сформировать и отправить ответы в режиме inline.

Убедитесь, что у вашего бота включен режим inline в настройках бота в BotFather. Вы можете проверить это, отправив команду /setinline в BotFather.

 

Понравилась статья? Поделиться с друзьями:
Школа Виктора Комлева
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.