mirror of
https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
synced 2026-02-16 00:50:31 +00:00
185 lines
7.0 KiB
Python
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)
|