diff --git a/core/settings/money_config.py b/core/settings/money_config.py index 0071f805..dc3ee775 100644 --- a/core/settings/money_config.py +++ b/core/settings/money_config.py @@ -11,6 +11,22 @@ from ..defaults import DEFAULT_MONEY_CONFIG MONEY_CONFIG: dict[str, Any] = DEFAULT_MONEY_CONFIG.copy() +def get_currency_mode() -> tuple[str, bool]: + mode_cfg = MONEY_CONFIG.get("CURRENCY_MODE", "RUB") + raw = str(mode_cfg or "RUB").upper() + + if raw not in ("RUB", "USD", "RUB+USD", "RUB+USD_ONE_SCREEN"): + raw = "RUB" + + one_screen = raw == "RUB+USD_ONE_SCREEN" + if raw in ("RUB+USD", "RUB+USD_ONE_SCREEN"): + base_mode = "RUB+USD" + else: + base_mode = raw + + return base_mode, one_screen + + async def load_money_config(session: AsyncSession) -> None: stmt = select(Setting).where(Setting.key == "MONEY_CONFIG") result = await session.execute(stmt) diff --git a/database/importer.py b/database/importer.py index a505acd9..4dbfa542 100644 --- a/database/importer.py +++ b/database/importer.py @@ -10,6 +10,7 @@ from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.ext.asyncio import AsyncSession from config import USE_COUNTRY_SELECTION +from core.bootstrap import MODES_CONFIG from database.models import Key, Server, User @@ -17,7 +18,9 @@ async def import_keys_from_3xui_db(db_path: str, session: AsyncSession) -> tuple imported = 0 skipped = 0 - if USE_COUNTRY_SELECTION: + use_country_selection = bool(MODES_CONFIG.get("COUNTRY_SELECTION_ENABLED", USE_COUNTRY_SELECTION)) + + if use_country_selection: result = await session.execute( select(Server.server_name).where(Server.enabled.is_(True), Server.panel_type == "3x-ui") ) diff --git a/handlers/admin/clusters/cluster_sync.py b/handlers/admin/clusters/cluster_sync.py index 4c258380..650307b5 100644 --- a/handlers/admin/clusters/cluster_sync.py +++ b/handlers/admin/clusters/cluster_sync.py @@ -16,6 +16,7 @@ from config import ( REMNAWAVE_PASSWORD, USE_COUNTRY_SELECTION, ) +from core.bootstrap import MODES_CONFIG from database import get_servers from database.models import Key, Server, Tariff from filters.admin import IsAdminFilter @@ -205,7 +206,9 @@ async def handle_sync_server( ) return - if USE_COUNTRY_SELECTION: + use_country_selection = bool(MODES_CONFIG.get("COUNTRY_SELECTION_ENABLED", USE_COUNTRY_SELECTION)) + + if use_country_selection: stmt = ( select( Server.api_url, @@ -402,7 +405,9 @@ async def handle_sync_cluster( servers = await get_servers(session) cluster_servers = servers.get(cluster_name, []) - if USE_COUNTRY_SELECTION: + use_country_selection = bool(MODES_CONFIG.get("COUNTRY_SELECTION_ENABLED", USE_COUNTRY_SELECTION)) + + if use_country_selection: server_names = [s.get("server_name") for s in cluster_servers if s.get("server_name")] if not server_names: await callback_query.message.edit_text( @@ -474,7 +479,7 @@ async def handle_sync_cluster( f"обновим без лимитов" ) - if USE_COUNTRY_SELECTION: + if use_country_selection: user_server = None for s in cluster_servers: if s.get("server_name") == key["server_id"]: @@ -573,7 +578,7 @@ async def handle_sync_cluster( delete(Key).where(Key.tg_id == key["tg_id"], Key.client_id == key["client_id"]) ) - cluster_id_for_recreate = key["server_id"] if USE_COUNTRY_SELECTION else cluster_name + cluster_id_for_recreate = key["server_id"] if use_country_selection else cluster_name await create_key_on_cluster( cluster_id_for_recreate, key["tg_id"], @@ -594,7 +599,7 @@ async def handle_sync_cluster( delete(Key).where(Key.tg_id == key["tg_id"], Key.client_id == key["client_id"]) ) - cluster_id_for_recreate = key["server_id"] if USE_COUNTRY_SELECTION else cluster_name + cluster_id_for_recreate = key["server_id"] if use_country_selection else cluster_name await create_key_on_cluster( cluster_id_for_recreate, key["tg_id"], diff --git a/handlers/admin/clusters/cluster_transfers.py b/handlers/admin/clusters/cluster_transfers.py index a821bfed..561094ee 100644 --- a/handlers/admin/clusters/cluster_transfers.py +++ b/handlers/admin/clusters/cluster_transfers.py @@ -5,6 +5,7 @@ from sqlalchemy import delete, update from sqlalchemy.ext.asyncio import AsyncSession from config import USE_COUNTRY_SELECTION +from core.bootstrap import MODES_CONFIG from database.models import Key, Server from logger import logger @@ -33,9 +34,11 @@ async def handle_server_transfer(callback_query: CallbackQuery, state: FSMContex await session.commit() + use_country_selection = bool(MODES_CONFIG.get("COUNTRY_SELECTION_ENABLED", USE_COUNTRY_SELECTION)) + base_text = f"✅ Ключи успешно перенесены на сервер '{new_server_name}', сервер '{old_server_name}' удален!" sync_reminder = '\n\n⚠️ Не забудьте сделать "Синхронизацию".' - final_text = base_text + (sync_reminder if USE_COUNTRY_SELECTION else "") + final_text = base_text + (sync_reminder if use_country_selection else "") await callback_query.message.edit_text( text=final_text, diff --git a/handlers/admin/settings/keyboard.py b/handlers/admin/settings/keyboard.py index c40601dc..9c96be26 100644 --- a/handlers/admin/settings/keyboard.py +++ b/handlers/admin/settings/keyboard.py @@ -2,6 +2,7 @@ from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup from aiogram.utils.keyboard import InlineKeyboardBuilder from ..panel.keyboard import AdminPanelCallback, build_admin_back_btn +from core.settings.money_config import get_currency_mode from .settings_config import ( BUTTON_TITLES, MODES_TITLES, @@ -192,12 +193,14 @@ def build_settings_money_kb(money_state: dict[str, object]) -> InlineKeyboardMar ).pack(), ) - mode = str(money_state.get("CURRENCY_MODE") or "RUB").upper() - if mode not in ("RUB", "USD", "RUB+USD"): - mode = "RUB" + mode, one_screen = get_currency_mode() + if mode == "RUB+USD" and one_screen: + mode_text = "RUB+USD (одним экраном)" + else: + mode_text = mode builder.button( - text=f"Режим валют: {mode}", + text=f"Режим валют: {mode_text}", callback_data=AdminPanelCallback( action="settings_money_currency", page=0, @@ -214,3 +217,4 @@ def build_settings_money_kb(money_state: dict[str, object]) -> InlineKeyboardMar ) return builder.as_markup() + diff --git a/handlers/admin/settings/settings_money.py b/handlers/admin/settings/settings_money.py index 1c0fc033..36023193 100644 --- a/handlers/admin/settings/settings_money.py +++ b/handlers/admin/settings/settings_money.py @@ -137,19 +137,21 @@ async def open_currency_mode_menu(callback: CallbackQuery) -> None: money_config = MONEY_CONFIG mode = str(money_config.get("CURRENCY_MODE") or "RUB").upper() - if mode not in ("RUB", "USD", "RUB+USD"): + if mode not in ("RUB", "USD", "RUB+USD", "RUB+USD_ONE_SCREEN"): mode = "RUB" text = ( "Выберите режим валют:\n\n" "• RUB — все цены только в рублях;\n" "• USD — все цены только в долларах;\n" - "• RUB+USD — мультивалюта, оба варианта." + "• RUB+USD — мультивалюта, выбор валюты перед оплатой;\n" + "• RUB+USD (одним экраном) — мультивалюта, все кассы на одном экране." ) rub_checked = mode == "RUB" usd_checked = mode == "USD" multi_checked = mode == "RUB+USD" + multi_one_screen_checked = mode == "RUB+USD_ONE_SCREEN" keyboard = InlineKeyboardMarkup( inline_keyboard=[ @@ -169,6 +171,12 @@ async def open_currency_mode_menu(callback: CallbackQuery) -> None: callback_data=AdminPanelCallback(action="settings_money_currency_set", page=3).pack(), ), ], + [ + InlineKeyboardButton( + text=("✅ RUB+USD (одним экраном)" if multi_one_screen_checked else "RUB+USD (одним экраном)"), + callback_data=AdminPanelCallback(action="settings_money_currency_set", page=4).pack(), + ), + ], [ InlineKeyboardButton( text="Назад", @@ -190,7 +198,7 @@ async def set_currency_mode( ) -> None: mode_index = callback_data.page - if mode_index not in (1, 2, 3): + if mode_index not in (1, 2, 3, 4): await callback.answer("Некорректный выбор", show_alert=True) return @@ -198,8 +206,10 @@ async def set_currency_mode( new_mode = "RUB" elif mode_index == 2: new_mode = "USD" - else: + elif mode_index == 3: new_mode = "RUB+USD" + else: + new_mode = "RUB+USD_ONE_SCREEN" money_config = MONEY_CONFIG.copy() money_config["CURRENCY_MODE"] = new_mode diff --git a/handlers/admin/users/users_keys.py b/handlers/admin/users/users_keys.py index 515d2cb9..3dca9bfb 100644 --- a/handlers/admin/users/users_keys.py +++ b/handlers/admin/users/users_keys.py @@ -15,6 +15,7 @@ from sqlalchemy import select, update from sqlalchemy.ext.asyncio import AsyncSession from config import USE_COUNTRY_SELECTION +from core.bootstrap import MODES_CONFIG from database import ( delete_key, delete_user_data, @@ -533,7 +534,9 @@ async def confirm_admin_key_reissue(callback_query: CallbackQuery, session: Asyn ) return - if USE_COUNTRY_SELECTION: + use_country_selection = bool(MODES_CONFIG.get("COUNTRY_SELECTION_ENABLED", USE_COUNTRY_SELECTION)) + + if use_country_selection: unique_countries = {srv["server_name"] for srv in cluster_servers} await state.update_data(tg_id=tg_id, email=email, cluster_id=cluster_id) builder = InlineKeyboardBuilder() @@ -809,7 +812,9 @@ async def handle_create_key_start( tg_id = callback_data.tg_id await state.update_data(tg_id=tg_id) - if USE_COUNTRY_SELECTION: + use_country_selection = bool(MODES_CONFIG.get("COUNTRY_SELECTION_ENABLED", USE_COUNTRY_SELECTION)) + + if use_country_selection: await state.set_state(UserEditorState.selecting_country) stmt = select(Server.server_name).distinct().order_by(Server.server_name) @@ -935,6 +940,8 @@ async def handle_create_key_duration(callback_query: CallbackQuery, state: FSMCo data = await state.get_data() tg_id = data.get("tg_id", callback_query.from_user.id) + use_country_selection = bool(MODES_CONFIG.get("COUNTRY_SELECTION_ENABLED", USE_COUNTRY_SELECTION)) + try: if not callback_query.data.startswith("tariff_"): raise ValueError("Некорректный callback_data") @@ -950,7 +957,7 @@ async def handle_create_key_duration(callback_query: CallbackQuery, state: FSMCo expiry = datetime.now(tz=timezone.utc) + timedelta(days=duration_days) expiry_ms = int(expiry.timestamp() * 1000) - if USE_COUNTRY_SELECTION and "country" in data: + if use_country_selection and "country" in data: country = data["country"] await create_key_on_cluster( country, diff --git a/handlers/keys/subscriptions.py b/handlers/keys/subscriptions.py index 92a60f4c..da86be53 100644 --- a/handlers/keys/subscriptions.py +++ b/handlers/keys/subscriptions.py @@ -19,6 +19,7 @@ from config import ( USERNAME_BOT, USE_COUNTRY_SELECTION, ) +from core.bootstrap import MODES_CONFIG from database import get_key_details, get_servers from database.models import Server from handlers.texts import HAPP_ANNOUNCE, HIDDIFY_PROFILE_TITLE, SUBSCRIPTION_INFO_TEXT, V2RAYTUN_ANNOUNCE @@ -73,7 +74,9 @@ async def get_subscription_urls( server_id: str, email: str, session: AsyncSession, include_remnawave_key: str = None ) -> list[str]: urls = [] - if USE_COUNTRY_SELECTION: + use_country_selection = bool(MODES_CONFIG.get("COUNTRY_SELECTION_ENABLED", USE_COUNTRY_SELECTION)) + + if use_country_selection: result = await session.execute( select(Server.subscription_url).where(Server.server_name == server_id, Server.enabled.is_(True)) ) diff --git a/handlers/payments/fast_payment_flow.py b/handlers/payments/fast_payment_flow.py index 238a6492..cd9561bd 100644 --- a/handlers/payments/fast_payment_flow.py +++ b/handlers/payments/fast_payment_flow.py @@ -5,8 +5,10 @@ from aiogram.fsm.context import FSMContext from aiogram.types import CallbackQuery, InlineKeyboardButton from aiogram.utils.keyboard import InlineKeyboardBuilder -from config import USE_NEW_PAYMENT_FLOW -from core.bootstrap import PAYMENTS_CONFIG, MONEY_CONFIG +from config import USE_NEW_PAYMENT_FLOW, TRIBUTE_LINK +from core.bootstrap import PAYMENTS_CONFIG +from core.settings.money_config import get_currency_mode + from database.temporary_data import create_temporary_data from handlers import buttons as btn from handlers.payments.currency_flow import ( @@ -28,14 +30,6 @@ async def get_payment_providers_config() -> dict[str, bool]: return dict(config) -def get_currency_mode() -> str: - mode_cfg = MONEY_CONFIG.get("CURRENCY_MODE", "RUB") - mode = str(mode_cfg or "RUB").upper() - if mode not in ("RUB", "USD", "RUB+USD"): - mode = "RUB" - return mode - - async def _run_provider_flow( provider: str, callback_query: CallbackQuery, @@ -97,46 +91,57 @@ async def try_fast_payment_flow( payment_config = await get_payment_providers_config() providers_map = await get_providers_with_hooks(payment_config) - providers = ( - [USE_NEW_PAYMENT_FLOW] - if isinstance(USE_NEW_PAYMENT_FLOW, str) - else [str(provider) for provider in (USE_NEW_PAYMENT_FLOW or [])] - ) - providers = [ - provider - for provider in providers - if (providers_map.get(str(provider).upper()) or {}).get("fast") - and (providers_map.get(str(provider).upper()) or {}).get("enabled", True) - ] + configured = [str(p) for p in (USE_NEW_PAYMENT_FLOW or [])] + configured_upper = [p.upper() for p in configured] + configured_set = set(configured_upper) - mode = get_currency_mode() - multicurrency_enabled = mode == "RUB+USD" + providers: list[str] = [] + for p_up in configured_upper: + cfg = providers_map.get(p_up) or {} + if cfg.get("fast") and cfg.get("enabled", True): + providers.append(p_up) - if not multicurrency_enabled: + mode, one_screen = get_currency_mode() + multicurrency_mode = mode == "RUB+USD" + + if not multicurrency_mode: allowed_currency = "RUB" if mode == "RUB" else "USD" - providers = [ - provider - for provider in providers - if (providers_map.get(provider.upper()) or {}).get("currency") in (allowed_currency, "RUB+USD") - ] + filtered: list[str] = [] + for p_up in providers: + cfg = providers_map.get(p_up) or {} + curr = str(cfg.get("currency") or "").upper() + if curr in (allowed_currency, "RUB+USD"): + filtered.append(p_up) + providers = filtered - if not providers: + if not providers and "TRIBUTE" not in configured_set: return False - if len(providers) == 1 and not multicurrency_enabled: - single_provider = providers[0].upper() - cfg = providers_map.get(single_provider) or {} - currency = cfg.get("currency") - if currency: - await state.update_data(chosen_currency=currency) - if await _run_provider_flow(single_provider, callback_query, session, state, required_amount): - return True - return False + tribute_cfg = providers_map.get("TRIBUTE") or {} + tribute_link = (TRIBUTE_LINK or "").strip() + tribute_enabled = ( + "TRIBUTE" in configured_set + and tribute_cfg.get("enabled", True) + and bool(tribute_link) + ) - if multicurrency_enabled: - show_stars = bool((providers_map.get("STARS") or {}).get("enabled")) - show_tribute = bool((providers_map.get("TRIBUTE") or {}).get("enabled")) - keyboard = build_currency_choice_kb(show_stars=show_stars, show_tribute=show_tribute) + stars_cfg = providers_map.get("STARS") or {} + stars_enabled_for_fast = ( + "STARS" in configured_set + and stars_cfg.get("fast") + and stars_cfg.get("enabled", True) + ) + + if multicurrency_mode and not one_screen: + show_stars = stars_enabled_for_fast + show_tribute = tribute_enabled + if not providers and not show_tribute: + return False + + keyboard = build_currency_choice_kb( + show_stars=show_stars, + show_tribute=show_tribute, + ) lead_text = await shortfall_lead_text( session, tg_id, @@ -157,11 +162,39 @@ async def try_fast_payment_flow( ) return True + total_options = len(providers) + (1 if tribute_enabled else 0) + if len(providers) == 1 and total_options == 1: + single_provider = providers[0] + cfg = providers_map.get(single_provider) or {} + currency = cfg.get("currency") + if currency: + await state.update_data(chosen_currency=currency) + if await _run_provider_flow(single_provider, callback_query, session, state, required_amount): + return True + return False + keyboard = InlineKeyboardBuilder() - for provider in providers: - provider_upper = provider.upper() + for provider_upper in providers: button_text = getattr(btn, provider_upper, provider_upper) - keyboard.row(InlineKeyboardButton(text=button_text, callback_data=f"choose_payment_provider|{provider_upper}")) + if one_screen: + cfg = providers_map.get(provider_upper) or {} + curr = cfg.get("currency") + if curr and curr != "RUB+USD": + button_text = f"{button_text} ({currency_label(curr)})" + keyboard.row( + InlineKeyboardButton( + text=button_text, + callback_data=f"choose_payment_provider|{provider_upper}", + ) + ) + + if tribute_enabled: + keyboard.row( + InlineKeyboardButton( + text=getattr(btn, "TRIBUTE", "TRIBUTE"), + url=tribute_link, + ) + ) keyboard.row(InlineKeyboardButton(text=btn.MAIN_MENU, callback_data="profile")) @@ -171,7 +204,11 @@ async def try_fast_payment_flow( required_amount, getattr(callback_query.from_user, "language_code", None), ) - await state.update_data(temp_key=temp_key, temp_payload=temp_payload, required_amount=required_amount) + await state.update_data( + temp_key=temp_key, + temp_payload=temp_payload, + required_amount=required_amount, + ) await edit_or_send_message( target_message=callback_query.message, text=f"{lead_text}.\n\n{FAST_PAY_CHOOSE_PROVIDER}", @@ -188,14 +225,14 @@ async def choose_payment_currency(callback_query: CallbackQuery, state: FSMConte currency = callback_query.data.split("|")[1] data = await state.get_data() - providers = data.get("fastflow_providers") or ( - [USE_NEW_PAYMENT_FLOW] - if isinstance(USE_NEW_PAYMENT_FLOW, str) - else [str(provider) for provider in (USE_NEW_PAYMENT_FLOW or [])] - ) + providers = data.get("fastflow_providers") or [] + if not providers: + configured = [str(p) for p in (USE_NEW_PAYMENT_FLOW or [])] + providers = [p.upper() for p in configured] + filtered = [ provider_upper - for provider_upper in (provider.upper() for provider in providers) + for provider_upper in (p.upper() for p in providers) if (providers_map.get(provider_upper) or {}).get("currency") == currency and (providers_map.get(provider_upper) or {}).get("fast") and (providers_map.get(provider_upper) or {}).get("enabled", True) @@ -228,7 +265,10 @@ async def choose_payment_currency(callback_query: CallbackQuery, state: FSMConte for provider_upper in filtered: button_text = getattr(btn, provider_upper, provider_upper) keyboard.row( - InlineKeyboardButton(text=button_text, callback_data=f"choose_payment_provider|{provider_upper}") + InlineKeyboardButton( + text=button_text, + callback_data=f"choose_payment_provider|{provider_upper}", + ) ) keyboard.row(InlineKeyboardButton(text=btn.MAIN_MENU, callback_data="profile")) @@ -241,7 +281,11 @@ async def choose_payment_currency(callback_query: CallbackQuery, state: FSMConte force_currency=currency, ) text = f"{lead_text}.\n\nВалюта: {currency_label(currency)}\n{FAST_PAY_CHOOSE_PROVIDER}" - await edit_or_send_message(target_message=callback_query.message, text=text, reply_markup=keyboard.as_markup()) + await edit_or_send_message( + target_message=callback_query.message, + text=text, + reply_markup=keyboard.as_markup(), + ) @router.callback_query(F.data.startswith("choose_payment_provider|")) diff --git a/handlers/payments/pay.py b/handlers/payments/pay.py index 1dcdb801..11a277eb 100644 --- a/handlers/payments/pay.py +++ b/handlers/payments/pay.py @@ -8,8 +8,9 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession -from config import DONATIONS_ENABLE -from core.bootstrap import PAYMENTS_CONFIG, MONEY_CONFIG, BUTTONS_CONFIG +from config import DONATIONS_ENABLE, TRIBUTE_LINK +from core.bootstrap import PAYMENTS_CONFIG, BUTTONS_CONFIG +from core.settings.money_config import get_currency_mode from database import get_last_payments from database.models import User from handlers import buttons as btn @@ -33,22 +34,18 @@ async def get_payment_providers_config() -> dict[str, bool]: return dict(config) -def get_currency_mode() -> str: - mode_cfg = MONEY_CONFIG.get("CURRENCY_MODE", "RUB") - mode = str(mode_cfg or "RUB").upper() - if mode not in ("RUB", "USD", "RUB+USD"): - mode = "RUB" - return mode - - @router.callback_query(F.data == "pay") async def handle_pay(callback_query: CallbackQuery, state: FSMContext, session: AsyncSession): providers_config = await get_payment_providers_config() providers_with_hooks = await get_providers_with_hooks(providers_config) - mode = get_currency_mode() + mode, one_screen = get_currency_mode() multicurrency_enabled = mode == "RUB+USD" + tribute_cfg = providers_with_hooks.get("TRIBUTE") or {} + tribute_link = (TRIBUTE_LINK or "").strip() + tribute_enabled = bool(tribute_cfg.get("enabled") and tribute_link) + if not multicurrency_enabled: allowed_currency = "RUB" if mode == "RUB" else "USD" filtered: dict[str, dict[str, Any]] = {} @@ -78,14 +75,15 @@ async def handle_pay(callback_query: CallbackQuery, state: FSMContext, session: ) donations_enabled = bool(BUTTONS_CONFIG.get("DONATIONS_BUTTON_ENABLE", DONATIONS_ENABLE)) - has_extra_menu_items = bool(module_buttons) or donations_enabled or bool( - (providers_with_hooks.get("TRIBUTE") or {}).get("enabled") - ) + has_extra_menu_items = bool(module_buttons) or donations_enabled or tribute_enabled - if multicurrency_enabled: + if multicurrency_enabled and not one_screen: show_stars = bool((providers_with_hooks.get("STARS") or {}).get("enabled")) - show_tribute = bool((providers_with_hooks.get("TRIBUTE") or {}).get("enabled")) - keyboard = build_currency_choice_kb(show_stars=show_stars, prefix="pay_currency", show_tribute=show_tribute) + keyboard = build_currency_choice_kb( + show_stars=show_stars, + prefix="pay_currency", + show_tribute=tribute_enabled, + ) await edit_or_send_message( target_message=callback_query.message, text=FAST_PAY_CHOOSE_CURRENCY, @@ -102,9 +100,19 @@ async def handle_pay(callback_query: CallbackQuery, state: FSMContext, session: for key, cfg in providers_with_hooks.items(): if not cfg.get("enabled"): continue + if key == "TRIBUTE": + continue text = getattr(btn, key, key) builder.row(InlineKeyboardButton(text=text, callback_data=cfg["value"])) + if tribute_enabled: + builder.row( + InlineKeyboardButton( + text=getattr(btn, "TRIBUTE", "TRIBUTE"), + url=tribute_link, + ) + ) + if donations_enabled: builder.row(InlineKeyboardButton(text=btn.DONAT_BUTTON, callback_data="donate")) @@ -124,6 +132,8 @@ async def _build_pay_menu_for_currency(currency: str) -> InlineKeyboardBuilder: builder = InlineKeyboardBuilder() for key, cfg in providers_with_hooks.items(): + if key == "TRIBUTE": + continue if not cfg.get("enabled"): continue if cfg.get("currency") != currency: