Встроил марзбан в бекенд, исправил бывшие проблемы с получением активной подписки
This commit is contained in:
@@ -5,6 +5,10 @@ from datetime import date, datetime, time, timezone
|
||||
import logging
|
||||
from instance import User, Subscription
|
||||
|
||||
class UserAlreadyExistsError(Exception):
|
||||
"""Пользователь уже существует в системе"""
|
||||
pass
|
||||
|
||||
class MarzbanUser:
|
||||
"""Модель пользователя Marzban"""
|
||||
def __init__(self, data: Dict[str, Any]):
|
||||
@@ -78,12 +82,14 @@ class MarzbanService:
|
||||
) as response:
|
||||
|
||||
response_data = await response.json() if response.content_length else {}
|
||||
|
||||
if response.status == 409:
|
||||
raise UserAlreadyExistsError(f"User already exists: {response_data}")
|
||||
if response.status not in (200, 201):
|
||||
raise Exception(f"HTTP {response.status}: {response_data}")
|
||||
|
||||
return response_data
|
||||
|
||||
except UserAlreadyExistsError:
|
||||
raise # Пробрасываем наверх
|
||||
except aiohttp.ClientError as e:
|
||||
logging.error(f"Network error during {method.upper()} to {url}: {e}")
|
||||
raise
|
||||
@@ -91,9 +97,9 @@ class MarzbanService:
|
||||
logging.error(f"Unexpected error during request to {url}: {e}")
|
||||
raise
|
||||
|
||||
async def create_user(self, user: User, subscription: Subscription) -> MarzbanUser:
|
||||
async def create_user(self, user: User, subscription: Subscription) -> str | MarzbanUser:
|
||||
"""Создает нового пользователя в Marzban"""
|
||||
username = f"user_{user.telegram_id}"
|
||||
logging.info(f"Конец подписки пользователя {user.telegram_id} {subscription.end_date}")
|
||||
if subscription.end_date:
|
||||
if isinstance(subscription.end_date, datetime):
|
||||
if subscription.end_date.tzinfo is None:
|
||||
@@ -114,7 +120,7 @@ class MarzbanService:
|
||||
expire_timestamp = 0
|
||||
|
||||
data = {
|
||||
"username": username,
|
||||
"username": user.username,
|
||||
"status": "active",
|
||||
"expire": expire_timestamp,
|
||||
"data_limit": 100 * 1073741824, # Конвертируем GB в bytes
|
||||
@@ -139,15 +145,18 @@ class MarzbanService:
|
||||
try:
|
||||
response_data = await self._make_request("/api/user", "post", data)
|
||||
marzban_user = MarzbanUser(response_data)
|
||||
logging.info(f"User {username} created successfully")
|
||||
logging.info(f"Пользователь {user.username} успешно создан в Marzban")
|
||||
return marzban_user
|
||||
except UserAlreadyExistsError:
|
||||
logging.warning(f"Пользователь {user.telegram_id} уже существует в Marzban")
|
||||
return "USER_ALREADY_EXISTS"
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to create user {username}: {e}")
|
||||
logging.error(f"Failed to create user {user.username}: {e}")
|
||||
raise Exception(f"Failed to create user: {e}")
|
||||
|
||||
async def update_user(self, user: User, subscription: Subscription) -> MarzbanUser:
|
||||
"""Обновляет существующего пользователя"""
|
||||
username = f"user_{user.telegram_id}"
|
||||
username = user.username
|
||||
|
||||
if subscription.end_date:
|
||||
if isinstance(subscription.end_date, datetime):
|
||||
@@ -186,7 +195,7 @@ class MarzbanService:
|
||||
|
||||
async def disable_user(self, user: User) -> bool:
|
||||
"""Отключает пользователя"""
|
||||
username = f"user_{user.telegram_id}"
|
||||
username = user.username
|
||||
|
||||
data = {
|
||||
"status": "disabled"
|
||||
@@ -202,7 +211,7 @@ class MarzbanService:
|
||||
|
||||
async def enable_user(self, user: User) -> bool:
|
||||
"""Включает пользователя"""
|
||||
username = f"user_{user.telegram_id}"
|
||||
username = user.username
|
||||
|
||||
data = {
|
||||
"status": "active"
|
||||
@@ -218,41 +227,38 @@ class MarzbanService:
|
||||
|
||||
async def delete_user(self, user: User) -> bool:
|
||||
"""Полностью удаляет пользователя из Marzban"""
|
||||
username = f"user_{user.telegram_id}"
|
||||
|
||||
try:
|
||||
await self._make_request(f"/api/user/{username}", "delete")
|
||||
logging.info(f"User {username} deleted successfully")
|
||||
await self._make_request(f"/api/user/{user.username}", "delete")
|
||||
logging.info(f"User {user.username} deleted successfully")
|
||||
return True
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to delete user {username}: {e}")
|
||||
logging.error(f"Failed to delete user {user.username}: {e}")
|
||||
return False
|
||||
|
||||
async def get_user_status(self, user: User) -> UserStatus:
|
||||
"""Получает текущий статус пользователя"""
|
||||
username = f"user_{user.telegram_id}"
|
||||
|
||||
try:
|
||||
response_data = await self._make_request(f"/api/user/{username}", "get")
|
||||
response_data = await self._make_request(f"/api/user/{user.username}", "get")
|
||||
return UserStatus(response_data)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to get status for user {username}: {e}")
|
||||
logging.error(f"Failed to get status for user {user.username}: {e}")
|
||||
raise Exception(f"Failed to get user status: {e}")
|
||||
|
||||
async def get_subscription_url(self, user: User) -> str:
|
||||
async def get_subscription_url(self, user: User) -> str | None:
|
||||
"""Возвращает готовую subscription_url для подключения"""
|
||||
username = f"user_{user.telegram_id}"
|
||||
|
||||
try:
|
||||
response_data = await self._make_request(f"/api/user/{username}", "get")
|
||||
response_data = await self._make_request(f"/api/user/{user.username}", "get")
|
||||
return response_data.get('subscription_url', '')
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to get subscription URL for user {username}: {e}")
|
||||
return ""
|
||||
logging.error(f"Failed to get subscription URL for user {user.username}: {e}")
|
||||
return None
|
||||
|
||||
async def get_config_links(self, user: User) -> str:
|
||||
"""Возвращает конфигурации для подключения"""
|
||||
username = f"user_{user.telegram_id}"
|
||||
username = user.username
|
||||
|
||||
try:
|
||||
response_data = await self._make_request(f"/api/user/{username}", "get")
|
||||
|
||||
Reference in New Issue
Block a user