Format RemnaWave username with Telegram names

This commit is contained in:
yazhog
2025-09-15 15:52:04 +03:00
parent 985260144e
commit a24b5e8145
5 changed files with 46 additions and 20 deletions

View File

@@ -331,6 +331,7 @@ class RemnaWaveAPI:
async def update_user(
self,
uuid: str,
username: Optional[str] = None,
status: Optional[UserStatus] = None,
traffic_limit_bytes: Optional[int] = None,
traffic_limit_strategy: Optional[TrafficLimitStrategy] = None,
@@ -343,7 +344,10 @@ class RemnaWaveAPI:
active_internal_squads: Optional[List[str]] = None
) -> RemnaWaveUser:
data = {'uuid': uuid}
if username is not None:
data['username'] = username
if status:
data['status'] = status.value
if traffic_limit_bytes is not None:

View File

@@ -25,6 +25,7 @@ from app.database.models import MonitoringLog, SubscriptionStatus, Subscription,
from app.services.subscription_service import SubscriptionService
from app.services.payment_service import PaymentService
from app.localization.texts import get_texts
from app.utils.user_utils import build_remnawave_username
from app.external.remnawave_api import (
RemnaWaveUser, UserStatus, TrafficLimitStrategy, RemnaWaveAPIError
@@ -145,20 +146,22 @@ class MonitoringService:
is_active = (subscription.status == SubscriptionStatus.ACTIVE.value and
subscription.end_date > current_time)
if (subscription.status == SubscriptionStatus.ACTIVE.value and
if (subscription.status == SubscriptionStatus.ACTIVE.value and
subscription.end_date <= current_time):
subscription.status = SubscriptionStatus.EXPIRED.value
await db.commit()
is_active = False
logger.info(f"📝 Статус подписки {subscription.id} обновлен на 'expired'")
username_for_api = build_remnawave_username(user)
async with self.api as api:
updated_user = await api.update_user(
uuid=user.remnawave_uuid,
username=username_for_api,
status=UserStatus.ACTIVE if is_active else UserStatus.EXPIRED,
expire_at=subscription.end_date,
traffic_limit_bytes=self._gb_to_bytes(subscription.traffic_limit_gb),
traffic_limit_strategy=TrafficLimitStrategy.MONTH,
traffic_limit_strategy=TrafficLimitStrategy.MONTH,
hwid_device_limit=subscription.device_limit,
active_internal_squads=subscription.connected_squads
)

View File

@@ -7,15 +7,16 @@ import re
from app.config import settings
from app.external.remnawave_api import (
RemnaWaveAPI, RemnaWaveUser, RemnaWaveInternalSquad,
RemnaWaveAPI, RemnaWaveUser, RemnaWaveInternalSquad,
RemnaWaveNode, UserStatus, TrafficLimitStrategy, RemnaWaveAPIError
)
from app.database.crud.user import get_users_list, get_user_by_telegram_id, update_user
from app.database.crud.subscription import get_subscription_by_user_id, update_subscription_usage
from app.database.models import (
User, SubscriptionServer, Transaction, ReferralEarning,
User, SubscriptionServer, Transaction, ReferralEarning,
PromoCodeUse, SubscriptionStatus
)
from app.utils.user_utils import build_remnawave_username
logger = logging.getLogger(__name__)
@@ -767,13 +768,15 @@ class RemnaWaveService:
for user in users:
if not user.subscription:
continue
try:
subscription = user.subscription
username_for_api = build_remnawave_username(user)
if user.remnawave_uuid:
await api.update_user(
uuid=user.remnawave_uuid,
username=username_for_api,
status=UserStatus.ACTIVE if subscription.is_active else UserStatus.EXPIRED,
expire_at=subscription.end_date,
traffic_limit_bytes=subscription.traffic_limit_gb * (1024**3) if subscription.traffic_limit_gb > 0 else 0,
@@ -783,10 +786,8 @@ class RemnaWaveService:
)
stats["updated"] += 1
else:
username = f"user_{user.telegram_id}"
new_user = await api.create_user(
username=username,
username=username_for_api,
expire_at=subscription.end_date,
status=UserStatus.ACTIVE if subscription.is_active else UserStatus.EXPIRED,
traffic_limit_bytes=subscription.traffic_limit_gb * (1024**3) if subscription.traffic_limit_gb > 0 else 0,
@@ -796,11 +797,11 @@ class RemnaWaveService:
description=f"Bot user: {user.full_name}",
active_internal_squads=subscription.connected_squads
)
await update_user(db, user, remnawave_uuid=new_user.uuid)
subscription.remnawave_short_uuid = new_user.short_uuid
await db.commit()
stats["created"] += 1
except Exception as e:

View File

@@ -6,7 +6,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from app.config import settings
from app.database.models import Subscription, User, SubscriptionStatus
from app.external.remnawave_api import (
RemnaWaveAPI, RemnaWaveUser, UserStatus,
RemnaWaveAPI, RemnaWaveUser, UserStatus,
TrafficLimitStrategy, RemnaWaveAPIError
)
from app.database.crud.user import get_user_by_id
@@ -16,6 +16,7 @@ from app.utils.pricing_utils import (
calculate_prorated_price,
validate_pricing_calculation
)
from app.utils.user_utils import build_remnawave_username
logger = logging.getLogger(__name__)
@@ -48,7 +49,8 @@ class SubscriptionService:
if not validation_success:
logger.error(f"Ошибка валидации подписки для пользователя {user.telegram_id}")
return None
username_for_api = build_remnawave_username(user)
async with self.api as api:
existing_users = await api.get_user_by_telegram_id(user.telegram_id)
if existing_users:
@@ -63,6 +65,7 @@ class SubscriptionService:
updated_user = await api.update_user(
uuid=remnawave_user.uuid,
username=username_for_api,
status=UserStatus.ACTIVE,
expire_at=subscription.end_date,
traffic_limit_bytes=self._gb_to_bytes(subscription.traffic_limit_gb),
@@ -73,9 +76,8 @@ class SubscriptionService:
else:
logger.info(f"🆕 Создаем нового пользователя в панели для {user.telegram_id}")
username = f"user_{user.telegram_id}"
updated_user = await api.create_user(
username=username,
username=username_for_api,
expire_at=subscription.end_date,
status=UserStatus.ACTIVE,
traffic_limit_bytes=self._gb_to_bytes(subscription.traffic_limit_gb),
@@ -115,9 +117,9 @@ class SubscriptionService:
if not user or not user.remnawave_uuid:
logger.error(f"RemnaWave UUID не найден для пользователя {subscription.user_id}")
return None
current_time = datetime.utcnow()
is_actually_active = (subscription.status == SubscriptionStatus.ACTIVE.value and
is_actually_active = (subscription.status == SubscriptionStatus.ACTIVE.value and
subscription.end_date > current_time)
if (subscription.status == SubscriptionStatus.ACTIVE.value and
@@ -129,13 +131,16 @@ class SubscriptionService:
is_actually_active = False
logger.info(f"🔔 Статус подписки {subscription.id} автоматически изменен на 'expired'")
username_for_api = build_remnawave_username(user)
async with self.api as api:
updated_user = await api.update_user(
uuid=user.remnawave_uuid,
username=username_for_api,
status=UserStatus.ACTIVE if is_actually_active else UserStatus.EXPIRED,
expire_at=subscription.end_date,
traffic_limit_bytes=self._gb_to_bytes(subscription.traffic_limit_gb),
traffic_limit_strategy=TrafficLimitStrategy.MONTH,
traffic_limit_strategy=TrafficLimitStrategy.MONTH,
hwid_device_limit=subscription.device_limit,
active_internal_squads=subscription.connected_squads
)

View File

@@ -296,3 +296,16 @@ async def get_referral_analytics(db: AsyncSession, user_id: int) -> Dict:
},
'top_referrals': []
}
def build_remnawave_username(user: User) -> str:
"""
Формирует имя пользователя для панели RemnaWave.
Если доступны имя, фамилия и username, возвращает строку
"Имя Фамилия @username". В противном случае возвращает
"user_{telegram_id}".
"""
if user.first_name and user.last_name and user.username:
return f"{user.first_name} {user.last_name} @{user.username}"
return f"user_{user.telegram_id}"