В библиотеке Aiogram, Dispatcher
— это класс, который играет центральную роль в управлении и обработке входящих событий (например, текстовых сообщений, команд, фотографий и т.д.) в Telegram ботах. Он является основной частью библиотеки для работы с асинхронными Telegram ботами на платформе Python.
Примеры, приведенные в этой статье работают на версии aiogram 2x
Основные методы и атрибуты класса Dispatcher
Методы
register_message_handler(handler, *custom_filters)
: Регистрирует обработчик сообщений.handler
— это функция или корутина, которая будет вызвана, когда пользователь отправит сообщение. `custom_filters` — дополнительные пользовательские фильтры для сообщений (опционально).register_callback_query_handler(handler, *custom_filters)
: Регистрирует обработчик для inline-кнопок (callback query).handler
— это функция или корутина, которая будет вызвана, когда пользователь нажмет на inline-кнопку.custom_filters
— дополнительные пользовательские фильтры для callback query (опционально).register_inline_handler(handler)
: Регистрирует обработчик для inline-режима.handler
— это функция или корутина, которая будет вызвана, когда пользователь начнет вводить запрос в строку поиска в inline-режиме.register_chosen_inline_handler(handler)
: Регистрирует обработчик для выбранных результатов inline-режима.handler
— это функция или корутина, которая будет вызвана, когда пользователь выберет один из результатов inline-режима.register_pre_checkout_query_handler(handler)
: Регистрирует обработчик для предварительных запросов на оформление платежа.handler
— это функция или корутина, которая будет вызвана, когда пользователь запрашивает предварительное оформление платежа.register_shipping_query_handler(handler)
: Регистрирует обработчик для запросов на доставку.handler
— это функция или корутина, которая будет вызвана, когда пользователь запрашивает информацию о доставке.register_errors_handler(handler)
: Регистрирует обработчик для обработки ошибок, которые могут возникнуть при обработке входящих событий.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.
Индивидуальное и групповое обучение «Python Junior»
Если вы хотите научиться программировать на Python, могу помочь. Запишитесь на мой курс «Python Junior» и начните свой путь в мир ИТ уже сегодня!
Контакты
Для получения дополнительной информации и записи на курсы свяжитесь со мной:
Телеграм: https://t.me/Vvkomlev
Email: victor.komlev@mail.ru
Объясняю сложное простыми словами. Даже если вы никогда не работали с ИТ и далеки от программирования, теперь у вас точно все получится! Проверено десятками примеров моих учеников.
Гибкий график обучения. Я предлагаю занятия в мини-группах и индивидуально, что позволяет каждому заниматься в удобном темпе. Вы можете совмещать обучение с работой или учебой.
Практическая направленность. 80%: практики, 20% теории. У меня множество авторских заданий, которые фокусируются на практике. Вы не просто изучаете теорию, а сразу применяете знания в реальных проектах и задачах.
Разнообразие учебных материалов: Теория представлена в виде текстовых уроков с примерами и видео, что делает обучение максимально эффективным и удобным.
Понимаю, что обучение информационным технологиям может быть сложным, особенно для новичков. Моя цель – сделать этот процесс максимально простым и увлекательным. У меня персонализированный подход к каждому ученику. Максимальный фокус внимания на ваши потребности и уровень подготовки.