Introduce balance field to User model with Alembic migration. Add referral menu, admin /refpay command, and deep link sharing. Update Dockerfile to multi-stage build and add Postgres service to compose. Fix deep link parsing logic and conditional proxy initialization.
106 lines
3.3 KiB
Python
106 lines
3.3 KiB
Python
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||
|
||
from config import settings
|
||
from misc.utils import convert_duration_to_int
|
||
from schemas.subscriptions import SubscriptionDuration
|
||
|
||
main_menu = InlineKeyboardBuilder(
|
||
[
|
||
[
|
||
InlineKeyboardButton(text="⚙️ Купить", callback_data="buy"),
|
||
InlineKeyboardButton(text="FAQ", callback_data="faq"),
|
||
],
|
||
[
|
||
InlineKeyboardButton(text="Наш Канал", url="https://goo.gle"),
|
||
InlineKeyboardButton(text="Тех. Поддержка", callback_data="support"),
|
||
],
|
||
[InlineKeyboardButton(text="🔗 Обновить ссылку", callback_data="update_link")],
|
||
[InlineKeyboardButton(text="👤 Реферальная система", callback_data="referal")],
|
||
]
|
||
).as_markup()
|
||
|
||
_return_to_menu_btn: InlineKeyboardButton = InlineKeyboardButton(
|
||
text="⬅️ Назад", callback_data="menu:main"
|
||
)
|
||
|
||
return_to_menu: InlineKeyboardMarkup = InlineKeyboardBuilder(
|
||
[[_return_to_menu_btn]]
|
||
).as_markup()
|
||
|
||
payment_gateways: InlineKeyboardMarkup = InlineKeyboardBuilder(
|
||
[
|
||
[InlineKeyboardButton(text="✍️ Перейти в поддержку", callback_data="checkout")],
|
||
[_return_to_menu_btn],
|
||
]
|
||
).as_markup()
|
||
|
||
|
||
def _return_btn(
|
||
data: str = "menu:main", text: str = "⬅️ Назад"
|
||
) -> InlineKeyboardButton:
|
||
return InlineKeyboardButton(text=text, callback_data=data)
|
||
|
||
|
||
def devices_selector(current: int = settings.min_devices, whitelists: bool = False):
|
||
builder = InlineKeyboardBuilder()
|
||
|
||
buttons = [
|
||
InlineKeyboardButton(
|
||
text=f"{'✅ ' if i == current else ''}{i}", callback_data=f"devices:{i}"
|
||
)
|
||
for i in range(settings.min_devices, settings.max_devices + 1)
|
||
]
|
||
builder.add(*buttons).adjust(6)
|
||
|
||
wl_icon = "✅ " if whitelists else ""
|
||
builder.row(
|
||
InlineKeyboardButton(
|
||
text=f"{wl_icon}Обход Белых Списков (+100₽)",
|
||
callback_data="whitelist:toggle",
|
||
)
|
||
)
|
||
builder.row(InlineKeyboardButton(text="🟢", callback_data="confirm"))
|
||
builder.row(_return_to_menu_btn)
|
||
|
||
return builder.as_markup()
|
||
|
||
|
||
def duration_selector(
|
||
current: SubscriptionDuration = SubscriptionDuration.MONTH,
|
||
back_cb: str = "menu:main",
|
||
) -> InlineKeyboardMarkup:
|
||
builder = InlineKeyboardBuilder()
|
||
duration_int = convert_duration_to_int(current)
|
||
|
||
durations = [
|
||
(1, "1 Месяц"),
|
||
(3, "3 Месяца"),
|
||
(6, "6 Месяцев"),
|
||
(12, "1 Год"),
|
||
]
|
||
|
||
for val, label in durations:
|
||
is_selected = val == duration_int
|
||
|
||
builder.button(
|
||
text=f"{'✅ ' if is_selected else ''}{label}",
|
||
callback_data=f"duration:{val}",
|
||
)
|
||
|
||
builder.row(
|
||
InlineKeyboardButton(text="🛒 Перейти к оплате", callback_data="confirm")
|
||
)
|
||
builder.row(_return_btn(back_cb))
|
||
|
||
return builder.as_markup()
|
||
|
||
|
||
def referals_kb(share_link: str) -> InlineKeyboardMarkup:
|
||
return InlineKeyboardBuilder(
|
||
[
|
||
[InlineKeyboardButton(text="🔗 Поделиться ссылкой", url=share_link)],
|
||
[_return_to_menu_btn],
|
||
]
|
||
).as_markup()
|