Files
Solo_bot/middlewares/user.py
T

70 lines
2.3 KiB
Python

from collections.abc import Awaitable, Callable
from time import monotonic
from typing import Any
from aiogram import BaseMiddleware
from aiogram.types import TelegramObject, User
from database import upsert_user
from logger import logger
class UserMiddleware(BaseMiddleware):
def __init__(self, debounce_sec: float = 60.0) -> None:
self._debounce = float(debounce_sec)
self._cache: dict[int, tuple[str, float, dict | None]] = {}
async def __call__(
self,
handler: Callable[[TelegramObject, dict[str, Any]], Awaitable[Any]],
event: TelegramObject,
data: dict[str, Any],
) -> Any:
try:
user: User | None = data.get("event_from_user")
if user and not user.is_bot:
session = data.get("session")
db_user = await self._process_user(user, session)
if db_user:
data["user"] = db_user
except Exception as e:
logger.error(f"Ошибка при обработке пользователя: {e}")
return await handler(event, data)
async def _process_user(self, user: User, session: Any = None) -> dict | None:
uid = user.id
fp = self._fingerprint(user)
now = monotonic()
cached = self._cache.get(uid)
if cached:
cached_fp, ts, cached_db_user = cached
if fp == cached_fp and now - ts < self._debounce:
return cached_db_user
logger.debug(f"Обработка пользователя: {uid}")
db_user = await upsert_user(
tg_id=uid,
username=user.username,
first_name=user.first_name,
last_name=user.last_name,
language_code=user.language_code,
is_bot=user.is_bot,
session=session,
only_if_exists=True,
)
self._cache[uid] = (fp, now, db_user)
if db_user:
logger.debug(f"Получены данные пользователя из БД: {uid}")
return db_user
def _fingerprint(self, user: User) -> str:
return "|".join([
str(user.id),
user.username or "",
user.first_name or "",
user.last_name or "",
user.language_code or "",
"1" if user.is_bot else "0",
])