import asyncio from aiogram import Router from aiogram.types import CallbackQuery from bot.states import twofa_tasks from bot.services.bot_accounts import get_owned_bot from bot.logging_utils import describe_user, get_logger from bot.services.twofa import auto_update_2fa, stop_twofa_task from bot.api.asf import accept_confirmations, get_confirmations from bot.ui.keyboards import back_keyboard, confirmations_keyboard router = Router() logger = get_logger(__name__) @router.callback_query( lambda c: c.data and c.data.startswith("2fa_") and not c.data.startswith("2fa_refresh_"), ) async def twofa_handler(callback: CallbackQuery) -> None: await callback.answer() if not callback.data: logger.debug( "Колбэк открытия 2FA пришел без data от %s", describe_user(callback.from_user), ) return try: account = await get_owned_bot(callback.from_user.id, int(callback.data.replace("2fa_", ""))) except ValueError: account = None if account is None: await callback.answer("Бот не найден или вам не принадлежит", show_alert=True); return bot_name = account.bot_name message_id = callback.message.message_id logger.info( "Пользователь %s открыл 2FA для бота %s", describe_user(callback.from_user), bot_name, ) await stop_twofa_task(message_id) await callback.message.edit_text( f"🔐 {bot_name}\n\nЗагрузка 2FA...", reply_markup=back_keyboard(f"bot_{account.id}"), ) task = asyncio.create_task(auto_update_2fa(callback.message, bot_name, account.id)) twofa_tasks[message_id] = task logger.info( "Запущено фоновое обновление 2FA для бота %s в сообщении %s", bot_name, message_id, ) @router.callback_query( lambda c: c.data and c.data.startswith("confirm_") and c.data.removeprefix("confirm_").isdigit() and not c.data.startswith("confirm_list_") and not c.data.startswith("confirm_all_"), ) async def confirm_trades(callback: CallbackQuery) -> None: await callback.answer() try: account = await get_owned_bot(callback.from_user.id, int(callback.data.replace("confirm_", ""))) except ValueError: account = None if account is None: await callback.answer("Бот не найден или вам не принадлежит", show_alert=True); return bot_name = account.bot_name logger.info( "Пользователь %s подтвердил сделки для бота %s", describe_user(callback.from_user), bot_name, ) try: status = await accept_confirmations(bot_name) if status != 200: logger.warning( "Не удалось подтвердить сделки для бота %s: HTTP %s", bot_name, status, ) await callback.answer("Ошибка HTTP", show_alert=True) return logger.info("Сделки для бота %s подтверждены", bot_name) await callback.answer("Подтверждено", show_alert=True) await twofa_handler(callback) except Exception as error: logger.exception( "Ошибка при подтверждении сделок для бота %s", bot_name, ) await callback.message.edit_text(f"Ошибка: {error}") @router.callback_query( lambda c: c.data and c.data.startswith("confirm_list_") ) async def confirm_list(callback: CallbackQuery) -> None: await stop_twofa_task(callback.message.message_id) await callback.answer() if not callback.data: logger.debug( "Колбэк списка подтверждений пришел без data от %s", describe_user(callback.from_user), ) return try: account = await get_owned_bot(callback.from_user.id, int(callback.data.replace("confirm_list_", ""))) except ValueError: account = None if account is None: await callback.answer("Бот не найден или вам не принадлежит", show_alert=True); return bot_name = account.bot_name logger.info( "Пользователь %s открыл список подтверждений для бота %s", describe_user(callback.from_user), bot_name, ) try: confirmations = await get_confirmations(bot_name) if not confirmations: logger.info("Для бота %s подтверждений не найдено", bot_name) text = "Подтверждений нет" else: logger.info( "Для бота %s найдено %s подтверждени(й)", bot_name, len(confirmations), ) text = f"🔐 {bot_name}\n\nПодтверждения:\n\n" for conf in confirmations: text += f"- {conf['type_name']}\nID: {conf['id']}\n\n" await callback.message.edit_text( text, reply_markup=confirmations_keyboard(account.id) ) except Exception as error: logger.exception( "Ошибка при загрузке списка подтверждений для бота %s", bot_name, ) await callback.message.edit_text(f"Ошибка: {error}") @router.callback_query( lambda c: c.data and c.data.startswith("confirm_all_") ) async def confirm_all(callback: CallbackQuery) -> None: await stop_twofa_task(callback.message.message_id) await callback.answer() if not callback.data: logger.debug( "Колбэк подтверждения всех сделок пришел без data от %s", describe_user(callback.from_user), ) return try: account = await get_owned_bot(callback.from_user.id, int(callback.data.replace("confirm_all_", ""))) except ValueError: account = None if account is None: await callback.answer("Бот не найден или вам не принадлежит", show_alert=True); return bot_name = account.bot_name logger.info( "Пользователь %s запустил подтверждение всех сделок для бота %s", describe_user(callback.from_user), bot_name, ) try: status = await accept_confirmations(bot_name) if status != 200: logger.warning( "Не удалось подтвердить все сделки для бота %s: HTTP %s", bot_name, status, ) await callback.answer("Ошибка HTTP", show_alert=True) return confirmations = await get_confirmations(bot_name) if not confirmations: logger.info("После подтверждения у бота %s не осталось сделок", bot_name) text = f"🔐 {bot_name}\n\nПодтверждений больше нет" else: logger.info( "После подтверждения у бота %s осталось %s подтверждени(й)", bot_name, len(confirmations), ) text = f"🔐 {bot_name}\n\nПодтверждения:\n\n" for conf in confirmations: text += f"- {conf['type_name']}\nID: {conf['id']}\n\n" await callback.message.edit_text( text, reply_markup=confirmations_keyboard(account.id) ) await callback.answer("Все подтверждено", show_alert=True) except Exception as error: logger.exception("Ошибка при подтверждении всех сделок для бота %s", bot_name) await callback.message.edit_text(f"Ошибка: {error}")