Обработчики и аргументы#

Обработчик (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). Основные доступные аргументы:

  1. Объект обновления (первый позиционный аргумент): типизированный объект события, например MessageCreated, MessageCallback. Содержит все данные, пришедшие от API.

  2. ctx: Ctx - контекст выполнения. Словарь-подобный объект, который живет в рамках обработки одного обновления. В нем хранятся ссылки на bot, update, а также любые данные, добавленные мидлварями.

  3. facade - обёртка над обновлением. Тип зависит от события: MessageCreatedFacade, MessageCallbackFacade и так далее (общий базовый класс - BaseUpdateFacade). Подробнее в разделе Фасады.

  4. 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)#

Вы можете передавать произвольные данные в обработчики через фильтры и мидлвари.

  1. Через фильтры: если фильтр изменяет ctx, эти данные будут добавлены в аргументы обработчика.

  2. Через мидлвари: мидлварь может изменить 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).