- 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`.
248 lines
11 KiB
Python
248 lines
11 KiB
Python
# ============================================================
|
||
# PREMIUM EMOJI
|
||
# ============================================================
|
||
|
||
|
||
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>'
|
||
|
||
|
||
# — Иконки бота
|
||
MALENIA_LOGO = PremiumEmoji(5265053829522562789, "☀️")
|
||
MALENIA_HEART = PremiumEmoji(5276516908257025723, "❤️")
|
||
MALENIA_LINK = PremiumEmoji(5276012730636082950, "🔗")
|
||
MALENIA_COINS = PremiumEmoji(5276298354551199712, "🪙")
|
||
MALENIA_LOCKED = PremiumEmoji(5276346642868508688, "🔒")
|
||
MALENIA_SUPPORT = PremiumEmoji(5275968088746006467, "🎧")
|
||
|
||
|
||
# ============================================================
|
||
# ШАБЛОНЫ — ОБЩИЕ БЛОКИ
|
||
# ============================================================
|
||
|
||
_SUPPORT_USER_DESCRIPTION = (
|
||
"👤 <b>Профиль:</b> {full_name}\n"
|
||
"🔗 <b>Alias:</b> {username_display}\n"
|
||
"🆔 <b>UID:</b> <code>{telegram_id}</code>\n\n"
|
||
"❤️ <b>Referal UID:</b> <code>{referal_id}</code>\n\n"
|
||
"💰 <b>Баланс:</b> <code>{balance}</code>"
|
||
)
|
||
|
||
_DIVIDER = "────────────────────────────\n\n"
|
||
|
||
|
||
# ============================================================
|
||
# МАППИНГИ
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
# СТАТУСЫ ПОДПИСКИ
|
||
# ============================================================
|
||
|
||
# — Иконки статусов
|
||
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_LEFT_POSITIVE = "{days} дн."
|
||
DAYS_LEFT_EXPIRED = "истекла {days} дн. назад"
|
||
DAYS_LEFT_TODAY = "подходит к концу сегодня"
|
||
|
||
# — Username
|
||
NO_USERNAME = "отсутствует"
|
||
USERNAME_DISPLAY = "@{username}"
|
||
|
||
# — Internal Squads
|
||
NO_SQUADS = "отсутствуют"
|
||
|
||
# — HWID лимит
|
||
UNLIMITED_HWID = "без лимитов"
|
||
|
||
# — Трафик
|
||
NO_TRAFFIC_LIMIT = "не ограничен"
|
||
TRAFFIC_WITH_LIMIT = "{used} / {limit}"
|
||
TRAFFIC_NO_LIMIT = "{used}"
|
||
|
||
# — Прочее
|
||
NOTHING_PLACEHOLDER = "∅"
|
||
|
||
|
||
# ============================================================
|
||
# ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС
|
||
# ============================================================
|
||
|
||
MAIN_MENU = (
|
||
str(MALENIA_LOGO)
|
||
+ " <b>Malenia — <i>{quote}</i></b>\n\n"
|
||
+ f"<i>{MALENIA_COINS} Личный кабинет</i>\n"
|
||
+ f"<b>{MALENIA_LINK} Ссылка на подписку: <code>{{link}}</code></b>"
|
||
)
|
||
|
||
FAQ_TEXT = (
|
||
"<b>Ваши частые вопросы:</b>\n\n"
|
||
"<b>— Зачем мне это?</b>\n"
|
||
"Если вас устраивает, что ваш интернет ограничен парой сайтов и банков, то вам не к нам. Но если хочется свободы и анонимности — добро пожаловать.\n\n"
|
||
"<b>— Это безопасно?</b>\n"
|
||
"Мы не храним ваши данные, не используем их в коммерческих целях и не передаем третьим лицам,"
|
||
"но важно понимать, что полной анонимности не существует. Мы делаем всё, чтобы минимизировать риски, но не продаём иллюзий.\n\n"
|
||
"<b>— Почему что-то не работает?</b>\n"
|
||
"Фильтры постоянно обновляются и подстраиваются под новые методы обхода. А мы подстраиваемся под них.\n"
|
||
"Если что-то перестало работать, скорее всего, это временно, и мы уже работаем над решением. Но обращения в поддержку с описанием проблемы и скриншотами всегда приветствуются, это помогает нам быстрее находить и устранять проблемы.\n\n"
|
||
"<b>— Как работает реферальная система?</b>\n"
|
||
"Вы получаете уникальную ссылку, по которой могут прийти ваши друзья. За каждого приведённого друга, который оформит подписку,"
|
||
"<b>вам будет начисляться процент от их оплаченной подписки</b> на баланс."
|
||
)
|
||
|
||
GENERAL_PROCESSING = "<i>⏳ Подождите...</i>"
|
||
|
||
STANDARD_FALLBACK = (
|
||
"<b>❌ Ошибка.</b> Прожмите /start. Если не поможет — значит, мы где-то не доглядели."
|
||
)
|
||
|
||
CALLBACK_FALLBACK = "❌ Что-то пошло не так. Повторите попытку или обратитесь в поддержку."
|
||
|
||
CONTEXT_REINITIATED = "🌑 Сессия сброшена. Данные могли обновиться."
|
||
|
||
UNDEFINED_MESSAGE = "❌ Таких команд у нас нет.\n\n<i>Ищете техподдержку? Вам в /support</i>\n<i>Потерялись? Вам в /start.</i>"
|
||
|
||
SUBSCRIPTION_INFORMATION = (
|
||
"<b>📊 Данные о подписке</b>\n\n"
|
||
f"{MALENIA_LINK} Ссылка на подписку: <code>{{link}}</code>\n\n"
|
||
"{status_icon} <b>Статус:</b> {status}\n"
|
||
+ "📅 <b>Истекает:</b> {expire_date}\n"
|
||
+ "⏳ <b>Осталось дней:</b> {days_left}\n"
|
||
+ "📊 <b>Израсходовано трафика:</b> {used_traffic}\n"
|
||
+ "📱 <b>Количество устройств:</b> {hwid_limit}\n"
|
||
)
|
||
|
||
NO_SUBSCRIPTION = "⚠️ <b>Подписка не найдена.</b>"
|
||
|
||
# ============================================================
|
||
# РЕФЕРАЛЬНАЯ СИСТЕМА
|
||
# ============================================================
|
||
|
||
REFERALS_MENU = (
|
||
"<b>👥 Реферальная система</b>\n\n"
|
||
"Делитесь свободой с друзьями и получайте деньги на оплату своей подписки.\n"
|
||
f"<b>{MALENIA_COINS} На вашем счету:</b> "
|
||
"<code>{balance}₽</code>\n"
|
||
f"<b>{MALENIA_LINK} Ваша реферальная ссылка:</b> "
|
||
"<code>{link}</code>"
|
||
)
|
||
|
||
# ============================================================
|
||
# ОФОРМЛЕНИЕ ПОДПИСКИ
|
||
# ============================================================
|
||
|
||
SUBSCRIPTION_DEVICE_SELECTOR = "Сколько устройств вы хотите подключить?\n\nЦена: <b>{price}₽</b>"
|
||
|
||
SUBSCRIPTION_DURATION_SELECTOR = (
|
||
"На какой срок хотите оформить подписку?\n\nИтого: <b>{price}₽</b> <i>(скидка: {discount}%)</i>"
|
||
)
|
||
|
||
WHITELISTS_ALREADY_ON = "Белые списки уже активны."
|
||
|
||
CHECKOUT_PAYMENT_CHOICE = "Пока что без автоплатежа. Нажмите кнопку ниже и обратитесь в поддержку для оплаты и активации подписки."
|
||
|
||
# ============================================================
|
||
# BILLING
|
||
# ============================================================
|
||
|
||
_BILL_TEMPLATE = (
|
||
"<b>💸 Счёт на {amount}₽</b>\n\n"
|
||
"<i>‼️ Вам придёт уведомление в течение нескольких минут после завершения платежа.</i>\n"
|
||
"<b>🔒 Способ оплаты:</b> <i>{provider}</i>\n\n"
|
||
)
|
||
|
||
_BILL_LINK = f"<b>{MALENIA_LINK} Ссылка на оплату:</b>"
|
||
|
||
BILL_CREATION = _BILL_TEMPLATE + _DIVIDER + GENERAL_PROCESSING
|
||
|
||
BILL_CREATED = _BILL_TEMPLATE + _DIVIDER + _BILL_LINK
|
||
|
||
|
||
# ============================================================
|
||
# ПОДДЕРЖКА
|
||
# ============================================================
|
||
|
||
SUPPORT_INIT = "<b>🎧 Тех. Поддержка Malenia</b> — не здесь. Кнопка ниже."
|
||
|
||
SUPPORT_MSG_SENT = "⏳ Приняли ваше сообщение. Мы постараемся ответить на него в ближайшее время.\n<i>Вернуться в меню: /cancel</i>"
|
||
|
||
SUPPORT_SIGNATURE = "<b>📡 Ответ от Malenia:</b>"
|
||
|
||
|
||
# ============================================================
|
||
# ШАБЛОНЫ — ЗАЯВКИ И ТИКЕТЫ
|
||
# ============================================================
|
||
|
||
SUPPORT_SUBSCRIPTION = (
|
||
"<b>🎫 ВХОДЯЩИЙ ЗАПРОС:</b>\n\n"
|
||
+ _SUPPORT_USER_DESCRIPTION
|
||
+ "\n"
|
||
+ _DIVIDER
|
||
+ "🗓️ Срок: <b>{duration} мес.</b>\n"
|
||
+ "📱 Устройства: <b>{devices}</b>\n"
|
||
+ "🏳️ Whitelists: <b>{whitelist_description}</b>\n\n"
|
||
+ "💰 К оплате: <b>{price}₽</b>"
|
||
)
|
||
|
||
ADMIN_TICKET_WITH_RW = (
|
||
"🎫 <b>ТИКЕТ T-{ticket_number:04d}</b>\n\n"
|
||
+ _SUPPORT_USER_DESCRIPTION
|
||
+ "\n"
|
||
+ _DIVIDER
|
||
+ "📊 <b>ТЕХ. ДАННЫЕ (Remnawave)</b>\n\n"
|
||
+ "{status_icon} <b>Статус:</b> {status}\n"
|
||
+ "📅 <b>Deadline:</b> {expire_date}\n"
|
||
+ "⏳ <b>Остаток:</b> {days_left}\n"
|
||
+ "📊 <b>Трафик:</b> {used_traffic}\n"
|
||
+ "📱 <b>HWID:</b> {hwid_limit}\n"
|
||
+ "🎯 <b>Squads:</b> {squads}\n\n"
|
||
+ _DIVIDER
|
||
+ "🔑 <b>UUID:</b> <code>{remnawave_uuid}</code>"
|
||
)
|
||
|
||
ADMIN_TICKET_WITHOUT_RW = (
|
||
"🎫 <b>ТИКЕТ T-{ticket_number:04d}</b>\n\n"
|
||
+ _SUPPORT_USER_DESCRIPTION
|
||
+ "\n"
|
||
+ _DIVIDER
|
||
+ NO_SUBSCRIPTION
|
||
)
|
||
|
||
ADMIN_STANDARD_FALLBACK = "<b>❌ Ошибка выполнения.</b> Проверь логи, что-то пошло не по чертежу."
|
||
|
||
|
||
# ============================================================
|
||
# АДМИНСКАЯ ХУЙНЯ
|
||
# ============================================================
|
||
|
||
ADMIN_PROMOTION_INIT = "👥 Введите текст рассылки"
|
||
ADMIN_PROMOTION_CONFIRMATION = "❓ Отправить сообщение всем пользователям бота?"
|
||
SUCCESSFULLY_SENT_PROMOTION = "Успешно разосланно {user_count} пользователям."
|
||
SPECIFY_REFERAL_PAYMENT_AMOUNT = "Укажите количество средств для перевода рефералу пользователя."
|
||
USER_NO_REFERAL = "❌ У пользователя нет реферала."
|
||
INVALID_ARGUMENT_REFPAY = "❌ Укажите в аргументах количество средств, которые необходимо перевести рефералу пользователя."
|
||
SUCCESSFUL_REFPAY = "<b>💸 Баланс реферала ({referal_id}) пополнен на {amount}₽</b>"
|