feat: Implement payment notification system and API structure
- Added notifications for successful payments in `api/core/notifications.py`. - Created main API entry point in `api/main.py` with FastAPI integration. - Established routing structure in `api/routes/__init__.py` and `api/routes/pally.py` for handling payment callbacks. - Developed billing handlers in `bot/handlers/billing.py` and `bot/handlers/buy.py` for subscription management. - Introduced state management for user interactions in `bot/states/`. - Created user interface elements in `bot/keyboards/` for navigation and payment processing. - Set up middleware for dependency injection in `bot/middlewares/di.py`. - Added support for user commands and interactions in `bot/handlers/common.py` and `bot/handlers/support.py`. - Implemented logging and error handling throughout the bot's functionality. - Created entry point script for API server in `entrypoints/api.sh`.
This commit is contained in:
0
bot/keyboards/__init__.py
Normal file
0
bot/keyboards/__init__.py
Normal file
16
bot/keyboards/admins.py
Normal file
16
bot/keyboards/admins.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
promotion_confirmation: InlineKeyboardMarkup = InlineKeyboardBuilder(
|
||||
[
|
||||
[InlineKeyboardButton(text="✅", callback_data="approve")],
|
||||
[InlineKeyboardButton(text="❌", callback_data="decline")],
|
||||
]
|
||||
).as_markup()
|
||||
|
||||
ticket_actions: InlineKeyboardMarkup = InlineKeyboardBuilder(
|
||||
[
|
||||
[InlineKeyboardButton(text="🔒", callback_data="close")],
|
||||
[InlineKeyboardButton(text="💸 Пополнить баланс реферала", callback_data="refpay")],
|
||||
]
|
||||
).as_markup()
|
||||
125
bot/keyboards/client.py
Normal file
125
bot/keyboards/client.py
Normal file
@@ -0,0 +1,125 @@
|
||||
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="sub_info")],
|
||||
[
|
||||
InlineKeyboardButton(text="⚙️ Купить", callback_data="buy"),
|
||||
InlineKeyboardButton(text="⁉️ FAQ", callback_data="faq"),
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(text="📢 Наш Канал", url="https://t.me/maleniavpn"),
|
||||
InlineKeyboardButton(text="🎧 Тех. Поддержка", url="https://t.me/maleniasupportbot"),
|
||||
],
|
||||
[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="💸 Pally (СБП / Карта)", callback_data="billing:pally")],
|
||||
[InlineKeyboardButton(text="✍️ Перейти в поддержку", url="https://t.me/maleniasupportbot")],
|
||||
[_return_to_menu_btn],
|
||||
]
|
||||
).as_markup()
|
||||
|
||||
close_kb: InlineKeyboardMarkup = InlineKeyboardBuilder(
|
||||
[[InlineKeyboardButton(text="❌", callback_data="delete")]]
|
||||
).as_markup()
|
||||
|
||||
support_url_kb: InlineKeyboardMarkup = InlineKeyboardBuilder(
|
||||
[
|
||||
[InlineKeyboardButton(text="✍️ Перейти в поддержку", url="https://t.me/maleniasupportbot")],
|
||||
[_return_to_menu_btn],
|
||||
]
|
||||
).as_markup()
|
||||
|
||||
|
||||
def _return_btn(data: str = "menu:main", text: str = "⬅️ Назад") -> InlineKeyboardButton:
|
||||
return InlineKeyboardButton(text=text, callback_data=data)
|
||||
|
||||
|
||||
def build_return_menu(data: str = "menu:main", text: str = "⬅️ Назад") -> InlineKeyboardMarkup:
|
||||
return InlineKeyboardBuilder([[_return_btn(data, text)]]).as_markup()
|
||||
|
||||
|
||||
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()
|
||||
|
||||
|
||||
def pay_url(url: str) -> InlineKeyboardMarkup:
|
||||
return InlineKeyboardBuilder(
|
||||
[
|
||||
[InlineKeyboardButton(text="💸 Оплатить", url=url)],
|
||||
[InlineKeyboardButton(text="❌", callback_data="menu:main")],
|
||||
]
|
||||
).as_markup()
|
||||
Reference in New Issue
Block a user