UI: тарифы Basic/Pro/Family и меню оплат
This commit is contained in:
@@ -4,11 +4,18 @@ from instences.config import BASE_URL_FASTAPI
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
from aiogram.enums.parse_mode import ParseMode
|
from aiogram.enums.parse_mode import ParseMode
|
||||||
from aiogram.filters import Command
|
from aiogram.filters import Command
|
||||||
from keyboard.keyboards import tarif_Lark_pro_keyboard, tarif_Lark_keyboard, tarif_confirm_keyboard,buy_keyboard
|
from keyboard.keyboards import (
|
||||||
|
tarif_Lark_pro_keyboard,
|
||||||
|
tarif_Lark_keyboard,
|
||||||
|
tarif_Lark_family_keyboard,
|
||||||
|
tarif_confirm_keyboard,
|
||||||
|
buy_keyboard,
|
||||||
|
)
|
||||||
|
|
||||||
router = Router()
|
router = Router()
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
async def call_api(method, endpoint, data=None):
|
async def call_api(method, endpoint, data=None):
|
||||||
"""
|
"""
|
||||||
Выполняет HTTP-запрос к FastAPI.
|
Выполняет HTTP-запрос к FastAPI.
|
||||||
@@ -19,22 +26,25 @@ async def call_api(method, endpoint, data=None):
|
|||||||
try:
|
try:
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
async with session.request(method, url, json=data) as response:
|
async with session.request(method, url, json=data) as response:
|
||||||
logger.info(f"Получен ответ от {url}: статус {response.status}")
|
logger.info(
|
||||||
|
f"Получен ответ от {url}: статус {response.status}")
|
||||||
|
|
||||||
if response.status in {200, 201}:
|
if response.status in {200, 201}:
|
||||||
result = await response.json()
|
result = await response.json()
|
||||||
logger.debug(f"Ответ JSON: {result}")
|
logger.debug(f"Ответ JSON: {result}")
|
||||||
return result
|
return result
|
||||||
if response.status in {404,400}:
|
if response.status in {404, 400}:
|
||||||
result = await response.json()
|
result = await response.json()
|
||||||
logger.debug(f"Код {response.status}, возвращаю {result}")
|
logger.debug(f"Код {response.status}, возвращаю {result}")
|
||||||
return result
|
return result
|
||||||
logger.error(f"Ошибка в запросе: статус {response.status}, причина {response.reason}")
|
logger.error(
|
||||||
|
f"Ошибка в запросе: статус {response.status}, причина {response.reason}")
|
||||||
return "ERROR"
|
return "ERROR"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Исключение при выполнении запроса к {url}: {e}")
|
logger.exception(f"Исключение при выполнении запроса к {url}: {e}")
|
||||||
return "ERROR"
|
return "ERROR"
|
||||||
|
|
||||||
|
|
||||||
def escape_markdown_v2(text: str) -> str:
|
def escape_markdown_v2(text: str) -> str:
|
||||||
"""
|
"""
|
||||||
Экранирует специальные символы для Markdown_V2.
|
Экранирует специальные символы для Markdown_V2.
|
||||||
@@ -45,7 +55,6 @@ def escape_markdown_v2(text: str) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@router.message(Command("subscriptions"))
|
@router.message(Command("subscriptions"))
|
||||||
async def supp(message: types.Message):
|
async def supp(message: types.Message):
|
||||||
"""
|
"""
|
||||||
@@ -56,7 +65,8 @@ async def supp(message: types.Message):
|
|||||||
try:
|
try:
|
||||||
# Вызов API для получения URI
|
# Вызов API для получения URI
|
||||||
result = await call_api("GET", f"/uri?telegram_id={message.from_user.id}")
|
result = await call_api("GET", f"/uri?telegram_id={message.from_user.id}")
|
||||||
uri = result.get('detail', "Error") # Получаем URI из ответа или "Error", если ключ отсутствует
|
# Получаем URI из ответа или "Error", если ключ отсутствует
|
||||||
|
uri = result.get('detail', "Error")
|
||||||
|
|
||||||
# Проверка результата
|
# Проверка результата
|
||||||
if uri == "Error":
|
if uri == "Error":
|
||||||
@@ -71,7 +81,8 @@ async def supp(message: types.Message):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Логирование ошибок
|
# Логирование ошибок
|
||||||
logger.error(f"Ошибка при вызове API для подписки: {e}")
|
logger.error(f"Ошибка при вызове API для подписки: {e}")
|
||||||
text = escape_markdown_v2("Произошла неожиданная ошибка при получении подписки.")
|
text = escape_markdown_v2(
|
||||||
|
"Произошла неожиданная ошибка при получении подписки.")
|
||||||
|
|
||||||
# Ответ пользователю
|
# Ответ пользователю
|
||||||
await message.answer(
|
await message.answer(
|
||||||
@@ -79,36 +90,67 @@ async def supp(message: types.Message):
|
|||||||
parse_mode=ParseMode.MARKDOWN_V2
|
parse_mode=ParseMode.MARKDOWN_V2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.callback_query(lambda callback: callback.data == "buy_subscription")
|
@router.callback_query(lambda callback: callback.data == "buy_subscription")
|
||||||
async def buy_subscription_callback_handler(callback: types.CallbackQuery):
|
async def buy_subscription_callback_handler(callback: types.CallbackQuery):
|
||||||
"""
|
"""
|
||||||
Обработчик callback_query с data="buy_subscription".
|
Меню выбора тарифа: Basic / Pro / Family + показ баланса.
|
||||||
"""
|
"""
|
||||||
await callback.message.edit_text(
|
# Тянем пользователя, чтобы показать баланс
|
||||||
f"Ознакомься с условиями в вкладке \"О тарифах\" и выбери подходящий 🦅",
|
user_data = await call_api("GET", f"/user/{callback.from_user.id}")
|
||||||
reply_markup=buy_keyboard()
|
balance = user_data.get("balance", 0) if user_data else "?"
|
||||||
|
|
||||||
|
text = (
|
||||||
|
"➕ <b>Подключить новую подписку</b>\n\n"
|
||||||
|
"🐣 Lark Basic - 200 ₽ / мес\n"
|
||||||
|
"🦅 Lark Pro - 400 ₽ / мес\n"
|
||||||
|
"👨👩👧 Lark Family - 700 ₽ / мес\n\n"
|
||||||
|
f"💰 Баланс: {balance} ₽\n\n"
|
||||||
|
"Выбери тариф:"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await callback.message.edit_text(
|
||||||
|
text,
|
||||||
|
parse_mode=ParseMode.HTML,
|
||||||
|
reply_markup=buy_keyboard(),
|
||||||
|
)
|
||||||
|
await callback.answer()
|
||||||
|
|
||||||
|
|
||||||
@router.callback_query(lambda callback: callback.data == "subs")
|
@router.callback_query(lambda callback: callback.data == "subs")
|
||||||
async def subs_callback_handler(callback: types.CallbackQuery):
|
async def subs_callback_handler(callback: types.CallbackQuery):
|
||||||
"""
|
"""
|
||||||
Обработчик callback_query с data="subs".
|
Обработчик callback_query с data="subs".
|
||||||
"""
|
"""
|
||||||
await callback.message.edit_text(
|
await callback.message.edit_text(
|
||||||
"Подписки птенчик",
|
"Подписки птенчик",
|
||||||
reply_markup=tarif_Lark_keyboard()
|
reply_markup=tarif_Lark_keyboard()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.callback_query(lambda callback: callback.data == "subs_pro")
|
@router.callback_query(lambda callback: callback.data == "subs_pro")
|
||||||
async def subs_pro_callback_handler(callback: types.CallbackQuery):
|
async def subs_pro_callback_handler(callback: types.CallbackQuery):
|
||||||
"""
|
"""
|
||||||
Обработчик callback_query с data="subs_pro".
|
Обработчик callback_query с data="subs_pro".
|
||||||
"""
|
"""
|
||||||
await callback.message.edit_text(
|
await callback.message.edit_text(
|
||||||
"Подписки птенчик ПРО",
|
"Подписки птенчик ПРО",
|
||||||
reply_markup=tarif_Lark_pro_keyboard()
|
reply_markup=tarif_Lark_pro_keyboard()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.callback_query(lambda callback: callback.data == "subs_family")
|
||||||
|
async def subs_family_callback_handler(callback: types.CallbackQuery):
|
||||||
|
"""
|
||||||
|
Обработчик callback_query с data="subs_family".
|
||||||
|
"""
|
||||||
|
await callback.message.edit_text(
|
||||||
|
"Подписки Lark Family",
|
||||||
|
reply_markup=tarif_Lark_family_keyboard(),
|
||||||
|
)
|
||||||
|
await callback.answer()
|
||||||
|
|
||||||
|
|
||||||
@router.callback_query(lambda callback: callback.data.startswith("Lark:"))
|
@router.callback_query(lambda callback: callback.data.startswith("Lark:"))
|
||||||
async def lark_tariff_callback_handler(callback: types.CallbackQuery):
|
async def lark_tariff_callback_handler(callback: types.CallbackQuery):
|
||||||
"""
|
"""
|
||||||
@@ -128,11 +170,12 @@ async def lark_tariff_callback_handler(callback: types.CallbackQuery):
|
|||||||
months = f"{tariff_time} месяцев"
|
months = f"{tariff_time} месяцев"
|
||||||
|
|
||||||
text = f"Тариф {tariff_name} на {months}. Продолжите покупку..."
|
text = f"Тариф {tariff_name} на {months}. Продолжите покупку..."
|
||||||
|
|
||||||
# Рендеринг клавиатуры
|
# Рендеринг клавиатуры
|
||||||
keyboard = tarif_confirm_keyboard(tariff_name, tariff_time, tariff_class)
|
keyboard = tarif_confirm_keyboard(tariff_name, tariff_time, tariff_class)
|
||||||
await callback.message.edit_text(text=text, reply_markup=keyboard)
|
await callback.message.edit_text(text=text, reply_markup=keyboard)
|
||||||
|
|
||||||
|
|
||||||
@router.callback_query(lambda callback: callback.data.startswith("confirm:"))
|
@router.callback_query(lambda callback: callback.data.startswith("confirm:"))
|
||||||
async def confirm_callback_handler(callback: types.CallbackQuery):
|
async def confirm_callback_handler(callback: types.CallbackQuery):
|
||||||
"""
|
"""
|
||||||
@@ -164,5 +207,3 @@ async def confirm_callback_handler(callback: types.CallbackQuery):
|
|||||||
await callback.message.edit_text("Произошла ошибка при оформлении подписки.")
|
await callback.message.edit_text("Произошла ошибка при оформлении подписки.")
|
||||||
finally:
|
finally:
|
||||||
await callback.answer()
|
await callback.answer()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -92,12 +92,11 @@ def ticket_keyboard():
|
|||||||
def buy_keyboard():
|
def buy_keyboard():
|
||||||
"""
|
"""
|
||||||
Меню выбора тарифа.
|
Меню выбора тарифа.
|
||||||
Лейблы ближе к твоему стилю, но callback’и остаются старые.
|
|
||||||
"""
|
"""
|
||||||
builder = InlineKeyboardBuilder()
|
builder = InlineKeyboardBuilder()
|
||||||
builder.row(
|
builder.row(
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
text="🐣 Lark (Basic)",
|
text="🐣 Lark Basic",
|
||||||
callback_data="subs",
|
callback_data="subs",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -109,8 +108,8 @@ def buy_keyboard():
|
|||||||
)
|
)
|
||||||
builder.row(
|
builder.row(
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
text="ℹ️ О тарифах",
|
text="👨👩👧 Lark Family",
|
||||||
url="https://t.me/proxylark/19",
|
callback_data="subs_family",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
builder.row(
|
builder.row(
|
||||||
@@ -136,51 +135,36 @@ def subhist_keyboard():
|
|||||||
return builder.as_markup()
|
return builder.as_markup()
|
||||||
|
|
||||||
|
|
||||||
def popup_keyboard():
|
def payment_methods_keyboard(amount: int):
|
||||||
"""
|
"""
|
||||||
Пополнение: суммы как в твоём топап-меню.
|
Способы оплаты для выбранной суммы.
|
||||||
|
ЛаркинсКоины убрал нахер
|
||||||
"""
|
"""
|
||||||
builder = InlineKeyboardBuilder()
|
builder = InlineKeyboardBuilder()
|
||||||
for amount in [200, 300, 600, 1000]:
|
builder.row(
|
||||||
builder.row(
|
InlineKeyboardButton(
|
||||||
InlineKeyboardButton(
|
text="⭐ Telegram Stars",
|
||||||
text=f"{amount} ₽",
|
callback_data=f"method_stars_{amount}",
|
||||||
callback_data=f"popup:{amount}",
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
builder.row(
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text="💵 YooKassa",
|
||||||
|
callback_data=f"method_ykassa_{amount}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
builder.row(
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text="🪙 CryptoBot",
|
||||||
|
callback_data=f"method_crypto_{amount}",
|
||||||
|
)
|
||||||
|
)
|
||||||
builder.row(
|
builder.row(
|
||||||
InlineKeyboardButton(
|
InlineKeyboardButton(
|
||||||
text="🔙 Назад",
|
text="🔙 Назад",
|
||||||
callback_data="profile",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return builder.as_markup()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def balance_keyboard():
|
|
||||||
"""
|
|
||||||
Баланс
|
|
||||||
"""
|
|
||||||
builder = InlineKeyboardBuilder()
|
|
||||||
builder.row(
|
|
||||||
InlineKeyboardButton(
|
|
||||||
text="🪙 Пополнить баланс",
|
|
||||||
callback_data="popup",
|
callback_data="popup",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
builder.row(
|
|
||||||
InlineKeyboardButton(
|
|
||||||
text="🧾 История транзакций",
|
|
||||||
callback_data="tranhist",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
builder.row(
|
|
||||||
InlineKeyboardButton(
|
|
||||||
text="🔙 Назад",
|
|
||||||
callback_data="profile",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return builder.as_markup()
|
return builder.as_markup()
|
||||||
|
|
||||||
|
|
||||||
@@ -248,6 +232,38 @@ def tarif_Lark_pro_keyboard():
|
|||||||
return builder.as_markup()
|
return builder.as_markup()
|
||||||
|
|
||||||
|
|
||||||
|
def tarif_Lark_family_keyboard():
|
||||||
|
"""
|
||||||
|
Тариф Lark Family.
|
||||||
|
"""
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
builder.row(
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text="👨👩👧 Lark Family 1 месяц",
|
||||||
|
callback_data="Lark:Family:1",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
builder.row(
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text="👨👩👧 Lark Family 6 месяцев",
|
||||||
|
callback_data="Lark:Family:6",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
builder.row(
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text="👨👩👧 Lark Family 12 месяцев",
|
||||||
|
callback_data="Lark:Family:12",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
builder.row(
|
||||||
|
InlineKeyboardButton(
|
||||||
|
text="🔙 Назад",
|
||||||
|
callback_data="buy_subscription",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return builder.as_markup()
|
||||||
|
|
||||||
|
|
||||||
def guide_keyboard():
|
def guide_keyboard():
|
||||||
"""
|
"""
|
||||||
Руководство по подключению
|
Руководство по подключению
|
||||||
|
|||||||
Reference in New Issue
Block a user