Обработчики и аргументы#
Обработчик (handler, хэндлер) - это асинхронная функция, которая выполняется в ответ на входящее событие (Update), прошедшее через все фильтры.
Регистрация#
Обработчики регистрируются через декораторы на роутере или диспетчере. В декоратор можно передать один или несколько фильтров.
from maxo.routing.ctx import Ctx
from maxo.routing.filters import Command, CommandStart
from maxo.types import MessageCreated
# Оба варианта эквивалентны:
@router.message_created(CommandStart())
# или
# @router.message_created(Command("start"))
async def my_handler(update: MessageCreated, ctx: Ctx):
...
Аргументы#
maxo автоматически внедряет аргументы в функцию-обработчик на основе их имен (ключей в ctx). Основные доступные аргументы:
Объект обновления (первый позиционный аргумент): типизированный объект события, например
MessageCreated,MessageCallback. Содержит все данные, пришедшие от API.ctx: Ctx- контекст выполнения. Словарь-подобный объект, который живет в рамках обработки одного обновления. В нем хранятся ссылки наbot,update, а также любые данные, добавленные мидлварями.facade- обёртка над обновлением. Тип зависит от события:MessageCreatedFacade,MessageCallbackFacadeи так далее (общий базовый класс -BaseUpdateFacade). Подробнее в разделе Фасады.fsm_context: FSMContext- контекст конечного автомата (FSM). Доступен, если FSM активирован. Подробнее в разделе Состояния (FSM).
from maxo.routing.ctx import Ctx
from maxo.types import MessageCreated
@router.message_created()
async def echo(update: MessageCreated, ctx: Ctx):
await update.answer_text(update.message.body.text or "Текста нет")
Dependency Injection (DI)#
Вы можете передавать произвольные данные в обработчики через фильтры и мидлвари.
Через фильтры: если фильтр изменяет
ctx, эти данные будут добавлены в аргументы обработчика.Через мидлвари: мидлварь может изменить
ctx, добавляя новые значения.
from maxo import Bot
from maxo.omit import is_defined
from maxo.routing.ctx import Ctx
from maxo.routing.filters import BaseFilter
from maxo.types import MessageCreated
from maxo.types import User
# Пример фильтра, который возвращает данные пользователя.
# get_user_from_db - ваша функция загрузки пользователя из БД.
class UserFilter(BaseFilter[MessageCreated]):
async def __call__(self, update: MessageCreated, ctx: Ctx) -> bool:
sender = update.message.sender
if not is_defined(sender):
return False
user = await get_user_from_db(sender.user_id)
if user:
ctx["user"] = user # Передаём user в обработчик
return True
return False
@router.message_created(UserFilter())
async def handler(update: MessageCreated, user: User, ctx: Ctx):
# Аргумент user будет автоматически передан из фильтра
bot: Bot = ctx["bot"]
await bot.send_message(user.user_id, f"Hello, {user.first_name}!")
Возвращаемые значения#
Обычно обработчики ничего не возвращают (None). Однако вы можете вернуть специальные значения для управления потоком (например, UNHANDLED для пропуска обработки, или вызвать исключение SkipHandler).