Files
Solo_bot/middlewares/loggings.py
T

59 lines
2.2 KiB
Python

import asyncio
from collections.abc import Awaitable, Callable
from typing import Any, TypedDict
from aiogram import BaseMiddleware
from aiogram.types import CallbackQuery, InlineQuery, Message, TelegramObject, User
from logger import logger
class UserInfo(TypedDict):
user_id: int | None
username: str | None
action: str | None
def _log_activity_sync(user_info: UserInfo) -> None:
"""Синхронный вывод в лог, чтобы не блокировать event loop в create_task."""
logger.info(
f"Активность пользователя │ "
f"ID: {str(user_info['user_id']).ljust(10)}"
f"Имя: {user_info['username'] or '':<15}"
f"Действие: {user_info['action'] or ''}"
)
class LoggingMiddleware(BaseMiddleware):
"""Middleware для логирования действий пользователя. Лог пишется в фоне, не задерживая обработчик."""
async def __call__(
self,
handler: Callable[[TelegramObject, dict[str, Any]], Awaitable[Any]],
event: TelegramObject,
data: dict[str, Any],
) -> Any:
user_info = self._extract_user_info(event)
if user_info["user_id"]:
asyncio.create_task(asyncio.to_thread(_log_activity_sync, user_info))
return await handler(event, data)
def _extract_user_info(self, event: TelegramObject) -> UserInfo:
"""Извлекает информацию о пользователе из различных типов событий."""
result: UserInfo = {"user_id": None, "username": None, "action": None}
if hasattr(event, "from_user") and isinstance(event.from_user, User):
result["user_id"] = event.from_user.id
result["username"] = event.from_user.username
if isinstance(event, Message):
result["action"] = f"Сообщение: {event.text}"
elif isinstance(event, CallbackQuery):
result["action"] = f"Обратный вызов: {event.data}"
elif isinstance(event, InlineQuery):
result["action"] = f"Inline запрос: {event.query}"
return result