Files
remnawave-bedolaga-telegram…/middlewares.py
2025-08-09 06:59:52 +03:00

185 lines
7.0 KiB
Python

from aiogram import BaseMiddleware
from aiogram.types import TelegramObject, User as TgUser, Message, CallbackQuery
from typing import Callable, Dict, Any, Awaitable
import logging
from database import Database, User
from config import Config
logger = logging.getLogger(__name__)
class DatabaseMiddleware(BaseMiddleware):
def __init__(self, db: Database):
self.db = db
async def __call__(
self,
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: TelegramObject,
data: Dict[str, Any]
) -> Any:
data['db'] = self.db
return await handler(event, data)
class UserMiddleware(BaseMiddleware):
def __init__(self, db: Database, config: Config):
self.db = db
self.config = config
async def __call__(
self,
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: TelegramObject,
data: Dict[str, Any]
) -> Any:
telegram_user: TgUser = data.get('event_from_user')
if telegram_user and not telegram_user.is_bot:
try:
user = await self.db.get_user_by_telegram_id(telegram_user.id)
if not user:
is_admin = telegram_user.id in self.config.ADMIN_IDS
user = await self.db.create_user(
telegram_id=telegram_user.id,
username=telegram_user.username,
first_name=telegram_user.first_name,
last_name=telegram_user.last_name,
language='',
is_admin=is_admin
)
logger.info(f"Created new user: {telegram_user.id} without language")
else:
updated = False
if user.username != telegram_user.username:
user.username = telegram_user.username
updated = True
if user.first_name != telegram_user.first_name:
user.first_name = telegram_user.first_name
updated = True
if user.last_name != telegram_user.last_name:
user.last_name = telegram_user.last_name
updated = True
should_be_admin = telegram_user.id in self.config.ADMIN_IDS
if user.is_admin != should_be_admin:
user.is_admin = should_be_admin
updated = True
if updated:
await self.db.update_user(user)
data['user'] = user
data['lang'] = user.language if user.language and user.language != '' else self.config.DEFAULT_LANGUAGE
except Exception as e:
logger.error(f"Error in UserMiddleware: {e}")
class FallbackUser:
def __init__(self, telegram_id: int, username: str = None, config: Config = None):
self.telegram_id = telegram_id
self.username = username
self.first_name = None
self.last_name = None
self.language = config.DEFAULT_LANGUAGE if config else 'ru'
self.balance = 0.0
self.is_admin = telegram_id in (config.ADMIN_IDS if config else [])
self.remnawave_uuid = None
try:
fallback_user = FallbackUser(telegram_user.id, telegram_user.username, self.config)
data['user'] = fallback_user
data['lang'] = self.config.DEFAULT_LANGUAGE
except:
data['user'] = None
data['lang'] = self.config.DEFAULT_LANGUAGE
else:
data['user'] = None
data['lang'] = self.config.DEFAULT_LANGUAGE
return await handler(event, data)
class LoggingMiddleware(BaseMiddleware):
async def __call__(
self,
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: TelegramObject,
data: Dict[str, Any]
) -> Any:
telegram_user: TgUser = data.get('event_from_user')
if isinstance(event, Message):
username = f"@{telegram_user.username}" if telegram_user and telegram_user.username else "no_username"
user_id = telegram_user.id if telegram_user else "unknown"
text = event.text or "no_text"
logger.info(f"Message from {user_id} ({username}): {text}")
elif isinstance(event, CallbackQuery):
username = f"@{telegram_user.username}" if telegram_user and telegram_user.username else "no_username"
user_id = telegram_user.id if telegram_user else "unknown"
callback_data = event.data or "no_data"
logger.info(f"Callback from {user_id} ({username}): {callback_data}")
return await handler(event, data)
class ThrottlingMiddleware(BaseMiddleware):
def __init__(self, rate_limit: float = 1.0):
self.rate_limit = rate_limit
self.user_last_action = {}
async def __call__(
self,
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: TelegramObject,
data: Dict[str, Any]
) -> Any:
telegram_user: TgUser = data.get('event_from_user')
if telegram_user:
import time
current_time = time.time()
user_id = telegram_user.id
if user_id in self.user_last_action:
if current_time - self.user_last_action[user_id] < self.rate_limit:
logger.warning(f"Throttling user {user_id}")
return
self.user_last_action[user_id] = current_time
return await handler(event, data)
class WorkflowDataMiddleware(BaseMiddleware):
async def __call__(
self,
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: TelegramObject,
data: Dict[str, Any]
) -> Any:
if hasattr(event, 'bot'):
dp = getattr(event.bot, '_dispatcher', None)
if dp and hasattr(dp, 'workflow_data'):
workflow_data = dp.workflow_data
for key, value in workflow_data.items():
if key not in data:
data[key] = value
return await handler(event, data)
class BotMiddleware(BaseMiddleware):
def __init__(self, bot):
self.bot = bot
async def __call__(
self,
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: TelegramObject,
data: Dict[str, Any]
) -> Any:
data['bot'] = self.bot
return await handler(event, data)