160 lines
4.7 KiB
Python
160 lines
4.7 KiB
Python
# 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(
|
||
"<b>📈 Рынок</b>\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(
|
||
"<b>📈 Рынок</b>\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 = (
|
||
"<b>📈 Рынок</b>\n\n"
|
||
f"Символ: <b>{ticker.symbol}</b>\n"
|
||
f"Название: {name}\n"
|
||
f"Цена: <b>{ticker.price:.2f}</b>\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) |