import logging.config import asyncio from aiogram import F, Router from aiogram.filters import CommandStart from aiogram.types import Message, CallbackQuery from aiogram.fsm.context import FSMContext import app.telegram.functions.functions as func import app.telegram.functions.main_settings.settings as func_main_settings import app.telegram.functions.risk_management_settings.settings as func_rmanagement_settings import app.telegram.functions.condition_settings.settings as func_condition_settings import app.telegram.functions.additional_settings.settings as func_additional_settings import app.telegram.database.requests as rq from app.services.Bybit.functions.balance import get_balance from app.services.Bybit.functions.bybit_ws import run_ws_for_user from logger_helper.logger_helper import LOGGING_CONFIG logging.config.dictConfig(LOGGING_CONFIG) logger = logging.getLogger("handlers") router = Router() @router.message(CommandStart()) async def start_message(message: Message) -> None: """ Обработчик команды /start. Инициализирует нового пользователя в БД. Args: message (Message): Входящее сообщение с командой /start. """ await rq.set_new_user_bybit_api(message.from_user.id) await func.start_message(message) @router.message(F.text == "👤 Профиль") async def profile_message(message: Message) -> None: """ Обработчик кнопки 'Профиль'. Проверяет существование пользователя и отображает профиль. Args: message (Message): Сообщение с текстом кнопки. """ user = await rq.check_user(message.from_user.id) tg_id = message.from_user.id balance = await get_balance(message.from_user.id, message) if user and balance: asyncio.create_task(run_ws_for_user(tg_id, message)) logger.info(f"Получение event loop") await func.profile_message(message.from_user.username, message) @router.callback_query(F.data == "clb_start_chatbot_message") async def clb_profile_msg(callback: CallbackQuery) -> None: """ Обработчик колбэка 'clb_start_chatbot_message'. Если пользователь есть в БД — показывает профиль, иначе регистрирует нового пользователя и инициализирует настройки. Args: callback (CallbackQuery): Полученный колбэк. """ user = await rq.check_user(callback.from_user.id) balance = await get_balance(callback.from_user.id, callback.message) first_name = callback.from_user.first_name or "" last_name = callback.from_user.last_name or "" username = f"{first_name} {last_name}".strip() or callback.from_user.username or "Пользователь" if user and balance: await func.profile_message(callback.from_user.username, callback.message) else: await rq.save_tg_id_new_user(callback.from_user.id) await func_main_settings.reg_new_user_default_main_settings(callback.from_user.id, callback.message) await func_rmanagement_settings.reg_new_user_default_risk_management_settings(callback.from_user.id, callback.message) await func_condition_settings.reg_new_user_default_condition_settings(callback.from_user.id) await func_additional_settings.reg_new_user_default_additional_settings(callback.from_user.id, callback.message) await callback.answer() @router.callback_query(F.data == "clb_settings_message") async def clb_settings_msg(callback: CallbackQuery) -> None: """ Показать главное меню настроек. Args: callback (CallbackQuery): полученный колбэк. """ await func.settings_message(callback.message) await callback.answer() @router.callback_query(F.data == "clb_back_to_special_settings_message") async def clb_back_to_settings_msg(callback: CallbackQuery) -> None: """ Вернуть пользователя к меню специальных настроек. Args: callback (CallbackQuery): полученный колбэк. """ await func.settings_message(callback.message) await callback.answer() @router.callback_query(F.data == "clb_change_main_settings") async def clb_change_main_settings_message(callback: CallbackQuery, state: FSMContext) -> None: """ Открыть меню изменения главных настроек. Args: callback (CallbackQuery): полученный колбэк. state (FSMContext): текущее состояние FSM. """ await func_main_settings.main_settings_message(callback.from_user.id, callback.message, state) await callback.answer() @router.callback_query(F.data == "clb_change_risk_management_settings") async def clb_change_risk_management_message(callback: CallbackQuery) -> None: """ Открыть меню изменения настроек управления рисками. Args: callback (CallbackQuery): полученный колбэк. """ await func_rmanagement_settings.main_settings_message(callback.from_user.id, callback.message) await callback.answer() @router.callback_query(F.data == "clb_change_condition_settings") async def clb_change_condition_message(callback: CallbackQuery, state: FSMContext) -> None: """ Открыть меню изменения настроек условий. Args: callback (CallbackQuery): полученный колбэк. state (FSMContext): текущее состояние FSM. """ await func_condition_settings.main_settings_message(callback.from_user.id, callback.message) await callback.answer() @router.callback_query(F.data == "clb_change_additional_settings") async def clb_change_additional_message(callback: CallbackQuery, state: FSMContext) -> None: """ Открыть меню изменения дополнительных настроек. Args: callback (CallbackQuery): полученный колбэк. state (FSMContext): текущее состояние FSM. """ await func_additional_settings.main_settings_message(callback.from_user.id, callback.message, state) await callback.answer() # Конкретные настройки каталогов list_main_settings = ['clb_change_trading_mode', 'clb_change_switch_mode', 'clb_change_margin_type', 'clb_change_size_leverage', 'clb_change_starting_quantity', 'clb_change_martingale_factor', 'clb_change_maximum_quantity' ] @router.callback_query(F.data.in_(list_main_settings)) async def clb_main_settings_msg(callback: CallbackQuery, state: FSMContext) -> None: """ Обработчик колбэков изменения главных настроек с dispatch через match-case. Args: callback (CallbackQuery): полученный колбэк. state (FSMContext): текущее состояние FSM. """ await callback.answer() try: match callback.data: case 'clb_change_trading_mode': await func_main_settings.trading_mode_message(callback.message, state) case 'clb_change_switch_mode': await func_main_settings.switch_mode_enabled_message(callback.message, state) case 'clb_change_margin_type': await func_main_settings.margin_type_message(callback.message, state) case 'clb_change_size_leverage': await func_main_settings.size_leverage_message(callback.message, state) case 'clb_change_starting_quantity': await func_main_settings.starting_quantity_message(callback.message, state) case 'clb_change_martingale_factor': await func_main_settings.martingale_factor_message(callback.message, state) case 'clb_change_maximum_quantity': await func_main_settings.maximum_quantity_message(callback.message, state) except Exception as e: logger.error(f"Error callback in main_settings match-case: {e}") list_risk_management_settings = ['clb_change_price_profit', 'clb_change_price_loss', 'clb_change_max_risk_deal', 'commission_fee', ] @router.callback_query(F.data.in_(list_risk_management_settings)) async def clb_risk_management_settings_msg(callback: CallbackQuery, state: FSMContext) -> None: """ Обработчик изменений настроек управления рисками. Args: callback (CallbackQuery): полученный колбэк. state (FSMContext): текущее состояние FSM. """ await callback.answer() try: match callback.data: case 'clb_change_price_profit': await func_rmanagement_settings.price_profit_message(callback.message, state) case 'clb_change_price_loss': await func_rmanagement_settings.price_loss_message(callback.message, state) case 'clb_change_max_risk_deal': await func_rmanagement_settings.max_risk_deal_message(callback.message, state) case 'commission_fee': await func_rmanagement_settings.commission_fee_message(callback.message, state) except Exception as e: logger.error(f"Error callback in risk_management match-case: {e}") list_condition_settings = ['clb_change_trigger', 'clb_change_timer', 'clb_change_filter_volatility', 'clb_change_external_cues', 'clb_change_tradingview_cues', 'clb_change_webhook', 'clb_change_ai_analytics' ] @router.callback_query(F.data.in_(list_condition_settings)) async def clb_condition_settings_msg(callback: CallbackQuery, state: FSMContext) -> None: """ Обработчик изменений настроек условий трейдинга. Args: callback (CallbackQuery): полученный колбэк. state (FSMContext): текущее состояние FSM. """ await callback.answer() try: match callback.data: case 'clb_change_trigger': await func_condition_settings.trigger_message(callback.from_user.id, callback.message, state) case 'clb_change_timer': await func_condition_settings.timer_message(callback.from_user.id, callback.message, state) case 'clb_change_filter_volatility': await func_condition_settings.filter_volatility_message(callback.message, state) case 'clb_change_external_cues': await func_condition_settings.external_cues_message(callback.message, state) case 'clb_change_tradingview_cues': await func_condition_settings.trading_cues_message(callback.message, state) case 'clb_change_webhook': await func_condition_settings.webhook_message(callback.message, state) case 'clb_change_ai_analytics': await func_condition_settings.ai_analytics_message(callback.message, state) except Exception as e: logger.error(f"Error callback in main_settings match-case: {e}") list_additional_settings = ['clb_change_save_pattern', 'clb_change_auto_start', 'clb_change_notifications', ] @router.callback_query(F.data.in_(list_additional_settings)) async def clb_additional_settings_msg(callback: CallbackQuery, state: FSMContext) -> None: """ Обработчик дополнительных настроек бота. Args: callback (CallbackQuery): полученный колбэк. state (FSMContext): текущее состояние FSM. """ await callback.answer() try: match callback.data: case 'clb_change_save_pattern': await func_additional_settings.save_pattern_message(callback.message, state) case 'clb_change_auto_start': await func_additional_settings.auto_start_message(callback.message, state) case 'clb_change_notifications': await func_additional_settings.notifications_message(callback.message, state) except Exception as e: logger.error(f"Error callback in additional_settings match-case: {e}")