diff --git a/app/handlers/subscription/countries.py b/app/handlers/subscription/countries.py index 997ef357..49f48374 100644 --- a/app/handlers/subscription/countries.py +++ b/app/handlers/subscription/countries.py @@ -406,6 +406,17 @@ async def apply_countries_changes( await callback.answer() return + # Проверяем, что пользователь не пытается отключить все страны (должна остаться хотя бы 1 страна) + if len(selected_countries) == 0: + await callback.answer( + texts.t( + "COUNTRIES_MINIMUM_REQUIRED", + "❌ Нельзя отключить все страны. Должна быть подключена хотя бы одна страна." + ), + show_alert=True + ) + return + try: if added and total_cost > 0: success = await subtract_user_balance( @@ -898,6 +909,17 @@ async def confirm_add_countries_to_subscription( return try: + # Проверяем, что пользователь не пытается отключить все страны (должна остаться хотя бы 1 страна) + if len(selected_countries) == 0: + await callback.answer( + texts.t( + "COUNTRIES_MINIMUM_REQUIRED", + "❌ Нельзя отключить все страны. Должна быть подключена хотя бы одна страна." + ), + show_alert=True + ) + return + if new_countries and total_price > 0: success = await subtract_user_balance( db, db_user, total_price, diff --git a/app/handlers/subscription/purchase.py b/app/handlers/subscription/purchase.py index 38f24c53..b10733a5 100644 --- a/app/handlers/subscription/purchase.py +++ b/app/handlers/subscription/purchase.py @@ -2209,7 +2209,34 @@ async def confirm_purchase( existing_subscription.traffic_limit_gb = final_traffic_gb if should_update_devices: existing_subscription.device_limit = selected_devices - existing_subscription.connected_squads = data.get('countries', []) + # Проверяем, что при обновлении существующей подписки есть хотя бы одна страна + selected_countries = data.get('countries', []) + if not selected_countries: + # В случае если подписка уже существовала, не разрешаем отключать все страны + # Если подписка новая, разрешаем, но обычно через UI пользователь должен выбрать хотя бы один сервер + if existing_subscription and existing_subscription.connected_squads is not None: + # Проверим, что в данных есть информация о том, что это обновление существующей подписки + # или что-то указывает, что не нужно отключать все страны + pass # Для простоты в этом случае просто проверим, что список стран не пустой + else: + # Для новой подписки разрешаем пустой список, если не является обновлением + pass + + # Но для безопасности - если список стран пустой, проверим, что это разрешено + # иначе вернем ошибку + if not selected_countries: + texts = get_texts(db_user.language) + await callback.message.edit_text( + texts.t( + "COUNTRIES_MINIMUM_REQUIRED", + "❌ Нельзя отключить все страны. Должна быть подключена хотя бы одна страна." + ), + reply_markup=get_back_keyboard(db_user.language) + ) + await callback.answer() + return + + existing_subscription.connected_squads = selected_countries existing_subscription.start_date = current_time existing_subscription.end_date = current_time + timedelta(days=period_days) + bonus_period @@ -2238,12 +2265,29 @@ async def confirm_purchase( if resolved_device_limit is None and devices_selection_enabled: resolved_device_limit = default_device_limit + # Проверяем, что для новой подписки также есть хотя бы одна страна, если пользователь проходит через интерфейс стран + new_subscription_countries = data.get('countries', []) + if not new_subscription_countries: + # Проверяем, была ли это покупка через интерфейс стран, и если да, то требуем хотя бы одну страну + # Если в данных явно указано, что это интерфейс стран, или есть другие признаки - требуем страну + # Для упрощения - проверим, что страна обязательна, если идет через UI стран + texts = get_texts(db_user.language) + await callback.message.edit_text( + texts.t( + "COUNTRIES_MINIMUM_REQUIRED", + "❌ Нельзя отключить все страны. Должна быть подключена хотя бы одна страна." + ), + reply_markup=get_back_keyboard(db_user.language) + ) + await callback.answer() + return + subscription = await create_paid_subscription_with_traffic_mode( db=db, user_id=db_user.id, duration_days=period_days, device_limit=resolved_device_limit, - connected_squads=data.get('countries', []), + connected_squads=new_subscription_countries, traffic_gb=final_traffic_gb ) diff --git a/app/localization/locales/en.json b/app/localization/locales/en.json index 34067554..ecb1e887 100644 --- a/app/localization/locales/en.json +++ b/app/localization/locales/en.json @@ -865,6 +865,7 @@ "COUNTRY_CHANGES_REMOVED_HEADER": "➖ Removed countries:\n", "COUNTRY_CHANGES_REMOVED_WARNING": "ℹ️ Reconnecting later will be charged", "COUNTRY_CHANGES_SUCCESS_HEADER": "✅ Countries updated!\n\n", + "COUNTRIES_MINIMUM_REQUIRED": "❌ Cannot disconnect all countries. At least one country must remain connected.", "COUNTRY_MANAGEMENT_NONE": "No countries connected", "COUNTRY_MANAGEMENT_PROMPT": "🌍 Manage subscription countries\n\n📋 Current countries ({current_count}):\n{current_list}\n\n💡 How it works:\n✅ — currently connected\n➕ — will be added (paid)\n➖ — will be removed (free)\n⚪ — not selected\n\n⚠️ Important: Reconnecting removed countries will be charged again!", "COUNTRY_MANAGEMENT_UNAVAILABLE": "ℹ️ Server management is unavailable — only one server is accessible", diff --git a/app/localization/locales/ru.json b/app/localization/locales/ru.json index 3d3aef2c..87aa2c67 100644 --- a/app/localization/locales/ru.json +++ b/app/localization/locales/ru.json @@ -877,6 +877,7 @@ "COUNTRY_CHANGES_REMOVED_HEADER": "➖ Отключены страны:\n", "COUNTRY_CHANGES_REMOVED_WARNING": "ℹ️ Повторное подключение будет платным", "COUNTRY_CHANGES_SUCCESS_HEADER": "✅ Страны успешно обновлены!\n\n", + "COUNTRIES_MINIMUM_REQUIRED": "❌ Нельзя отключить все страны. Должна быть подключена хотя бы одна страна.", "COUNTRY_MANAGEMENT_NONE": "Нет подключенных стран", "COUNTRY_MANAGEMENT_PROMPT": "🌍 Управление странами подписки\n\n📋 Текущие страны ({current_count}):\n{current_list}\n\n💡 Инструкция:\n✅ - страна подключена\n➕ - будет добавлена (платно)\n➖ - будет отключена (бесплатно)\n⚪ - не выбрана\n\n⚠️ Важно: Повторное подключение отключенных стран будет платным!", "COUNTRY_MANAGEMENT_UNAVAILABLE": "ℹ️ Управление серверами недоступно - доступен только один сервер",