Files
social-post-writer-bot/keyboards.py
T

127 lines
5.0 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.
"""Клавиатуры главного меню и пользовательских режимов бота."""
from __future__ import annotations
from aiogram.types import (
InlineKeyboardButton,
InlineKeyboardMarkup,
KeyboardButton,
ReplyKeyboardMarkup,
)
from help_message import HELP_SECTIONS, HELP_SECTION_ORDER
from user_store import SUBSCRIPTION_PLANS
MODE_BUTTONS: dict[str, str] = {
"🎓 Обучение": "/training",
"✍️ Генерация": "/generate",
"💳 Подписка": "/subscription",
"📖 Помощь": "/help",
}
MAIN_MENU_BUTTON = "🏠 Главное меню"
MAIN_MENU_VALUE = "__main_menu__"
TRAINING_RESET_BUTTON = "🗑 Сбросить данные"
TRAINING_RESET_VALUE = "__training_reset__"
TRAINING_INFO_BUTTON = "ℹ️ Инфо"
TRAINING_INFO_VALUE = "__training_info__"
POST_GENERATE_BUTTON = "✍️ Придумать пост"
SUPPORT_BUTTON = "🆘 Поддержка"
SUPPORT_VALUE = "__support__"
SUBSCRIPTION_ACTION_VALUE = "__subscription_action__"
BUY_SUBSCRIPTION_BUTTON = "🛒 Купить подписку"
RENEW_SUBSCRIPTION_BUTTON = "🔄 Продлить подписку"
BUTTON_TEXT_MAP: dict[str, str] = {
**MODE_BUTTONS,
MAIN_MENU_BUTTON: MAIN_MENU_VALUE,
"Главное меню": MAIN_MENU_VALUE,
TRAINING_RESET_BUTTON: TRAINING_RESET_VALUE,
TRAINING_INFO_BUTTON: TRAINING_INFO_VALUE,
POST_GENERATE_BUTTON: "/post",
SUPPORT_BUTTON: SUPPORT_VALUE,
BUY_SUBSCRIPTION_BUTTON: SUBSCRIPTION_ACTION_VALUE,
RENEW_SUBSCRIPTION_BUTTON: SUBSCRIPTION_ACTION_VALUE,
}
def main_menu_keyboard() -> ReplyKeyboardMarkup:
"""Показывает только четыре доступных пользователю режима."""
return ReplyKeyboardMarkup(
keyboard=[
[KeyboardButton(text="🎓 Обучение"), KeyboardButton(text="✍️ Генерация")],
[KeyboardButton(text="💳 Подписка"), KeyboardButton(text="📖 Помощь")],
],
resize_keyboard=True,
input_field_placeholder="Выбери действие",
)
def mode_keyboard(
mode: str,
support: bool = False,
subscription_purchased: bool = False,
) -> ReplyKeyboardMarkup:
"""Внутри режима показывает релевантные действия и возврат в меню.
В активном обращении поддержки остаётся только кнопка «Главное меню».
"""
rows = [[KeyboardButton(text=MAIN_MENU_BUTTON)]]
if support:
return ReplyKeyboardMarkup(
keyboard=rows,
resize_keyboard=True,
input_field_placeholder="Опиши проблему или вернись в главное меню",
)
if mode == "training":
rows.insert(0, [KeyboardButton(text=TRAINING_INFO_BUTTON)])
rows.append([KeyboardButton(text=TRAINING_RESET_BUTTON)])
elif mode == "generation":
rows.insert(0, [KeyboardButton(text=POST_GENERATE_BUTTON)])
elif mode == "help":
rows.insert(0, [KeyboardButton(text=SUPPORT_BUTTON)])
elif mode == "subscription":
action = RENEW_SUBSCRIPTION_BUTTON if subscription_purchased else BUY_SUBSCRIPTION_BUTTON
rows.insert(0, [KeyboardButton(text=action)])
return ReplyKeyboardMarkup(
keyboard=rows,
resize_keyboard=True,
input_field_placeholder=(
"Управляй обучением или вернись в меню"
if mode == "training"
else "Напиши сообщение или вернись в главное меню"
),
)
def subscription_plans_keyboard() -> InlineKeyboardMarkup:
return InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="0 дней — 1 ⭐", callback_data="subscription:plan:0")],
[InlineKeyboardButton(text="1 день — 15 ⭐", callback_data="subscription:plan:1")],
[InlineKeyboardButton(text="10 дней — 150 ⭐", callback_data="subscription:plan:10")],
[InlineKeyboardButton(text="30 дней — 450 ⭐", callback_data="subscription:plan:30")],
])
def help_inline_keyboard() -> InlineKeyboardMarkup:
"""Стандартная inline-клавиатура для навигации по разделам справки."""
return InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text=HELP_SECTIONS[section][0], callback_data=f"help:{section}")]
for section in HELP_SECTION_ORDER
],
)
MAIN_MENU = main_menu_keyboard()
LOCKED_MENU = mode_keyboard("subscription")
def resolve_button_text(text: str | None) -> str | None:
"""Возвращает команду или текст запроса для нажатой кнопки, иначе None."""
if not text:
return None
return BUTTON_TEXT_MAP.get(text.strip())
def price_hint() -> str:
return f"Продление подписки — {SUBSCRIPTION_PLANS[30]} ⭐ за 30 дней."