Инлайн-клавиатуры и обработка колбэков¶
CactusLib предоставляет элегантный способ создания инлайн-клавиатур и обработки нажатий на кнопки. Вся логика находится в пространстве имен CactusUtils.Inline.
1. Создание клавиатуры¶
Клавиатура состоит из рядов, а ряды — из кнопок.
CactusUtils.Inline.CallbackData¶
Создает данные для колбэка для кнопки.
CactusUtils.Inline.CallbackData(
plugin_id: str,
method: str,
# ... другие
**kwargs
)
plugin_id: ID плагина. (Обычно этоself.id)method: Имя метода плагина, который будет вызван при нажатии.**kwargs: Дополнительные аргументы, которые будут переданы в метод плагина.
# Создаем кнопку с колбэком
button = CactusUtils.Inline.Button(
text="Нажми меня",
callback_data=CactusUtils.Inline.CallbackData(
plugin_id=self.id,
method="on_button_click",
arg1="value1",
arg2="value2",
# ...
)
)
CactusUtils.Inline.Markup¶
Собирает кнопки в полноценную клавиатуру.
def __init__(self, is_global: bool = False, on_sent: Optional[Callable] = None, *args, **kwargs)
is_global: ЕслиTrue, то сообщение будет отправлено в чат с метаданными внутри текста сообщения. Это позволит увидеть всем пользователям с CactusLib данную клавиатуру.on_sent: Функция, которая будет вызвана после отправки сообщения с клавиатурой и полной инициализации.argsиkwargs: Опциональные аргументы, которые будут переданы в функциюon_sent.
Примечание
Если вы используете is_global=True, то on_sent будет проигнорирован.
# Создаем экземпляр разметки
markup = CactusUtils.Inline.Markup()
# Добавляем ряд с одной или несколькими кнопками
markup.add_row(button1, button2)
# Добавляем следующий ряд
markup.add_row(button3)
Или
# Создаем экземпляр разметки
markup = CactusUtils.Inline.Markup().add_row(button1, button2).add_row(button3)
2. Отправка сообщения с клавиатурой¶
Просто передайте созданный объект Markup в метод answer или send_message.
def send_menu(self, cmd: CactusUtils.Command):
# Создаем данные для колбэка.
# Формат: "cactus://{plugin_id}/{method}?{key}={value}"
cb_data = CactusUtils.Inline.CallbackData(self.id, "menu_press", item="A")
markup = CactusUtils.Inline.Markup().add_row(
CactusUtils.Inline.Button("Открыть Google", url="https://google.com/"),
CactusUtils.Inline.Button("Нажми меня!", callback_data=cb_data)
)
cmd.answer("Выберите опцию:", markup=markup)
return HookResult(strategy=HookStrategy.CANCEL)
3. Обработка нажатий (колбэков)¶
Для обработки нажатий используется декоратор @CactusUtils.Inline.on_click.
@CactusUtils.Inline.on_click(method: str): Декорирует функцию, которая будет вызвана, когда пользователь нажмет на кнопку сcallback_data, гдеmethodсовпадает с методом вCallbackData.
В функцию-обработчик передается объект CactusUtils.Inline.CallbackParams.
params.message: MessageObject: Объект сообщения, к которому привязана клавиатура.params.cell: ChatMessageCell: UI-элемент сообщения.params.edit(text, **kwargs): Редактирует текст сообщения. АльтернативаCactusUtils.edit_message(params.message, text, fragment=get_last_fragment(), **kwargs).params.edit_markup(new_markup): Редактирует клавиатуру сообщения.params.delete(): Удаляет сообщение.
Полный пример¶
class MyPlugin(CactusUtils.Plugin):
@command(doc="Показывает интерактивное меню")
def menu(self, cmd: CactusUtils.Command):
# Создаем клавиатуру с 1 рядом в 1 кнопку
markup = CactusUtils.Inline.Markup().add_row(
CactusUtils.Inline.Button(
"<icon id=msg_add/> Увеличить счетчик",
callback_data=CactusUtils.Inline.CallbackData(self.id, "counter_click")
)
)
# Получаем текущий счетчик
count = self.get("menu_counter", 0)
cmd.answer(f"Счетчик: {count}", markup=markup)
return HookResult(strategy=HookStrategy.CANCEL)
@CactusUtils.Inline.on_click("counter_click")
def _on_counter_click(self, params: CactusUtils.Inline.CallbackParams):
# Увеличиваем счетчик
count = self.get("menu_counter", 0) + 1
self.set("menu_counter", count)
# Создаем новую клавиатуру
markup = CactusUtils.Inline.Markup().add_row(
CactusUtils.Inline.Button(
"<icon id=msg_add/> Увеличить счетчик",
callback_data=CactusUtils.Inline.CallbackData(self.id, "counter_click")
)
)
# Редактируем исходное сообщение, чтобы показать новый счетчик
params.edit(f"Счетчик: {count}", markup=markup)
Как это работает:
Пользователь пишет
.menu.Плагин отправляет сообщение «Счетчик: 0» с кнопкой.
Пользователь нажимает на кнопку.
CactusLib перехватывает колбэк и видит, что метод —
counter_click.Вызывается функция
_on_counter_click.Функция обновляет значение в БД и редактирует исходное сообщение, заменяя его на «Счетчик: 1». Клавиатура остается на месте.
Отправка сообщения с клавиатурой в чат с метаданными внутри¶
Чтобы отправить сообщение с клавиатурой в чат с метаданными, нужно передать is_global=True в конструктор CactusUtils.Inline.Markup.
class MyPlugin(CactusUtils.Plugin):
@command(doc="Показывает интерактивное меню всем пользователям")
def items(self, cmd: CactusUtils.Command):
# Создаем клавиатуру с 1 рядом в 1 кнопку
markup = CactusUtils.Inline.Markup(is_global=True).add_row(
CactusUtils.Inline.Button(
"Нажми меня!",
url="https://t.me/CactusPlugins"
)
)
cmd.answer(f"Сообщение с Inline-кнопками для всех", markup=markup)
return HookResult(strategy=HookStrategy.CANCEL)
@command(doc="Показывает интерактивное меню всем пользователям альтернативным методом")
def items2(self, cmd: CactusUtils.Command):
# Создаем клавиатуру с 1 рядом в 1 кнопку
markup = CactusUtils.Inline.Markup(is_global=True).add_row(
CactusUtils.Inline.Button(
"Нажми меня!",
url="https://t.me/CactusPlugins"
)
)
# Ставим ссылку с метаданными в пробел, чтобы не было заметно
cmd.answer(f"Сообщение с<a href='{markup.to_url_with_data()}'> </a>Inline-кнопками для всех")
return HookResult(strategy=HookStrategy.CANCEL)
.items1 - Показывает интерактивное меню всем пользователям обычным способом¶
.items2 - Показывает интерактивное меню всем пользователям альтернативным способом¶