from typing import Callable, Awaitable, Any, Dict, Optional from aiogram import BaseMiddleware from aiogram.filters.command import CommandObject from aiogram.types import TelegramObject, Message from middleware.loggers import logger class ReferralMiddleware(BaseMiddleware): """ Middleware для перехвата и обработки реферальных ссылок (?start=...). Основные задачи: - Отслеживание перехода по deep-link (например, /start ref123) - Централизованное логирование - Возможность передачи кода дальше в хендлеры - Подготовка к сохранению кода в базу данных """ async def __call__( self, handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]], event: TelegramObject, data: Dict[str, Any], ) -> Any: """ Перехватывает входящие сообщения и извлекает deep-link аргумент, если пользователь зашёл по реферальной ссылке. Args: handler: Следующий обработчик в цепочке middleware event: Входящее событие (Message, CallbackQuery и др.) data: Контекстные данные, доступные хендлеру Returns: Результат работы следующего обработчика """ # Проверяем, что событие — это именно сообщение if isinstance(event, Message): # Извлекаем объект команды (если был установлен фильтр CommandStart) command: Optional[CommandObject] = data.get("command") # Проверяем, что это именно команда /start с аргументом if command and command.command.casefold() == "start" and command.args: ref_code: str = command.args user_id: int = event.from_user.id username: Optional[str] = event.from_user.username # 👉 Здесь можно сохранить код в БД logger.debug( f"[Referral] user={user_id}, username={username}, ref={ref_code}" ) # Пробрасываем реф-код в data, чтобы использовать в хендлере data["ref_code"] = ref_code # Передаём управление дальше return await handler(event, data)