feat: кнопка 'Просмотреть все счета' при массовом добавлении (>50)
Some checks reported errors
continuous-integration/drone/push Build encountered an error
Some checks reported errors
continuous-integration/drone/push Build encountered an error
This commit is contained in:
@@ -22,6 +22,14 @@ class AddAccountStates(StatesGroup):
|
|||||||
choosing_lottery = State()
|
choosing_lottery = State()
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(Command("cancel"))
|
||||||
|
@admin_only
|
||||||
|
async def cancel_command(message: Message, state: FSMContext):
|
||||||
|
"""Отменить текущую операцию и сбросить состояние"""
|
||||||
|
await state.clear()
|
||||||
|
await message.answer("✅ Состояние сброшено. Все операции отменены.")
|
||||||
|
|
||||||
|
|
||||||
@router.message(Command("add_account"))
|
@router.message(Command("add_account"))
|
||||||
@admin_only
|
@admin_only
|
||||||
async def add_account_command(message: Message, state: FSMContext):
|
async def add_account_command(message: Message, state: FSMContext):
|
||||||
@@ -120,9 +128,30 @@ async def process_accounts_data(message: Message, state: FSMContext):
|
|||||||
return
|
return
|
||||||
|
|
||||||
lines = message.text.strip().split('\n')
|
lines = message.text.strip().split('\n')
|
||||||
|
|
||||||
|
# Ограничение: максимум 1000 счетов за раз
|
||||||
|
MAX_ACCOUNTS = 1000
|
||||||
|
if len(lines) > MAX_ACCOUNTS:
|
||||||
|
await message.answer(
|
||||||
|
f"⚠️ Слишком много счетов!\n\n"
|
||||||
|
f"Максимум за раз: {MAX_ACCOUNTS}\n"
|
||||||
|
f"Вы отправили: {len(lines)} строк\n\n"
|
||||||
|
f"Разделите данные на несколько частей."
|
||||||
|
)
|
||||||
|
await state.clear()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Отправляем начальное уведомление
|
||||||
|
progress_msg = await message.answer(
|
||||||
|
f"⏳ Обработка {len(lines)} строк...\n"
|
||||||
|
f"Пожалуйста, подождите..."
|
||||||
|
)
|
||||||
|
|
||||||
accounts_data = []
|
accounts_data = []
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
|
BATCH_SIZE = 100 # Обрабатываем по 100 счетов за раз
|
||||||
|
|
||||||
# Универсальный парсер: поддержка однострочного и многострочного формата
|
# Универсальный парсер: поддержка однострочного и многострочного формата
|
||||||
i = 0
|
i = 0
|
||||||
while i < len(lines):
|
while i < len(lines):
|
||||||
@@ -176,6 +205,16 @@ async def process_accounts_data(message: Message, state: FSMContext):
|
|||||||
'owner': owner,
|
'owner': owner,
|
||||||
'owner_id': owner.telegram_id if owner else None
|
'owner_id': owner.telegram_id if owner else None
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Обновляем progress каждые 50 счетов
|
||||||
|
if len(accounts_data) % 50 == 0:
|
||||||
|
try:
|
||||||
|
await progress_msg.edit_text(
|
||||||
|
f"⏳ Обработано: {len(accounts_data)} / ~{len(lines)}\n"
|
||||||
|
f"❌ Ошибок: {len(errors)}"
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass # Игнорируем ошибки редактирования
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
errors.append(f"Счет {account_number} (карта {club_card}): {str(e)}")
|
errors.append(f"Счет {account_number} (карта {club_card}): {str(e)}")
|
||||||
@@ -184,6 +223,12 @@ async def process_accounts_data(message: Message, state: FSMContext):
|
|||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
|
# Удаляем progress сообщение
|
||||||
|
try:
|
||||||
|
await progress_msg.delete()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
# Группируем счета по владельцам и отправляем групповые уведомления
|
# Группируем счета по владельцам и отправляем групповые уведомления
|
||||||
if accounts_data:
|
if accounts_data:
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
@@ -203,8 +248,13 @@ async def process_accounts_data(message: Message, state: FSMContext):
|
|||||||
f"💳 `{account_numbers[0]}`\n\n"
|
f"💳 `{account_numbers[0]}`\n\n"
|
||||||
"Теперь вы можете участвовать в розыгрышах!"
|
"Теперь вы можете участвовать в розыгрышах!"
|
||||||
)
|
)
|
||||||
else:
|
await message.bot.send_message(
|
||||||
# Групповое уведомление
|
owner_id,
|
||||||
|
notification_text,
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
elif len(account_numbers) <= 50:
|
||||||
|
# Групповое уведомление (до 50 счетов)
|
||||||
notification_text = (
|
notification_text = (
|
||||||
f"✅ К вашему профилю добавлено счетов: *{len(account_numbers)}*\n\n"
|
f"✅ К вашему профилю добавлено счетов: *{len(account_numbers)}*\n\n"
|
||||||
"💳 *Ваши счета:*\n"
|
"💳 *Ваши счета:*\n"
|
||||||
@@ -212,12 +262,37 @@ async def process_accounts_data(message: Message, state: FSMContext):
|
|||||||
for acc_num in account_numbers:
|
for acc_num in account_numbers:
|
||||||
notification_text += f"• `{acc_num}`\n"
|
notification_text += f"• `{acc_num}`\n"
|
||||||
notification_text += "\nТеперь вы можете участвовать в розыгрышах!"
|
notification_text += "\nТеперь вы можете участвовать в розыгрышах!"
|
||||||
|
|
||||||
await message.bot.send_message(
|
await message.bot.send_message(
|
||||||
owner_id,
|
owner_id,
|
||||||
notification_text,
|
notification_text,
|
||||||
parse_mode="Markdown"
|
parse_mode="Markdown"
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
# Много счетов - показываем первые 10 и кнопку
|
||||||
|
notification_text = (
|
||||||
|
f"✅ К вашему профилю добавлено счетов: *{len(account_numbers)}*\n\n"
|
||||||
|
"💳 *Первые 10 счетов:*\n"
|
||||||
|
)
|
||||||
|
for acc_num in account_numbers[:10]:
|
||||||
|
notification_text += f"• `{acc_num}`\n"
|
||||||
|
notification_text += f"\n_...и ещё {len(account_numbers) - 10} счетов_\n\n"
|
||||||
|
notification_text += "Теперь вы можете участвовать в розыгрышах!"
|
||||||
|
|
||||||
|
# Кнопка для просмотра всех счетов
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(
|
||||||
|
text="📋 Просмотреть все счета",
|
||||||
|
callback_data="view_my_accounts"
|
||||||
|
)]
|
||||||
|
])
|
||||||
|
|
||||||
|
await message.bot.send_message(
|
||||||
|
owner_id,
|
||||||
|
notification_text,
|
||||||
|
parse_mode="Markdown",
|
||||||
|
reply_markup=keyboard
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass # Игнорируем ошибки отправки уведомлений
|
pass # Игнорируем ошибки отправки уведомлений
|
||||||
|
|
||||||
@@ -627,3 +702,43 @@ async def user_info_command(message: Message):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await message.answer(f"❌ Ошибка: {str(e)}")
|
await message.answer(f"❌ Ошибка: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
@router.callback_query(F.data == "view_my_accounts")
|
||||||
|
async def view_my_accounts_callback(callback: CallbackQuery):
|
||||||
|
"""Показать все счета пользователя"""
|
||||||
|
try:
|
||||||
|
async with async_session_maker() as session:
|
||||||
|
# Получаем пользователя
|
||||||
|
user_result = await session.execute(
|
||||||
|
select(User).where(User.telegram_id == callback.from_user.id)
|
||||||
|
)
|
||||||
|
user = user_result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
await callback.answer("❌ Пользователь не найден", show_alert=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Получаем все счета
|
||||||
|
accounts = await AccountService.get_user_accounts(session, user.id)
|
||||||
|
|
||||||
|
if not accounts:
|
||||||
|
await callback.answer("У вас нет счетов", show_alert=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Формируем сообщение с пагинацией (по 50 счетов на сообщение)
|
||||||
|
BATCH_SIZE = 50
|
||||||
|
for i in range(0, len(accounts), BATCH_SIZE):
|
||||||
|
batch = accounts[i:i+BATCH_SIZE]
|
||||||
|
|
||||||
|
text = f"💳 *Ваши счета ({i+1}-{min(i+BATCH_SIZE, len(accounts))} из {len(accounts)}):*\n\n"
|
||||||
|
for acc in batch:
|
||||||
|
status = "✅" if acc.is_active else "❌"
|
||||||
|
text += f"{status} `{acc.account_number}`\n"
|
||||||
|
|
||||||
|
await callback.message.answer(text, parse_mode="Markdown")
|
||||||
|
|
||||||
|
await callback.answer("✅ Список счетов отправлен")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
await callback.answer(f"❌ Ошибка: {str(e)}", show_alert=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user