From 790ffecade98ea25d30b3f20e8598ccaf0e205f6 Mon Sep 17 00:00:00 2001 From: Egor Date: Wed, 15 Oct 2025 02:35:37 +0300 Subject: [PATCH] Revert "fix: group WATA payments in the admin menu" --- app/handlers/admin/bot_configuration.py | 233 +++++------------------- app/services/system_settings_service.py | 5 - 2 files changed, 42 insertions(+), 196 deletions(-) diff --git a/app/handlers/admin/bot_configuration.py b/app/handlers/admin/bot_configuration.py index 2fc90616..a6531fab 100644 --- a/app/handlers/admin/bot_configuration.py +++ b/app/handlers/admin/bot_configuration.py @@ -46,18 +46,9 @@ CATEGORY_GROUP_METADATA: Dict[str, Dict[str, object]] = { }, "payments": { "title": "💳 Платежные системы", - "description": "YooKassa, WATA, CryptoBot, MulenPay, PAL24, Tribute и Telegram Stars.", + "description": "YooKassa, CryptoBot, MulenPay, PAL24, Tribute и Telegram Stars.", "icon": "💳", - "categories": ( - "PAYMENT", - "YOOKASSA", - "CRYPTOBOT", - "MULENPAY", - "PAL24", - "TRIBUTE", - "TELEGRAM", - "WATA", - ), + "categories": ("PAYMENT", "YOOKASSA", "CRYPTOBOT", "MULENPAY", "PAL24", "TRIBUTE", "TELEGRAM"), }, "subscriptions": { "title": "📅 Подписки и цены", @@ -221,21 +212,6 @@ def _get_group_description(group_key: str) -> str: return str(meta.get("description", "")) -def _format_days(count: int) -> str: - remainder = count % 100 - if 11 <= remainder <= 14: - suffix = "дней" - else: - last_digit = count % 10 - if last_digit == 1: - suffix = "день" - elif last_digit in {2, 3, 4}: - suffix = "дня" - else: - suffix = "дней" - return f"{count} {suffix}" - - def _get_group_icon(group_key: str) -> str: meta = _get_group_meta(group_key) return str(meta.get("icon", "⚙️")) @@ -250,7 +226,6 @@ def _get_group_status(group_key: str) -> Tuple[str, str]: "MulenPay": settings.is_mulenpay_enabled(), "PAL24": settings.is_pal24_enabled(), "Tribute": settings.TRIBUTE_ENABLED, - "WATA": settings.is_wata_enabled(), "Stars": settings.TELEGRAM_STARS_ENABLED, } active = sum(1 for value in payment_statuses.values() if value) @@ -269,7 +244,7 @@ def _get_group_status(group_key: str) -> Tuple[str, str]: or (settings.REMNAWAVE_USERNAME and settings.REMNAWAVE_PASSWORD) ) ) - return ("🟢", "Подключено") if api_ready else ("🟡", "Нужно указать URL и ключи") + return ("🟢", "API подключено") if api_ready else ("🟡", "Нужно указать URL и ключи") if key == "server": mode = (settings.SERVER_STATUS_MODE or "").lower() @@ -289,14 +264,14 @@ def _get_group_status(group_key: str) -> Tuple[str, str]: user_on = settings.is_notifications_enabled() admin_on = settings.is_admin_notifications_enabled() if user_on and admin_on: - return "🟢", "Все включены" + return "🟢", "Все уведомления включены" if user_on or admin_on: return "🟡", "Часть уведомлений включена" return "⚪", "Уведомления отключены" if key == "trial": if settings.TRIAL_DURATION_DAYS > 0: - return "🟢", f"{_format_days(settings.TRIAL_DURATION_DAYS)}" + return "🟢", f"{settings.TRIAL_DURATION_DAYS} дней пробного периода" return "⚪", "Триал отключен" if key == "referral": @@ -306,14 +281,7 @@ def _get_group_status(group_key: str) -> Tuple[str, str]: or settings.REFERRAL_INVITER_BONUS_KOPEKS or settings.get_referred_user_reward_kopeks() ) - return ("🟢", "Активна") if active else ("⚪", "Бонусы не заданы") - - if key == "support": - if not settings.SUPPORT_MENU_ENABLED: - return "⚪", "Меню отключено" - if settings.SUPPORT_USERNAME and settings.SUPPORT_USERNAME != "@support": - return "🟢", "Команда готова" - return "🟡", "Требует настройки" + return ("🟢", "Программа активна") if active else ("⚪", "Бонусы не заданы") if key == "core": token_ok = bool(getattr(settings, "BOT_TOKEN", "")) @@ -338,12 +306,7 @@ def _get_group_status(group_key: str) -> Tuple[str, str]: branding = bool(settings.ENABLE_LOGO_MODE or settings.MINIAPP_CUSTOM_URL) return ("🟢", "Брендинг настроен") if branding else ("⚪", "Настройки по умолчанию") - if key == "external_admin": - if getattr(settings, "WEB_API_DEFAULT_TOKEN", ""): - return "🟢", "Настроено" - return "⚪", "Требуется токен" - - return "🟢", "Готово" + return "🟢", "Готово к работе" def _get_setting_icon(definition, current_value: object) -> str: @@ -390,27 +353,22 @@ def _render_dashboard_overview() -> str: ) lines: List[str] = [ - "⚙️ ПАНЕЛЬ УПРАВЛЕНИЯ БОТОМ", + "⚙️ Панель управления ботом", "", f"Всего параметров: {total_settings} • Переопределено: {total_overrides}", "", - "Группы настроек:", + "Выберите категорию ниже или используйте быстрые действия:", "", ] for group_key, title, items in grouped: status_icon, status_text = _get_group_status(group_key) - description = ( - _get_group_description(group_key) - if group_key != CATEGORY_FALLBACK_KEY - else "Настройки без категории." - ) + description = _get_group_description(group_key) if group_key != CATEGORY_FALLBACK_KEY else "Настройки без категории." total = sum(count for _, _, count in items) - icon = _get_group_icon(group_key) - lines.append(f"{status_icon} {icon} {title} — {status_text}") + lines.append(f"{status_icon} {title} — {status_text}") if description: lines.append(f" {description}") - lines.append(f"└ Настроек: {total}") + lines.append(f" Настроек: {total}") lines.append("") lines.append("🔍 Кнопка поиска поможет найти параметр по названию, описанию или ключу.") @@ -503,15 +461,7 @@ def _build_search_results_keyboard(results: List[Dict[str, object]]) -> types.In rows.append( [ types.InlineKeyboardButton( - text="⬅️ Попробовать снова", - callback_data="botcfg_action:search", - ) - ] - ) - rows.append( - [ - types.InlineKeyboardButton( - text="🏠 Главное меню", + text="⬅️ В главное меню", callback_data="admin_bot_config", ) ] @@ -555,7 +505,7 @@ async def start_settings_search( await callback.message.edit_text( "🔍 Поиск по настройкам\n\n" - "Отправьте часть ключа или названия.\n" + "Отправьте часть ключа или названия настройки. \n" "Например: yookassa или уведомления.", reply_markup=keyboard, parse_mode="HTML", @@ -592,8 +542,6 @@ async def handle_search_query( lines.append( f"{index}. {item['name']} — {item['value']} ({item['category_label']})" ) - lines.append("") - lines.append("Нажмите на нужную настройку, чтобы открыть её.") text = "\n".join(lines) else: keyboard = types.InlineKeyboardMarkup( @@ -632,7 +580,7 @@ async def show_presets( lines = [ "🎯 Готовые пресеты", "", - "Выберите набор параметров:", + "Выберите набор параметров, чтобы быстро применить его к боту.", "", ] for key, meta in PRESET_METADATA.items(): @@ -766,14 +714,12 @@ async def apply_preset( title = PRESET_METADATA.get(preset_key, {}).get("title", preset_key) summary_lines = [ - f'✅ Пресет "{title}" применен', + f"✅ Пресет {title} применен", "", f"Изменено параметров: {len(applied)}", ] if applied: - summary_lines.extend( - ["", "\n".join(f"• {key}" for key in applied)] - ) + summary_lines.append("\n".join(f"• {key}" for key in applied)) keyboard = types.InlineKeyboardMarkup( inline_keyboard=[ @@ -860,7 +806,7 @@ async def start_import_settings( await callback.message.edit_text( "📥 Импорт настроек\n\n" - "Прикрепите .env файл или отправьте текстом пары KEY=value.\n\n" + "Прикрепите .env файл или отправьте текстом пары KEY=value.\n" "Неизвестные параметры будут проигнорированы.", parse_mode="HTML", reply_markup=keyboard, @@ -940,30 +886,15 @@ async def handle_import_message( f"Обновлено параметров: {len(applied)}", ] if applied: - summary_lines.extend( - [ - "", - "\n".join(f"• {key}" for key in applied), - ] - ) + summary_lines.append("\n".join(f"• {key}" for key in applied)) if skipped: - summary_lines.extend( - [ - "", - "Пропущено (неизвестные ключи):", - "\n".join(f"• {key}" for key in skipped), - ] - ) + summary_lines.append("\nПропущено (неизвестные ключи):") + summary_lines.append("\n".join(f"• {key}" for key in skipped)) if errors: - summary_lines.extend( - [ - "", - "Ошибки разбора:", - "\n".join(f"• {html.escape(err)}" for err in errors), - ] - ) + summary_lines.append("\nОшибки разбора:") + summary_lines.append("\n".join(f"• {html.escape(err)}" for err in errors)) keyboard = types.InlineKeyboardMarkup( inline_keyboard=[ @@ -1006,9 +937,7 @@ async def show_settings_history( ) except Exception: formatted_value = row.value or "—" - lines.append( - f"{ts_text} • {row.key} = {html.escape(str(formatted_value))}" - ) + lines.append(f"{ts_text} • {row.key} = {formatted_value}") else: lines.append("История изменений пуста.") @@ -1180,12 +1109,8 @@ def _build_groups_keyboard() -> types.InlineKeyboardMarkup: for group_key, title, items in grouped: total = sum(count for _, _, count in items) - status_icon, status_text = _get_group_status(group_key) - icon = _get_group_icon(group_key) - button_text = ( - f"{status_icon} {icon} {title} — {status_text}\n" - f"└ Настроек: {total}" - ) + status_icon, _ = _get_group_status(group_key) + button_text = f"{status_icon} {title} ({total})" rows.append( [ types.InlineKeyboardButton( @@ -1237,7 +1162,7 @@ def _build_groups_keyboard() -> types.InlineKeyboardMarkup: rows.append( [ types.InlineKeyboardButton( - text="⬅️ Назад в админку", + text="⬅️ Назад", callback_data="admin_submenu_settings", ) ] @@ -1268,10 +1193,7 @@ def _build_categories_keyboard( rows.append( [ types.InlineKeyboardButton( - text=( - f"{status_icon} {_get_group_icon(group_key)} {group_title}\n" - f"└ Статус: {_status_text}" - ), + text=f"{status_icon} {group_title}", callback_data="botcfg_group:noop", ) ] @@ -1284,7 +1206,7 @@ def _build_categories_keyboard( if bot_configuration_service.has_override(definition.key): overrides += 1 badge = "✳️" if overrides else "•" - button_text = f"{badge} • {label} ({count})" + button_text = f"{badge} {label} ({count})" buttons.append( types.InlineKeyboardButton( text=button_text, @@ -1306,7 +1228,7 @@ def _build_categories_keyboard( ) nav_row.append( types.InlineKeyboardButton( - text=f"[{page}/{total_pages}]", + text=f"{page}/{total_pages}", callback_data="botcfg_group:noop", ) ) @@ -1431,7 +1353,7 @@ def _build_settings_keyboard( ) nav_row.append( types.InlineKeyboardButton( - text=f"[{page}/{total_pages}]", callback_data="botcfg_cat_page:noop" + text=f"{page}/{total_pages}", callback_data="botcfg_cat_page:noop" ) ) if page < total_pages: @@ -1542,11 +1464,6 @@ def _build_setting_keyboard( def _render_setting_text(key: str) -> str: summary = bot_configuration_service.get_setting_summary(key) guidance = bot_configuration_service.get_setting_guidance(key) - description = guidance.get("description") or "—" - format_hint = guidance.get("format") or "—" - example = guidance.get("example") or "—" - warning = guidance.get("warning") or "—" - dependencies = guidance.get("dependencies") or "—" lines = [ f"🧩 {summary['name']}", @@ -1562,11 +1479,11 @@ def _render_setting_text(key: str) -> str: else [] ), "", - f"📘 Описание: {description}", - f"📐 Формат: {format_hint}", - f"💡 Пример: {example}", - f"⚠️ Важно: {warning}", - f"🔗 Связанные настройки: {dependencies}", + f"📘 Описание: {guidance['description']}", + f"📐 Формат: {guidance['format']}", + f"💡 Пример: {guidance['example']}", + f"⚠️ Важно: {guidance['warning']}", + f"🔗 Связанные настройки: {guidance['dependencies']}", ] choices = bot_configuration_service.get_choice_options(key) @@ -1626,13 +1543,11 @@ async def show_bot_config_group( keyboard = _build_categories_keyboard(group_key, group_title, items, page) status_icon, status_text = _get_group_status(group_key) description = _get_group_description(group_key) - icon = _get_group_icon(group_key) - lines = [f"{icon} {group_title}"] - lines.append(f"Хлебные крошки: 🏠 → {group_title}") - if status_text: - lines.append(f"Статус: {status_icon} {status_text}") + lines = [f"{status_icon} {group_title}"] if description: lines.append(description) + if status_text: + lines.append(f"Статус: {status_text}") lines.append("") lines.append("📂 Выберите категорию настроек:") await callback.message.edit_text( @@ -1672,12 +1587,12 @@ async def show_bot_config_category( ) text_lines = [ f"🗂 {category_label}", - f"Хлебные крошки: 🏠 → {group_title} → {category_label}", + f"Навигация: 🏠 Главное → {group_title} → {category_label}", ] if category_description: text_lines.append(category_description) text_lines.append("") - text_lines.append("📋 Список настроек категории:") + text_lines.append("📋 Выберите настройку для просмотра или редактирования:") await callback.message.edit_text( "\n".join(text_lines), reply_markup=keyboard, @@ -1923,70 +1838,6 @@ async def test_payment_provider( await _refresh_markup() return - if method == "wata": - if not settings.is_wata_enabled(): - await callback.answer("❌ WATA отключена", show_alert=True) - return - - amount_kopeks = 10 * 100 - description = settings.get_balance_payment_description(amount_kopeks) - try: - payment_result = await payment_service.create_wata_payment( - db=db, - user_id=db_user.id, - amount_kopeks=amount_kopeks, - description=f"Тестовый платеж WATA (админ): {description}", - language=language, - ) - except Exception: - payment_result = None - - if not payment_result or not payment_result.get("payment_url"): - await callback.answer("❌ Не удалось создать платеж WATA", show_alert=True) - await _refresh_markup() - return - - payment_url = payment_result["payment_url"] - local_payment_id = payment_result.get("local_payment_id") - payment_link_id = payment_result.get("payment_link_id") - - message_lines = [ - "🧪 Тестовый платеж WATA", - "", - f"💰 Сумма: {texts.format_price(amount_kopeks)}", - ] - if payment_link_id: - message_lines.append(f"🆔 ID: {payment_link_id}") - - reply_rows: list[list[types.InlineKeyboardButton]] = [ - [ - types.InlineKeyboardButton( - text="💳 Перейти к оплате", - url=payment_url, - ) - ] - ] - - if local_payment_id: - reply_rows.append( - [ - types.InlineKeyboardButton( - text="📊 Проверить статус", - callback_data=f"check_wata_{local_payment_id}", - ) - ] - ) - - reply_markup = types.InlineKeyboardMarkup(inline_keyboard=reply_rows) - await callback.message.answer( - "\n".join(message_lines), - reply_markup=reply_markup, - parse_mode="HTML", - ) - await callback.answer("✅ Ссылка на платеж WATA отправлена", show_alert=True) - await _refresh_markup() - return - if method == "pal24": if not settings.is_pal24_enabled(): await callback.answer("❌ PayPalych отключен", show_alert=True) @@ -2220,7 +2071,7 @@ async def show_bot_config_setting( return text = _render_setting_text(key) keyboard = _build_setting_keyboard(key, group_key, category_page, settings_page) - await callback.message.edit_text(text, reply_markup=keyboard, parse_mode="HTML") + await callback.message.edit_text(text, reply_markup=keyboard) await _store_setting_context( state, key=key, diff --git a/app/services/system_settings_service.py b/app/services/system_settings_service.py index dd711e13..02cf22ee 100644 --- a/app/services/system_settings_service.py +++ b/app/services/system_settings_service.py @@ -72,7 +72,6 @@ class BotConfigurationService: "LOCALIZATION": "🌍 Языки интерфейса", "CHANNEL": "📣 Обязательная подписка", "PAYMENT": "💳 Общие платежные настройки", - "WATA": "💳 WATA", "TELEGRAM": "⭐ Telegram Stars", "CRYPTOBOT": "🪙 CryptoBot", "YOOKASSA": "🟣 YooKassa", @@ -122,7 +121,6 @@ class BotConfigurationService: "LOCALIZATION": "Доступные языки, локализация интерфейса и выбор языка.", "CHANNEL": "Настройки обязательной подписки на канал или группу.", "PAYMENT": "Общие тексты платежей, описания чеков и шаблоны.", - "WATA": "Интеграция WATA для платежных ссылок и лимитов.", "YOOKASSA": "Интеграция с YooKassa: идентификаторы магазина и вебхуки.", "CRYPTOBOT": "CryptoBot и криптоплатежи через Telegram.", "MULENPAY": "Платежи MulenPay и параметры магазина.", @@ -221,7 +219,6 @@ class BotConfigurationService: "PAYMENT_SUBSCRIPTION_DESCRIPTION": "PAYMENT", "PAYMENT_BALANCE_TEMPLATE": "PAYMENT", "PAYMENT_SUBSCRIPTION_TEMPLATE": "PAYMENT", - "DISABLE_TOPUP_BUTTONS": "PAYMENT", "ENABLE_NOTIFICATIONS": "NOTIFICATIONS", "NOTIFICATION_RETRY_ATTEMPTS": "NOTIFICATIONS", "NOTIFICATION_CACHE_HOURS": "NOTIFICATIONS", @@ -270,10 +267,8 @@ class BotConfigurationService: "CRYPTOBOT_": "CRYPTOBOT", "MULENPAY_": "MULENPAY", "PAL24_": "PAL24", - "WATA_": "WATA", "PAYMENT_": "PAYMENT", "EXTERNAL_ADMIN_": "EXTERNAL_ADMIN", - "BOT_": "CORE", "CONNECT_BUTTON_HAPP": "HAPP", "HAPP_": "HAPP", "SKIP_": "SKIP",