74a855819d
Из ТЗ Кибершколы БАЗА эти сценарии заменены воронкой подбора, поэтому убран мёртвый код: - клиентские FSM: FORM_* (форма-заявка, возвращающийся клиент, редактирование, согласия, выбор услуги, карусель) и VAC_* (карьера: игроки/сотрудники); - меню «Частые вопросы» и config.FAQ_ANSWERS; - осиротевшая админка: управление услугами + карусель, вакансии, кандидаты (в панели и в мастере ADMIN_SVC_*/ADMIN_VAC_*), блок статистики по откликам; - старый _handoff_to_operator и _notify_operator_about_lead (заменены _baza_to_manager); - неиспользуемые клавиатуры (форма/услуги/вакансии/согласия) и импорты (validators, random, string). Оставлено (используется/по ТЗ): воронка БАЗА, быстрые ответы (custom_faq), стата по лидам, рассылка, управление админами, чат с оператором, логотип. Слой БД не тронут — существующие установки не ломаются (таблицы services/applications/vacancy_options просто не используются). bot.py: -1490 строк. Тесты: pytest 28 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
187 lines
8.6 KiB
Python
187 lines
8.6 KiB
Python
"""Клавиатуры интерфейса бота (VK)."""
|
||
from vk_api.keyboard import VkKeyboard, VkKeyboardColor
|
||
import config
|
||
|
||
|
||
# ==========================================
|
||
# КЛАВИАТУРЫ ДЛЯ ИНТЕРФЕЙСА (UX/UI ВКонтакте)
|
||
# ==========================================
|
||
|
||
def get_main_keyboard(is_admin: bool = False) -> str:
|
||
"""Главное меню Кибершколы БАЗА. Для админа добавляется кнопка «Админка ⚙️»."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Подобрать тренировку 🎯", color=VkKeyboardColor.PRIMARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Летний интенсив CS2 🔥", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Посмотреть цены 💰", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("Задать вопрос 💬", color=VkKeyboardColor.SECONDARY)
|
||
if is_admin:
|
||
keyboard.add_line()
|
||
keyboard.add_button("Админка ⚙️", color=VkKeyboardColor.POSITIVE)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
# ==========================================
|
||
# КЛАВИАТУРЫ ВОРОНКИ «ПОДОБРАТЬ ТРЕНИРОВКУ» (БАЗА)
|
||
# ==========================================
|
||
|
||
def _kb(rows, back=False, ask_manager=False, back_menu=True):
|
||
"""Хелпер: строит нижнюю клавиатуру из строк кнопок + служебные кнопки снизу.
|
||
|
||
back — кнопка «Назад ⬅️» (к предыдущему вопросу воронки);
|
||
ask_manager — кнопка «Задать вопрос менеджеру 💬»;
|
||
back_menu — кнопка «В главное меню ↩️».
|
||
"""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
for i, row in enumerate(rows):
|
||
if i:
|
||
keyboard.add_line()
|
||
for label in row:
|
||
keyboard.add_button(label, color=VkKeyboardColor.SECONDARY)
|
||
if ask_manager:
|
||
keyboard.add_line()
|
||
keyboard.add_button("Задать вопрос менеджеру 💬", color=VkKeyboardColor.SECONDARY)
|
||
if back or back_menu:
|
||
keyboard.add_line()
|
||
if back:
|
||
keyboard.add_button("Назад ⬅️", color=VkKeyboardColor.SECONDARY)
|
||
if back_menu:
|
||
keyboard.add_button("В главное меню ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_baza_forwho_keyboard() -> str:
|
||
return _kb([["Для себя", "Для подростка"]])
|
||
|
||
|
||
def get_baza_age_keyboard() -> str:
|
||
return _kb([["12–13 лет", "14–15 лет"], ["16 лет и старше", "Младше 12 лет"]], back=True)
|
||
|
||
|
||
def get_baza_younger12_keyboard() -> str:
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Обсудить с менеджером 💬", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Назад ⬅️", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("В главное меню ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_baza_game_keyboard() -> str:
|
||
return _kb([["CS2", "Dota 2"], ["World of Tanks", "Другая игра"]], back=True)
|
||
|
||
|
||
def get_baza_level_keyboard() -> str:
|
||
return _kb([["Только начинает"], ["Играет для себя"],
|
||
["Есть рейтинг или ранг"], ["Играет в команде или турнирах"]], back=True)
|
||
|
||
|
||
def get_baza_format_keyboard() -> str:
|
||
return _kb([["Групповые тренировки"], ["Индивидуальные тренировки"],
|
||
["Пока не знаю, нужен совет"]], back=True)
|
||
|
||
|
||
def get_baza_group_keyboard() -> str:
|
||
return _kb([["Записаться на пробное"], ["Купить 4 тренировки", "Купить 8 тренировок"]],
|
||
back=True, ask_manager=True)
|
||
|
||
|
||
def get_baza_individual_keyboard() -> str:
|
||
return _kb([["Записаться на пробное"], ["Купить 1 тренировку"],
|
||
["Купить 4 тренировки", "Купить 8 тренировок"]],
|
||
back=True, ask_manager=True)
|
||
|
||
|
||
def get_baza_help_keyboard() -> str:
|
||
return _kb([["Записаться на пробное"], ["Подобрать заново 🎯"]], ask_manager=True)
|
||
|
||
|
||
def get_baza_intensive_keyboard() -> str:
|
||
return _kb([["Хочу участвовать 🔥"]], ask_manager=True)
|
||
|
||
|
||
def get_baza_prices_keyboard() -> str:
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Подобрать тренировку 🎯", color=VkKeyboardColor.PRIMARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Записаться на пробное", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("Выбрать абонемент", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Задать вопрос 💬", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_admin_keyboard(is_super: bool = False) -> str:
|
||
"""Клавиатура админ-панели с разделами. Супер-админу — раздел «Администраторы»."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Статистика 📊", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("Быстрые ответы 💬", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Рассылка 📣", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
if is_super:
|
||
keyboard.add_button("Администраторы 👑", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("В главное меню ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_faq_admin_keyboard() -> str:
|
||
"""Клавиатура раздела управления быстрыми ответами."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("➕ Добавить ответ", color=VkKeyboardColor.PRIMARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("✏️ Изменить ответ", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("🗑 Удалить ответ", color=VkKeyboardColor.NEGATIVE)
|
||
keyboard.add_line()
|
||
keyboard.add_button("В админку ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_pick_keyboard(items: list) -> str:
|
||
"""Клавиатура выбора из списка пар (id, label). Кнопка отправляет '<id>. <label>'."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
count = 0
|
||
for _id, label in items[:10]:
|
||
if count and count % 2 == 0:
|
||
keyboard.add_line()
|
||
short = label if len(label) <= 30 else label[:29] + "…"
|
||
keyboard.add_button(f"{_id}. {short}", color=VkKeyboardColor.SECONDARY)
|
||
count += 1
|
||
keyboard.add_line()
|
||
keyboard.add_button("Отмена ❌", color=VkKeyboardColor.NEGATIVE)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_cancel_admin_keyboard() -> str:
|
||
"""Кнопка отмены для админских мастеров ввода."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Отмена ❌", color=VkKeyboardColor.NEGATIVE)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_socials_keyboard() -> str:
|
||
"""Клавиатура с кнопками-ссылками на площадки ИКП (открываются в один тап)."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_openlink_button("VK Live 📺", "https://live.vkvideo.ru/ikp")
|
||
keyboard.add_line()
|
||
keyboard.add_openlink_button("Telegram ✈️", "https://t.me/ikp_team")
|
||
keyboard.add_openlink_button("Lolka 🎮", "https://vk.com/away.php?to=https%3A%2F%2Flolka.gg%2FlNfM3F9DD&utf=1")
|
||
keyboard.add_line()
|
||
keyboard.add_openlink_button("ВКонтакте 🌐", "https://vk.com/ikpro")
|
||
keyboard.add_line()
|
||
keyboard.add_openlink_button("Наш сайт 🔗", "https://infocyber.pro/")
|
||
keyboard.add_line()
|
||
keyboard.add_button("Назад в меню ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_operator_keyboard() -> str:
|
||
"""Клавиатура при активном диалоге с оператором."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Завершить диалог 🚪", color=VkKeyboardColor.NEGATIVE)
|
||
return keyboard.get_keyboard()
|
||
|
||
|