Files
bot_vk_ikp_prodagi/keyboards.py
T
Kenik 261e5c2da0 Тексты воронки по ТЗ + смена ссылок из админки
Тексты:
- «Сколько лет игроку?» (было «…будущему ученику?») во всех местах;
- сообщение для «Младше 12 лет» приведено дословно к ТЗ (§4);
- убраны отсебятины-преамбулы, которых нет в ТЗ (приветствие, старт воронки,
  цены «Что дальше?», интенсив «Хотите записаться?»); кнопка младше-12 «Вернуться назад».

Смена ссылок в админке:
- таблица bot_links (key, url) + методы get_link/get_all_links/set_link;
- _link(key): БД-переопределение → дефолт из config/.env; используется на шагах оплаты;
- раздел «Ссылки 🔗» в админ-панели: список текущих адресов + «✏️ Изменить ссылку»
  (выбор из 8 кнопок → ввод URL с валидацией http/https). UTM добавляются автоматически.

Тесты: добавлен test_admin_edit_link. pytest 31 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:45:47 +03:00

218 lines
10 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.
"""Клавиатуры интерфейса бота (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([["1213 лет", "1415 лет"], ["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_menu_only_keyboard() -> str:
"""Только «В главное меню» — для шагов со свободным вводом (совет/вопрос)."""
return _kb([])
def get_baza_intensive_keyboard() -> str:
keyboard = VkKeyboard(one_time=False)
keyboard.add_button("Хочу участвовать 🔥", color=VkKeyboardColor.SECONDARY)
keyboard.add_line()
keyboard.add_button("Задать вопрос 💬", color=VkKeyboardColor.SECONDARY)
keyboard.add_line()
keyboard.add_button("Посмотреть другие тренировки", color=VkKeyboardColor.SECONDARY)
return keyboard.get_keyboard()
def get_baza_int_level_keyboard() -> str:
return _kb([["Только начинаю"], ["Уже знаю основы"],
["Играю регулярно"], ["Есть рейтинг или командный опыт"]], back=True)
def get_baza_int_pay_keyboard() -> str:
keyboard = VkKeyboard(one_time=False)
keyboard.add_button("Оплатить интенсив 💳", color=VkKeyboardColor.SECONDARY)
keyboard.add_line()
keyboard.add_button("Сначала задать вопрос 💬", color=VkKeyboardColor.SECONDARY)
keyboard.add_line()
keyboard.add_button("Вернуться в меню ↩️", color=VkKeyboardColor.SECONDARY)
return keyboard.get_keyboard()
def get_baza_int_young_keyboard() -> str:
keyboard = VkKeyboard(one_time=False)
keyboard.add_button("Передать менеджеру 💬", color=VkKeyboardColor.SECONDARY)
keyboard.add_line()
keyboard.add_button("Посмотреть другие тренировки", color=VkKeyboardColor.SECONDARY)
return keyboard.get_keyboard()
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_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()