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}")