diff --git a/.env.example b/.env.example index 439962de..77f05953 100644 --- a/.env.example +++ b/.env.example @@ -294,7 +294,6 @@ MINIAPP_SERVICE_NAME_EN=Bedolaga VPN MINIAPP_SERVICE_NAME_RU=Bedolaga VPN MINIAPP_SERVICE_DESCRIPTION_EN=Secure & Fast Connection MINIAPP_SERVICE_DESCRIPTION_RU=Безопасное и быстрое подключение -MINIAPP_PURCHASE_URL= # Параметры режима happ_cryptolink CONNECT_BUTTON_HAPP_DOWNLOAD_ENABLED=false diff --git a/README.md b/README.md index 8c688eaf..c1fdb9f1 100644 --- a/README.md +++ b/README.md @@ -539,7 +539,6 @@ MINIAPP_SERVICE_NAME_EN=Bedolaga VPN MINIAPP_SERVICE_NAME_RU=Bedolaga VPN MINIAPP_SERVICE_DESCRIPTION_EN=Secure & Fast Connection MINIAPP_SERVICE_DESCRIPTION_RU=Безопасное и быстрое подключение -MINIAPP_PURCHASE_URL= # Параметры режима happ_cryptolink CONNECT_BUTTON_HAPP_DOWNLOAD_ENABLED=false diff --git a/app/config.py b/app/config.py index a4057c24..773f4f45 100644 --- a/app/config.py +++ b/app/config.py @@ -217,7 +217,6 @@ class Settings(BaseSettings): MINIAPP_SERVICE_NAME_RU: str = "Bedolaga VPN" MINIAPP_SERVICE_DESCRIPTION_EN: str = "Secure & Fast Connection" MINIAPP_SERVICE_DESCRIPTION_RU: str = "Безопасное и быстрое подключение" - MINIAPP_PURCHASE_URL: str = "" CONNECT_BUTTON_HAPP_DOWNLOAD_ENABLED: bool = False HAPP_CRYPTOLINK_REDIRECT_TEMPLATE: Optional[str] = None HAPP_DOWNLOAD_LINK_IOS: Optional[str] = None diff --git a/app/webapi/routes/miniapp.py b/app/webapi/routes/miniapp.py index b6aca0a0..64bc7bd4 100644 --- a/app/webapi/routes/miniapp.py +++ b/app/webapi/routes/miniapp.py @@ -24,7 +24,6 @@ from app.utils.telegram_webapp import ( from ..dependencies import get_db_session from ..schemas.miniapp import ( - MiniAppConfigResponse, MiniAppConnectedServer, MiniAppDevice, MiniAppPromoGroup, @@ -64,11 +63,6 @@ def _format_limit_label(limit: Optional[int]) -> str: return f"{limit} GB" -def _get_purchase_url() -> Optional[str]: - value = (settings.MINIAPP_PURCHASE_URL or "").strip() - return value or None - - def _bytes_to_gb(bytes_value: Optional[int]) -> float: if not bytes_value: return 0.0 @@ -264,11 +258,6 @@ async def _load_subscription_links( return payload -@router.get("/config", response_model=MiniAppConfigResponse) -async def get_miniapp_config() -> MiniAppConfigResponse: - return MiniAppConfigResponse(purchase_url=_get_purchase_url()) - - @router.post("/subscription", response_model=MiniAppSubscriptionResponse) async def get_subscription_details( payload: MiniAppSubscriptionRequest, @@ -375,7 +364,6 @@ async def get_subscription_details( user=response_user, subscription_url=subscription_url, subscription_crypto_link=subscription_crypto_link, - purchase_url=_get_purchase_url(), links=links, ss_conf_links=ss_conf_links, connected_squads=connected_squads, diff --git a/app/webapi/schemas/miniapp.py b/app/webapi/schemas/miniapp.py index 3e644aa7..a0d5cb1a 100644 --- a/app/webapi/schemas/miniapp.py +++ b/app/webapi/schemas/miniapp.py @@ -11,10 +11,6 @@ class MiniAppBranding(BaseModel): service_description: Dict[str, Optional[str]] = Field(default_factory=dict) -class MiniAppConfigResponse(BaseModel): - purchase_url: Optional[str] = None - - class MiniAppSubscriptionRequest(BaseModel): init_data: str = Field(..., alias="initData") @@ -78,7 +74,6 @@ class MiniAppSubscriptionResponse(BaseModel): user: MiniAppSubscriptionUser subscription_url: Optional[str] = None subscription_crypto_link: Optional[str] = None - purchase_url: Optional[str] = None links: List[str] = Field(default_factory=list) ss_conf_links: Dict[str, str] = Field(default_factory=dict) connected_squads: List[str] = Field(default_factory=list) diff --git a/miniapp/index.html b/miniapp/index.html index b84030cd..fe03f136 100644 --- a/miniapp/index.html +++ b/miniapp/index.html @@ -314,19 +314,6 @@ line-height: 1.6; } - .error-actions { - margin-top: 24px; - display: flex; - justify-content: center; - } - - .error-actions .btn { - width: auto; - min-width: 200px; - padding-left: 32px; - padding-right: 32px; - } - /* Cards */ .card { background: var(--bg-secondary); @@ -771,7 +758,6 @@ overflow: hidden; text-transform: uppercase; letter-spacing: 0.5px; - text-decoration: none; } .btn::before { @@ -1200,9 +1186,6 @@
⚠️
Subscription Not Found
Please contact support to activate your subscription
- @@ -1538,7 +1521,6 @@ 'info.autopay': 'Auto-pay', 'button.connect.default': 'Connect to VPN', 'button.connect.happ': 'Connect', - 'button.buy_subscription': 'Buy subscription', 'button.copy': 'Copy subscription link', 'card.balance.title': 'Balance', 'card.history.title': 'Transaction History', @@ -1601,7 +1583,6 @@ 'info.autopay': 'Автоплатеж', 'button.connect.default': 'Подключиться к VPN', 'button.connect.happ': 'Подключиться', - 'button.buy_subscription': 'Купить подписку', 'button.copy': 'Скопировать ссылку подписки', 'card.balance.title': 'Баланс', 'card.history.title': 'История операций', @@ -1716,7 +1697,6 @@ let userData = null; let appsConfig = {}; - let miniAppConfig = {}; let currentPlatform = 'android'; let preferredLanguage = 'en'; let languageLockedByUser = false; @@ -1793,38 +1773,6 @@ textElement.textContent = message; } - function getPurchaseUrl() { - const raw = miniAppConfig?.purchase_url - || miniAppConfig?.purchaseUrl - || userData?.purchase_url - || userData?.purchaseUrl - || ''; - return typeof raw === 'string' ? raw.trim() : ''; - } - - function updateBuySubscriptionButtonVisibility(showInErrorState = false) { - const actions = document.getElementById('errorActions'); - const button = document.getElementById('buySubscriptionBtn'); - if (!actions || !button) { - return; - } - - const url = getPurchaseUrl(); - const shouldShow = Boolean(showInErrorState && url); - - if (shouldShow) { - button.href = url; - button.setAttribute('target', '_blank'); - button.setAttribute('rel', 'noopener'); - } else { - button.removeAttribute('href'); - button.removeAttribute('target'); - button.removeAttribute('rel'); - } - - actions.classList.toggle('hidden', !shouldShow); - } - function applyTranslations() { document.title = t('app.title'); document.documentElement.setAttribute('lang', preferredLanguage); @@ -1848,8 +1796,7 @@ if (!label) { return; } - const link = getConnectLink(); - const useHappLabel = typeof link === 'string' && link.startsWith('happ:'); + const useHappLabel = Boolean(userData?.happ_cryptolink_redirect_link); const key = useHappLabel ? 'button.connect.happ' : 'button.connect.default'; label.textContent = t(key); } @@ -1920,7 +1867,6 @@ } } - await loadMiniAppConfig(); await loadAppsConfig(); const initData = tg.initData || ''; @@ -1972,7 +1918,6 @@ document.getElementById('loadingState').classList.add('hidden'); document.getElementById('mainContent').classList.remove('hidden'); - updateBuySubscriptionButtonVisibility(false); // Add animation to cards document.querySelectorAll('.card').forEach((card, index) => { @@ -1986,23 +1931,6 @@ } } - async function loadMiniAppConfig() { - try { - const response = await fetch('/miniapp/config', { cache: 'no-cache' }); - if (!response.ok) { - throw new Error(`Failed to load mini app config: ${response.status}`); - } - - const data = await response.json(); - miniAppConfig = data || {}; - } catch (error) { - console.warn('Unable to load mini app config:', error); - miniAppConfig = {}; - } finally { - updateBuySubscriptionButtonVisibility(false); - } - } - async function loadAppsConfig() { try { const response = await fetch('/app-config.json', { cache: 'no-cache' }); @@ -2528,6 +2456,10 @@ return null; } + if (userData.happ_cryptolink_redirect_link) { + return userData.happ_cryptolink_redirect_link; + } + const subscriptionUrl = getCurrentSubscriptionUrl(); if (!subscriptionUrl) { return null; @@ -2584,7 +2516,6 @@ }; updateErrorTexts(); document.getElementById('errorState').classList.remove('hidden'); - updateBuySubscriptionButtonVisibility(true); updateActionButtons(); }