Initial commit: VPN Telegram bot (sanitized defaults)
This commit is contained in:
+280
@@ -0,0 +1,280 @@
|
||||
"""Часто задаваемые вопросы (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}"
|
||||
Reference in New Issue
Block a user