Files
vpn-telegram-bot/services/faq.py
T

281 lines
15 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Часто задаваемые вопросы (FAQ)."""
from __future__ import annotations
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class FaqItem:
id: str
question: str
answer: str
FAQ_ITEMS: tuple[FaqItem, ...] = (
FaqItem(
id="what_is",
question="Что это за VPN?",
answer=(
"Это сервис на базе Remnawave: после оплаты ты получаешь "
"<b>ссылку подписки</b>. Её вставляешь в клиент (Hiddify, Streisand, "
"v2rayNG и др.) — и подключаешься к серверам."
),
),
FaqItem(
id="how_start",
question="Как начать пользоваться?",
answer=(
"1) Пополни баланс: Stars / криптой в боте или кодом (карта/СБП — через покупку кода)\n"
"2) Купи тариф в «Тарифы» или Mini App\n"
"3) Открой «Моя подписка» → скопируй ссылку\n"
"4) Скачай клиент → вставь ссылку подписки\n"
"5) Выбери сервер и подключись"
),
),
FaqItem(
id="clients",
question="Какой клиент скачать?",
answer=(
"В боте есть раздел <b>«Скачать клиент»</b> — топ приложений с docs.rw.\n"
"Популярные варианты:\n"
"• iOS / macOS — Streisand, Happ, Shadowrocket\n"
"• Android — v2rayNG, Hiddify, Happ\n"
"• Windows — Hiddify, FlClash\n\n"
"Главное — клиент с поддержкой subscription URL."
),
),
FaqItem(
id="sub_link",
question="Где взять ссылку подписки?",
answer=(
"«Моя подписка» в боте или главная в Mini App.\n"
"Ссылка выглядит как HTTPS URL — её целиком копируешь в клиент "
"(Add subscription / Import from URL)."
),
),
FaqItem(
id="devices",
question="Сколько устройств можно?",
answer=(
"База — <b>10 устройств</b> на подписку (в тарифе).\n"
"Доп. слот: <b>50 ₽/мес</b> за каждое (первый месяц при покупке).\n"
"Списание с баланса <b>каждые 30 дней</b> за все доп. устройства.\n"
"Если средств нет — доп. слоты отключаются до пополнения.\n"
"Если устройств больше оплаченной квоты — "
"<b>подписка отключается</b>, пока не оплатишь превышение "
"или не отвяжешь лишние устройства в клиенте."
),
),
FaqItem(
id="extras_monthly",
question="Почему списывают за доп. трафик и устройства каждый месяц?",
answer=(
"Дополнительные <b>500 ГБ</b> и <b>устройства сверх 10</b> — "
"это отдельная подписка к основному тарифу.\n\n"
"• При покупке списывается первый месяц\n"
"• Далее — автоматически с баланса раз в <b>30 дней</b>\n"
"• Сумма = (число пакетов × 50 ₽) + (число доп. устройств × 50 ₽)\n"
"• Не хватает баланса — доп. лимиты приостанавливаются, "
"основная подписка остаётся на базовых 1000 ГБ и 10 устройств"
),
),
FaqItem(
id="traffic",
question="Сколько трафика даётся?",
answer=(
"В каждом тарифе база — <b>1000 ГБ</b> (включено в тариф).\n"
"Докупка: <b>+500 ГБ = 50 ₽/мес</b> (можно несколько пакетов).\n"
"Первый месяц списывается при покупке, далее — <b>каждые 30 дней</b> "
"с баланса за все подключённые пакеты.\n"
"Если на балансе не хватает — доп. ГБ отключаются до оплаты.\n"
"Расход смотри в «Моя подписка» или Mini App."
),
),
FaqItem(
id="traffic_over",
question="Что если трафик закончится?",
answer=(
"Подключение может ограничиться, пока не докупишь пакет "
"или не начнётся новый период после продления тарифа.\n"
"Докупка трафика не продлевает срок подписки — только лимит ГБ."
),
),
FaqItem(
id="pay",
question="Как оплатить?",
answer=(
"• <b>Тарифы и услуги</b> — с баланса\n\n"
"<b>Без кода (напрямую в боте)</b>:\n"
"• <b>Telegram Stars</b> — оплата ⭐ прямо в Telegram\n"
"• <b>Crypto Bot</b> — крипта\n"
"• <b>Heleket</b> — резервная крипта\n\n"
"<b>Карта, СБП и другие фиатные способы</b> — через "
"<b>код пополнения</b>:\n"
"• На странице покупки кода — <b>более 40 способов оплаты</b>\n"
"• После оплаты введи код в «Баланс» → «Код пополнения» "
"или в Mini App\n\n"
"Пополнение — раздел «Баланс» в боте."
),
),
FaqItem(
id="stars",
question="Как пополнить через Telegram Stars?",
answer=(
"1) «Баланс» → «Telegram Stars» в боте\n"
" или в Mini App / Telegram Web — блок «Telegram Stars»\n"
"2) Выбери сумму в рублях (курс задаёт сервис)\n"
"3) Оплати инвойс Stars в Telegram\n"
"4) Баланс зачислится сразу после оплаты\n\n"
"В веб-версии Telegram удобнее кнопка оплаты по ссылке "
"или оплата прямо из Mini App."
),
),
FaqItem(
id="topup_code",
question="Как пополнить по коду?",
answer=(
"Нужен, если хочешь оплатить <b>картой, СБП</b> или другим фиатом "
"(напрямую в боте без кода — только крипта).\n\n"
"1) «Баланс» → «Код пополнения» → «Купить код» "
"или кнопка в Mini App\n"
"2) На странице оплаты — <b>более 40 способов</b>\n"
"3) Введи код в боте или на главной Mini App\n"
"4) Сумма зачислится на баланс сразу\n\n"
"Один код — одно использование."
),
),
FaqItem(
id="cards_sbp",
question="Картой или СБП — как пополнить?",
answer=(
"Купи <b>код пополнения</b> по ссылке из бота или кабинета.\n"
"На странице оплаты доступно <b>более 40 способов</b> "
"(банковские карты, СБП, электронные кошельки и др.).\n\n"
"После успешной оплаты придёт код — активируй его в боте "
"или на сайте. Дальше тарифы оплачиваешь с баланса.\n\n"
"<b>Без кода</b> напрямую в боте пополнить можно "
"только <b>криптовалютой</b>."
),
),
FaqItem(
id="lava",
question="Как пополнить через Lava?",
answer=(
"Если в меню «Баланс» есть Lava — можно попробовать этот способ.\n"
"Для <b>карты и СБП</b> основной вариант — <b>код пополнения</b> "
"(40+ способов на странице покупки кода).\n\n"
"Напрямую без кода в боте доступна только <b>крипта</b>."
),
),
FaqItem(
id="digiseller",
question="Как пополнить через Digiseller?",
answer=(
"1) «Баланс» → Digiseller → «Оплатить на Digiseller»\n"
"2) Оплати товар на сайте\n"
"3) Digiseller сам откроет страницу проверки — баланс "
"зачислится автоматически, в бот придёт уведомление\n\n"
"Код вводить не нужно. Если автозачисление не сработало — "
"в боте есть «Не зачислилось? Ввести код»."
),
),
FaqItem(
id="renew",
question="Как продлить подписку?",
answer=(
"«Моя подписка» → «Продлить с баланса» или купи тариф снова.\n"
"Дни <b>добавляются</b> к текущей дате окончания, "
"если подписка ещё активна.\n\n"
"<b>За 7 дней до конца</b> бот пришлёт напоминание раз в сутки.\n"
"Если автопродление включено и на балансе хватает на последний тариф — "
"за сутки до окончания подписка <b>продлится автоматически</b> "
"(вкл/выкл в кабинете)."
),
),
FaqItem(
id="auto_renew",
question="Автопродление подписки",
answer=(
"Если автопродление <b>включено</b>, система смотрит на "
"<b>последний купленный тариф</b> и баланс.\n\n"
"• За 7 дней до окончания — ежедневное напоминание в Telegram\n"
"• В последние 24 часа (или сразу после истечения до 3 дней) "
"при достаточном балансе — автоматическое продление с баланса\n"
"• Включить или выключить можно при регистрации и в любой момент "
"в кабинете на вкладке «Главная»\n"
"• Если средств мало или автопродление выключено — "
"пополни баланс или продли вручную в боте / Mini App"
),
),
FaqItem(
id="not_working",
question="Не подключается / не работает",
answer=(
"Проверь по шагам:\n"
"1) Подписка не истекла и трафик не на нуле\n"
"2) Ссылка в клиенте актуальная (обнови subscription)\n"
"3) Сервер онлайн — «Статус серверов»\n"
"4) Попробуй другой сервер / другой клиент\n"
"5) Выключи лишний VPN/антивирус на телефоне\n\n"
"Если не помогло — напиши админу и приложи скрин ошибки."
),
),
FaqItem(
id="slow",
question="Медленно / высокий пинг",
answer=(
"Смени сервер в клиенте (ближе к тебе или менее загруженный).\n"
"Проверь «Статус серверов» — оффлайн ноды не выбирай.\n"
"На мобильном интернете скорость зависит от оператора и Wi‑Fi."
),
),
FaqItem(
id="miniapp",
question="Зачем Mini App?",
answer=(
"Это кабинет в Telegram: баланс, подписка, трафик, тарифы, "
"клиенты и серверы в одном окне.\n"
"Сайт тоже открывается в браузере — там можно войти по логину "
"или через Telegram Login."
),
),
FaqItem(
id="refund",
question="Можно вернуть деньги?",
answer=(
"Автоматического возврата нет: доступ выдаётся сразу после оплаты.\n"
"Если была техническая ошибка (списали, а ключ не выдали) — "
"создай тикет в боте или Mini App, разберём и вернём на баланс "
"или перевыпустим."
),
),
FaqItem(
id="tickets",
question="Как связаться с поддержкой?",
answer=(
"В боте: кнопка «🎫 Тикеты» → «Новый тикет».\n"
"В Mini App: вкладка «Тикеты».\n"
"Ответ придёт в Telegram и будет виден в переписке тикета."
),
),
)
def get_faq(item_id: str) -> FaqItem | None:
for item in FAQ_ITEMS:
if item.id == item_id:
return item
return None
def faq_intro() -> str:
return (
"<b>❓ FAQ — частые вопросы</b>\n\n"
"Выбери вопрос ниже. Если не нашёл ответ — создай тикет."
)
def faq_answer_text(item: FaqItem) -> str:
return f"<b>❓ {item.question}</b>\n\n{item.answer}"