Move DTO definitions from dto/ to schemas/ and update imports. Add buy handler with FSM state management for device selection, whitelist toggling, and duration choice. Include pricing logic, inline keyboards, and new configuration fields.
139 lines
5.3 KiB
Python
139 lines
5.3 KiB
Python
from misc.utils import fetch_quote
|
||
from db.models.tickets import TicketStatus
|
||
|
||
|
||
class PremiumEmoji:
|
||
def __init__(self, emoji_id: int, emoji: str):
|
||
self.emoji_id = emoji_id
|
||
self.emoji = emoji
|
||
|
||
def __str__(self) -> str:
|
||
return f'<tg-emoji emoji-id="{self.emoji_id}">{self.emoji}</tg-emoji>'
|
||
|
||
|
||
## EMOJIS
|
||
|
||
|
||
MALENIA_LOGO = PremiumEmoji(5265053829522562789, "☀️")
|
||
MALENIA_HEART = PremiumEmoji(5276516908257025723, "❤️")
|
||
MALENIA_LINK = PremiumEmoji(5276012730636082950, "🔗")
|
||
MALENIA_COINS = PremiumEmoji(5276298354551199712, "🪙")
|
||
MALENIA_LOCKED = PremiumEmoji(5276346642868508688, "🔒")
|
||
MALENIA_SUPPORT = PremiumEmoji(5275968088746006467, "🎧")
|
||
|
||
## MAPPING
|
||
TICKET_STATUS_EMOJIS = {
|
||
TicketStatus.CLOSED.value: "🔴",
|
||
TicketStatus.OPEN.value: "🟢",
|
||
TicketStatus.PENDING.value: "🟡",
|
||
}
|
||
|
||
## TEXTS
|
||
MAIN_MENU = (
|
||
str(MALENIA_LOGO)
|
||
+ " <b>Malenia — <i>{quote}</i></b>\n\n"
|
||
+ f"<i>{MALENIA_COINS} Личный кабинет</i>"
|
||
)
|
||
STANDARD_FALLBACK = (
|
||
"<b>❌ Что-то пошло не так</b>, прожмите /start и повторите попытку позже."
|
||
)
|
||
|
||
CALLBACK_FALLBACK = "❌ Что-то пошло не так"
|
||
CONTEXT_REINITIATED = "🔴 Контекст данного взаимодействия сброшен. Данные могут отличаться от указанных вами."
|
||
|
||
GENERAL_PROCESSING = "<i>⏳ Выполняю...</i>"
|
||
|
||
SUBSCRIPTION_DEVICE_SELECTOR = (
|
||
"выбери колво устройств епта. тут ещё цена есть смотри опа: {price}"
|
||
)
|
||
WHITELISTS_ALREADY_ON = "уже включены!"
|
||
SUBSCRIPTION_DURATION_SELECTOR = (
|
||
"тут короче сколько время. а ещё цена смотри ОПА {price}"
|
||
)
|
||
|
||
SUPPORT_INIT = f"<b>{MALENIA_SUPPORT} <i>Что-то не работает? Жалоба? Предложение?</i></b>\n— всё сюда, желательно со скриншотами. Чем детальнее описание, тем быстрее ответ.\n\n<i>❌ Для отмены — /cancel</i>"
|
||
SUPPORT_MSG_SENT = "⏳ Сообщение отправлено. Для выхода — /cancel, вы можете вернуться сюда из главного меню в любое время."
|
||
SUPPORT_SIGNATURE = "<b>✍️ Сообщение от технической поддержки:</b>"
|
||
ADMIN_TICKET_WITH_RW = (
|
||
"🎫 <b>ТИКЕТ T-{ticket_number:04d}</b>\n\n"
|
||
"👤 <b>Имя:</b> {full_name}\n"
|
||
"🔗 <b>Username:</b> {username_display}\n"
|
||
"🆔 <b>Telegram ID:</b> <code>{telegram_id}</code>\n\n"
|
||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
|
||
"📋 <b>ПОДПИСКА REMNAWAVE</b>\n\n"
|
||
"{status_icon} <b>Статус:</b> {status}\n"
|
||
"📅 <b>Истекает:</b> {expire_date}\n"
|
||
"⏳ <b>Осталось:</b> {days_left}\n"
|
||
"📊 <b>Трафик:</b> {used_traffic}\n"
|
||
"📱 <b>HWID лимит:</b> {hwid_limit}\n"
|
||
"🎯 <b>Internal Squads:</b> {squads}\n\n"
|
||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
|
||
"🔑 <b>UUID в Remnawave:</b> <code>{remnawave_uuid}</code>"
|
||
)
|
||
ADMIN_TICKET_WITHOUT_RW = (
|
||
"🎫 <b>ТИКЕТ T-{ticket_number:04d}</b>\n\n"
|
||
"👤 <b>Имя:</b> {full_name}\n"
|
||
"🔗 <b>Username:</b> {username_display}\n"
|
||
"🆔 <b>Telegram ID:</b> <code>{telegram_id}</code>\n\n"
|
||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
|
||
"⚠️ <b>Аккаунт в Remnawave не найден</b>"
|
||
)
|
||
|
||
|
||
ADMIN_STANDARD_FALLBACK = (
|
||
"<b>❌ Что-то пошло не так</b>, обратитесь к логам для подробностей."
|
||
)
|
||
|
||
|
||
## FUNCTIONS
|
||
def build_main_menu_text() -> str:
|
||
return MAIN_MENU.format(quote=fetch_quote())
|
||
|
||
|
||
NO_USERNAME = "нет юзернейма"
|
||
STATUS_ICON_ACTIVE = "🟢"
|
||
STATUS_ICON_DISABLED = "🔴"
|
||
STATUS_ICON_EXPIRED = "🟡"
|
||
STATUS_ICON_LIMITED = "🟠"
|
||
STATUS_ICON_UNKNOWN = "⚪"
|
||
|
||
# Текст статуса подписки
|
||
STATUS_ACTIVE = "Активна"
|
||
STATUS_DISABLED = "Отключена"
|
||
STATUS_EXPIRED = "Истекла"
|
||
STATUS_LIMITED = "Превышен лимит трафика"
|
||
STATUS_UNKNOWN = "Неизвестен"
|
||
|
||
# Шаблон для остатка дней: {days} дн.
|
||
DAYS_LEFT_POSITIVE = "{days} дн."
|
||
|
||
# Когда подписка уже истекла
|
||
DAYS_LEFT_EXPIRED = "истекла {days} дн. назад"
|
||
|
||
# Когда подписка истекает сегодня
|
||
DAYS_LEFT_TODAY = "истекает сегодня"
|
||
|
||
# Когда нет username в Telegram
|
||
NO_USERNAME = "нет username"
|
||
|
||
# Формат отображения username (с @)
|
||
USERNAME_DISPLAY = "@{username}"
|
||
|
||
# Когда у пользователя нет Internal Squads
|
||
NO_SQUADS = "нет"
|
||
|
||
# Когда лимит HWID не установлен (0 или None)
|
||
UNLIMITED_HWID = "без ограничений"
|
||
|
||
# Когда лимит трафика не установлен
|
||
NO_TRAFFIC_LIMIT = "без ограничений"
|
||
|
||
# Шаблон для отображения трафика с лимитом: {used} / {limit}
|
||
TRAFFIC_WITH_LIMIT = "{used} / {limit}"
|
||
|
||
# Шаблон для отображения трафика без лимита: {used}
|
||
TRAFFIC_NO_LIMIT = "{used}"
|
||
|
||
|
||
NOTHING_PLACEHOLDER = "🍃"
|