diff --git a/bot/app/web/frontend/src/App.svelte b/bot/app/web/frontend/src/App.svelte index 8a47f8d..8ba76fd 100644 --- a/bot/app/web/frontend/src/App.svelte +++ b/bot/app/web/frontend/src/App.svelte @@ -461,6 +461,8 @@ $: trafficMode = Boolean(appSettings?.traffic_mode); $: tariffMode = plans.some((plan) => plan?.tariff_key); $: tariffCatalog = buildTariffCatalog(plans); + $: singleTariffMode = tariffMode && tariffCatalog.length === 1; + $: hasMultipleTariffs = tariffCatalog.length > 1; $: selectedTariff = tariffCatalog.find((tariff) => tariff.key === selectedTariffKey) || null; $: selectedTariffPlans = tariffMode ? (selectedTariffKey ? plans.filter((plan) => plan?.tariff_key === selectedTariffKey) : []) : plans; $: devicesEnabled = Boolean(appSettings?.my_devices_enabled); @@ -498,10 +500,15 @@ $: applyFavicon(CFG.logoUrl, brandEmoji); $: syncBodyScrollLock(paymentModalOpen || changeModalOpen || changeConfirmOpen || topupModalOpen || deviceTopupModalOpen || linkEmailOpen); $: if (!tariffMode && !selectedPlan && plans.length) selectedPlan = plans[Math.min(1, plans.length - 1)]; + $: if (singleTariffMode && tariffCatalog[0]?.key && selectedTariffKey !== tariffCatalog[0].key) { + selectedTariffKey = tariffCatalog[0].key; + selectedPlan = plans.find((plan) => plan?.tariff_key === selectedTariffKey) || null; + if (paymentStep === "tariff") paymentStep = "checkout"; + } $: if (tariffMode && selectedTariffKey && !tariffCatalog.some((tariff) => tariff.key === selectedTariffKey)) { selectedTariffKey = ""; selectedPlan = null; - paymentStep = "tariff"; + paymentStep = singleTariffMode ? "checkout" : "tariff"; } $: if (tariffMode && selectedTariffKey && (!selectedPlan || selectedPlan.tariff_key !== selectedTariffKey)) { selectedPlan = selectedTariffPlans[0] || null; @@ -1753,7 +1760,11 @@ function openPaymentModal() { if (tariffMode) { - if (subscription?.active && subscription?.tariff_key && tariffCatalog.some((t) => t.key === subscription.tariff_key)) { + if (singleTariffMode && tariffCatalog[0]?.key) { + selectedTariffKey = tariffCatalog[0].key; + selectedPlan = plans.find((plan) => plan?.tariff_key === selectedTariffKey) || null; + paymentStep = "checkout"; + } else if (subscription?.active && subscription?.tariff_key && tariffCatalog.some((t) => t.key === subscription.tariff_key)) { selectedTariffKey = subscription.tariff_key; selectedPlan = plans.find((plan) => plan?.tariff_key === selectedTariffKey) || null; paymentStep = "checkout"; @@ -2004,12 +2015,18 @@ } function paymentTitle() { + if (singleTariffMode) { + return selectedTariff?.billing_model === "traffic" ? t("wa_traffic_packages_title") : t("wa_subscription_title"); + } if (tariffMode) return t("wa_tariffs_title"); return trafficMode ? t("wa_traffic_packages_title") : t("wa_subscription_title"); } function paymentDescription() { if (tariffMode) { + if (singleTariffMode) { + return selectedTariff?.billing_model === "traffic" ? t("wa_traffic_packages_choose") : t("wa_subscription_choose_period"); + } return paymentStep === "checkout" && selectedTariff ? t("wa_tariff_choose_period_payment", { tariff: selectedTariff.title }) : t("wa_tariffs_choose"); @@ -2435,7 +2452,7 @@

{trafficMode ? t("wa_home_access_active") : t("wa_home_subscription_active")} | {activeSubscriptionTermLabel(subscription)}

- {#if hasActiveTariffSubscription && currentTariffName} + {#if hasActiveTariffSubscription && hasMultipleTariffs && currentTariffName}

{t("wa_current_tariff", { tariff: currentTariffName })}

{/if}

{subscription.end_date_text ? t("wa_until_date", { date: subscription.end_date_text }) : subscription.remaining_text}

@@ -2841,7 +2858,7 @@ class="payment-dialog-card" >
- {#if tariffMode && paymentStep === "tariff"} + {#if tariffMode && !singleTariffMode && paymentStep === "tariff"} {#if tariffCatalog.length}
{#each tariffCatalog as tariff} @@ -2875,13 +2892,13 @@ {/if} {:else} {#if tariffMode} - {#if !(subscription?.active && subscription?.tariff_key && tariffCatalog.some((t) => t.key === subscription.tariff_key))} + {#if !singleTariffMode && !(subscription?.active && subscription?.tariff_key && tariffCatalog.some((t) => t.key === subscription.tariff_key))} {/if} - {#if selectedTariff} + {#if hasMultipleTariffs && selectedTariff}

{t("wa_selected_tariff", { tariff: selectedTariff.title })}

{/if} {/if} diff --git a/bot/handlers/user/subscription/core.py b/bot/handlers/user/subscription/core.py index e1a6c53..e9888db 100644 --- a/bot/handlers/user/subscription/core.py +++ b/bot/handlers/user/subscription/core.py @@ -1,5 +1,4 @@ import hashlib -import hashlib import logging from aiogram import Router, F, types, Bot from aiogram.filters import Command @@ -45,6 +44,29 @@ def _hwid_callback_token(hwid: Optional[str]) -> str: return hashlib.sha256(hwid_str.encode()).hexdigest()[:32] +def _enabled_tariffs(settings: Settings) -> list: + config = getattr(settings, "tariffs_config", None) + return list(config.enabled_tariffs) if config else [] + + +def _has_multiple_enabled_tariffs(settings: Settings) -> bool: + return len(_enabled_tariffs(settings)) > 1 + + +def _tariff_purchase_markup(tariff, current_lang: str, i18n: JsonI18n, settings: Settings) -> InlineKeyboardMarkup: + if tariff.billing_model == "period": + return get_tariff_periods_keyboard(tariff, current_lang, i18n, settings) + return get_tariff_packages_keyboard(tariff, tariff.traffic_packages.rub, current_lang, i18n) + + +def _tariff_purchase_text(tariff, current_lang: str, i18n: JsonI18n, settings: Settings) -> str: + if not _has_multiple_enabled_tariffs(settings): + if tariff.billing_model == "period": + return i18n.gettext(current_lang, "select_subscription_period") + return i18n.gettext(current_lang, "select_traffic_package") + return f"{tariff.name(current_lang)}\n{tariff.description(current_lang)}".strip() + + async def display_subscription_options( event: Union[types.Message, types.CallbackQuery], i18n_data: dict, @@ -71,8 +93,14 @@ async def display_subscription_options( currency_symbol_val = settings.DEFAULT_CURRENCY_SYMBOL tariffs_config = getattr(settings, "tariffs_config", None) if tariffs_config: - text_content = get_text("select_subscription_period") - reply_markup = get_tariff_catalog_keyboard(tariffs_config.enabled_tariffs, current_lang, i18n) + enabled_tariffs = list(tariffs_config.enabled_tariffs) + if len(enabled_tariffs) == 1: + tariff = enabled_tariffs[0] + text_content = _tariff_purchase_text(tariff, current_lang, i18n, settings) + reply_markup = _tariff_purchase_markup(tariff, current_lang, i18n, settings) + else: + text_content = get_text("select_subscription_period") + reply_markup = get_tariff_catalog_keyboard(enabled_tariffs, current_lang, i18n) target_message_obj = event.message if isinstance(event, types.CallbackQuery) else event if isinstance(event, types.CallbackQuery): try: @@ -159,11 +187,8 @@ async def select_tariff_callback(callback: types.CallbackQuery, i18n_data: dict, except Exception: await callback.answer(get_text("error_try_again"), show_alert=True) return - if tariff.billing_model == "period": - markup = get_tariff_periods_keyboard(tariff, current_lang, i18n, settings) - else: - markup = get_tariff_packages_keyboard(tariff, tariff.traffic_packages.rub, current_lang, i18n) - text = f"{tariff.name(current_lang)}\n{tariff.description(current_lang)}".strip() + markup = _tariff_purchase_markup(tariff, current_lang, i18n, settings) + text = _tariff_purchase_text(tariff, current_lang, i18n, settings) await callback.message.edit_text(text, reply_markup=markup) await callback.answer() @@ -567,7 +592,7 @@ async def my_subscription_command_handler( ) else: tariff_prefix = "" - if active.get("tariff_name"): + if _has_multiple_enabled_tariffs(settings) and active.get("tariff_name"): tariff_prefix = f"🎟 {active.get('tariff_name')}\n" if active.get("tariff_description"): tariff_prefix += f"{active.get('tariff_description')}\n" @@ -699,10 +724,11 @@ async def my_subscription_command_handler( ]) if settings.tariffs_config and local_sub and local_sub.tariff_key: - prepend_rows.append([ - InlineKeyboardButton(text="Сменить тариф", callback_data="tariff_change:list"), - InlineKeyboardButton(text="Докупить трафик", callback_data="tariff_topup:list"), - ]) + tariff_actions = [] + if _has_multiple_enabled_tariffs(settings): + tariff_actions.append(InlineKeyboardButton(text="Сменить тариф", callback_data="tariff_change:list")) + tariff_actions.append(InlineKeyboardButton(text="Докупить трафик", callback_data="tariff_topup:list")) + prepend_rows.append(tariff_actions) if prepend_rows: kb = prepend_rows + kb