forked from kodorvan/stcs
919 lines
36 KiB
Python
919 lines
36 KiB
Python
import logging.config
|
||
|
||
from aiogram import F, Router
|
||
from aiogram.fsm.context import FSMContext
|
||
from aiogram.types import CallbackQuery, Message
|
||
|
||
import app.telegram.keyboards.inline as kbi
|
||
import database.request as rq
|
||
from app.bybit.get_functions.get_instruments_info import get_instruments_info
|
||
from app.bybit.set_functions.set_leverage import set_leverage
|
||
from app.bybit.set_functions.set_margin_mode import set_margin_mode
|
||
from app.helper_functions import is_int, is_number, safe_float
|
||
from app.telegram.states.states import AdditionalSettingsState
|
||
from logger_helper.logger_helper import LOGGING_CONFIG
|
||
|
||
logging.config.dictConfig(LOGGING_CONFIG)
|
||
logger = logging.getLogger("additional_settings")
|
||
|
||
router_additional_settings = Router(name="additional_settings")
|
||
|
||
|
||
@router_additional_settings.callback_query(F.data == "trade_mode")
|
||
async def settings_for_trade_mode(
|
||
callback_query: CallbackQuery, state: FSMContext
|
||
) -> None:
|
||
"""
|
||
Handles the 'trade_mode' callback query.
|
||
|
||
Clears the current FSM state, edits the message text to display trade mode options
|
||
with explanation for 'Long' and 'Short' modes, and shows an inline keyboard for selection.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
await callback_query.message.edit_text(
|
||
text="Выберите режим торговли:\n\n"
|
||
"Лонг - все сделки серии открываются на покупку.\n"
|
||
"Шорт - все сделки серии открываются на продажу.\n"
|
||
"Свитч - направление каждой сделки серии меняется по переменно.\n",
|
||
reply_markup=kbi.trade_mode,
|
||
)
|
||
logger.debug(
|
||
"Command trade_mode processed successfully for user: %s",
|
||
callback_query.from_user.id,
|
||
)
|
||
|
||
except Exception as e:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже."
|
||
)
|
||
logger.error(
|
||
"Error processing command trade_mode for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
|
||
|
||
@router_additional_settings.callback_query(
|
||
lambda c: c.data == "Long" or c.data == "Short" or c.data == "Switch"
|
||
)
|
||
async def trade_mode(callback_query: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles callback queries related to trade mode selection.
|
||
|
||
Updates FSM context with selected trade mode and persists the choice in database.
|
||
Sends an acknowledgement to user and clears FSM state afterward.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query indicating selected trade mode.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
req = await rq.set_trade_mode(
|
||
tg_id=callback_query.from_user.id, trade_mode=callback_query.data
|
||
)
|
||
|
||
if not req:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка при установке режима торговли"
|
||
)
|
||
return
|
||
|
||
await callback_query.answer(text="Режим торговли успешно изменен")
|
||
logger.debug(
|
||
"Trade mode changed successfully for user: %s", callback_query.from_user.id
|
||
)
|
||
except Exception as e:
|
||
await callback_query.answer(text="Произошла ошибка при смене режима позиции.")
|
||
logger.error(
|
||
"Error processing set trade_mode for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
finally:
|
||
await state.clear()
|
||
|
||
|
||
@router_additional_settings.callback_query(F.data == "switch_side_start")
|
||
async def switch_side_start(callback_query: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles the 'switch_side_start' callback query.
|
||
|
||
Clears the current FSM state, edits the message text to display the switch side start message,
|
||
and shows an inline keyboard for selection.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
await callback_query.message.edit_text(
|
||
text="Выберите направление первой сделки серии:\n\n"
|
||
"По направлению - сделка открывается в направлении последней сделки предыдущей серии.\n"
|
||
"Противоположно - сделка открывается в противоположном направлении последней сделки предыдущей серии.\n",
|
||
reply_markup=kbi.switch_side,
|
||
)
|
||
logger.debug(
|
||
"Command switch_side_start processed successfully for user: %s",
|
||
callback_query.from_user.id,
|
||
)
|
||
except Exception as e:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже."
|
||
)
|
||
logger.error(
|
||
"Error processing command switch_side_start for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
|
||
|
||
@router_additional_settings.callback_query(lambda c: c.data == "switch_direction" or c.data == "switch_opposite")
|
||
async def switch_side_handler(callback_query: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles callback queries related to switch side selection.
|
||
|
||
Updates FSM context with selected switch side and persists the choice in database.
|
||
Sends an acknowledgement to user and clears FSM state afterward.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query indicating selected switch side.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
if callback_query.data == "switch_direction":
|
||
switch_side = "По направлению"
|
||
elif callback_query.data == "switch_opposite":
|
||
switch_side = "Противоположно"
|
||
else:
|
||
switch_side = None
|
||
|
||
req = await rq.set_switch_side(
|
||
tg_id=callback_query.from_user.id, switch_side=switch_side
|
||
)
|
||
|
||
if not req:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка при установке направления переключения"
|
||
)
|
||
return
|
||
|
||
await callback_query.answer(text=f"Выбрано: {switch_side}")
|
||
logger.debug(
|
||
"Switch side changed successfully for user: %s", callback_query.from_user.id
|
||
)
|
||
except Exception as e:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка при смене направления переключения"
|
||
)
|
||
logger.error(
|
||
"Error processing set switch_side for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
finally:
|
||
await state.clear()
|
||
|
||
|
||
@router_additional_settings.callback_query(F.data == "margin_type")
|
||
async def settings_for_margin_type(
|
||
callback_query: CallbackQuery, state: FSMContext
|
||
) -> None:
|
||
"""
|
||
Handles the 'margin_type' callback query.
|
||
|
||
Clears the current FSM state, edits the message text to display margin type options,
|
||
and shows an inline keyboard for selection.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
await callback_query.message.edit_text(
|
||
text="Выберите тип маржи:\n\n"
|
||
"Примечание: Если у вас есть открытые позиции, то маржа примениться ко всем позициям",
|
||
reply_markup=kbi.margin_type
|
||
)
|
||
logger.debug(
|
||
"Command margin_type processed successfully for user: %s",
|
||
callback_query.from_user.id,
|
||
)
|
||
except Exception as e:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже."
|
||
)
|
||
logger.error(
|
||
"Error processing command margin_type for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
|
||
|
||
@router_additional_settings.callback_query(
|
||
lambda c: c.data == "ISOLATED_MARGIN" or c.data == "REGULAR_MARGIN"
|
||
)
|
||
async def set_margin_type(callback_query: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles callback queries starting with 'Isolated' or 'Cross'.
|
||
|
||
Updates FSM context with selected margin type and persists the choice in database.
|
||
Sends an acknowledgement to user and clears FSM state afterward.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query indicating selected margin type.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
symbol = await rq.get_user_symbol(tg_id=callback_query.from_user.id)
|
||
additional_settings = await rq.get_user_additional_settings(
|
||
tg_id=callback_query.from_user.id
|
||
)
|
||
get_leverage = additional_settings.leverage or "10"
|
||
|
||
leverage_to_float = safe_float(get_leverage)
|
||
bybit_margin_mode = callback_query.data
|
||
response = await set_margin_mode(
|
||
tg_id=callback_query.from_user.id, margin_mode=bybit_margin_mode
|
||
)
|
||
|
||
if not response:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка при установке типа маржи"
|
||
)
|
||
return
|
||
|
||
req = await rq.set_margin_type(
|
||
tg_id=callback_query.from_user.id, margin_type=callback_query.data
|
||
)
|
||
|
||
if not req:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка при установке типа маржи"
|
||
)
|
||
return
|
||
|
||
await set_leverage(
|
||
tg_id=callback_query.from_user.id,
|
||
symbol=symbol,
|
||
leverage=str(leverage_to_float),
|
||
)
|
||
|
||
if callback_query.data.startswith("ISOLATED_MARGIN"):
|
||
await callback_query.answer(text="Выбран тип маржи: Изолированная")
|
||
elif callback_query.data.startswith("REGULAR_MARGIN"):
|
||
await callback_query.answer(text="Выбран тип маржи: Кросс")
|
||
else:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка при установке типа маржи"
|
||
)
|
||
|
||
except Exception as e:
|
||
await callback_query.answer(text="Произошла ошибка при установке типа маржи")
|
||
logger.error(
|
||
"Error processing command margin_type for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
finally:
|
||
await state.clear()
|
||
|
||
|
||
@router_additional_settings.callback_query(lambda c: c.data == "trigger_price")
|
||
async def trigger_price(callback_query: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles the 'trigger_price' callback query.
|
||
|
||
Clears the current FSM state, edits the message text to prompt for the trigger price,
|
||
and shows an inline keyboard for input.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
await state.set_state(AdditionalSettingsState.trigger_price_state)
|
||
await callback_query.answer()
|
||
await state.update_data(prompt_message_id=callback_query.message.message_id)
|
||
msg = await callback_query.message.edit_text(
|
||
text="Введите цену:", reply_markup=kbi.back_to_additional_settings
|
||
)
|
||
await state.update_data(prompt_message_id=msg.message_id)
|
||
logger.debug(
|
||
"Command trigger_price processed successfully for user: %s",
|
||
callback_query.from_user.id,
|
||
)
|
||
except Exception as e:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже."
|
||
)
|
||
logger.error(
|
||
"Error processing command trigger_price for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
|
||
|
||
@router_additional_settings.message(AdditionalSettingsState.trigger_price_state)
|
||
async def set_trigger_price(message: Message, state: FSMContext) -> None:
|
||
"""
|
||
Handles user input for setting the trigger price.
|
||
|
||
Updates FSM context with the selected trigger price and persists the choice in database.
|
||
Sends an acknowledgement to user and clears FSM state afterward.
|
||
|
||
Args:
|
||
message (Message): Incoming message from user containing the selected trigger price.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
try:
|
||
data = await state.get_data()
|
||
if "prompt_message_id" in data:
|
||
prompt_message_id = data["prompt_message_id"]
|
||
await message.bot.delete_message(
|
||
chat_id=message.chat.id, message_id=prompt_message_id
|
||
)
|
||
await message.delete()
|
||
except Exception as e:
|
||
if "message to delete not found" in str(e).lower():
|
||
pass # Ignore this error
|
||
else:
|
||
raise e
|
||
|
||
trigger_price_value = message.text
|
||
|
||
if not is_number(trigger_price_value):
|
||
await message.answer(
|
||
"Ошибка: введите валидное число.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.debug(
|
||
"User %s input invalid (not an valid number): %s",
|
||
message.from_user.id,
|
||
trigger_price_value,
|
||
)
|
||
return
|
||
|
||
req = await rq.set_trigger_price(
|
||
tg_id=message.from_user.id, trigger_price=safe_float(trigger_price_value)
|
||
)
|
||
if req:
|
||
await message.answer(
|
||
text=f"Цена триггера установлена на: {trigger_price_value}",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
else:
|
||
await message.answer(
|
||
text="Произошла ошибка при установке цены триггера.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
|
||
await state.clear()
|
||
except Exception as e:
|
||
await message.answer(
|
||
text="Произошла ошибка при установке цены триггера.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.error(
|
||
"Error processing set_trigger_price for user %s: %s",
|
||
message.from_user.id,
|
||
e,
|
||
)
|
||
|
||
|
||
@router_additional_settings.callback_query(F.data == "leverage")
|
||
async def leverage_handler(callback_query: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles the 'leverage' callback query.
|
||
|
||
Clears the current FSM state, edits the message text to display the leverage options,
|
||
and shows an inline keyboard for selection.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
await callback_query.answer()
|
||
await state.set_state(AdditionalSettingsState.leverage_state)
|
||
msg = await callback_query.message.edit_text(
|
||
text="Введите размер кредитного плеча:",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
await state.update_data(prompt_message_id=msg.message_id)
|
||
logger.debug(
|
||
"Command leverage processed successfully for user: %s",
|
||
callback_query.from_user.id,
|
||
)
|
||
except Exception as e:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже."
|
||
)
|
||
logger.error(
|
||
"Error processing command leverage for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
|
||
|
||
@router_additional_settings.message(AdditionalSettingsState.leverage_state)
|
||
async def set_leverage_handler(message: Message, state: FSMContext) -> None:
|
||
"""
|
||
Handles user input for setting the leverage.
|
||
|
||
Updates FSM context with the selected leverage and persists the choice in database.
|
||
Sends an acknowledgement to user and clears FSM state afterward.
|
||
|
||
Args:
|
||
message (Message): Incoming message from user containing the selected leverage.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
try:
|
||
data = await state.get_data()
|
||
if "prompt_message_id" in data:
|
||
prompt_message_id = data["prompt_message_id"]
|
||
await message.bot.delete_message(
|
||
chat_id=message.chat.id, message_id=prompt_message_id
|
||
)
|
||
await message.delete()
|
||
except Exception as e:
|
||
if "message to delete not found" in str(e).lower():
|
||
pass # Ignore this error
|
||
else:
|
||
raise e
|
||
|
||
get_leverage = message.text
|
||
tg_id = message.from_user.id
|
||
if not is_number(get_leverage):
|
||
await message.answer(
|
||
"Ошибка: введите валидное число.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.debug(
|
||
"User %s input invalid (not an valid number): %s",
|
||
message.from_user.id,
|
||
get_leverage,
|
||
)
|
||
return
|
||
|
||
leverage_float = safe_float(get_leverage)
|
||
|
||
symbol = await rq.get_user_symbol(tg_id=tg_id)
|
||
instruments_info = await get_instruments_info(tg_id=tg_id, symbol=symbol)
|
||
|
||
if instruments_info is not None:
|
||
min_leverage = (
|
||
safe_float(instruments_info.get("leverageFilter").get("minLeverage"))
|
||
or 1
|
||
)
|
||
max_leverage = (
|
||
safe_float(instruments_info.get("leverageFilter").get("maxLeverage"))
|
||
or 100
|
||
)
|
||
|
||
if leverage_float > max_leverage or leverage_float < min_leverage:
|
||
await message.answer(
|
||
text=f"Кредитное плечо должно быть от {min_leverage} до {max_leverage}",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.info(
|
||
"User %s input invalid (out of range): %s, %s, %s: %s",
|
||
message.from_user.id,
|
||
symbol,
|
||
min_leverage,
|
||
max_leverage,
|
||
leverage_float,
|
||
)
|
||
return
|
||
else:
|
||
await message.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
|
||
response = await set_leverage(
|
||
tg_id=message.from_user.id, symbol=symbol, leverage=str(leverage_float)
|
||
)
|
||
|
||
if not response:
|
||
await message.answer(
|
||
text="Невозможно установить кредитное плечо для текущего режима торговли.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
return
|
||
|
||
req_leverage = await rq.set_leverage(
|
||
tg_id=message.from_user.id, leverage=str(leverage_float)
|
||
)
|
||
|
||
if req_leverage:
|
||
await message.answer(
|
||
text=f"Кредитное плечо успешно установлено на {leverage_float}",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
risk_percent = 100 / safe_float(leverage_float)
|
||
await rq.set_stop_loss_percent(
|
||
tg_id=message.from_user.id, stop_loss_percent=risk_percent)
|
||
logger.info(
|
||
"User %s set leverage: %s", message.from_user.id, leverage_float
|
||
)
|
||
else:
|
||
await message.answer(
|
||
text="Произошла ошибка при установке кредитного плеча. Пожалуйста, попробуйте позже.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
|
||
await state.clear()
|
||
except Exception as e:
|
||
await message.answer(
|
||
text="Произошла ошибка при установке кредитного плеча. Пожалуйста, попробуйте позже.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.error(
|
||
"Error processing command leverage for user %s: %s", message.from_user.id, e
|
||
)
|
||
|
||
|
||
@router_additional_settings.callback_query(F.data == "order_quantity")
|
||
async def order_quantity(callback_query: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles the 'order_quantity' callback query.
|
||
|
||
Clears the current FSM state, edits the message text to display the order quantity options,
|
||
and shows an inline keyboard for selection.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
await state.set_state(AdditionalSettingsState.quantity_state)
|
||
msg = await callback_query.message.edit_text(
|
||
text=f"Введите базовую ставку в USDT:",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
await state.update_data(prompt_message_id=msg.message_id)
|
||
logger.debug(
|
||
"Command order_quantity processed successfully for user: %s",
|
||
callback_query.from_user.id,
|
||
)
|
||
except Exception as e:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже."
|
||
)
|
||
logger.error(
|
||
"Error processing command order_quantity for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
|
||
|
||
@router_additional_settings.message(AdditionalSettingsState.quantity_state)
|
||
async def set_order_quantity(message: Message, state: FSMContext) -> None:
|
||
"""
|
||
Handles user input for setting the order quantity.
|
||
|
||
Updates FSM context with the selected order quantity and persists the choice in database.
|
||
Sends an acknowledgement to user and clears FSM state afterward.
|
||
|
||
Args:
|
||
message (Message): Incoming message from user containing the selected order quantity.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
try:
|
||
data = await state.get_data()
|
||
if "prompt_message_id" in data:
|
||
prompt_message_id = data["prompt_message_id"]
|
||
await message.bot.delete_message(
|
||
chat_id=message.chat.id, message_id=prompt_message_id
|
||
)
|
||
await message.delete()
|
||
except Exception as e:
|
||
if "message to delete not found" in str(e).lower():
|
||
pass # Ignore this error
|
||
else:
|
||
raise e
|
||
|
||
order_quantity_value = message.text
|
||
|
||
if not is_number(order_quantity_value):
|
||
await message.answer(
|
||
"Ошибка: введите валидное число.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.debug(
|
||
"User %s input invalid (not an valid number): %s",
|
||
message.from_user.id,
|
||
order_quantity_value,
|
||
)
|
||
return
|
||
|
||
quantity = safe_float(order_quantity_value)
|
||
|
||
req = await rq.set_order_quantity(
|
||
tg_id=message.from_user.id, order_quantity=quantity
|
||
)
|
||
|
||
if req:
|
||
await message.answer(
|
||
text=f"Базовая ставка установлена на {message.text} USDT",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
else:
|
||
await message.answer(
|
||
text="Произошла ошибка при установке кол-ва ордера. Пожалуйста, попробуйте позже.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
|
||
await state.clear()
|
||
except Exception as e:
|
||
await message.answer(
|
||
text="Произошла ошибка при установке базовой ставки. Пожалуйста, попробуйте позже.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.error("Error processing command set_order_quantity: %s", e)
|
||
|
||
|
||
@router_additional_settings.callback_query(F.data == "martingale_factor")
|
||
async def martingale_factor(callback_query: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles the 'martingale_factor' callback query.
|
||
|
||
Clears the current FSM state, edits the message text to display the martingale factor options,
|
||
and shows an inline keyboard for selection.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
await state.set_state(AdditionalSettingsState.martingale_factor_state)
|
||
msg = await callback_query.message.edit_text(
|
||
text="Введите коэффициент мартингейла:",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
await state.update_data(prompt_message_id=msg.message_id)
|
||
logger.debug(
|
||
"Command martingale_factor processed successfully for user: %s",
|
||
callback_query.from_user.id,
|
||
)
|
||
except Exception as e:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже."
|
||
)
|
||
logger.error(
|
||
"Error processing command martingale_factor for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
|
||
|
||
@router_additional_settings.message(AdditionalSettingsState.martingale_factor_state)
|
||
async def set_martingale_factor(message: Message, state: FSMContext) -> None:
|
||
"""
|
||
Handles user input for setting the martingale factor.
|
||
|
||
Updates FSM context with the selected martingale factor and persists the choice in database.
|
||
Sends an acknowledgement to user and clears FSM state afterward.
|
||
|
||
Args:
|
||
message (Message): Incoming message from user containing the selected martingale factor.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
try:
|
||
data = await state.get_data()
|
||
if "prompt_message_id" in data:
|
||
prompt_message_id = data["prompt_message_id"]
|
||
await message.bot.delete_message(
|
||
chat_id=message.chat.id, message_id=prompt_message_id
|
||
)
|
||
await message.delete()
|
||
except Exception as e:
|
||
if "message to delete not found" in str(e).lower():
|
||
pass # Ignore this error
|
||
else:
|
||
raise e
|
||
|
||
martingale_factor_value = message.text
|
||
|
||
if not is_number(martingale_factor_value):
|
||
await message.answer(
|
||
"Ошибка: введите валидное число.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.debug(
|
||
"User %s input invalid (not an valid number): %s",
|
||
message.from_user.id,
|
||
martingale_factor_value,
|
||
)
|
||
return
|
||
|
||
martingale_factor_value_float = safe_float(martingale_factor_value)
|
||
|
||
if martingale_factor_value_float < 0.1 or martingale_factor_value_float > 10:
|
||
await message.answer(text="Ошибка: коэффициент мартингейла должен быть в диапазоне от 0.1 до 10")
|
||
logger.debug("User %s input invalid (not in range 0.1 to 10): %s", message.from_user.id,
|
||
martingale_factor_value_float)
|
||
return
|
||
|
||
req = await rq.set_martingale_factor(
|
||
tg_id=message.from_user.id, martingale_factor=martingale_factor_value_float
|
||
)
|
||
|
||
if req:
|
||
await message.answer(
|
||
text=f"Коэффициент мартингейла установлен на {message.text}",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
else:
|
||
await message.answer(
|
||
text="Произошла ошибка при установке коэффициента мартингейла. Пожалуйста, попробуйте позже.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
|
||
await state.clear()
|
||
except Exception as e:
|
||
await message.answer(
|
||
text="Произошла ошибка при установке коэффициента мартингейла. Пожалуйста, попробуйте позже.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.error("Error processing command set_martingale_factor: %s", e)
|
||
|
||
|
||
@router_additional_settings.callback_query(F.data == "max_bets_in_series")
|
||
async def max_bets_in_series(callback_query: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles the 'max_bets_in_series' callback query.
|
||
|
||
Clears the current FSM state, edits the message text to display the max bets in series options,
|
||
and shows an inline keyboard for selection.
|
||
|
||
Args:
|
||
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
await state.set_state(AdditionalSettingsState.max_bets_in_series_state)
|
||
msg = await callback_query.message.edit_text(
|
||
text="Введите максимальное количество ставок в серии:",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
await state.update_data(prompt_message_id=msg.message_id)
|
||
logger.debug(
|
||
"Command max_bets_in_series processed successfully for user: %s",
|
||
callback_query.from_user.id,
|
||
)
|
||
except Exception as e:
|
||
await callback_query.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже."
|
||
)
|
||
logger.error(
|
||
"Error processing command max_bets_in_series for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
|
||
|
||
@router_additional_settings.message(AdditionalSettingsState.max_bets_in_series_state)
|
||
async def set_max_bets_in_series(message: Message, state: FSMContext) -> None:
|
||
"""
|
||
Handles user input for setting the max bets in series.
|
||
|
||
Updates FSM context with the selected max steps and persists the choice in database.
|
||
Sends an acknowledgement to user and clears FSM state afterward.
|
||
|
||
Args:
|
||
message (Message): Incoming message from user containing the selected max bets in series.
|
||
state (FSMContext): Finite State Machine context for the current user session.
|
||
|
||
Logs:
|
||
Success or error messages with user identification.
|
||
"""
|
||
try:
|
||
try:
|
||
data = await state.get_data()
|
||
if "prompt_message_id" in data:
|
||
prompt_message_id = data["prompt_message_id"]
|
||
await message.bot.delete_message(
|
||
chat_id=message.chat.id, message_id=prompt_message_id
|
||
)
|
||
await message.delete()
|
||
except Exception as e:
|
||
if "message to delete not found" in str(e).lower():
|
||
pass # Ignore this error
|
||
else:
|
||
raise e
|
||
|
||
max_bets_in_series_value = message.text
|
||
|
||
if not is_int(max_bets_in_series_value):
|
||
await message.answer(
|
||
"Ошибка: введите валидное число.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.debug(
|
||
"User %s input invalid (not an valid number): %s",
|
||
message.from_user.id,
|
||
max_bets_in_series_value,
|
||
)
|
||
return
|
||
|
||
if safe_float(max_bets_in_series_value) < 1 or safe_float(max_bets_in_series_value) > 100:
|
||
await message.answer(
|
||
"Ошибка: число должно быть в диапазоне от 1 до 100.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.debug(
|
||
"User %s input invalid (not in range 1 to 100): %s",
|
||
message.from_user.id,
|
||
max_bets_in_series_value,
|
||
)
|
||
return
|
||
|
||
req = await rq.set_max_bets_in_series(
|
||
tg_id=message.from_user.id, max_bets_in_series=int(max_bets_in_series_value)
|
||
)
|
||
|
||
if req:
|
||
await message.answer(
|
||
text=f"Максимальное количество шагов установлено на {message.text}",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
else:
|
||
await message.answer(
|
||
text="Произошла ошибка при установке максимального количества шагов. Пожалуйста, попробуйте позже.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
|
||
await state.clear()
|
||
except Exception as e:
|
||
await message.answer(
|
||
text="Произошла ошибка при установке максимального количества шагов. Пожалуйста, попробуйте позже.",
|
||
reply_markup=kbi.back_to_additional_settings,
|
||
)
|
||
logger.error(
|
||
"Error processing command set_max_bets_in_series for user %s: %s",
|
||
message.from_user.id,
|
||
e,
|
||
)
|