151 lines
6.9 KiB
Python
151 lines
6.9 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 app.telegram.keyboards.reply as kbr
|
||
import database.request as rq
|
||
from app.bybit.profile_bybit import user_profile_bybit
|
||
from app.telegram.states.states import AddBybitApiState
|
||
from logger_helper.logger_helper import LOGGING_CONFIG
|
||
|
||
logging.config.dictConfig(LOGGING_CONFIG)
|
||
logger = logging.getLogger("add_bybit_api")
|
||
|
||
router_add_bybit_api = Router(name="add_bybit_api")
|
||
|
||
|
||
@router_add_bybit_api.callback_query(F.data == "connect_platform")
|
||
async def connect_platform(callback: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles the callback query to initiate Bybit platform connection.
|
||
Sends instructions on how to create and provide API keys to the bot.
|
||
|
||
:param callback: CallbackQuery object triggered by user interaction.
|
||
:param state: FSMContext object to manage state data.
|
||
:return: None
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
await callback.answer()
|
||
user = await rq.get_user(tg_id=callback.from_user.id)
|
||
if user:
|
||
await callback.message.answer(
|
||
text=(
|
||
"Подключение Bybit аккаунта \n\n"
|
||
"1. Зарегистрируйтесь или войдите в свой аккаунт на Bybit по ссылке: "
|
||
"[Перейти на Bybit](https://www.bybit.com/invite?ref=YME83OJ).\n"
|
||
"2. В личном кабинете выберите раздел API. \n"
|
||
"3. Создание нового API ключа\n"
|
||
" - Нажмите кнопку Create New Key (Создать новый ключ).\n"
|
||
" - Выберите системно-сгенерированный ключ.\n"
|
||
" - Укажите название API ключа (любое). \n"
|
||
" - Выберите права доступа для торговли (Trade). \n"
|
||
" - Можно ограничить доступ по IP для безопасности.\n"
|
||
"4. Подтверждение создания\n"
|
||
" - Подтвердите создание ключа.\n"
|
||
" - Отправьте чат-роботу.\n\n"
|
||
"Важно: сохраните отдельно API Key и Secret Key в надежном месте. Secret ключ отображается только один раз."
|
||
),
|
||
parse_mode="Markdown",
|
||
reply_markup=kbi.add_bybit_api,
|
||
disable_web_page_preview=True,
|
||
)
|
||
else:
|
||
await rq.create_user(
|
||
tg_id=callback.from_user.id, username=callback.from_user.username
|
||
)
|
||
await rq.set_user_symbol(tg_id=callback.from_user.id, symbol="BTCUSDT")
|
||
await rq.create_user_additional_settings(tg_id=callback.from_user.id)
|
||
await rq.create_user_risk_management(tg_id=callback.from_user.id)
|
||
await rq.create_user_conditional_settings(tg_id=callback.from_user.id)
|
||
await connect_platform(callback=callback, state=state)
|
||
except Exception as e:
|
||
logger.error("Error adding bybit API for user %s: %s", callback.from_user.id, e)
|
||
await callback.message.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже."
|
||
)
|
||
|
||
|
||
@router_add_bybit_api.callback_query(F.data == "add_bybit_api")
|
||
async def process_api_key(callback: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Starts the FSM flow to add Bybit API keys.
|
||
Sets the FSM state to prompt user to enter API Key.
|
||
|
||
:param callback: CallbackQuery object.
|
||
:param state: FSMContext for managing user state.
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
await state.set_state(AddBybitApiState.api_key_state)
|
||
await callback.answer()
|
||
await callback.message.answer(text="Введите API Key:")
|
||
except Exception as e:
|
||
logger.error("Error adding bybit API for user %s: %s", callback.from_user.id, e)
|
||
await callback.message.answer(
|
||
text="Произошла ошибка. Пожалуйста, попробуйте позже."
|
||
)
|
||
|
||
|
||
@router_add_bybit_api.message(AddBybitApiState.api_key_state)
|
||
async def process_secret_key(message: Message, state: FSMContext) -> None:
|
||
"""
|
||
Receives the API Key input from the user, stores it in FSM context,
|
||
then sets state to collect Secret Key.
|
||
|
||
:param message: Message object with user's input.
|
||
:param state: FSMContext for managing user state.
|
||
"""
|
||
try:
|
||
api_key = message.text
|
||
await state.update_data(api_key=api_key)
|
||
await state.set_state(AddBybitApiState.api_secret_state)
|
||
await message.answer(text="Введите Secret Key:")
|
||
except Exception as e:
|
||
logger.error("Error adding bybit API for user %s: %s", message.from_user.id, e)
|
||
await message.answer(text="Произошла ошибка. Пожалуйста, попробуйте позже.")
|
||
|
||
|
||
@router_add_bybit_api.message(AddBybitApiState.api_secret_state)
|
||
async def add_bybit_api(message: Message, state: FSMContext) -> None:
|
||
"""
|
||
Receives the Secret Key input, stores it, saves both API keys in the database,
|
||
clears FSM state and confirms success to the user.
|
||
|
||
:param message: Message object with user's input.
|
||
:param state: FSMContext for managing user state.
|
||
"""
|
||
try:
|
||
api_secret = message.text
|
||
api_key = (await state.get_data()).get("api_key")
|
||
await state.update_data(api_secret=api_secret)
|
||
|
||
if not api_key or not api_secret:
|
||
await message.answer("Введите корректные данные.")
|
||
return
|
||
|
||
result = await rq.set_user_api(
|
||
tg_id=message.from_user.id, api_key=api_key, api_secret=api_secret
|
||
)
|
||
|
||
if result:
|
||
await message.answer(text="Данные добавлены.", reply_markup=kbr.profile)
|
||
await user_profile_bybit(
|
||
tg_id=message.from_user.id, message=message, state=state
|
||
)
|
||
logger.debug(
|
||
"Bybit API added successfully for user: %s", message.from_user.id
|
||
)
|
||
else:
|
||
await message.answer(text="Произошла ошибка. Пожалуйста, попробуйте позже.")
|
||
logger.error(
|
||
"Error adding bybit API for user %s: %s", message.from_user.id, result
|
||
)
|
||
await state.clear()
|
||
except Exception as e:
|
||
logger.error("Error adding bybit API for user %s: %s", message.from_user.id, e)
|
||
await message.answer(text="Произошла ошибка. Пожалуйста, попробуйте позже.")
|