diff --git a/src/handlers/admin_account_handlers.py b/src/handlers/admin_account_handlers.py index 4d5d221..94f7a96 100644 --- a/src/handlers/admin_account_handlers.py +++ b/src/handlers/admin_account_handlers.py @@ -438,31 +438,70 @@ async def skip_lottery_add(callback: CallbackQuery, state: FSMContext): @admin_only async def remove_account_command(message: Message): """ - Деактивировать счет - Формат: /remove_account + Деактивировать счет(а) + Формат: /remove_account [account_number2] [account_number3] ... + Можно указать несколько счетов через пробел для массового удаления """ parts = message.text.split() - if len(parts) != 2: + if len(parts) < 2: await message.answer( "❌ Неверный формат команды\n\n" - "Используйте: /remove_account " + "Используйте: /remove_account [account_number2] ...\n\n" + "Примеры:\n" + "• /remove_account 12-34-56-78-90-12-34\n" + "• /remove_account 12-34-56-78-90-12-34 98-76-54-32-10-98-76" ) return - account_number = parts[1] + account_numbers = parts[1:] # Все аргументы после команды try: - async with async_session_maker() as session: - success = await AccountService.deactivate_account(session, account_number) + results = { + 'success': [], + 'not_found': [], + 'errors': [] + } - if success: - await message.answer(f"✅ Счет {account_number} деактивирован") + async with async_session_maker() as session: + for account_number in account_numbers: + try: + success = await AccountService.deactivate_account(session, account_number) + if success: + results['success'].append(account_number) + else: + results['not_found'].append(account_number) + except Exception as e: + results['errors'].append((account_number, str(e))) + + # Формируем отчёт + response_parts = [] + + if results['success']: + response_parts.append( + f"✅ *Деактивировано счетов: {len(results['success'])}*\n" + + "\n".join(f"• `{acc}`" for acc in results['success']) + ) + + if results['not_found']: + response_parts.append( + f"❌ *Не найдено счетов: {len(results['not_found'])}*\n" + + "\n".join(f"• `{acc}`" for acc in results['not_found']) + ) + + if results['errors']: + response_parts.append( + f"⚠️ *Ошибки при обработке: {len(results['errors'])}*\n" + + "\n".join(f"• `{acc}`: {err}" for acc, err in results['errors']) + ) + + if not response_parts: + await message.answer("❌ Не удалось обработать ни один счет") else: - await message.answer(f"❌ Счет {account_number} не найден") + await message.answer("\n\n".join(response_parts), parse_mode="Markdown") except Exception as e: - await message.answer(f"❌ Ошибка: {str(e)}") + await message.answer(f"❌ Критическая ошибка: {str(e)}") @router.message(Command("verify_winner")) @@ -707,6 +746,8 @@ async def user_info_command(message: Message): @router.callback_query(F.data == "view_my_accounts") async def view_my_accounts_callback(callback: CallbackQuery): """Показать все счета пользователя""" + import asyncio + try: async with async_session_maker() as session: # Получаем пользователя @@ -726,6 +767,19 @@ async def view_my_accounts_callback(callback: CallbackQuery): await callback.answer("У вас нет счетов", show_alert=True) return + # Отвечаем на callback сразу, чтобы не было timeout + await callback.answer("⏳ Загружаю ваши счета...") + + # Если счетов много - предупреждаем о задержке + batches_count = (len(accounts) + 49) // 50 # Округление вверх + if batches_count > 5: + await callback.message.answer( + f"📊 Найдено счетов: *{len(accounts)}*\n" + f"📤 Отправка {batches_count} сообщений с задержкой (~{batches_count//2} сек)\n\n" + f"⏳ _Пожалуйста, подождите. Бот не завис._", + parse_mode="Markdown" + ) + # Формируем сообщение с пагинацией (по 50 счетов на сообщение) BATCH_SIZE = 50 for i in range(0, len(accounts), BATCH_SIZE): @@ -736,9 +790,22 @@ async def view_my_accounts_callback(callback: CallbackQuery): status = "✅" if acc.is_active else "❌" text += f"{status} `{acc.account_number}`\n" - await callback.message.answer(text, parse_mode="Markdown") - - await callback.answer("✅ Список счетов отправлен") + try: + await callback.message.answer(text, parse_mode="Markdown") + # Задержка между сообщениями для избежания flood control + if i + BATCH_SIZE < len(accounts): + await asyncio.sleep(0.5) # 500ms между сообщениями + except Exception as send_error: + # Если flood control - ждём дольше + if "Flood control" in str(send_error) or "Too Many Requests" in str(send_error): + await asyncio.sleep(2) + await callback.message.answer(text, parse_mode="Markdown") + else: + raise except Exception as e: - await callback.answer(f"❌ Ошибка: {str(e)}", show_alert=True) + # Не используем callback.answer в except - может быть timeout + try: + await callback.message.answer(f"❌ Ошибка: {str(e)}") + except: + pass # Игнорируем если не получилось отправить