import asyncio from aiogram import Router from aiogram.types import CallbackQuery from aiogram.fsm.context import FSMContext from bot.filters import AdminCallbackFilter from bot.logging_utils import describe_user, get_logger from bot.api.asf import get_plugins, restart_asf as restart_asf_request from bot.services.twofa import stop_twofa_task from bot.ui.formatters import get_asf_status_text, get_asf_status from bot.ui.keyboards import back_keyboard, confirm_action_keyboard, main_keyboard router = Router() logger = get_logger(__name__) @router.callback_query(lambda c: c.data == "back", AdminCallbackFilter()) async def back_button(callback: CallbackQuery, state: FSMContext) -> None: user = describe_user(callback.from_user.id) logger.info("Нажата кнопка возврата: %s", user) await state.clear() await stop_twofa_task(callback.message.message_id) await callback.answer() try: await callback.message.edit_text( get_asf_status_text(), reply_markup=main_keyboard() ) logger.info("Пользователь возвращен в главное меню: %s", user) except Exception as error: logger.exception("Не удалось вернуть пользователя в главное меню: %s", user) await callback.message.edit_text(f"Ошибка: {error}") @router.callback_query(lambda c: c.data == "refresh", AdminCallbackFilter()) async def refresh_handler(callback: CallbackQuery) -> None: user = describe_user(callback.from_user.id) logger.info("Запрошено обновление главного экрана: %s", user) await callback.answer() try: await callback.message.edit_text( get_asf_status_text(), reply_markup=main_keyboard() ) logger.info("Главный экран обновлен: %s", user) except Exception as error: logger.exception("Не удалось обновить главный экран: %s", user) await callback.message.edit_text(f"Ошибка: {error}") @router.callback_query(lambda c: c.data == "delete_msg", AdminCallbackFilter()) async def delete_message(callback: CallbackQuery) -> None: user = describe_user(callback.from_user.id) logger.info("Запрошено удаление сообщения: %s", user) await callback.answer() try: await callback.message.delete() logger.info("Сообщение удалено: %s", user) except Exception: logger.exception("Не удалось удалить сообщение: %s", user) @router.callback_query(lambda c: c.data == "restart_asf_confirm", AdminCallbackFilter()) async def restart_asf_confirm(callback: CallbackQuery) -> None: user = describe_user(callback.from_user.id) logger.info("Открыто подтверждение перезапуска ASF: %s", user) await callback.answer() await callback.message.edit_text( "♻ Точно перезапустить ASF?\n\nВо время перезапуска IPC будет недоступен несколько секунд.", reply_markup=confirm_action_keyboard("restart_asf", "back"), ) @router.callback_query(lambda c: c.data == "restart_asf", AdminCallbackFilter()) async def restart_asf(callback: CallbackQuery) -> None: user = describe_user(callback.from_user.id) logger.info("Подтвержден перезапуск ASF: %s", user) await callback.answer() try: await callback.message.edit_text("♻ ASF перезапускается...") response = restart_asf_request() if response.status_code != 200: logger.warning( "Перезапуск ASF завершился ошибкой HTTP: %s status=%s", user, response.status_code, ) await callback.message.edit_text( f"Ошибка HTTP {response.status_code}", reply_markup=main_keyboard(), ) return # ! Меняется подход к перезапуску ASF: вместо того чтобы ждать # ! 6 секунд, лучше проверять статус ASF до тех пор он не запустится # await asyncio.sleep(6) status = get_asf_status() await asyncio.sleep(1) while status.status_code != 200: status = get_asf_status() await asyncio.sleep(1) await callback.message.edit_text( f"ASF успешно перезапущен\n\n{get_asf_status_text()}", reply_markup=main_keyboard(), ) logger.info("ASF успешно перезапущен: %s", user) except Exception as error: logger.exception("Не удалось перезапустить ASF: %s", user) await callback.message.edit_text( f"Ошибка: {error}", reply_markup=main_keyboard(), ) @router.callback_query(lambda c: c.data == "plugins", AdminCallbackFilter()) async def plugins_handler(callback: CallbackQuery) -> None: user = describe_user(callback.from_user.id) logger.info("Открыт список плагинов ASF: %s", user) await stop_twofa_task(callback.message.message_id) await callback.answer() try: response = get_plugins() if response.status_code != 200: logger.warning( "Не удалось получить список плагинов: %s status=%s", user, response.status_code, ) await callback.message.edit_text("Ошибка API") return data = response.json() if not data.get("Success"): logger.warning("ASF вернул ошибку при получении плагинов: %s", user) await callback.message.edit_text("ASF вернул ошибку") return plugins = data.get("Result", []) if not plugins: logger.info("Плагины ASF не установлены: %s", user) text = "Плагины не установлены" else: logger.info("Получен список плагинов ASF: %s count=%s", user, len(plugins)) text = "📁 Плагины ASF:\n\n" for plugin in plugins: text += ( f"{plugin.get('Name', '???')} ({plugin.get('Version', '???')})\n" ) await callback.message.edit_text(text.strip(), reply_markup=back_keyboard()) except Exception as error: logger.exception("Не удалось отобразить список плагинов: %s", user) await callback.message.edit_text(f"Ошибка: {error}")