Проміжні програми#

aiogram надає потужний механізм для налаштування обробників(handler) подій через проміжні програми.

Проміжні програми у фреймворку для ботів виглядають як механізм проміжних програм у веб-фреймворках, таких як aiohttp, fastapi, Django тощо) з невеликою різницею – тут реалізовано два рівні проміжного програмних програм (до та після фільтрів).

Примітка

Проміжна програма — це функція, яка запускається під час кожної події, отриманої від Telegram Bot API у багатьох точках процесу обробки.

Основні поняття#

Більшість книг та Інтернет-джерел стверджують:

Проміжна програма — це програма, багаторазового використання, що використовує шаблони та фреймворки для ліквідування розриву між функціональними вимогами додатків і основними операційними системами, стеками мережевих протоколів і базами даних.

Проміжна програма може змінювати, розширювати або відхиляти подію обробки у багатьох точках процесу обробки.

Основи#

Екземпляр проміжної програми можна застосувати для кожного типу події Telegram (оновлення, повідомлення тощо) у двох місцях

  1. Зовнішня область - перед обробкою фільтрами (<router>.<event>.outer_middleware(...))

  2. Внутрішня область – після обробки фільтрами, але перед обробником (handler) (<router>.<event>.middleware(...))

Основи проміжних програм

Увага

Проміжна програма має бути підкласом BaseMiddleware (from aiogram import BaseMiddleware) або будь-якою асинхронною функцією

Специфікація аргументів#

class aiogram.dispatcher.middlewares.base.BaseMiddleware[source]#

Основа: ABC

Узагальнений клас проміжних програм

abstract async __call__(handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], event: TelegramObject, data: Dict[str, Any]) Any[source]#

Виконання проміжної програми

Параметри:
  • handler – Обробник (handler), обгорнутий у ланцюжок проміжних програм

  • event – Вхідна подія (підклас aiogram.types.base.TelegramObject)

  • data – Контекстні дані. Будуть зіставлені з аргументами обробника

Повертає:

Any

Приклади#

Небезпека

Middleware should always call await handler(event, data) to propagate event for next middleware/handler. If you want to stop processing event in middleware you should not call await handler(event, data).

Класово орієнтований#

from aiogram import BaseMiddleware
from aiogram.types import Message


class CounterMiddleware(BaseMiddleware):
    def __init__(self) -> None:
        self.counter = 0

    async def __call__(
        self,
        handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]],
        event: Message,
        data: Dict[str, Any]
    ) -> Any:
        self.counter += 1
        data['counter'] = self.counter
        return await handler(event, data)

і тоді

router = Router()
router.message.middleware(CounterMiddleware())

Функціонально-орієнтований#

@dispatcher.update.outer_middleware()
async def database_transaction_middleware(
    handler: Callable[[Update, Dict[str, Any]], Awaitable[Any]],
    event: Update,
    data: Dict[str, Any]
) -> Any:
    async with database.transaction():
        return await handler(event, data)

Факти#

  1. Проміжні програми із зовнішньої області викликатимуться під час кожної вхідної події

  2. Проміжні програми із внутрішньої області викликатимуться лише після проходження фільтрів

  3. Внутрішні проміжні програми викликають тип події aiogram.types.update.Update , через те, що всі вхідні оновлення надходять до обробника (handler) певного типу подій через вбудований обробник (handler) оновлень