diff --git a/app/handlers/subscription.py b/app/handlers/subscription.py
index 6622fa34..9454217b 100644
--- a/app/handlers/subscription.py
+++ b/app/handlers/subscription.py
@@ -1,9 +1,7 @@
-import base64
import json
import logging
from datetime import datetime, timedelta
from typing import Dict, List, Any, Tuple, Optional
-from urllib.parse import quote
from aiogram import Dispatcher, types, F
from aiogram.fsm.context import FSMContext
@@ -5541,17 +5539,6 @@ async def handle_device_guide(
return
featured_app = next((app for app in apps if app.get('isFeatured', False)), apps[0])
- featured_app_id = featured_app.get('id')
- other_apps = [
- app for app in apps
- if isinstance(app, dict) and app.get('id') and app.get('id') != featured_app_id
- ]
-
- other_app_names = ", ".join(
- str(app.get('name')).strip()
- for app in other_apps
- if isinstance(app.get('name'), str) and app.get('name').strip()
- )
if hide_subscription_link:
link_section = (
@@ -5569,20 +5556,6 @@ async def handle_device_guide(
+ f"\n{subscription_link}\n\n"
)
- installation_description = get_step_description(featured_app, "installationStep", db_user.language)
- add_description = get_step_description(featured_app, "addSubscriptionStep", db_user.language)
- connect_description = get_step_description(featured_app, "connectAndUseStep", db_user.language)
- additional_before_text = format_additional_section(
- featured_app.get("additionalBeforeAddSubscriptionStep"),
- texts,
- db_user.language,
- )
- additional_after_text = format_additional_section(
- featured_app.get("additionalAfterAddSubscriptionStep"),
- texts,
- db_user.language,
- )
-
guide_text = (
texts.t(
"SUBSCRIPTION_DEVICE_GUIDE_TITLE",
@@ -5593,36 +5566,17 @@ async def handle_device_guide(
+ texts.t(
"SUBSCRIPTION_DEVICE_FEATURED_APP",
"π Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌΠΎΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅: {app_name}",
- ).format(app_name=featured_app.get('name', ''))
- )
-
- if other_app_names:
- guide_text += "\n\n" + texts.t(
- "SUBSCRIPTION_DEVICE_OTHER_APPS",
- "π¦ ΠΡΡΠ³ΠΈΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ: {app_list}",
- ).format(app_list=other_app_names)
- guide_text += "\n" + texts.t(
- "SUBSCRIPTION_DEVICE_OTHER_APPS_HINT",
- "ΠΠ°ΠΆΠΌΠΈΡΠ΅ ΠΊΠ½ΠΎΠΏΠΊΡ \"ΠΡΡΠ³ΠΈΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ\" Π½ΠΈΠΆΠ΅, ΡΡΠΎΠ±Ρ Π²ΡΠ±ΡΠ°ΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅.",
- )
-
- guide_text += "\n\n" + texts.t("SUBSCRIPTION_DEVICE_STEP_INSTALL_TITLE", "Π¨Π°Π³ 1 - Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°:")
- if installation_description:
- guide_text += f"\n{installation_description}"
-
- if additional_before_text:
- guide_text += f"\n\n{additional_before_text}"
-
- guide_text += "\n\n" + texts.t("SUBSCRIPTION_DEVICE_STEP_ADD_TITLE", "Π¨Π°Π³ 2 - ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ:")
- if add_description:
- guide_text += f"\n{add_description}"
-
- guide_text += "\n\n" + texts.t("SUBSCRIPTION_DEVICE_STEP_CONNECT_TITLE", "Π¨Π°Π³ 3 - ΠΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅:")
- if connect_description:
- guide_text += f"\n{connect_description}"
-
- guide_text += "\n\n" + texts.t("SUBSCRIPTION_DEVICE_HOW_TO_TITLE", "π‘ ΠΠ°ΠΊ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡ:")
- guide_text += "\n" + "\n".join(
+ ).format(app_name=featured_app['name'])
+ + "\n\n"
+ + texts.t("SUBSCRIPTION_DEVICE_STEP_INSTALL_TITLE", "Π¨Π°Π³ 1 - Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°:")
+ + f"\n{featured_app['installationStep']['description'][db_user.language]}\n\n"
+ + texts.t("SUBSCRIPTION_DEVICE_STEP_ADD_TITLE", "Π¨Π°Π³ 2 - ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ:")
+ + f"\n{featured_app['addSubscriptionStep']['description'][db_user.language]}\n\n"
+ + texts.t("SUBSCRIPTION_DEVICE_STEP_CONNECT_TITLE", "Π¨Π°Π³ 3 - ΠΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅:")
+ + f"\n{featured_app['connectAndUseStep']['description'][db_user.language]}\n\n"
+ + texts.t("SUBSCRIPTION_DEVICE_HOW_TO_TITLE", "π‘ ΠΠ°ΠΊ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡ:")
+ + "\n"
+ + "\n".join(
[
texts.t(
"SUBSCRIPTION_DEVICE_HOW_TO_STEP1",
@@ -5630,7 +5584,7 @@ async def handle_device_guide(
),
texts.t(
"SUBSCRIPTION_DEVICE_HOW_TO_STEP2",
- "2. ΠΠ°ΠΆΠΌΠΈΡΠ΅ ΠΊΠ½ΠΎΠΏΠΊΡ \"ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡΡΡ\" Π½ΠΈΠΆΠ΅",
+ "2. Π‘ΠΊΠΎΠΏΠΈΡΡΠΉΡΠ΅ ΡΡΡΠ»ΠΊΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ (Π½Π°ΠΆΠΌΠΈΡΠ΅ Π½Π° Π½Π΅Ρ)",
),
texts.t(
"SUBSCRIPTION_DEVICE_HOW_TO_STEP3",
@@ -5642,18 +5596,14 @@ async def handle_device_guide(
),
]
)
-
- if additional_after_text:
- guide_text += f"\n\n{additional_after_text}"
+ )
await callback.message.edit_text(
guide_text,
reply_markup=get_connection_guide_keyboard(
subscription_link,
featured_app,
- device_type,
- db_user.language,
- has_other_apps=bool(other_apps),
+ db_user.language
),
parse_mode="HTML"
)
@@ -5741,46 +5691,31 @@ async def handle_specific_app_guide(
+ f"\n{subscription_link}\n\n"
)
- installation_description = get_step_description(app, "installationStep", db_user.language)
- add_description = get_step_description(app, "addSubscriptionStep", db_user.language)
- connect_description = get_step_description(app, "connectAndUseStep", db_user.language)
- additional_before_text = format_additional_section(
- app.get("additionalBeforeAddSubscriptionStep"),
- texts,
- db_user.language,
- )
- additional_after_text = format_additional_section(
- app.get("additionalAfterAddSubscriptionStep"),
- texts,
- db_user.language,
- )
-
guide_text = (
texts.t(
"SUBSCRIPTION_SPECIFIC_APP_TITLE",
"π± {app_name} - {device_name}",
- ).format(app_name=app.get('name', ''), device_name=get_device_name(device_type, db_user.language))
+ ).format(app_name=app['name'], device_name=get_device_name(device_type, db_user.language))
+ "\n\n"
+ link_section
+ + texts.t("SUBSCRIPTION_DEVICE_STEP_INSTALL_TITLE", "Π¨Π°Π³ 1 - Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°:")
+ + f"\n{app['installationStep']['description'][db_user.language]}\n\n"
+ + texts.t("SUBSCRIPTION_DEVICE_STEP_ADD_TITLE", "Π¨Π°Π³ 2 - ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ:")
+ + f"\n{app['addSubscriptionStep']['description'][db_user.language]}\n\n"
+ + texts.t("SUBSCRIPTION_DEVICE_STEP_CONNECT_TITLE", "Π¨Π°Π³ 3 - ΠΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅:")
+ + f"\n{app['connectAndUseStep']['description'][db_user.language]}"
)
- guide_text += texts.t("SUBSCRIPTION_DEVICE_STEP_INSTALL_TITLE", "Π¨Π°Π³ 1 - Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°:")
- if installation_description:
- guide_text += f"\n{installation_description}"
-
- if additional_before_text:
- guide_text += f"\n\n{additional_before_text}"
-
- guide_text += "\n\n" + texts.t("SUBSCRIPTION_DEVICE_STEP_ADD_TITLE", "Π¨Π°Π³ 2 - ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ:")
- if add_description:
- guide_text += f"\n{add_description}"
-
- guide_text += "\n\n" + texts.t("SUBSCRIPTION_DEVICE_STEP_CONNECT_TITLE", "Π¨Π°Π³ 3 - ΠΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅:")
- if connect_description:
- guide_text += f"\n{connect_description}"
-
- if additional_after_text:
- guide_text += f"\n\n{additional_after_text}"
+ if 'additionalAfterAddSubscriptionStep' in app:
+ additional = app['additionalAfterAddSubscriptionStep']
+ guide_text += (
+ "\n\n"
+ + texts.t(
+ "SUBSCRIPTION_ADDITIONAL_STEP_TITLE",
+ "{title}:",
+ ).format(title=additional['title'][db_user.language])
+ + f"\n{additional['description'][db_user.language]}"
+ )
await callback.message.edit_text(
guide_text,
@@ -5923,119 +5858,14 @@ def load_app_config() -> Dict[str, Any]:
config_path = settings.get_app_config_path()
with open(config_path, 'r', encoding='utf-8') as f:
- data = json.load(f)
- if isinstance(data, dict):
- return data
- logger.error("ΠΠ΅ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΡΠΉ ΡΠΎΡΠΌΠ°Ρ app-config.json: ΠΎΠΆΠΈΠ΄Π°Π΅ΡΡΡ ΠΎΠ±ΡΠ΅ΠΊΡ")
+ return json.load(f)
except Exception as e:
logger.error(f"ΠΡΠΈΠ±ΠΊΠ° Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΠΊΠΎΠ½ΡΠΈΠ³Π° ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ: {e}")
-
- return {}
-
-
-def get_localized_value(values: Any, language: str, default_language: str = "en") -> str:
- if not isinstance(values, dict):
- return ""
-
- candidates: List[str] = []
- normalized_language = (language or "").strip().lower()
-
- if normalized_language:
- candidates.append(normalized_language)
- if "-" in normalized_language:
- candidates.append(normalized_language.split("-")[0])
-
- default_language = (default_language or "").strip().lower()
- if default_language and default_language not in candidates:
- candidates.append(default_language)
-
- for candidate in candidates:
- if not candidate:
- continue
- value = values.get(candidate)
- if isinstance(value, str) and value.strip():
- return value
-
- for value in values.values():
- if isinstance(value, str) and value.strip():
- return value
-
- return ""
-
-
-def get_step_description(app: Dict[str, Any], step_key: str, language: str) -> str:
- if not isinstance(app, dict):
- return ""
-
- step = app.get(step_key)
- if not isinstance(step, dict):
- return ""
-
- description = step.get("description")
- return get_localized_value(description, language)
-
-
-def format_additional_section(additional: Any, texts, language: str) -> str:
- if not isinstance(additional, dict):
- return ""
-
- title = get_localized_value(additional.get("title"), language)
- description = get_localized_value(additional.get("description"), language)
-
- parts: List[str] = []
-
- if title:
- parts.append(
- texts.t(
- "SUBSCRIPTION_ADDITIONAL_STEP_TITLE",
- "{title}:",
- ).format(title=title)
- )
-
- if description:
- parts.append(description)
-
- return "\n".join(parts)
-
-
-def build_redirect_link(target_link: Optional[str], template: Optional[str]) -> Optional[str]:
- if not target_link or not template:
- return None
-
- normalized_target = str(target_link).strip()
- normalized_template = str(template).strip()
-
- if not normalized_target or not normalized_template:
- return None
-
- encoded_target = quote(normalized_target, safe="")
- result = normalized_template
- replaced = False
-
- replacements = [
- ("{subscription_link}", encoded_target),
- ("{link}", encoded_target),
- ("{subscription_link_raw}", normalized_target),
- ("{link_raw}", normalized_target),
- ]
-
- for placeholder, replacement in replacements:
- if placeholder in result:
- result = result.replace(placeholder, replacement)
- replaced = True
-
- if not replaced:
- result = f"{result}{encoded_target}"
-
- return result
+ return {}
def get_apps_for_device(device_type: str, language: str = "ru") -> List[Dict[str, Any]]:
- config = load_app_config()
- platforms = config.get("platforms", {}) if isinstance(config, dict) else {}
-
- if not isinstance(platforms, dict):
- return []
+ config = load_app_config()['platforms']
device_mapping = {
'ios': 'ios',
@@ -6046,49 +5876,32 @@ def get_apps_for_device(device_type: str, language: str = "ru") -> List[Dict[str
}
config_key = device_mapping.get(device_type, device_type)
- apps = platforms.get(config_key, [])
- return apps if isinstance(apps, list) else []
+ return config.get(config_key, [])
def get_device_name(device_type: str, language: str = "ru") -> str:
- names = {
- 'ios': 'iPhone/iPad',
- 'android': 'Android',
- 'windows': 'Windows',
- 'mac': 'macOS',
- 'tv': 'Android TV'
- }
+ if language == "en":
+ names = {
+ 'ios': 'iPhone/iPad',
+ 'android': 'Android',
+ 'windows': 'Windows',
+ 'mac': 'macOS',
+ 'tv': 'Android TV'
+ }
+ else:
+ names = {
+ 'ios': 'iPhone/iPad',
+ 'android': 'Android',
+ 'windows': 'Windows',
+ 'mac': 'macOS',
+ 'tv': 'Android TV'
+ }
return names.get(device_type, device_type)
-def create_deep_link(app: Dict[str, Any], subscription_url: str) -> Optional[str]:
- if not subscription_url:
- return None
-
- if not isinstance(app, dict):
- return subscription_url
-
- scheme = str(app.get("urlScheme", "")).strip()
- payload = subscription_url
-
- if app.get("isNeedBase64Encoding"):
- try:
- payload = base64.b64encode(subscription_url.encode("utf-8")).decode("utf-8")
- except Exception as exc:
- logger.warning(
- "ΠΠ΅ ΡΠ΄Π°Π»ΠΎΡΡ Π·Π°ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°ΡΡ ΡΡΡΠ»ΠΊΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ Π² base64 Π΄Π»Ρ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ %s: %s",
- app.get("id"),
- exc,
- )
- payload = subscription_url
-
- scheme_link = f"{scheme}{payload}" if scheme else None
-
- template = settings.get_happ_cryptolink_redirect_template()
- redirect_link = build_redirect_link(scheme_link, template) if scheme_link and template else None
-
- return redirect_link or scheme_link or subscription_url
+def create_deep_link(app: Dict[str, Any], subscription_url: str) -> str:
+ return subscription_url
def get_reset_devices_confirm_keyboard(language: str = "ru") -> InlineKeyboardMarkup:
diff --git a/app/keyboards/inline.py b/app/keyboards/inline.py
index aec10d24..b6cb2212 100644
--- a/app/keyboards/inline.py
+++ b/app/keyboards/inline.py
@@ -17,64 +17,6 @@ import logging
logger = logging.getLogger(__name__)
-
-def _get_localized_value(values, language: str, default_language: str = "en") -> str:
- if not isinstance(values, dict):
- return ""
-
- candidates = []
- normalized_language = (language or "").strip().lower()
-
- if normalized_language:
- candidates.append(normalized_language)
- if "-" in normalized_language:
- candidates.append(normalized_language.split("-")[0])
-
- default_language = (default_language or "").strip().lower()
- if default_language and default_language not in candidates:
- candidates.append(default_language)
-
- for candidate in candidates:
- if not candidate:
- continue
- value = values.get(candidate)
- if isinstance(value, str) and value.strip():
- return value
-
- for value in values.values():
- if isinstance(value, str) and value.strip():
- return value
-
- return ""
-
-
-def _build_additional_buttons(additional_section, language: str) -> List[InlineKeyboardButton]:
- if not isinstance(additional_section, dict):
- return []
-
- buttons = additional_section.get("buttons")
- if not isinstance(buttons, list):
- return []
-
- localized_buttons: List[InlineKeyboardButton] = []
-
- for button in buttons:
- if not isinstance(button, dict):
- continue
-
- button_text = _get_localized_value(button.get("buttonText"), language)
- button_link = button.get("buttonLink")
-
- if not button_text or not button_link:
- continue
-
- localized_buttons.append(
- InlineKeyboardButton(text=button_text, url=button_link)
- )
-
- return localized_buttons
-
-
_LANGUAGE_DISPLAY_NAMES = {
"ru": "π·πΊ Π ΡΡΡΠΊΠΈΠΉ",
"en": "π¬π§ English",
@@ -1622,80 +1564,42 @@ def get_device_selection_keyboard(language: str = DEFAULT_LANGUAGE) -> InlineKey
def get_connection_guide_keyboard(
- subscription_url: str,
- app: dict,
- device_type: str,
- language: str = DEFAULT_LANGUAGE,
- has_other_apps: bool = False,
+ subscription_url: str,
+ app: dict,
+ language: str = DEFAULT_LANGUAGE
) -> InlineKeyboardMarkup:
from app.handlers.subscription import create_deep_link
texts = get_texts(language)
-
+
keyboard = []
-
+
if 'installationStep' in app and 'buttons' in app['installationStep']:
app_buttons = []
for button in app['installationStep']['buttons']:
- button_text = _get_localized_value(button.get('buttonText'), language)
- button_link = button.get('buttonLink')
-
- if not button_text or not button_link:
- continue
-
+ button_text = button['buttonText'].get(language, button['buttonText']['en'])
app_buttons.append(
- InlineKeyboardButton(text=f"π₯ {button_text}", url=button_link)
+ InlineKeyboardButton(text=f"π₯ {button_text}", url=button['buttonLink'])
)
if len(app_buttons) == 2:
keyboard.append(app_buttons)
app_buttons = []
-
+
if app_buttons:
keyboard.append(app_buttons)
-
- additional_before_buttons = _build_additional_buttons(
- app.get('additionalBeforeAddSubscriptionStep'),
- language,
- )
-
- for button in additional_before_buttons:
- keyboard.append([button])
-
- connect_link = create_deep_link(app, subscription_url)
-
- if connect_link:
- connect_button = InlineKeyboardButton(
- text=texts.t("CONNECT_BUTTON", "π ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡΡΡ"),
- url=connect_link,
- )
- elif settings.is_happ_cryptolink_mode():
- connect_button = InlineKeyboardButton(
- text=texts.t("CONNECT_BUTTON", "π ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡΡΡ"),
+
+ if settings.is_happ_cryptolink_mode():
+ copy_button = InlineKeyboardButton(
+ text=texts.t("COPY_SUBSCRIPTION_LINK", "π Π‘ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ ΡΡΡΠ»ΠΊΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ"),
callback_data="open_subscription_link",
)
else:
- connect_button = InlineKeyboardButton(
- text=texts.t("CONNECT_BUTTON", "π ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡΡΡ"),
+ copy_button = InlineKeyboardButton(
+ text=texts.t("COPY_SUBSCRIPTION_LINK", "π Π‘ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ ΡΡΡΠ»ΠΊΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ"),
url=subscription_url,
)
- keyboard.append([connect_button])
-
- additional_after_buttons = _build_additional_buttons(
- app.get('additionalAfterAddSubscriptionStep'),
- language,
- )
-
- for button in additional_after_buttons:
- keyboard.append([button])
-
- if has_other_apps:
- keyboard.append([
- InlineKeyboardButton(
- text=texts.t("OTHER_APPS_BUTTON", "π ΠΡΡΠ³ΠΈΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ"),
- callback_data=f"app_list_{device_type}",
- )
- ])
-
+ keyboard.append([copy_button])
+
keyboard.extend([
[
InlineKeyboardButton(text=texts.t("CHOOSE_ANOTHER_DEVICE", "π± ΠΡΠ±ΡΠ°ΡΡ Π΄ΡΡΠ³ΠΎΠ΅ ΡΡΡΡΠΎΠΉΡΡΠ²ΠΎ"), callback_data="subscription_connect")
@@ -1748,64 +1652,43 @@ def get_specific_app_keyboard(
) -> InlineKeyboardMarkup:
from app.handlers.subscription import create_deep_link
texts = get_texts(language)
-
+
keyboard = []
-
+
if 'installationStep' in app and 'buttons' in app['installationStep']:
app_buttons = []
for button in app['installationStep']['buttons']:
- button_text = _get_localized_value(button.get('buttonText'), language)
- button_link = button.get('buttonLink')
-
- if not button_text or not button_link:
- continue
-
+ button_text = button['buttonText'].get(language, button['buttonText']['en'])
app_buttons.append(
- InlineKeyboardButton(text=f"π₯ {button_text}", url=button_link)
+ InlineKeyboardButton(text=f"π₯ {button_text}", url=button['buttonLink'])
)
if len(app_buttons) == 2:
keyboard.append(app_buttons)
app_buttons = []
-
+
if app_buttons:
keyboard.append(app_buttons)
-
- additional_before_buttons = _build_additional_buttons(
- app.get('additionalBeforeAddSubscriptionStep'),
- language,
- )
-
- for button in additional_before_buttons:
- keyboard.append([button])
-
- connect_link = create_deep_link(app, subscription_url)
-
- if connect_link:
- connect_button = InlineKeyboardButton(
- text=texts.t("CONNECT_BUTTON", "π ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡΡΡ"),
- url=connect_link,
- )
- elif settings.is_happ_cryptolink_mode():
- connect_button = InlineKeyboardButton(
- text=texts.t("CONNECT_BUTTON", "π ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡΡΡ"),
+
+ if settings.is_happ_cryptolink_mode():
+ copy_button = InlineKeyboardButton(
+ text=texts.t("COPY_SUBSCRIPTION_LINK", "π Π‘ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ ΡΡΡΠ»ΠΊΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ"),
callback_data="open_subscription_link",
)
else:
- connect_button = InlineKeyboardButton(
- text=texts.t("CONNECT_BUTTON", "π ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡΡΡ"),
+ copy_button = InlineKeyboardButton(
+ text=texts.t("COPY_SUBSCRIPTION_LINK", "π Π‘ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ ΡΡΡΠ»ΠΊΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ"),
url=subscription_url,
)
- keyboard.append([connect_button])
-
- additional_after_buttons = _build_additional_buttons(
- app.get('additionalAfterAddSubscriptionStep'),
- language,
- )
-
- for button in additional_after_buttons:
- keyboard.append([button])
-
+ keyboard.append([copy_button])
+
+ if 'additionalAfterAddSubscriptionStep' in app and 'buttons' in app['additionalAfterAddSubscriptionStep']:
+ for button in app['additionalAfterAddSubscriptionStep']['buttons']:
+ button_text = button['buttonText'].get(language, button['buttonText']['en'])
+ keyboard.append([
+ InlineKeyboardButton(text=button_text, url=button['buttonLink'])
+ ])
+
keyboard.extend([
[
InlineKeyboardButton(text=texts.t("OTHER_APPS_BUTTON", "π ΠΡΡΠ³ΠΈΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ"), callback_data=f"app_list_{device_type}")
diff --git a/app/localization/locales/en.json b/app/localization/locales/en.json
index 4c10c0ec..8b1cdb3a 100644
--- a/app/localization/locales/en.json
+++ b/app/localization/locales/en.json
@@ -435,14 +435,12 @@
"SUBSCRIPTION_DEVICE_GUIDE_TITLE": "π± Setup for {device_name}",
"SUBSCRIPTION_DEVICE_LINK_TITLE": "π Subscription link:",
"SUBSCRIPTION_DEVICE_FEATURED_APP": "π Recommended app: {app_name}",
- "SUBSCRIPTION_DEVICE_OTHER_APPS": "π¦ Other apps: {app_list}",
- "SUBSCRIPTION_DEVICE_OTHER_APPS_HINT": "Tap the \"Other apps\" button below to choose another app.",
"SUBSCRIPTION_DEVICE_STEP_INSTALL_TITLE": "Step 1 - Install:",
"SUBSCRIPTION_DEVICE_STEP_ADD_TITLE": "Step 2 - Add subscription:",
"SUBSCRIPTION_DEVICE_STEP_CONNECT_TITLE": "Step 3 - Connect:",
"SUBSCRIPTION_DEVICE_HOW_TO_TITLE": "π‘ How to connect:",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP1": "1. Install the app from the link above",
- "SUBSCRIPTION_DEVICE_HOW_TO_STEP2": "2. Tap the \"Connect\" button below",
+ "SUBSCRIPTION_DEVICE_HOW_TO_STEP2": "2. Copy the subscription link (tap on it)",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP3": "3. Open the app and paste the link",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP4": "4. Connect to a server",
"SUBSCRIPTION_APPS_TITLE": "π± Apps for {device_name}",
diff --git a/app/localization/locales/ru.json b/app/localization/locales/ru.json
index 3eb90aae..ca6ba4fd 100644
--- a/app/localization/locales/ru.json
+++ b/app/localization/locales/ru.json
@@ -445,14 +445,12 @@
"SUBSCRIPTION_DEVICE_GUIDE_TITLE": "π± ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π΄Π»Ρ {device_name}",
"SUBSCRIPTION_DEVICE_LINK_TITLE": "π Π‘ΡΡΠ»ΠΊΠ° ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ:",
"SUBSCRIPTION_DEVICE_FEATURED_APP": "π Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌΠΎΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅: {app_name}",
- "SUBSCRIPTION_DEVICE_OTHER_APPS": "π¦ ΠΡΡΠ³ΠΈΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ: {app_list}",
- "SUBSCRIPTION_DEVICE_OTHER_APPS_HINT": "ΠΠ°ΠΆΠΌΠΈΡΠ΅ ΠΊΠ½ΠΎΠΏΠΊΡ \"ΠΡΡΠ³ΠΈΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ\" Π½ΠΈΠΆΠ΅, ΡΡΠΎΠ±Ρ Π²ΡΠ±ΡΠ°ΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅.",
"SUBSCRIPTION_DEVICE_STEP_INSTALL_TITLE": "Π¨Π°Π³ 1 - Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°:",
"SUBSCRIPTION_DEVICE_STEP_ADD_TITLE": "Π¨Π°Π³ 2 - ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ:",
"SUBSCRIPTION_DEVICE_STEP_CONNECT_TITLE": "Π¨Π°Π³ 3 - ΠΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅:",
"SUBSCRIPTION_DEVICE_HOW_TO_TITLE": "π‘ ΠΠ°ΠΊ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡ:",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP1": "1. Π£ΡΡΠ°Π½ΠΎΠ²ΠΈΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎ ΡΡΡΠ»ΠΊΠ΅ Π²ΡΡΠ΅",
- "SUBSCRIPTION_DEVICE_HOW_TO_STEP2": "2. ΠΠ°ΠΆΠΌΠΈΡΠ΅ ΠΊΠ½ΠΎΠΏΠΊΡ \"ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡΡΡ\" Π½ΠΈΠΆΠ΅",
+ "SUBSCRIPTION_DEVICE_HOW_TO_STEP2": "2. Π‘ΠΊΠΎΠΏΠΈΡΡΠΉΡΠ΅ ΡΡΡΠ»ΠΊΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ (Π½Π°ΠΆΠΌΠΈΡΠ΅ Π½Π° Π½Π΅Ρ)",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP3": "3. ΠΡΠΊΡΠΎΠΉΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΈ Π²ΡΡΠ°Π²ΡΡΠ΅ ΡΡΡΠ»ΠΊΡ",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP4": "4. ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΠ΅ΡΡ ΠΊ ΡΠ΅ΡΠ²Π΅ΡΡ",
"SUBSCRIPTION_APPS_TITLE": "π± ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π΄Π»Ρ {device_name}",
diff --git a/locales/en.json b/locales/en.json
index 0114b186..e4b12469 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -475,14 +475,12 @@
"SUBSCRIPTION_HAPP_CRYPTOLINK_BLOCK": "
{crypto_link}",
"SUBSCRIPTION_DEVICE_LINK_TITLE": "π Subscription link:",
"SUBSCRIPTION_DEVICE_FEATURED_APP": "π Recommended app: {app_name}",
- "SUBSCRIPTION_DEVICE_OTHER_APPS": "π¦ Other apps: {app_list}",
- "SUBSCRIPTION_DEVICE_OTHER_APPS_HINT": "Tap the \"Other apps\" button below to choose another app.",
"SUBSCRIPTION_DEVICE_STEP_INSTALL_TITLE": "Step 1 - Install:",
"SUBSCRIPTION_DEVICE_STEP_ADD_TITLE": "Step 2 - Add subscription:",
"SUBSCRIPTION_DEVICE_STEP_CONNECT_TITLE": "Step 3 - Connect:",
"SUBSCRIPTION_DEVICE_HOW_TO_TITLE": "π‘ How to connect:",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP1": "1. Install the app from the link above",
- "SUBSCRIPTION_DEVICE_HOW_TO_STEP2": "2. Tap the \"Connect\" button below",
+ "SUBSCRIPTION_DEVICE_HOW_TO_STEP2": "2. Copy the subscription link (tap on it)",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP3": "3. Open the app and paste the link",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP4": "4. Connect to a server",
"SUBSCRIPTION_APPS_TITLE": "π± Apps for {device_name}",
diff --git a/locales/ru.json b/locales/ru.json
index 5fe17fbb..31d2704e 100644
--- a/locales/ru.json
+++ b/locales/ru.json
@@ -477,14 +477,12 @@
"SUBSCRIPTION_HAPP_CRYPTOLINK_BLOCK": "{crypto_link}",
"SUBSCRIPTION_DEVICE_LINK_TITLE": "π Π‘ΡΡΠ»ΠΊΠ° ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ:",
"SUBSCRIPTION_DEVICE_FEATURED_APP": "π Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌΠΎΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅: {app_name}",
- "SUBSCRIPTION_DEVICE_OTHER_APPS": "π¦ ΠΡΡΠ³ΠΈΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ: {app_list}",
- "SUBSCRIPTION_DEVICE_OTHER_APPS_HINT": "ΠΠ°ΠΆΠΌΠΈΡΠ΅ ΠΊΠ½ΠΎΠΏΠΊΡ \"ΠΡΡΠ³ΠΈΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ\" Π½ΠΈΠΆΠ΅, ΡΡΠΎΠ±Ρ Π²ΡΠ±ΡΠ°ΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅.",
"SUBSCRIPTION_DEVICE_STEP_INSTALL_TITLE": "Π¨Π°Π³ 1 - Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°:",
"SUBSCRIPTION_DEVICE_STEP_ADD_TITLE": "Π¨Π°Π³ 2 - ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ:",
"SUBSCRIPTION_DEVICE_STEP_CONNECT_TITLE": "Π¨Π°Π³ 3 - ΠΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅:",
"SUBSCRIPTION_DEVICE_HOW_TO_TITLE": "π‘ ΠΠ°ΠΊ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡ:",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP1": "1. Π£ΡΡΠ°Π½ΠΎΠ²ΠΈΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎ ΡΡΡΠ»ΠΊΠ΅ Π²ΡΡΠ΅",
- "SUBSCRIPTION_DEVICE_HOW_TO_STEP2": "2. ΠΠ°ΠΆΠΌΠΈΡΠ΅ ΠΊΠ½ΠΎΠΏΠΊΡ \"ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΡΡΡ\" Π½ΠΈΠΆΠ΅",
+ "SUBSCRIPTION_DEVICE_HOW_TO_STEP2": "2. Π‘ΠΊΠΎΠΏΠΈΡΡΠΉΡΠ΅ ΡΡΡΠ»ΠΊΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ (Π½Π°ΠΆΠΌΠΈΡΠ΅ Π½Π° Π½Π΅Ρ)",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP3": "3. ΠΡΠΊΡΠΎΠΉΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΈ Π²ΡΡΠ°Π²ΡΡΠ΅ ΡΡΡΠ»ΠΊΡ",
"SUBSCRIPTION_DEVICE_HOW_TO_STEP4": "4. ΠΠΎΠ΄ΠΊΠ»ΡΡΠΈΡΠ΅ΡΡ ΠΊ ΡΠ΅ΡΠ²Π΅ΡΡ",
"SUBSCRIPTION_APPS_TITLE": "π± ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ Π΄Π»Ρ {device_name}",