- Added support for a mini-app connect button in the subscription command handler, allowing users to access additional features if the URL is configured. - Implemented an auto-renew toggle button and payment methods management button, improving user interaction based on subscription status and settings. - Refactored inline keyboard construction to prepend new buttons above the existing markup, enhancing the user experience in subscription management.
323 lines
13 KiB
Python
323 lines
13 KiB
Python
from aiogram.utils.keyboard import InlineKeyboardBuilder, InlineKeyboardButton
|
|
from aiogram.types import InlineKeyboardMarkup, WebAppInfo
|
|
from typing import Dict, Optional, List, Tuple
|
|
|
|
from config.settings import Settings
|
|
|
|
|
|
def get_main_menu_inline_keyboard(
|
|
lang: str,
|
|
i18n_instance,
|
|
settings: Settings,
|
|
show_trial_button: bool = False) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
|
|
if show_trial_button and settings.TRIAL_ENABLED:
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="menu_activate_trial_button"),
|
|
callback_data="main_action:request_trial"))
|
|
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="menu_subscribe_inline"),
|
|
callback_data="main_action:subscribe"))
|
|
builder.row(
|
|
InlineKeyboardButton(
|
|
text=_(key="menu_my_subscription_inline"),
|
|
callback_data="main_action:my_subscription",
|
|
)
|
|
)
|
|
|
|
referral_button = InlineKeyboardButton(
|
|
text=_(key="menu_referral_inline"),
|
|
callback_data="main_action:referral")
|
|
promo_button = InlineKeyboardButton(
|
|
text=_(key="menu_apply_promo_button"),
|
|
callback_data="main_action:apply_promo")
|
|
builder.row(referral_button, promo_button)
|
|
|
|
language_button = InlineKeyboardButton(
|
|
text=_(key="menu_language_settings_inline"),
|
|
callback_data="main_action:language")
|
|
status_button_list = []
|
|
if settings.SERVER_STATUS_URL:
|
|
status_button_list.append(
|
|
InlineKeyboardButton(text=_(key="menu_server_status_button"),
|
|
url=settings.SERVER_STATUS_URL))
|
|
|
|
if status_button_list:
|
|
builder.row(language_button, *status_button_list)
|
|
else:
|
|
builder.row(language_button)
|
|
|
|
if settings.SUPPORT_LINK:
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="menu_support_button"),
|
|
url=settings.SUPPORT_LINK))
|
|
|
|
if settings.TERMS_OF_SERVICE_URL:
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="menu_terms_button"),
|
|
url=settings.TERMS_OF_SERVICE_URL))
|
|
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_language_selection_keyboard(i18n_instance,
|
|
current_lang: str) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(current_lang, key, **kwargs
|
|
)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.button(text=f"🇬🇧 English {'✅' if current_lang == 'en' else ''}",
|
|
callback_data="set_lang_en")
|
|
builder.button(text=f"🇷🇺 Русский {'✅' if current_lang == 'ru' else ''}",
|
|
callback_data="set_lang_ru")
|
|
builder.button(text=_(key="back_to_main_menu_button"),
|
|
callback_data="main_action:back_to_main")
|
|
builder.adjust(1)
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_trial_confirmation_keyboard(lang: str,
|
|
i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.button(text=_(key="trial_confirm_activate_button"),
|
|
callback_data="trial_action:confirm_activate")
|
|
builder.button(text=_(key="cancel_button"),
|
|
callback_data="main_action:back_to_main")
|
|
builder.adjust(1)
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_subscription_options_keyboard(subscription_options: Dict[
|
|
int, Optional[int]], currency_symbol_val: str, lang: str,
|
|
i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
if subscription_options:
|
|
for months, price in subscription_options.items():
|
|
if price is not None:
|
|
button_text = _("subscribe_for_months_button",
|
|
months=months,
|
|
price=price,
|
|
currency_symbol=currency_symbol_val)
|
|
builder.button(text=button_text,
|
|
callback_data=f"subscribe_period:{months}")
|
|
builder.adjust(1)
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="back_to_main_menu_button"),
|
|
callback_data="main_action:back_to_main"))
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_payment_method_keyboard(months: int, price: float,
|
|
tribute_url: Optional[str],
|
|
stars_price: Optional[int],
|
|
currency_symbol_val: str, lang: str,
|
|
i18n_instance, settings: Settings) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
if settings.STARS_ENABLED and stars_price is not None:
|
|
builder.button(text=_("pay_with_stars_button"),
|
|
callback_data=f"pay_stars:{months}:{stars_price}")
|
|
if settings.TRIBUTE_ENABLED and tribute_url:
|
|
builder.button(text=_("pay_with_tribute_button"), url=tribute_url)
|
|
if settings.YOOKASSA_ENABLED:
|
|
builder.button(text=_("pay_with_yookassa_button"),
|
|
callback_data=f"pay_yk:{months}:{price}")
|
|
if settings.CRYPTOPAY_ENABLED:
|
|
builder.button(text=_("pay_with_cryptopay_button"),
|
|
callback_data=f"pay_crypto:{months}:{price}")
|
|
builder.button(text=_(key="cancel_button"),
|
|
callback_data="main_action:subscribe")
|
|
builder.adjust(1)
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_payment_url_keyboard(payment_url: str, lang: str,
|
|
i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.button(text=_(key="pay_button"), url=payment_url)
|
|
builder.button(text=_(key="back_to_main_menu_button"),
|
|
callback_data="main_action:back_to_main")
|
|
builder.adjust(1)
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_referral_link_keyboard(lang: str,
|
|
i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.button(text=_(key="referral_share_message_button"),
|
|
callback_data="referral_action:share_message")
|
|
builder.button(text=_(key="back_to_main_menu_button"),
|
|
callback_data="main_action:back_to_main")
|
|
builder.adjust(1)
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_back_to_main_menu_markup(lang: str,
|
|
i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.button(text=_(key="back_to_main_menu_button"),
|
|
callback_data="main_action:back_to_main")
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_subscribe_only_markup(lang: str, i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.button(text=_(key="menu_subscribe_inline"),
|
|
callback_data="main_action:subscribe")
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_user_banned_keyboard(support_link: Optional[str], lang: str,
|
|
i18n_instance) -> Optional[InlineKeyboardMarkup]:
|
|
if not support_link:
|
|
return None
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.button(text=_(key="menu_support_button"), url=support_link)
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_connect_and_main_keyboard(
|
|
lang: str,
|
|
i18n_instance,
|
|
settings: Settings,
|
|
config_link: Optional[str]) -> InlineKeyboardMarkup:
|
|
"""Keyboard with a connect button and a back to main menu button."""
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
|
|
if settings.SUBSCRIPTION_MINI_APP_URL:
|
|
builder.row(
|
|
InlineKeyboardButton(
|
|
text=_("connect_button"),
|
|
web_app=WebAppInfo(url=settings.SUBSCRIPTION_MINI_APP_URL),
|
|
)
|
|
)
|
|
elif config_link:
|
|
builder.row(
|
|
InlineKeyboardButton(text=_("connect_button"), url=config_link)
|
|
)
|
|
else:
|
|
builder.row(
|
|
InlineKeyboardButton(
|
|
text=_("connect_button"),
|
|
callback_data="main_action:my_subscription",
|
|
)
|
|
)
|
|
|
|
builder.row(
|
|
InlineKeyboardButton(
|
|
text=_("back_to_main_menu_button"),
|
|
callback_data="main_action:back_to_main",
|
|
)
|
|
)
|
|
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_payment_methods_manage_keyboard(lang: str, i18n_instance, has_card: bool) -> InlineKeyboardMarkup:
|
|
"""Deprecated in favor of get_payment_methods_list_keyboard. Kept for backward compatibility."""
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="payment_method_bind_button"), callback_data="pm:bind")
|
|
)
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="back_to_main_menu_button"), callback_data="main_action:back_to_main")
|
|
)
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_payment_methods_list_keyboard(
|
|
cards: List[Tuple[str, str]],
|
|
page: int,
|
|
lang: str,
|
|
i18n_instance,
|
|
) -> InlineKeyboardMarkup:
|
|
"""
|
|
Build a paginated list of saved payment methods.
|
|
cards: list of tuples (payment_method_id, display_title)
|
|
page: 0-based page index
|
|
"""
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
per_page = 5
|
|
total = len(cards)
|
|
start = page * per_page
|
|
end = start + per_page
|
|
for pm_id, title in cards[start:end]:
|
|
builder.row(
|
|
InlineKeyboardButton(text=title, callback_data=f"pm:view:{pm_id}")
|
|
)
|
|
|
|
# Pagination controls if needed
|
|
nav_buttons: List[InlineKeyboardButton] = []
|
|
if start > 0:
|
|
nav_buttons.append(InlineKeyboardButton(text="⬅️", callback_data=f"pm:list:{page-1}"))
|
|
if end < total:
|
|
nav_buttons.append(InlineKeyboardButton(text="➡️", callback_data=f"pm:list:{page+1}"))
|
|
if nav_buttons:
|
|
builder.row(*nav_buttons)
|
|
|
|
# Bind new card and back
|
|
builder.row(InlineKeyboardButton(text=_(key="payment_method_bind_button"), callback_data="pm:bind"))
|
|
builder.row(InlineKeyboardButton(text=_(key="back_to_main_menu_button"), callback_data="main_action:back_to_main"))
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_payment_method_delete_confirm_keyboard(pm_id: str, lang: str, i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="yes_button"), callback_data=f"pm:delete:{pm_id}"),
|
|
InlineKeyboardButton(text=_(key="cancel_button"), callback_data=f"pm:view:{pm_id}"),
|
|
)
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_payment_method_details_keyboard(pm_id: str, lang: str, i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="payment_method_tx_history_title"), callback_data=f"pm:history:{pm_id}")
|
|
)
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="payment_method_delete_button"), callback_data=f"pm:delete_confirm:{pm_id}")
|
|
)
|
|
builder.row(
|
|
InlineKeyboardButton(text=_(key="back_to_main_menu_button"), callback_data="pm:list:0")
|
|
)
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_bind_url_keyboard(bind_url: str, lang: str, i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.button(text=_(key="payment_method_bind_button"), url=bind_url)
|
|
builder.button(text=_(key="back_to_main_menu_button"), callback_data="pm:manage")
|
|
builder.adjust(1)
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_back_to_payment_methods_keyboard(lang: str, i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
builder.row(InlineKeyboardButton(text=_(key="back_to_main_menu_button"), callback_data="pm:list:0"))
|
|
return builder.as_markup()
|
|
|
|
|
|
def get_back_to_payment_method_details_keyboard(pm_id: str, lang: str, i18n_instance) -> InlineKeyboardMarkup:
|
|
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
|
|
builder = InlineKeyboardBuilder()
|
|
# Back one step: return to specific payment method details
|
|
builder.row(InlineKeyboardButton(text=_(key="back_to_main_menu_button"), callback_data=f"pm:view:{pm_id}"))
|
|
return builder.as_markup()
|