Админка: показ/скрытие кнопок меню + экстренный стоп бота (/favi-stop)

1) Кнопки меню: раздел «Кнопки меню 🧩» в админке — показать/скрыть любую кнопку
   главного меню (Подобрать/Интенсив/Цены/Вопрос/Вебинар). Флаги в БД (bot_flags),
   дефолты в config.MENU_FEATURES (вебинар по умолчанию скрыт). Скрытый раздел не
   реагирует и на кодовые слова (интенсив выкл → «лето» игнорируется). Вебинар
   получил кнопку в меню (для теста ветки) + вход по callback из поста работает всегда.

2) Экстренное отключение (только супер-админ): /favi-stop → запрос пароля → бот
   уходит в аварийный режим и молчит для всех; /favi-start возвращает. Пароль хранится
   как PBKDF2-хэш в .env (FAVI_STOP_HASH), не в коде; сравнение константное, 3 попытки.

pytest 43 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kenik
2026-07-26 10:58:54 +03:00
parent 24daec1c09
commit d2ca750a2d
6 changed files with 279 additions and 36 deletions
+15
View File
@@ -49,6 +49,11 @@ else:
SUPER_ADMIN_IDS = [350793273]
# ============================================================
# Экстренное отключение бота супер-админом командой /favi-stop.
# Хранится ТОЛЬКО хэш пароля (PBKDF2), не сам пароль. Задаётся в .env: FAVI_STOP_HASH.
# Сгенерировать новый хэш: см. README/USER_GUIDE. Пусто — команда отключена.
FAVI_STOP_HASH = os.getenv("FAVI_STOP_HASH", "")
# Ссылки на юридические документы (инлайн-кнопки в боте)
OFFER_URL = os.getenv("OFFER_URL", "https://infocyber.pro/form/Dogovor_oferty_kibersport_versia_izmenennaya.pdf")
POLICY_URL = os.getenv("POLICY_URL", "https://infocyber.pro/form/Политика%20ПД.pdf")
@@ -121,6 +126,16 @@ LINK_LABELS = {
"summer": "Летний интенсив CS2",
}
# --- Кнопки/разделы главного меню: показать/скрыть (админка) ---
# key: (человеческое название, показывать ли по умолчанию)
MENU_FEATURES = {
"pickup": ("Подобрать тренировку 🎯", True),
"intensive": ("Летний интенсив CS2 🔥", True),
"prices": ("Посмотреть цены 💰", True),
"question": ("Задать вопрос 💬", True),
"webinar": ("Записаться на вебинар 🎓", False),
}
# --- Триггеры запуска (регистронезависимо) ---
MAIN_TRIGGERS = ["начать", "тренировки", "занятия", "цена", "стоимость", "записаться",
"привет", "здравствуйте", "старт", "меню"]