Files

118 lines
3.8 KiB
Python

from __future__ import annotations
from typing import Any
import structlog
from sqlalchemy.ext.asyncio import AsyncSession
from app.config import settings
from app.database.crud.subscription import get_active_subscriptions_by_user_id
from app.database.models import User
from app.services.subscription_service import SubscriptionService
logger = structlog.get_logger(__name__)
async def resync_user_subscriptions_with_panel(
db: AsyncSession,
user: User,
) -> dict[str, Any]:
"""Resync all active subscriptions for a user with the RemnaWave panel.
Should be called after any identity change (TG linking, account merge,
email verification) to ensure the panel has up-to-date telegram_id,
email, and squads.
Returns a stats dict with keys:
synced - number of subscriptions successfully synced
failed - number of subscriptions that failed to sync
total - total number of active subscriptions found
skipped - True when the panel is not configured
"""
service = SubscriptionService()
service._refresh_configuration()
if not service.is_configured:
logger.warning(
'remnawave_resync: panel not configured, skipping resync',
user_id=user.id,
config_error=service.configuration_error,
)
return {'synced': 0, 'failed': 0, 'total': 0, 'skipped': True}
subscriptions = await get_active_subscriptions_by_user_id(db, int(user.id))
if not subscriptions:
logger.info(
'remnawave_resync: no active subscriptions found',
user_id=user.id,
)
return {'synced': 0, 'failed': 0, 'total': 0, 'skipped': False}
synced = 0
failed = 0
for subscription in subscriptions:
# Eagerly refresh tariff to avoid lazy-loading in async context.
try:
await db.refresh(subscription, ['tariff'])
except Exception as exc:
logger.debug(
'remnawave_resync: could not refresh tariff for subscription',
subscription_id=subscription.id,
error=exc,
)
# Determine whether a panel user already exists for this subscription.
if settings.is_multi_tariff_enabled():
panel_user_exists = bool(subscription.remnawave_uuid)
else:
panel_user_exists = bool(user.remnawave_uuid)
try:
if panel_user_exists:
result = await service.update_remnawave_user(
db,
subscription,
sync_squads=True,
)
else:
result = await service.create_remnawave_user(db, subscription)
if result is not None:
synced += 1
logger.info(
'remnawave_resync: subscription synced',
subscription_id=subscription.id,
user_id=user.id,
action='update' if panel_user_exists else 'create',
)
else:
failed += 1
logger.warning(
'remnawave_resync: subscription sync returned None',
subscription_id=subscription.id,
user_id=user.id,
action='update' if panel_user_exists else 'create',
)
except Exception as exc:
failed += 1
logger.error(
'remnawave_resync: unexpected error syncing subscription',
subscription_id=subscription.id,
user_id=user.id,
error=exc,
)
total = len(subscriptions)
logger.info(
'remnawave_resync: completed',
user_id=user.id,
total=total,
synced=synced,
failed=failed,
)
return {'synced': synced, 'failed': failed, 'total': total, 'skipped': False}