feat: улучшения массовой обработки счетов
Some checks reported errors
continuous-integration/drone/push Build encountered an error
Some checks reported errors
continuous-integration/drone/push Build encountered an error
- Добавлено уведомление о задержке при отправке >250 счетов - Реализовано массовое удаление счетов через /remove_account - Исправлен flood control с задержкой 500ms между сообщениями - Callback.answer() перенесён в начало для предотвращения timeout - Добавлена обработка TelegramRetryAfter с повторной попыткой
This commit is contained in:
@@ -438,31 +438,70 @@ async def skip_lottery_add(callback: CallbackQuery, state: FSMContext):
|
||||
@admin_only
|
||||
async def remove_account_command(message: Message):
|
||||
"""
|
||||
Деактивировать счет
|
||||
Формат: /remove_account <account_number>
|
||||
Деактивировать счет(а)
|
||||
Формат: /remove_account <account_number1> [account_number2] [account_number3] ...
|
||||
Можно указать несколько счетов через пробел для массового удаления
|
||||
"""
|
||||
|
||||
parts = message.text.split()
|
||||
if len(parts) != 2:
|
||||
if len(parts) < 2:
|
||||
await message.answer(
|
||||
"❌ Неверный формат команды\n\n"
|
||||
"Используйте: /remove_account <account_number>"
|
||||
"Используйте: /remove_account <account_number1> [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 # Игнорируем если не получилось отправить
|
||||
|
||||
Reference in New Issue
Block a user