from collections.abc import Awaitable, Callable from typing import Any from aiogram import BaseMiddleware from aiogram.types import CallbackQuery, Message, TelegramObject from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from config import ADMIN_ID from core.cache_config import ADMIN_CACHE_TTL_SEC from core.redis_cache import cache_get, cache_key, cache_set from database.models import Admin _ADMIN_CACHE_TTL = ADMIN_CACHE_TTL_SEC class AdminMiddleware(BaseMiddleware): """Проверяет, является ли пользователь администратором. Сессию не создаёт — только data['session'].""" _admin_ids: set[int] = set(ADMIN_ID) if isinstance(ADMIN_ID, list | tuple) else {ADMIN_ID} async def __call__( self, handler: Callable[[TelegramObject, dict[str, Any]], Awaitable[Any]], event: TelegramObject, data: dict[str, Any], ) -> Any: session: AsyncSession | None = data.get("session") data["admin"] = await self._check_admin_access(event, session) return await handler(event, data) async def _check_admin_access( self, event: TelegramObject, session: AsyncSession | None, ) -> bool: try: user_id = None if isinstance(event, Message): if event.from_user: user_id = event.from_user.id elif isinstance(event, CallbackQuery): if event.from_user: user_id = event.from_user.id else: from_user = getattr(event, "from_user", None) if from_user: user_id = getattr(from_user, "id", None) if not user_id: return False if user_id in self._admin_ids: return True cached = await cache_get(cache_key("admin_access", user_id)) if isinstance(cached, bool): return cached if not session: await cache_set(cache_key("admin_access", user_id), False, _ADMIN_CACHE_TTL) return False result = await session.execute(select(Admin).where(Admin.tg_id == user_id)) is_admin = result.scalar_one_or_none() is not None await cache_set(cache_key("admin_access", user_id), bool(is_admin), _ADMIN_CACHE_TTL) return is_admin except Exception: if session is not None: try: await session.rollback() except Exception: pass return False