Files
telegram-helper-bot/.cursor/rules/middleware-patterns.md
Andrey d2d7c83575 Обновлен Python до версии 3.11.9 и изменены зависимости в Dockerfile и pyproject.toml. Удалены устаревшие файлы RATE_LIMITING_SOLUTION.md и тесты для rate limiting.
Обновлены пути к библиотекам в Dockerfile для соответствия новой версии Python.
Исправлены все тесты, теперь все проходят
2026-01-25 16:07:27 +03:00

3.7 KiB
Raw Permalink Blame History

description, globs
description globs
Паттерны создания и использования middleware в aiogram
helper_bot/middlewares/**/*.py

Паттерны Middleware

Структура Middleware

Все middleware наследуются от aiogram.BaseMiddleware:

from typing import Any, Dict
from aiogram import BaseMiddleware
from aiogram.types import TelegramObject

class CustomMiddleware(BaseMiddleware):
    """Описание middleware."""
    
    async def __call__(
        self,
        handler: Callable,
        event: TelegramObject,
        data: Dict[str, Any]
    ) -> Any:
        # Логика до обработки handler
        ...
        
        # Вызов следующего handler в цепочке
        result = await handler(event, data)
        
        # Логика после обработки handler
        ...
        
        return result

Порядок регистрации Middleware

В main.py middleware регистрируются в следующем порядке (важно!):

# 1. DependenciesMiddleware - внедрение зависимостей
dp.update.outer_middleware(DependenciesMiddleware())

# 2. MetricsMiddleware - сбор метрик
dp.update.outer_middleware(MetricsMiddleware())

# 3. BlacklistMiddleware - проверка черного списка
dp.update.outer_middleware(BlacklistMiddleware())

# 4. RateLimitMiddleware - ограничение частоты запросов
dp.update.outer_middleware(RateLimitMiddleware())

DependenciesMiddleware

Внедряет глобальные зависимости во все handlers:

class DependenciesMiddleware(BaseMiddleware):
    async def __call__(self, handler, event: TelegramObject, data: Dict[str, Any]) -> Any:
        bdf = get_global_instance()
        
        # Внедрение зависимостей
        if 'bot_db' not in data:
            data['bot_db'] = bdf.get_db()
        if 'settings' not in data:
            data['settings'] = bdf.settings
        
        return await handler(event, data)

Обработка ошибок в Middleware

class CustomMiddleware(BaseMiddleware):
    async def __call__(self, handler, event, data):
        try:
            # Предобработка
            ...
            result = await handler(event, data)
            # Постобработка
            ...
            return result
        except Exception as e:
            # Обработка ошибок
            logger.error(f"Ошибка в middleware: {e}")
            # Решаем: пробрасывать дальше или обработать
            raise

Регистрация на уровне Router

Middleware можно регистрировать на уровне конкретного router:

router = Router()
router.message.middleware(SomeMiddleware())  # Только для message handlers
router.callback_query.middleware(SomeMiddleware())  # Только для callback handlers

Best Practices

  1. Регистрируйте middleware в правильном порядке - зависимости должны быть первыми
  2. Не изменяйте event напрямую, используйте data для передачи информации
  3. Обрабатывайте ошибки в middleware, но не глотайте их без логирования
  4. Используйте outer_middleware для глобальной регистрации
  5. Используйте router.middleware() для локальной регистрации на уровне модуля