718 lines
23 KiB
Python
718 lines
23 KiB
Python
"""Клавиатуры бота."""
|
||
|
||
from __future__ import annotations
|
||
|
||
from aiogram.types import (
|
||
InlineKeyboardButton,
|
||
InlineKeyboardMarkup,
|
||
KeyboardButton,
|
||
ReplyKeyboardMarkup,
|
||
WebAppInfo,
|
||
)
|
||
|
||
from services.tariffs import Tariff
|
||
|
||
|
||
def main_menu(is_admin: bool = False, *, webapp_url: str | None = None) -> ReplyKeyboardMarkup:
|
||
rows: list[list[KeyboardButton]] = []
|
||
if webapp_url:
|
||
rows.append(
|
||
[
|
||
KeyboardButton(
|
||
text="🚀 Mini App",
|
||
web_app=WebAppInfo(url=webapp_url),
|
||
)
|
||
]
|
||
)
|
||
rows.extend(
|
||
[
|
||
[KeyboardButton(text="🛒 Тарифы"), KeyboardButton(text="💰 Баланс")],
|
||
[KeyboardButton(text="📱 Моя подписка"), KeyboardButton(text="📡 Статус серверов")],
|
||
[KeyboardButton(text="📥 Скачать клиент"), KeyboardButton(text="❓ FAQ")],
|
||
[KeyboardButton(text="🎫 Тикеты"), KeyboardButton(text="ℹ️ Помощь")],
|
||
]
|
||
)
|
||
if is_admin:
|
||
rows.append([KeyboardButton(text="🛠 Админка")])
|
||
return ReplyKeyboardMarkup(
|
||
keyboard=rows,
|
||
resize_keyboard=True,
|
||
input_field_placeholder="Выберите действие…",
|
||
)
|
||
|
||
|
||
def faq_root_inline() -> InlineKeyboardMarkup:
|
||
from services.faq import FAQ_ITEMS
|
||
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
for item in FAQ_ITEMS:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text=item.question,
|
||
callback_data=f"faq:view:{item.id}",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="🏠 Меню", callback_data="menu:home")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def faq_back_inline() -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[InlineKeyboardButton(text="⬅️ Все вопросы", callback_data="faq:root")],
|
||
[InlineKeyboardButton(text="🏠 Меню", callback_data="menu:home")],
|
||
]
|
||
)
|
||
|
||
|
||
def clients_root_inline() -> InlineKeyboardMarkup:
|
||
from services.clients import TOP_CLIENTS
|
||
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
row: list[InlineKeyboardButton] = []
|
||
for client in TOP_CLIENTS:
|
||
prefix = "⭐ " if client.featured else ""
|
||
row.append(
|
||
InlineKeyboardButton(
|
||
text=f"{prefix}{client.name}",
|
||
callback_data=f"clients:view:{client.id}",
|
||
)
|
||
)
|
||
if len(row) == 2:
|
||
rows.append(row)
|
||
row = []
|
||
if row:
|
||
rows.append(row)
|
||
rows.append(
|
||
[InlineKeyboardButton(text="📚 Все клиенты (docs.rw)", url="https://docs.rw/clients")]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="🏠 Меню", callback_data="menu:home")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def clients_links_inline(links: tuple, *, back: str = "clients:root") -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
for link in links:
|
||
rows.append([InlineKeyboardButton(text=f"⬇️ {link.title}", url=link.url)])
|
||
rows.append([InlineKeyboardButton(text="⬅️ Назад", callback_data=back)])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def servers_inline() -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[InlineKeyboardButton(text="🔄 Обновить", callback_data="servers:refresh")],
|
||
[InlineKeyboardButton(text="🏠 Меню", callback_data="menu:home")],
|
||
]
|
||
)
|
||
|
||
|
||
def balance_inline(
|
||
*,
|
||
crypto_enabled: bool = False,
|
||
heleket_enabled: bool = False,
|
||
digiseller_enabled: bool = False,
|
||
lava_enabled: bool = False,
|
||
anypay_enabled: bool = False,
|
||
stars_enabled: bool = False,
|
||
) -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
if stars_enabled:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="⭐ Telegram Stars",
|
||
callback_data="pay:stars",
|
||
)
|
||
]
|
||
)
|
||
if crypto_enabled or heleket_enabled:
|
||
rows.append(
|
||
[InlineKeyboardButton(text="🪙 Пополнить криптой", callback_data="pay:topup")]
|
||
)
|
||
if lava_enabled:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="💳 Lava (карта / СБП)",
|
||
callback_data="pay:lava",
|
||
)
|
||
]
|
||
)
|
||
if anypay_enabled:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="💳 AnyPay",
|
||
callback_data="pay:anypay",
|
||
)
|
||
]
|
||
)
|
||
if digiseller_enabled:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="💳 Digiseller",
|
||
callback_data="pay:digiseller",
|
||
)
|
||
]
|
||
)
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="🎫 Код пополнения",
|
||
callback_data="pay:topup_code",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="🛒 Купить тариф", callback_data="shop:list")])
|
||
rows.append([InlineKeyboardButton(text="🏠 Меню", callback_data="menu:home")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def digiseller_inline(*, pay_url: str) -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
if pay_url:
|
||
rows.append([InlineKeyboardButton(text="💳 Оплатить на Digiseller", url=pay_url)])
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="🔄 Не зачислилось? Ввести код",
|
||
callback_data="pay:digiseller_code",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="⬅️ Назад", callback_data="pay:balance")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def digiseller_cancel_inline() -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[InlineKeyboardButton(text="❌ Отмена", callback_data="pay:digiseller_cancel")]
|
||
]
|
||
)
|
||
|
||
|
||
def topup_code_inline(*, pay_url: str = "") -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
if pay_url:
|
||
rows.append([InlineKeyboardButton(text="🛒 Купить код", url=pay_url)])
|
||
rows.append(
|
||
[InlineKeyboardButton(text="❌ Отмена", callback_data="pay:topup_code_cancel")]
|
||
)
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def topup_providers_inline(
|
||
*,
|
||
crypto_enabled: bool,
|
||
heleket_enabled: bool,
|
||
) -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
if crypto_enabled:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="Crypto Bot",
|
||
callback_data="pay:topup_provider:cryptobot",
|
||
)
|
||
]
|
||
)
|
||
if heleket_enabled:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="Heleket (резерв)",
|
||
callback_data="pay:topup_provider:heleket",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="⬅️ Назад", callback_data="pay:balance")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def topup_amounts_inline(provider: str = "cryptobot") -> InlineKeyboardMarkup:
|
||
amounts = [50, 100, 200, 500, 1000, 2000, 3000]
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
row: list[InlineKeyboardButton] = []
|
||
for amount in amounts:
|
||
row.append(
|
||
InlineKeyboardButton(
|
||
text=f"{amount} ₽",
|
||
callback_data=f"pay:topup_amount:{provider}:{amount}",
|
||
)
|
||
)
|
||
if len(row) == 3:
|
||
rows.append(row)
|
||
row = []
|
||
if row:
|
||
rows.append(row)
|
||
back = "pay:stars" if provider == "stars" else "pay:topup"
|
||
rows.append([InlineKeyboardButton(text="⬅️ Назад", callback_data=back)])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def stars_amounts_inline(*, rub_per_star: float) -> InlineKeyboardMarkup:
|
||
from services.stars import STAR_TOPUP_AMOUNTS_RUB, quote_topup
|
||
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
for amount in STAR_TOPUP_AMOUNTS_RUB:
|
||
q = quote_topup(amount, rub_per_star=rub_per_star)
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text=f"{q.rub_label} · {q.stars_label}",
|
||
callback_data=f"pay:stars_amount:{amount}",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="⬅️ Назад", callback_data="pay:balance")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def tariffs_inline(tariffs: list[Tariff]) -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
for t in tariffs:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text=f"{t.title} · {t.format_price()}",
|
||
callback_data=f"shop:view:{t.id}",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="🏠 Меню", callback_data="menu:home")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def renew_tariffs_inline(tariffs: list[Tariff]) -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
for t in tariffs:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text=f"➕ {t.title} · {t.format_price()}",
|
||
callback_data=f"renew:view:{t.id}",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="⬅️ К подписке", callback_data="sub:mine")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def renew_confirm_inline(tariff_id: str) -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(
|
||
text="✅ Продлить с баланса",
|
||
callback_data=f"renew:buy:{tariff_id}",
|
||
)
|
||
],
|
||
[InlineKeyboardButton(text="⬅️ Назад", callback_data="renew:list")],
|
||
]
|
||
)
|
||
|
||
|
||
def subscription_inline(
|
||
*,
|
||
has_subscription: bool,
|
||
devices_over: bool = False,
|
||
) -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
if has_subscription:
|
||
if devices_over:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="⚠️ Оплатить лишние устройства",
|
||
callback_data="devices:list",
|
||
)
|
||
]
|
||
)
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="🔄 Продлить с баланса",
|
||
callback_data="renew:list",
|
||
)
|
||
]
|
||
)
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="📦 Докупить трафик",
|
||
callback_data="traffic:list",
|
||
)
|
||
]
|
||
)
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="📱 Доп. устройства",
|
||
callback_data="devices:list",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="🛒 Тарифы", callback_data="shop:list")])
|
||
rows.append([InlineKeyboardButton(text="🏠 Меню", callback_data="menu:home")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def device_packs_inline(*, excess: int = 0) -> InlineKeyboardMarkup:
|
||
from services.devices import DEVICE_PACKS, EXTRA_DEVICE_PRICE_RUB
|
||
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
if excess > 0:
|
||
price = int(excess * EXTRA_DEVICE_PRICE_RUB)
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text=f"⚠️ Оплатить превышение +{excess} · {price} ₽",
|
||
callback_data=f"devices:confirm:{excess}",
|
||
)
|
||
]
|
||
)
|
||
for pack in DEVICE_PACKS:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text=f"{pack.title} · {pack.format_price()}",
|
||
callback_data=f"devices:buy:{pack.slots}",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="⬅️ К подписке", callback_data="sub:mine")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def device_confirm_inline(slots: int) -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(
|
||
text="✅ Купить с баланса",
|
||
callback_data=f"devices:confirm:{slots}",
|
||
)
|
||
],
|
||
[InlineKeyboardButton(text="⬅️ Назад", callback_data="devices:list")],
|
||
]
|
||
)
|
||
|
||
|
||
def traffic_packs_inline() -> InlineKeyboardMarkup:
|
||
from services.traffic import TRAFFIC_PACKS
|
||
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
for pack in TRAFFIC_PACKS:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text=f"{pack.title} · {pack.format_price()}",
|
||
callback_data=f"traffic:buy:{pack.packs}",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="⬅️ К подписке", callback_data="sub:mine")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def traffic_confirm_inline(packs: int) -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(
|
||
text="✅ Купить с баланса",
|
||
callback_data=f"traffic:confirm:{packs}",
|
||
)
|
||
],
|
||
[InlineKeyboardButton(text="⬅️ Назад", callback_data="traffic:list")],
|
||
]
|
||
)
|
||
|
||
|
||
def tariff_pay_methods_inline(
|
||
tariff_id: str,
|
||
*,
|
||
crypto_enabled: bool,
|
||
heleket_enabled: bool = False,
|
||
lava_enabled: bool = False,
|
||
anypay_enabled: bool = False,
|
||
) -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = [
|
||
[
|
||
InlineKeyboardButton(
|
||
text="💰 С баланса",
|
||
callback_data=f"shop:buy_balance:{tariff_id}",
|
||
)
|
||
]
|
||
]
|
||
if crypto_enabled:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="🪙 Crypto Bot",
|
||
callback_data=f"shop:buy_crypto:{tariff_id}",
|
||
)
|
||
]
|
||
)
|
||
if heleket_enabled:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="🪙 Heleket",
|
||
callback_data=f"shop:buy_heleket:{tariff_id}",
|
||
)
|
||
]
|
||
)
|
||
if lava_enabled:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="💳 Lava (карта / СБП)",
|
||
callback_data=f"shop:buy_lava:{tariff_id}",
|
||
)
|
||
]
|
||
)
|
||
if anypay_enabled:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="💳 AnyPay",
|
||
callback_data=f"shop:buy_anypay:{tariff_id}",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="⬅️ Назад", callback_data="shop:list")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def invoice_inline(
|
||
invoice_id: int,
|
||
pay_url: str,
|
||
*,
|
||
provider: str = "cryptobot",
|
||
) -> InlineKeyboardMarkup:
|
||
if provider == "anypay":
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[InlineKeyboardButton(text="💳 Оплатить AnyPay", url=pay_url)],
|
||
[InlineKeyboardButton(text="🏠 Меню", callback_data="menu:home")],
|
||
]
|
||
)
|
||
if provider == "heleket":
|
||
check_cb = f"pay:check_hk:{invoice_id}"
|
||
elif provider == "lava":
|
||
check_cb = f"pay:check_lava:{invoice_id}"
|
||
else:
|
||
check_cb = f"pay:check:{invoice_id}"
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[InlineKeyboardButton(text="🪙 Оплатить", url=pay_url)],
|
||
[
|
||
InlineKeyboardButton(
|
||
text="✅ Я оплатил — проверить",
|
||
callback_data=check_cb,
|
||
)
|
||
],
|
||
[InlineKeyboardButton(text="🏠 Меню", callback_data="menu:home")],
|
||
]
|
||
)
|
||
|
||
|
||
def admin_inline() -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(text="📡 Серверы", callback_data="admin:servers"),
|
||
InlineKeyboardButton(text="💚 Health API", callback_data="admin:health"),
|
||
],
|
||
[
|
||
InlineKeyboardButton(text="👥 Пользователи", callback_data="admin:users"),
|
||
InlineKeyboardButton(text="📊 Статистика", callback_data="admin:stats"),
|
||
],
|
||
[
|
||
InlineKeyboardButton(
|
||
text="🎫 Тикеты",
|
||
callback_data="admin:tickets",
|
||
)
|
||
],
|
||
[
|
||
InlineKeyboardButton(
|
||
text="💰 Пополнить пользователю",
|
||
callback_data="admin:topup",
|
||
)
|
||
],
|
||
[
|
||
InlineKeyboardButton(text="🔄 Обновить панель", callback_data="admin:home"),
|
||
InlineKeyboardButton(text="🏠 В меню", callback_data="menu:home"),
|
||
],
|
||
]
|
||
)
|
||
|
||
|
||
def tickets_root_inline(*, has_open: bool = False) -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = [
|
||
[InlineKeyboardButton(text="✍️ Новый тикет", callback_data="tix:new")],
|
||
[InlineKeyboardButton(text="📋 Мои тикеты", callback_data="tix:list")],
|
||
]
|
||
if has_open:
|
||
rows.insert(
|
||
1,
|
||
[InlineKeyboardButton(text="🟢 Открытые", callback_data="tix:list:open")],
|
||
)
|
||
rows.append([InlineKeyboardButton(text="🏠 Меню", callback_data="menu:home")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def tickets_list_inline(
|
||
tickets: list,
|
||
*,
|
||
prefix: str = "tix:view",
|
||
back: str = "tix:root",
|
||
) -> InlineKeyboardMarkup:
|
||
from services.tickets import status_label
|
||
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
for t in tickets[:20]:
|
||
tid = int(t["id"])
|
||
st = status_label(str(t.get("status") or ""), short=True)
|
||
subj = str(t.get("subject") or "")[:28]
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text=f"#{tid} · {st} · {subj}",
|
||
callback_data=f"{prefix}:{tid}",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="⬅️ Назад", callback_data=back)])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def ticket_view_inline(ticket_id: int, *, status: str, is_admin: bool = False) -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
if status != "closed":
|
||
reply_cb = f"admin:tix:reply:{ticket_id}" if is_admin else f"tix:reply:{ticket_id}"
|
||
close_cb = f"admin:tix:close:{ticket_id}" if is_admin else f"tix:close:{ticket_id}"
|
||
rows.append([InlineKeyboardButton(text="💬 Ответить", callback_data=reply_cb)])
|
||
rows.append([InlineKeyboardButton(text="🔒 Закрыть", callback_data=close_cb)])
|
||
elif is_admin:
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="🔓 Открыть снова",
|
||
callback_data=f"admin:tix:reopen:{ticket_id}",
|
||
)
|
||
]
|
||
)
|
||
back = "admin:tickets" if is_admin else "tix:list"
|
||
rows.append([InlineKeyboardButton(text="⬅️ К списку", callback_data=back)])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def ticket_cancel_inline(*, back: str = "tix:root") -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[InlineKeyboardButton(text="❌ Отмена", callback_data=back)],
|
||
]
|
||
)
|
||
|
||
|
||
def ticket_notify_inline(ticket_id: int) -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(
|
||
text="Открыть тикет",
|
||
callback_data=f"tix:view:{ticket_id}",
|
||
)
|
||
]
|
||
]
|
||
)
|
||
|
||
|
||
def admin_ticket_notify_inline(ticket_id: int) -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(
|
||
text="Открыть тикет",
|
||
callback_data=f"admin:tix:view:{ticket_id}",
|
||
)
|
||
]
|
||
]
|
||
)
|
||
|
||
|
||
def admin_tickets_root_inline(stats: dict | None = None) -> InlineKeyboardMarkup:
|
||
open_n = int((stats or {}).get("open") or 0)
|
||
ans_n = int((stats or {}).get("answered") or 0)
|
||
rows = [
|
||
[
|
||
InlineKeyboardButton(
|
||
text=f"🟢 Открытые ({open_n})",
|
||
callback_data="admin:tickets:open",
|
||
)
|
||
],
|
||
[
|
||
InlineKeyboardButton(
|
||
text=f"💬 С ответом ({ans_n})",
|
||
callback_data="admin:tickets:answered",
|
||
)
|
||
],
|
||
[InlineKeyboardButton(text="📋 Все", callback_data="admin:tickets:all")],
|
||
[InlineKeyboardButton(text="⬅️ Админка", callback_data="admin:home")],
|
||
]
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def admin_back_inline() -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(text="🔄 Обновить", callback_data="admin:servers"),
|
||
InlineKeyboardButton(text="⬅️ Назад", callback_data="admin:home"),
|
||
]
|
||
]
|
||
)
|
||
|
||
|
||
def admin_topup_cancel() -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[InlineKeyboardButton(text="❌ Отмена", callback_data="admin:topup_cancel")]
|
||
]
|
||
)
|
||
|
||
|
||
def admin_topup_amounts(telegram_id: int) -> InlineKeyboardMarkup:
|
||
amounts = [100, 200, 500, 1000, 2000, 5000]
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
row: list[InlineKeyboardButton] = []
|
||
for amount in amounts:
|
||
row.append(
|
||
InlineKeyboardButton(
|
||
text=f"+{amount} ₽",
|
||
callback_data=f"admin:topup_do:{telegram_id}:{amount}",
|
||
)
|
||
)
|
||
if len(row) == 3:
|
||
rows.append(row)
|
||
row = []
|
||
if row:
|
||
rows.append(row)
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text="✏️ Своя сумма",
|
||
callback_data=f"admin:topup_custom:{telegram_id}",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="❌ Отмена", callback_data="admin:topup_cancel")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|