from aiogram import Router, types import logging from instences.config import BASE_URL_FASTAPI import aiohttp from aiogram.enums.parse_mode import ParseMode from aiogram.filters import Command from keyboard.keyboards import tarif_Lark_pro_keyboard, tarif_Lark_keyboard, tarif_confirm_keyboard,buy_keyboard router = Router() logger = logging.getLogger(__name__) async def call_api(method, endpoint, data=None): """ Выполняет HTTP-запрос к FastAPI. """ url = f"{BASE_URL_FASTAPI}{endpoint}" logger.info(f"Инициализация запроса: {method} {url} с данными {data}") try: async with aiohttp.ClientSession() as session: async with session.request(method, url, json=data) as response: logger.info(f"Получен ответ от {url}: статус {response.status}") if response.status in {200, 201}: result = await response.json() logger.debug(f"Ответ JSON: {result}") return result if response.status in {404,400}: result = await response.json() logger.debug(f"Код {response.status}, возвращаю {result}") return result logger.error(f"Ошибка в запросе: статус {response.status}, причина {response.reason}") return "ERROR" except Exception as e: logger.exception(f"Исключение при выполнении запроса к {url}: {e}") return "ERROR" def escape_markdown_v2(text: str) -> str: """ Экранирует специальные символы для Markdown_V2. """ special_chars = r"_*[]()~`>#+-=|{}.!" for char in special_chars: text = text.replace(char, f"\\{char}") return text @router.message(Command("subscriptions")) async def supp(message: types.Message): """ Меню системы подписок """ text = "" uri = None # Инициализация переменной try: # Вызов API для получения URI result = await call_api("GET", f"/uri?telegram_id={message.from_user.id}") uri = result.get('detail', "Error") # Получаем URI из ответа или "Error", если ключ отсутствует # Проверка результата if uri == "Error": text = escape_markdown_v2("Произошла ошибка при получении URI") elif uri == "SUB_ERROR": text = escape_markdown_v2("Вы ещё не приобрели подписки!!") elif "trojan" in uri: escaped_uri = escape_markdown_v2(uri) # Экранирование URI text = f"Ваша подписка: ```{escaped_uri}```" else: text = escape_markdown_v2("Произошла ошибка при обработке URI") except Exception as e: # Логирование ошибок logger.error(f"Ошибка при вызове API для подписки: {e}") text = escape_markdown_v2("Произошла неожиданная ошибка при получении подписки.") # Ответ пользователю await message.answer( text, parse_mode=ParseMode.MARKDOWN_V2 ) @router.callback_query(lambda callback: callback.data == "buy_subscription") async def buy_subscription_callback_handler(callback: types.CallbackQuery): """ Обработчик callback_query с data="buy_subscription". """ await callback.message.edit_text( f"Ознакомься с условиями в вкладке \"О тарифах\" и выбери подходящий 🦅", reply_markup=buy_keyboard() ) @router.callback_query(lambda callback: callback.data == "subs") async def subs_callback_handler(callback: types.CallbackQuery): """ Обработчик callback_query с data="subs". """ await callback.message.edit_text( "Подписки птенчик", reply_markup=tarif_Lark_keyboard() ) @router.callback_query(lambda callback: callback.data == "subs_pro") async def subs_pro_callback_handler(callback: types.CallbackQuery): """ Обработчик callback_query с data="subs_pro". """ await callback.message.edit_text( "Подписки птенчик ПРО", reply_markup=tarif_Lark_pro_keyboard() ) @router.callback_query(lambda callback: callback.data.startswith("Lark:")) async def lark_tariff_callback_handler(callback: types.CallbackQuery): """ Обработчик для выбора тарифа Lark. """ data = callback.data.split(":") tariff_name = data[0] tariff_class = data[1] tariff_time = int(data[2]) # Определение окончания для месяцев if tariff_time == 1: months = f"{tariff_time} месяц" elif 2 <= tariff_time <= 4: months = f"{tariff_time} месяца" else: months = f"{tariff_time} месяцев" text = f"Тариф {tariff_name} на {months}. Продолжите покупку..." # Рендеринг клавиатуры keyboard = tarif_confirm_keyboard(tariff_name, tariff_time, tariff_class) await callback.message.edit_text(text=text, reply_markup=keyboard) @router.callback_query(lambda callback: callback.data.startswith("confirm:")) async def confirm_callback_handler(callback: types.CallbackQuery): """ Обработчик подтверждения подписки. """ try: data = callback.data.split(":")[1] tariff_info = data.split("_") plan_id = f"{tariff_info[0]}_{tariff_info[1]}_{tariff_info[2]}" result = await call_api("POST", "/subscription/buy", {"telegram_id": callback.from_user.id, "plan_name": "basic"}) detail = result.get("detail", {}) if detail == "ERROR": await callback.message.edit_text("Произошла ошибка при оформлении подписки.") elif detail == "INSUFFICIENT_FUNDS": await callback.message.edit_text("Денег на вашем балансе не достаточно.") elif detail == "TARIFF_NOT_FOUND": await callback.message.edit_text("Ваш тариф не найден.") elif detail == "ACTIVE_SUBSCRIPTION_EXISTS": await callback.message.edit_text("Вы уже имеете активную подписку.") else: uri = result.get("uri", {}) escaped_text = escape_markdown_v2(f"Подписка успешно оформлена!") answer_text = f"Ваш конфиг для подключения: ```{uri}```" await callback.message.edit_text(escaped_text) await callback.message.answer(answer_text, parse_mode=ParseMode.MARKDOWN_V2) except Exception as e: logger.exception(f"Ошибка при обработке подтверждения подписки: {e}") await callback.message.edit_text("Произошла ошибка при оформлении подписки.") finally: await callback.answer()