Кнопки и меню выбора
Кнопки в пользовательских командах не только открывают ссылки — они запускают действия. «Подтвердить», «Следующая страница», «Получить роль», выбор варианта из меню — все это кнопки.
Функция button
{% do button('PRIMARY', 'accept', 'Подтвердить', '✅', '59f7f318-17c9-45b8-be61-33c1f89d54ba') %}Аргументы по порядку:
| № | Аргумент | Что писать |
|---|---|---|
| 1 | Стиль | PRIMARY — синяя, SUCCESS — зеленая, DANGER — красная, SECONDARY — обычная, LINK — ссылка |
| 2 | ID или ссылка | Для обычных кнопок — ID кнопки, который вы придумываете сами ('accept'). Для LINK — адрес https://… |
| 3 | Надпись | Текст на кнопке. Можно null, если есть эмодзи |
| 4 | Эмодзи | Необязательно. Встанет перед надписью |
| 5 | Действие | UUID действия этой команды или 'self' — текущее действие |
| 6 | Неактивная | Необязательно. true — кнопка видна, но не нажимается |
Какие бывают кнопки
Кнопки, добавленные подряд, встают в один ряд. {% do row() %} начинает новый ряд.
Где работают кнопки с действиями
Кнопки, которые запускают действие, есть только в пользовательских командах. В приветствиях и других местах доступны кнопки-ссылки и «Скопировать» — см. Кнопки под сообщением.
Какая кнопка нажата
Когда кнопка запускает действие, в шаблоне появляется переменная component:
| Свойство | Что в нем |
|---|---|
component.id | ID нажатой кнопки — тот, что вы указали вторым аргументом |
component.type | BUTTON — нажата кнопка, SELECTION_MENU — выбран пункт меню |
component.selectedOptions | Выбранные пункты меню |
Если действие запущено командой, а не кнопкой, component.id пустой. Так одно действие может вести себя по-разному:
{% if component.id == 'refresh' %}Обновлено!{% else %}Первый запуск{% endif %}Кто может нажимать
Нажать кнопку может любой, кто видит сообщение, но бот проверяет права: у нажавшего должен быть доступ к команде и к действию кнопки (если у действия переопределены права). Если прав нет, бот покажет всплывающее уведомление.
Действие кнопки выполняется от имени нажавшего: в member будет он, а не тот, кто вызвал команду.
Пример: подтверждение бана
Три действия: «Спросить» (по умолчанию), «Бан» и «Отмена».
«Спросить» — отправка сообщения:
{% set target = arguments.targetMember %}
{% require target returning 'Укажите участника!' %}
{% do parameters.store('memberId', target.id) %}
{% do parameters.store('reason', arguments.after(2) ?: 'Без причины') %}
### Забанить {{ target }}?
{{ quote(arguments.after(2) ?: 'Причина не указана') }}
{% do button('DANGER', 'accept', 'Забанить', '⛔', '59f7f318-17c9-45b8-be61-33c1f89d54ba') %}
{% do button('SECONDARY', 'cancel', 'Отмена', null, 'c18e2b11-2760-464b-b9f4-f04b7db349bc') %}«Бан» — встроенная команда:
ban {{ parameters.memberId }} {{ parameters.reason }}«Отмена» — отправка сообщения с флажком «Заменять сообщение с нажатой кнопкой»:
Бан отменен.Листание страниц
Кнопки «⬅️» и «➡️» перезапускают то же действие ('self'), а номер страницы хранится в параметрах. Включите у действия флажок «Заменять сообщение с нажатой кнопкой», чтобы страница менялась в том же сообщении.
{% set page = parameters.get('page') ?: 0 %}
{% if component.id == 'next' %}{% set page += 1 %}{% elseif component.id == 'prev' and page > 0 %}{% set page -= 1 %}{% endif %}
{% do parameters.store('page', page) %}
{% set items = ['Броулбол', 'Захват кристаллов', 'Ограбление', 'Нокаут', 'Горячая зона', 'Награда за поимку', 'Осада'] %}
{% set pageItems = items | slice(page * 3, 3) %}
**Режимы** · страница {{ page + 1 }}
{% for item in pageItems %}
{{ page * 3 + loop.index }}. {{ item }}
{% endfor %}
{% do button('SECONDARY', 'prev', null, '⬅️', 'self', page == 0) %}
{% do button('SECONDARY', 'next', null, '➡️', 'self', (page + 1) * 3 >= (items | length)) %}Режимы · страница 1
- Броулбол
- Захват кристаллов
- Ограбление
Готовый пример с топом по данным из индексов — в статье Полезные примеры.
Меню выбора
В Telegram нет выпадающих списков, поэтому меню выбора бот рисует кнопками-вариантами. Участник нажимает вариант — запускается действие меню.
Какой режим тебе нравится?
{% do select_menu('STRING', 'mode', 'Выбери режим', 'self')
.addOption('Броулбол', 'brawlball', '⚽')
.addOption('Захват кристаллов', 'gemgrab', '💎')
.addOption('Одиночное ШД', 'showdown', '🌵') %}Какой режим тебе нравится?
Аргументы select_menu: тип меню, ID меню, подсказка, действие и (необязательно) неактивность.
| Метод | Что делает |
|---|---|
.addOption(надпись, значение, эмодзи?, описание?) | Добавить вариант. Описание в Telegram не показывается |
.withDefaultOption(значение) | Отметить вариант галочкой ✓ |
.endMenu() | Завершить меню, если оно строится внутри createMessage() |
В действии меню выбранное значение лежит в component.selectedOptions — это список из одного элемента:
{% if component.type == 'SELECTION_MENU' %}
{% set choice = component.selectedOptions | first %}
Ты выбрал: {{ choice }}
{% endif %}| Тип меню | Что в вариантах |
|---|---|
STRING | Ваши варианты из addOption |
ROLE | Роли бота |
USER, CHANNEL, MENTIONABLE | Не поддерживаются: Telegram не дает боту списки участников и каналов. Редактор покажет ошибку |
Скоро: выбор нескольких вариантов
Меню с выбором нескольких пунктов и кнопкой «Готово» (withMinValues, withMaxValues, withRequiredRange) появится позже. Сейчас выбирается один вариант.
Кнопки внутри текста
В rich-сообщениях кнопки можно поставить прямо между абзацами, а не только под сообщением:
| Функция | Что делает |
|---|---|
button_row([кнопки], выравнивание?) | Ряд из 1–8 кнопок между блоками текста. Выравнивание: 'left', 'center', 'right' |
inline_button(…) | Одна кнопка прямо в строке текста. Аргументы — как у button |
## Выбери сторону
{{ button_row([
button('PRIMARY', 'red', 'Красные', '🔴', 'self'),
button('PRIMARY', 'blue', 'Синие', '🔵', 'self')
], 'center') }}
Голосование закончится в полночь.В режиме Text такие кнопки переедут в обычную клавиатуру под сообщением.
Кнопка «Скопировать»
{% do copy_button('Скопировать мой ID', member.id) %}Кнопка копирует текст в буфер обмена и не запускает действие.
Сколько живут кнопки
- Кнопка работает 180 дней с последнего нажатия. Если нажать старую кнопку, бот ответит «Кнопка устарела».
- Один участник может нажимать кнопки не чаще 20 раз за 10 секунд — иначе бот ответит «Слишком часто».
- Под одним сообщением — не больше 25 кнопок.