From f6bc671add1d028b835fe3755f3db9115559ace2 Mon Sep 17 00:00:00 2001 From: ITQ Date: Wed, 19 Feb 2025 14:37:33 +0300 Subject: [PATCH] feat(telegram_bot): added middlewares folder --- .../telegram_bot/middlewares/__init__.py | 0 .../services/telegram_bot/middlewares/auth.py | 43 +++++++++++++++++++ .../telegram_bot/middlewares/throttling.py | 24 +++++++++++ 3 files changed, 67 insertions(+) create mode 100644 solution/services/telegram_bot/middlewares/__init__.py create mode 100644 solution/services/telegram_bot/middlewares/auth.py create mode 100644 solution/services/telegram_bot/middlewares/throttling.py diff --git a/solution/services/telegram_bot/middlewares/__init__.py b/solution/services/telegram_bot/middlewares/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/solution/services/telegram_bot/middlewares/auth.py b/solution/services/telegram_bot/middlewares/auth.py new file mode 100644 index 0000000..d7fecec --- /dev/null +++ b/solution/services/telegram_bot/middlewares/auth.py @@ -0,0 +1,43 @@ +from collections.abc import Awaitable, Callable +from typing import Any + +from aiogram import BaseMiddleware +from aiogram.fsm.context import FSMContext +from aiogram.types import Message + +from api.client import AdNovaClient +from api.errors import HTTPError + + +class AuthMiddleware(BaseMiddleware): + def __init__(self) -> None: + pass + + async def __call__( + self, + handler: Callable[[Message, dict[str, Any]], Awaitable[Any]], + event: Message, + data: dict[str, Any], + ) -> Any: + state: FSMContext = data["state"] + state_data = await state.get_data() + + if "advertiser_id" in state_data: + advertiser_id = state_data["advertiser_id"] + async with AdNovaClient() as client: + try: + advertiser = await client.get_advertiser(advertiser_id) + state_data["authenticated"] = True + state_data["advertiser"] = advertiser.model_dump( + mode="json" + ) + except HTTPError: + state_data["authenticated"] = False + state_data["advertiser_id"] = None + else: + state_data["authenticated"] = False + state_data["advertiser_id"] = None + + await state.set_data(state_data) + + return await handler(event, data) diff --git a/solution/services/telegram_bot/middlewares/throttling.py b/solution/services/telegram_bot/middlewares/throttling.py new file mode 100644 index 0000000..37adb23 --- /dev/null +++ b/solution/services/telegram_bot/middlewares/throttling.py @@ -0,0 +1,24 @@ +from collections.abc import Awaitable, Callable +from typing import Any + +from aiogram import BaseMiddleware +from aiogram.types import Message +from cachetools import TTLCache + + +class ThrottlingMiddleware(BaseMiddleware): + def __init__(self, time_limit: float = 2) -> None: + self.limit = TTLCache(maxsize=10_000, ttl=time_limit) + + async def __call__( + self, + handler: Callable[[Message, dict[str, Any]], Awaitable[Any]], + event: Message, + data: dict[str, Any], + ) -> Any | None: + if event.chat.id in self.limit: + return None + + self.limit[event.chat.id] = None + + return await handler(event, data)