# app/src/telegram/handlers/market.py from __future__ import annotations from aiogram import F, Router from aiogram.fsm.context import FSMContext from aiogram.types import Message from src.integrations.exchange.exceptions import ExchangeError from src.integrations.exchange.service import ExchangeService from src.trading.journal.service import JournalService router = Router(name="market") def _safe_log_info( journal: JournalService, event_type: str, message: str, payload: dict | None = None, ) -> None: try: journal.log_info(event_type, message, payload) except Exception: pass def _safe_log_warning( journal: JournalService, event_type: str, message: str, payload: dict | None = None, ) -> None: try: journal.log_warning(event_type, message, payload) except Exception: pass def _safe_log_error( journal: JournalService, event_type: str, message: str, payload: dict | None = None, ) -> None: try: journal.log_error(event_type, message, payload) except Exception: pass @router.message(F.text == "📈 Рынок") async def open_market(message: Message, state: FSMContext) -> None: # Глобальный экран: всегда выходим из текущего FSM-сценария. await state.clear() service = ExchangeService() journal = JournalService() user_id = message.from_user.id if message.from_user else None chat_id = message.chat.id if message.chat else None requested_symbol = service.settings.default_symbol _safe_log_info( journal, "user_open_market", "Пользователь открыл экран рынка.", { "user_id": user_id, "chat_id": chat_id, "symbol": requested_symbol, }, ) try: validation = service.validate_symbol(requested_symbol) if not validation.is_valid: _safe_log_warning( journal, "market_symbol_invalid", f"Символ не прошел проверку: {validation.message}", { "user_id": user_id, "chat_id": chat_id, "symbol": requested_symbol, }, ) await message.answer( "📈 Рынок\n\n" f"Ошибка инструмента: {validation.message}" ) return ticker = service.get_price(validation.normalized_symbol) except ExchangeError as exc: _safe_log_error( journal, "market_open_error", f"Не удалось открыть экран рынка: {exc}", { "user_id": user_id, "chat_id": chat_id, "symbol": requested_symbol, }, ) await message.answer( "📈 Рынок\n\n" "Не удалось получить цену с биржи.\n" f"Ошибка: {exc}" ) return symbol_info = validation.symbol_info symbol_status = symbol_info.status if symbol_info else "n/a" market_type = symbol_info.market_type if symbol_info else "n/a" market_modes = ( ", ".join(symbol_info.market_modes) if symbol_info and symbol_info.market_modes else "n/a" ) tick_size = ( f"{symbol_info.tick_size}" if symbol_info and symbol_info.tick_size is not None else "n/a" ) base_asset = symbol_info.base_asset if symbol_info and symbol_info.base_asset else "n/a" quote_asset = symbol_info.quote_asset if symbol_info and symbol_info.quote_asset else "n/a" name = symbol_info.name if symbol_info and symbol_info.name else ticker.symbol text = ( "📈 Рынок\n\n" f"Символ: {ticker.symbol}\n" f"Название: {name}\n" f"Цена: {ticker.price:.2f}\n" f"Статус: {symbol_status}\n" f"Тип рынка: {market_type}\n" f"Режимы: {market_modes}\n" f"Base asset: {base_asset}\n" f"Quote asset: {quote_asset}\n" f"Tick size: {tick_size}\n" f"Источник: {ticker.source}\n" f"Обновлено: {ticker.updated_at}" ) _safe_log_info( journal, "market_open_success", "Экран рынка успешно показан пользователю.", { "user_id": user_id, "chat_id": chat_id, "symbol": ticker.symbol, "price": ticker.price, "base_asset": base_asset, "quote_asset": quote_asset, }, ) await message.answer(text)