Dispatcher
It will process incoming updates: messages, edited messages, channel posts, edited channel posts, inline queries, chosen inline results, callback queries, shipping queries, pre-checkout queries.
You can skip old incoming updates from queue. This method is not recommended for using in production.
Note that the webhook will be deleted!
async process_updates ( updates , fast : bool = True ) [source]
Process list of updates
updates –
fast –
Process single update object
update –
async reset_webhook ( check = True ) → bool [source]
check – check before deleting
async start_polling ( timeout = 20 , relax = 0.1 , limit = None , reset_webhook = None , fast : bool = True , error_sleep : int = 5 , allowed_updates : Optional [ List [ str ] ] = None ) [source]
timeout –
relax –
limit –
reset_webhook –
fast –
error_sleep –
allowed_updates –
Break long-polling process.
Wait for the long-polling to close
Check if polling is enabled
register_message_handler ( callback , * custom_filters , commands = None , regexp = None , content_types = None , state = None , run_task = None , ** kwargs ) [source]
Register handler for message
callback –
commands – list of commands
regexp – REGEXP
content_types – List of content types.
custom_filters – list of custom filters
kwargs –
state –
message_handler ( * custom_filters , commands = None , regexp = None , content_types = None , state = None , run_task = None , ** kwargs ) [source]
Decorator for message handler
Simple commands handler:
Filter messages by regular expression:
Filter messages by command regular expression:
Filter by content type:
Filter by custom function:
Use multiple filters:
Register multiple filters set for one handler:
This handler will be called if the message starts with ‘/command’ OR is some emoji
By default content_type is ContentType.TEXT
commands – list of commands
regexp – REGEXP
content_types – List of content types.
custom_filters – list of custom filters
kwargs –
state –
run_task – run callback in task (no wait results)
register_edited_message_handler ( callback , * custom_filters , commands = None , regexp = None , content_types = None , state = None , run_task = None , ** kwargs ) [source]
Register handler for edited message
callback –
commands – list of commands
regexp – REGEXP
content_types – List of content types.
state –
custom_filters – list of custom filters
run_task – run callback in task (no wait results)
kwargs –
edited_message_handler ( * custom_filters , commands = None , regexp = None , content_types = None , state = None , run_task = None , ** kwargs ) [source]
Decorator for edited message handler
You can use combination of different handlers
commands – list of commands
regexp – REGEXP
content_types – List of content types.
state –
custom_filters – list of custom filters
run_task – run callback in task (no wait results)
kwargs –
register_channel_post_handler ( callback , * custom_filters , commands = None , regexp = None , content_types = None , state = None , run_task = None , ** kwargs ) [source]
Register handler for channel post
callback –
commands – list of commands
regexp – REGEXP
content_types – List of content types.
state –
custom_filters – list of custom filters
run_task – run callback in task (no wait results)
kwargs –
channel_post_handler ( * custom_filters , commands = None , regexp = None , content_types = None , state = None , run_task = None , ** kwargs ) [source]
Decorator for channel post handler
commands – list of commands
regexp – REGEXP
content_types – List of content types.
state –
custom_filters – list of custom filters
run_task – run callback in task (no wait results)
kwargs –
register_edited_channel_post_handler ( callback , * custom_filters , commands = None , regexp = None , content_types = None , state = None , run_task = None , ** kwargs ) [source]
Register handler for edited channel post
callback –
commands – list of commands
regexp – REGEXP
content_types – List of content types.
state –
custom_filters – list of custom filters
run_task – run callback in task (no wait results)
kwargs –
edited_channel_post_handler ( * custom_filters , commands = None , regexp = None , content_types = None , state = None , run_task = None , ** kwargs ) [source]
Decorator for edited channel post handler
commands – list of commands
regexp – REGEXP
content_types – List of content types.
custom_filters – list of custom filters
state –
run_task – run callback in task (no wait results)
kwargs –
register_inline_handler ( callback , * custom_filters , state = None , run_task = None , ** kwargs ) [source]
Register handler for inline query
callback –
custom_filters – list of custom filters
state –
run_task – run callback in task (no wait results)
kwargs –
inline_handler ( * custom_filters , state = None , run_task = None , ** kwargs ) [source]
Decorator for inline query handler
state –
custom_filters – list of custom filters
run_task – run callback in task (no wait results)
kwargs –
register_chosen_inline_handler ( callback , * custom_filters , state = None , run_task = None , ** kwargs ) [source]
Register handler for chosen inline query
callback –
state –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
chosen_inline_handler ( * custom_filters , state = None , run_task = None , ** kwargs ) [source]
Decorator for chosen inline query handler
state –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
register_callback_query_handler ( callback , * custom_filters , state = None , run_task = None , ** kwargs ) [source]
Register handler for callback query
callback –
state –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Decorator for callback query handler
state –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Register handler for shipping query
callback –
state –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Decorator for shipping query handler
state –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Register handler for pre-checkout query
callback –
state –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Decorator for pre-checkout query handler
state –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Register handler for poll
callback –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Decorator for poll handler
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Register handler for poll_answer
callback –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Decorator for poll_answer handler
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Register handler for my_chat_member
callback –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Decorator for my_chat_member handler
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Register handler for chat_member
callback –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Decorator for chat_member handler
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Register handler for chat_join_request
callback –
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Decorator for chat_join_request handler
custom_filters –
run_task – run callback in task (no wait results)
kwargs –
Register handler for errors
callback –
exception – you can make handler for specific errors type
run_task – run callback in task (no wait results)
Decorator for errors handler
exception – you can make handler for specific errors type
run_task – run callback in task (no wait results)
current_state ( * , chat : Optional [ Union [ str , int ] ] = None , user : Optional [ Union [ str , int ] ] = None ) → FSMContext [source]
Get current state for user in chat as context
chat –
user –
async throttle ( key , * , rate = None , user_id = None , chat_id = None , no_error = None ) → bool [source]
Execute throttling manager. Returns True if limit has not exceeded otherwise raises ThrottleError or returns False
key – key in storage
rate – limit (by default is equal to default rate limit)
user_id – user id
chat_id – chat id
no_error – return boolean value instead of raising error
async check_key ( key , chat_id = None , user_id = None ) [source]
Get information about key in bucket
key –
chat_id –
user_id –
async release_key ( key , chat_id = None , user_id = None ) [source]
Release blocked key
key –
chat_id –
user_id –
Execute handler as task and return None. Use this decorator for slow handlers (with timeouts)
func –
throttled ( on_throttled : Optional [ Callable ] = None , key = None , rate = None , user_id = None , chat_id = None ) [source]
Meta-decorator for throttling. Invokes on_throttled if the handler was throttled.
on_throttled – the callable object that should be either a function or return a coroutine
key – key in storage
rate – limit (by default is equal to default rate limit)
user_id – user id
chat_id – chat id
bind_filter ( callback : Union [ Callable , AbstractFilter ] , validator : Optional [ Callable ] = None , event_handlers : Optional [ List [ Handler ] ] = None , exclude_event_handlers : Optional [ Iterable [ Handler ] ] = None ) [source]
callback – callable or subclass of AbstractFilter
validator – custom validator.
event_handlers – list of instances of Handler
exclude_event_handlers – list of excluded event handlers ( Handler )
Знакомство с aiogram¶
Автор этой книги убеждён, что помимо теории должна быть и практика. Чтобы максимально упростить повторение приведённого далее кода, пришлось пойти на использование подходов, пригодных только для локальной разработки и обучения.
Так, например, во всех или почти во всех главах токен бота будет указываться прямо в исходных текстах. Это плохой подход, поскольку может привести к раскрытию токена, если вы забудете его удалить перед заливкой кода в публичный репозиторий (например, GitHub).
Или иногда в качестве хранилищ данных будут использоваться структуры, расположенные исключительно в оперативной памяти (словари, списки. ). В действительности такие объекты нежелательны, поскольку остановка бота приведёт безвозвратной потере данных.
Также механизмом получения апдейтов от Telegram выбран поллинг, поскольку он гарантированно работает в подавляющем большинстве окружений и подходит практически всем разработчикам.
Важно помнить, что автор ставит перед собой цель объяснить именно работу с Telegram Bot API при помощи aiogram, а не вообще весь Computer Science во всём его многообразии.
Терминология¶
Чтобы разговаривать в одних и тех же понятиях, введём некоторые термины, дабы в дальнейшем не путаться:
- ЛС — личные сообщения, в контексте бота это диалог один-на-один с пользователем, а не группа/канал.
- Чат — общее название для ЛС, групп, супергрупп и каналов.
- Апдейт — любое событие из этого списка: сообщение, редактирование сообщения, колбэк, инлайн-запрос, платёж, добавление бота в группу и т.д.
- Хэндлер — асинхронная функция, которая получает от диспетчера/роутера очередной апдейт и обрабатывает его.
- Диспетчер — объект, занимающийся получением апдейтов от Telegram с последующим выбором хэндлера для обработки принятого апдейта.
- Роутер — аналогично диспетчеру, но отвечает за подмножество множества хэндлеров. Можно сказать, что диспетчер — это корневой роутер.
- Фильтр — выражение, которое обычно возвращает True или False и влияет на то, будет вызван хэндлер или нет.
- Мидлварь — прослойка, которая вклинивается в обработку апдейтов.
Установка¶
Для начала давайте создадим каталог для бота, организуем там virtual environment (далее venv) и установим библиотеку aiogram.
Проверим, что установлен Python версии 3.9 (если вы знаете, что установлен 3.9 и выше, можете пропустить этот раздел):
Теперь создадим файл requirements.txt , в котором укажем используемую нами версию aiogram. Также нам понадобится библиотека python-dotenv для файлов конфигурации.
О версиях aiogram
В этой главе используется aiogram 3.x, перед началом работы рекомендую заглянуть в канал релизов библиотеки и проверить наличие более новой версии. Подойдёт любая более новая, начинающаяся с цифры 3, поскольку aiogram 2.x более рассматриваться не будет и считается устаревшим.
Обратите внимание на префикс «venv» в терминале. Он указывает, что мы находимся в виртуальном окружении с именем «venv». Проверим, что внутри venv вызов команды python указывает на всё тот же Python 3.9:
Последней командой deactivate мы вышли из venv, чтобы он нам не мешал.
Если для написания ботов вы используете PyCharm, рекомендую также установить сторонний плагин Pydantic для поддержки автодополнения кода в телеграмных объектах.
Первый бот¶
Давайте создадим файл bot.py с базовым шаблоном бота на aiogram:
Первое, на что нужно обратить внимание: aiogram — асинхронная библиотека, поэтому ваши хэндлеры тоже должны быть асинхронными, а перед вызовами методов API нужно ставить ключевое слово await, т.к. эти вызовы возвращают корутины.
Асинхронное программирование в Python
Не стоит пренебрегать официальной документацией!
Прекрасный туториал по asyncio доступен на сайте Python.
Если вы в прошлом работали с какой-то другой библиотекой для Telegram, например, pyTelegramBotAPI, то концепция хэндлеров (обработчиков событий) вам сразу станет понятна, разница лишь в том, что в aiogram хэндлерами управляет диспетчер.
Диспетчер регистрирует функции-обработчики, дополнительно ограничивая перечень вызывающих их событий через фильтры. После получения очередного апдейта (события от Telegram), диспетчер выберет нужную функцию обработки, подходящую по всем фильтрам, например, «обработка сообщений, являющихся изображениями, в чате с ID икс и с длиной подписи игрек». Если две функции имеют одинаковые по логике фильтры, то будет вызвана та, что зарегистрирована раньше.
Чтобы зарегистрировать функцию как обработчик сообщений, нужно сделать одно из двух действий:
1. Навесить на неё декоратор, как в примере выше. С различными типами декораторов мы познакомимся позднее.
2. Напрямую вызвать метод регистрации у диспетчера или роутера.
Рассмотрим следующий код:
Давайте запустим с ним бота:
Хэндлер cmd_test2 не сработает, т.к. диспетчер о нём не знает. Исправим эту ошибку и отдельно зарегистрируем функцию:
Снова запустим бота:
Синтаксический сахар¶
Для того чтобы сделать код чище и читабельнее, aiogram расширяет возможности стандартных объектов Telegram. Например, вместо bot.send_message(. ) можно написать message.answer(. ) или message.reply(. ) . В последних двух случаях не нужно подставлять chat_id , подразумевается, что он такой же, как и в исходном сообщении.
Разница между answer и reply простая: первый метод просто отправляет сообщение в тот же чат, второй делает «ответ» на сообщение из message :
Более того, для большинства типов сообщений есть вспомогательные методы вида «answer_
что значит ‘message: types.Message’ ?
Python является интерпретируемым языком с сильной, но динамической типизацией, поэтому встроенная проверка типов, как, например, в C++ или Java, отсутствует. Однако начиная с версии 3.5 в языке появилась поддержка подсказок типов, благодаря которой различные чекеры и IDE вроде PyCharm анализируют типы используемых значений и подсказывают программисту, если он передаёт что-то не то. В данном случае подсказка types.Message соообщает PyCharm-у, что переменная message имеет тип Message , описанный в модуле types библиотеки aiogram (см. импорты в начале кода). Благодаря этому IDE может на лету подсказывать атрибуты и функции.
При вызове команды /dice бот отправит в тот же чат игральный кубик. Разумеется, если его надо отправить в какой-то другой чат, то придётся по-старинке вызывать await bot.send_dice(. ) . Но объект bot (экземпляр класса Bot) может быть недоступен в области видимости конкретной функции. В aiogram 3.x объект бота, которому пришёл апдейт, неявно прокидывается в хэндлер и его можно достать как аргумент bot . Предположим, вы хотите по команде /dice отправлять кубик не в тот же чат, а в канал с ID -100123456789. Перепишем предыдущую функцию:
Передача доп. параметров¶
Иногда при запуске бота может потребоваться передать одно или несколько дополнительных значений. Это может быть объект конфигурации, список администраторов группы, отметка времени и что угодно ещё. Для этого достаточно передать параметры как дополнительные именованные (!) аргументы функции start_polling(. ) (для вебхуков есть аналогичный способ). В хэндлерах для получения этих значений достаточно указать их как те же аргументы. Более того, изменение таких объектов в одних хэндлерах влияют на их содержимое в других. Рассмотрим на примере:
Теперь список mylist можно читать и писать в разных хэндлерах. Существует также ещё один вариант, более подходящий в других ситуациях. Речь, конечно же, о мидлварях, про которые подробно рассказывается в соответствующей главе.
Файлы конфигурации¶
Чтобы не хранить токен прямо в коде (вдруг вы захотите залить своего бота в публичный репозиторий?) можно вынести подобные данные в отдельный конфигурационный файл. Существует хорошее и адекватное мнение, что для прода достаточно переменных окружения, однако в рамках этой книги мы будем пользоваться отдельными файлами .env , чтобы немного упростить себе жизнь и сэкономить читателям время на разворачивание демонстрационного проекта.
Итак, создадим рядом с bot.py отдельный файл config_reader.py со следующим содержимым
Теперь немного отредактируем наш bot.py :
Наконец, создадим файл .env (с точкой в начале), где опишем токен бота:
Если всё сделано правильно, то при запуске python-dotenv подгрузит переменные из файла .env , pydantic их провалидирует и объект бота успешно создастся с нужным токеном.
На этом мы закончим знакомство с библиотекой, а в следующих главах рассмотрим другие «фишки» aiogram и Telegram Bot API.
Name already in use
aiogram / aiogram / dispatcher / dispatcher.py /
- Go to file T
- Go to line L
- Go to definition R
- Copy path
- Copy permalink
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
[AIOGram | Python] Урок 1. Вступление. Простой бот
Привет! Как-то захотел я сделать своего бота в телеграме. Ну, знаете. Есть свой канал, пара чатов, знаю Python. Но скажу честно, первые попытки были заброшены. Оказалось, что в разработке ботов не было единого подхода, а найти хороший фреймворк оказалось сложнее, чем казалось. Или я не особо внимательный. Но в начале 2021 я нашел свой идеал. Это AIOGram.
А теперь я решил совместить приятное с полезным, так что буду писать какие-то нововведения для бота параллельно документируя их для сайта. Такая себе коллаборация с самим собой для получения побочных продуктов)
AIOGram быстрый старт
Создаём простой проект в PyCharm, ждём завершения и открываем main.py. Его содержимое нас не интересует, так что удаляем. Вместо этого пишем:
Дабы почувствовать всю прелесть разработки в PyCharm – используем Context Action для импорта фреймрворка. Ставим указатель на aiogram и нажимаем Alt + Enter, и выбираем Install Package.
Если что-то не получилось, то необходимые библиотеки можно установить через Python Packages.
В будущем мы создадим файлик requirements.txt, в котором будут прописаны все необходимые библиотеки для автоматической установки. А токен и другие важные переменные вынесем в .env файл. Но для простоты эти шаги пока опустим.
Далее пишем следующее:
Переменная с токеном должна содержать токен вашего бота, который можно получить в специальном боте @BotFather при создании своего.
Так и пишите в телеге @BotFather
Как вы могли заметить, мы создали объект бота, которому передали токен. Теперь сообщения отправленные боту будут приходить нашему боту на aiogram. Dispatcher это своего рода диспетчер, которые будет выполнять множество задач по взаимодействию с ботом. В т.ч. получение сообщений.
А polling не даст завершить работу бота пока приложение активно.
Запустить можно уже, но интереса никакого. Предлагаю добавить эхо функцию.
Т.е. теперь dispatcher для любого полученного сообщения будет выполнять функцию echo. Если что-то не особо понятно, то полный код будет в конце статьи.
Проверим? Нажимаем Ctrl +Shift + F10 для запуска скрипта.
И вправду эхо
Расширяем функционал
Кстати, message_handler не только текст принимает. А любые сообщения, плюс мы можем указывать свои фильтры. Вроде сообщений от админа, личные, группа и т.д. Поддерживает он и команды. Например, эта функция будет срабатывать только при вводе команды /start. Только разместите её выше, чем echo, это важно. В ином случае сообщение перехватит эхо и до этой функции /start не дойдёт.
Уже интереснее
Добавим ещё аналогичную help, но ради интереса пропишем её ниже, чем echo:
Неа, не получилось
Как видите, старт так и срабатывает, а вот help нет. Как я и говорил. Обрабатывать мы можем только одну функцию за раз, и если какой-то обработчик соответствует, то дальнейшие будут отброшены.
Именно поэтому, когда мы пишем /start не срабатывает echo. И именно поэтому не сработал help. Потому что echo собирает все сообщения, которые не /start. Переместим help куда-то выше и попробуем снова.
Прекрасно!
Кстати, можно указать ещё и фильтр на тип сообщения. Стикер, аудио, файл. А можно даже прописывать особые состояния, благодаря которым бот будет ожидать от пользователя конкретных действий. И, конечно же, мы всё это попробуем дальше. А пока вы можете прописать набор каких-то команд и насладиться своим собственным ботом (пока активна IDE, как только выключите, то и бот отвечать перестанет)