diff --git a/app/webapi/routes/miniapp.py b/app/webapi/routes/miniapp.py index 6a158550..9ebdec4b 100644 --- a/app/webapi/routes/miniapp.py +++ b/app/webapi/routes/miniapp.py @@ -2085,69 +2085,39 @@ async def get_subscription_details( user = await get_user_by_telegram_id(db, telegram_id) purchase_url = (settings.MINIAPP_PURCHASE_URL or "").strip() - - if not user: - bot_username = settings.get_bot_username() - detail: Dict[str, Any] = { - "code": "user_not_registered", - "message": "User is not registered in the bot", - } - if bot_username: - detail["bot_url"] = f"https://t.me/{bot_username}" + if not user or not user.subscription: + detail: Union[str, Dict[str, str]] = "Subscription not found" if purchase_url: - detail["purchase_url"] = purchase_url - detail["title"] = "Registration required" + detail = { + "message": "Subscription not found", + "purchase_url": purchase_url, + } raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=detail, ) subscription = user.subscription - - traffic_used = 0.0 - traffic_limit = 0 + traffic_used = _format_gb(subscription.traffic_used_gb) + traffic_limit = subscription.traffic_limit_gb or 0 lifetime_used = _bytes_to_gb(getattr(user, "lifetime_used_traffic_bytes", 0)) - status_actual = "inactive" - subscription_status_value = "inactive" - subscription_type_value = "none" - subscription_id = 0 - remnawave_short_uuid: Optional[str] = None - subscription_url: Optional[str] = None - subscription_crypto_link: Optional[str] = None - happ_redirect_link: Optional[str] = None - links_payload: Dict[str, Any] = {} - connected_squads: List[str] = [] - connected_servers: List[MiniAppConnectedServer] = [] - links: List[str] = [] - ss_conf_links: Dict[str, str] = {} + status_actual = subscription.actual_status + links_payload = await _load_subscription_links(subscription) - if subscription: - traffic_used = _format_gb(subscription.traffic_used_gb) - traffic_limit = subscription.traffic_limit_gb or 0 - status_actual = subscription.actual_status - subscription_status_value = subscription.status - subscription_type_value = "trial" if subscription.is_trial else "paid" - subscription_id = subscription.id - remnawave_short_uuid = subscription.remnawave_short_uuid - links_payload = await _load_subscription_links(subscription) - subscription_url = ( - links_payload.get("subscription_url") - or subscription.subscription_url - ) - subscription_crypto_link = ( - links_payload.get("happ_crypto_link") - or subscription.subscription_crypto_link - ) - happ_redirect_link = get_happ_cryptolink_redirect_link( - subscription_crypto_link - ) - connected_squads = list(subscription.connected_squads or []) - connected_servers = await _resolve_connected_servers(db, connected_squads) - links = links_payload.get("links") or connected_squads - ss_conf_links = links_payload.get("ss_conf_links") or {} + subscription_url = links_payload.get("subscription_url") or subscription.subscription_url + subscription_crypto_link = ( + links_payload.get("happ_crypto_link") + or subscription.subscription_crypto_link + ) + happ_redirect_link = get_happ_cryptolink_redirect_link(subscription_crypto_link) + + connected_squads: List[str] = list(subscription.connected_squads or []) + connected_servers = await _resolve_connected_servers(db, connected_squads) devices_count, devices = await _load_devices_info(user) + links: List[str] = links_payload.get("links") or connected_squads + ss_conf_links: Dict[str, str] = links_payload.get("ss_conf_links") or {} transactions_query = ( select(Transaction) @@ -2357,11 +2327,11 @@ async def get_subscription_details( ), language=user.language, status=user.status, - subscription_status=subscription_status_value, + subscription_status=subscription.status, subscription_actual_status=status_actual, status_label=_status_label(status_actual), - expires_at=subscription.end_date if subscription else None, - device_limit=subscription.device_limit if subscription else 0, + expires_at=subscription.end_date, + device_limit=subscription.device_limit, traffic_used_gb=round(traffic_used, 2), traffic_used_label=_format_gb_label(traffic_used), traffic_limit_gb=traffic_limit, @@ -2376,8 +2346,8 @@ async def get_subscription_details( referral_info = await _build_referral_info(db, user) return MiniAppSubscriptionResponse( - subscription_id=subscription_id, - remnawave_short_uuid=remnawave_short_uuid, + subscription_id=subscription.id, + remnawave_short_uuid=subscription.remnawave_short_uuid, user=response_user, subscription_url=subscription_url, subscription_crypto_link=subscription_crypto_link, @@ -2410,8 +2380,8 @@ async def get_subscription_details( total_spent_kopeks=total_spent_kopeks, total_spent_rubles=round(total_spent_kopeks / 100, 2), total_spent_label=settings.format_price(total_spent_kopeks), - subscription_type=subscription_type_value, - autopay_enabled=bool(subscription.autopay_enabled) if subscription else False, + subscription_type="trial" if subscription.is_trial else "paid", + autopay_enabled=bool(subscription.autopay_enabled), branding=settings.get_miniapp_branding(), faq=faq_payload, legal_documents=legal_documents_payload, diff --git a/miniapp/index.html b/miniapp/index.html index 501b4649..f99c02b6 100644 --- a/miniapp/index.html +++ b/miniapp/index.html @@ -331,31 +331,6 @@ min-width: 220px; } - .register-callout { - margin-top: 24px; - padding: 20px; - border-radius: var(--radius-xl); - background: linear-gradient(135deg, rgba(var(--primary-rgb), 0.12), rgba(var(--primary-rgb), 0.04)); - box-shadow: var(--shadow-sm); - display: flex; - flex-direction: column; - gap: 12px; - align-items: center; - text-align: center; - } - - .register-callout-title { - font-size: 18px; - font-weight: 700; - color: var(--text-primary); - } - - .register-callout-text { - font-size: 14px; - color: var(--text-secondary); - line-height: 1.5; - } - /* Cards */ .card { background: var(--bg-secondary); @@ -371,44 +346,6 @@ transform: translateY(-2px); } - .no-subscription-card { - display: flex; - align-items: center; - gap: 18px; - padding: 20px; - border: 1px solid rgba(var(--primary-rgb), 0.18); - background: linear-gradient(135deg, rgba(var(--primary-rgb), 0.1), rgba(var(--primary-rgb), 0.02)); - } - - .no-subscription-icon { - font-size: 32px; - line-height: 1; - } - - .no-subscription-content { - display: flex; - flex-direction: column; - gap: 10px; - } - - .no-subscription-title { - font-size: 18px; - font-weight: 700; - color: var(--text-primary); - } - - .no-subscription-text { - font-size: 14px; - color: var(--text-secondary); - line-height: 1.5; - } - - .no-subscription-actions { - display: flex; - gap: 12px; - flex-wrap: wrap; - } - .card-header { padding: 16px; cursor: pointer; @@ -769,16 +706,6 @@ color: #fff; } - :root[data-theme="dark"] .register-callout { - background: linear-gradient(135deg, rgba(var(--primary-rgb), 0.2), rgba(var(--primary-rgb), 0.08)); - box-shadow: var(--shadow-md); - } - - :root[data-theme="dark"] .no-subscription-card { - border-color: rgba(var(--primary-rgb), 0.32); - background: linear-gradient(135deg, rgba(var(--primary-rgb), 0.28), rgba(var(--primary-rgb), 0.1)); - } - .subscription-purchase-card { position: relative; margin-top: 16px; @@ -4286,11 +4213,6 @@