Files
bot_vk_ikp_prodagi/keyboards.py
T
Kenik 6ecbd7aa94 Напоминалки: кнопка смены часового пояса в разделе
Раньше сменить уже заданный пояс можно было только скрытой командой
'часовой пояс <±N>', нигде не упомянутой в интерфейсе. Добавлена кнопка
«🌐 Часовой пояс» — открывает тот же выбор (кнопки городов + ручной ввод)
заново, показывая текущее значение.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 15:22:57 +03:00

282 lines
13 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, flags: dict = None) -> str:
"""Главное меню Кибершколы БАЗА. flags — какие кнопки показывать (по умолчанию — все,
кроме вебинара). Для админа добавляется кнопка «Админка ⚙️»."""
f = {"pickup": True, "intensive": True, "prices": True, "question": True, "webinar": False}
if flags:
f.update(flags)
keyboard = VkKeyboard(one_time=False)
has = False
def row(label, color=VkKeyboardColor.SECONDARY):
nonlocal has
if has:
keyboard.add_line()
keyboard.add_button(label, color=color)
has = True
if f.get("pickup"):
row("Подобрать тренировку 🎯", VkKeyboardColor.PRIMARY)
if f.get("intensive"):
row("Летний интенсив CS2 🔥")
if f.get("webinar"):
row("Записаться на вебинар 🎓")
if f.get("prices"):
row("Посмотреть цены 💰")
if f.get("question"):
row("Задать вопрос 💬")
if is_admin:
row("Админка ⚙️", 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)
has = False # была ли уже добавлена хоть одна кнопка (чтобы не создавать пустой ряд)
for row in rows:
if has:
keyboard.add_line()
for label in row:
keyboard.add_button(label, color=VkKeyboardColor.SECONDARY)
has = True
if ask_manager:
if has:
keyboard.add_line()
keyboard.add_button("Задать вопрос менеджеру 💬", color=VkKeyboardColor.SECONDARY)
has = True
if back or back_menu:
if has:
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([["Counter-Strike 2", "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, muted: 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()
keyboard.add_button("Кнопки меню 🧩", color=VkKeyboardColor.SECONDARY)
keyboard.add_button("Уведомления: выкл 🔕" if muted else "Уведомления: вкл 🔔",
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_reminders_admin_keyboard() -> str:
"""Клавиатура раздела «Напоминалки». Обычная (не инлайн) клавиатура — важно:
она заменяет собой нижнюю клавиатуру предыдущего шага мастера (например,
«Разово / Каждую неделю / …»), иначе старые кнопки остаются висеть после
завершения мастера."""
keyboard = VkKeyboard(one_time=False)
keyboard.add_button(" Добавить", color=VkKeyboardColor.PRIMARY)
keyboard.add_line()
keyboard.add_button("🗑 Удалить напоминание", color=VkKeyboardColor.NEGATIVE)
keyboard.add_line()
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_timezone_keyboard() -> str:
"""Клавиатура выбора часового пояса: частые российские города-пояса
кнопками (кнопка шлёт 'Город, UTC±N' — _parse_tz_offset вытаскивает
смещение из этого текста), плюс можно просто ввести своё смещение
вручную, если города в списке нет."""
cities = [
("Калининград", 2), ("Москва", 3), ("Самара", 4),
("Екатеринбург", 5), ("Омск", 6), ("Красноярск", 7),
("Иркутск", 8), ("Якутск", 9), ("Владивосток", 10),
("Магадан", 11), ("Камчатка", 12),
]
keyboard = VkKeyboard(one_time=False)
for i, (city, offset) in enumerate(cities):
if i and i % 2 == 0:
keyboard.add_line()
keyboard.add_button(f"{city}, UTC+{offset}", color=VkKeyboardColor.SECONDARY)
keyboard.add_line()
keyboard.add_button("Отмена ❌", color=VkKeyboardColor.NEGATIVE)
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_reminder_period_keyboard() -> str:
"""Клавиатура выбора периодичности напоминания (шаг мастера ADMIN_REMINDER_PERIOD)."""
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)
keyboard.add_line()
keyboard.add_button("Каждый год", color=VkKeyboardColor.SECONDARY)
keyboard.add_line()
keyboard.add_button("Отмена ❌", color=VkKeyboardColor.NEGATIVE)
return keyboard.get_keyboard()
def get_operator_keyboard() -> str:
"""Клавиатура при активном диалоге с оператором."""
keyboard = VkKeyboard(one_time=False)
keyboard.add_button("Завершить диалог 🚪", color=VkKeyboardColor.NEGATIVE)
return keyboard.get_keyboard()