Встроенные и пользовательские клавиатуры (встроенно)
Ваш бот может отправлять несколько кнопок, которые будут либо отображаться под сообщением, либо заменять клавиатуру пользователя. Они называются inline-клавиатурами и custom-клавиатурами, соответственно. Если вы думаете, что это запутанно, то так оно и есть. Спасибо, Telegram, за эту пересекающуюся терминологию.
Давайте попробуем немного прояснить ситуацию:
Термин | Определение |
---|---|
Встроенные клавиатуры | набор кнопок, который отображается под сообщением в чате. |
Пользовательские клавиатуры | набор кнопок, который отображается вместо системной клавиатуры пользователя. |
Кнопка встроенной клавиатуры | кнопка в встроенной клавиатуре, при нажатии посылает callback запрос, не видимый пользователю, иногда называется просто inline button. |
Кнопка пользовательской клавиатуры | кнопка клавиатуры, при нажатии отправляет текстовое сообщение со своим ярлыком, иногда называется просто keyboard button. |
Inline | класс в grammY для создания встроенных клавиатур. |
Keyboard | класс в grammY для создания пользовательских клавиатур. |
Обратите внимание, что и кнопки пользовательской клавиатуры, и кнопки встроенной клавиатуры могут выполнять и другие функции, например, запрашивать местоположение пользователя, открывать веб-сайт и так далее. Это было опущено для краткости.
Невозможно указать в одном сообщении и пользовательскую, и встроенную клавиатуру. Эти два варианта являются взаимоисключающими. Более того, отправленный вид разметки ответа нельзя изменить впоследствии, отредактировав сообщение. Например, невозможно сначала отправить пользовательскую клавиатуру вместе с сообщением, а затем отредактировать сообщение, чтобы использовать встроенную клавиатуру.
Встроенные клавиатуры
Пересмотрите раздел о встроенной клавиатуре в статье Возможности Telegram Бота, написанной командой Telegram.
В grammY есть простой и интуитивно понятный способ создания встроенных клавиатур, которые ваш бот может отправлять вместе с сообщением. Для этого он предоставляет класс Inline
.
Кнопки, добавляемые вызовом
switch
,Inline switch
иInline Current switch
, запускают встроенные запросы. Подробнее о том, как они работают, читайте в разделе о встроенные запросы.Inline Chosen
Построение встроенных клавиатур
Вы можете создать встроенную клавиатуру, создав новый экземпляр класса Inline
, а затем добавив в него нужные вам кнопки с помощью .text()
и других его методов.
Вот пример:
const inlineKeyboard = new InlineKeyboard()
.text("« 1", "first")
.text("‹ 3", "prev")
.text("· 4 ·", "stay")
.text("5 ›", "next")
.text("31 »", "last");
2
3
4
5
6
Вызовите .row()
, если хотите начать новый ряд кнопок. Вы также можете использовать другие методы, например .url()
, чтобы позволить клиенту пользователя открыть определенный URL или сделать другие интересные вещи. Обязательно ознакомьтесь со всеми методами класса Inline
.
Если у вас уже есть массив строк, который вы хотели бы превратить в встроенную клавиатуру, вы можете использовать второй, альтернативный стиль построения экземпляров встроенной клавиатуры. Класс Inline
имеет статические методы, такие как Inline
, которые позволяют создавать объекты кнопок. В свою очередь, вы можете создать экземпляр встроенной клавиатуры из массива объектов кнопок с помощью Inline
.
Таким образом, вы можете построить описанную выше линейную клавиатуру функциональным способом.
const labelDataPairs = [
["« 1", "first"],
["‹ 3", "prev"],
["· 4 ·", "stay"],
["5 ›", "next"],
["31 »", "last"],
];
const buttonRow = labelDataPairs
.map(([label, data]) => InlineKeyboard.text(label, data));
const keyboard = InlineKeyboard.from([buttonRow]);
2
3
4
5
6
7
8
9
10
Отправка встроенных клавиатур
Вы можете отправить встроенную клавиатуру прямо вместе с сообщением, независимо от того, используете ли вы bot
, ctx
или ctx
:
// Отправьте встроенную клавиатуру с сообщением.
await ctx.reply(text, {
reply_markup: inlineKeyboard,
});
2
3
4
Естественно, все остальные методы, отправляющие сообщения, отличные от текстовых, поддерживают те же опции, которые указаны в Telegram Bot API. Например, вы можете отредактировать клавиатуру, вызвав edit
и передав новый экземпляр Inline
в качестве reply
. Укажите пустую клавиатуру, чтобы удалить все кнопки под сообщением.
Ответ на нажатие по встроенной клавиатуре
Плагин для меню
Плагин клавиатуры дает вам прямой доступ к объектам обновлений, которые отправляет Telegram. Однако реагировать на нажатия таким образом может быть утомительно. Если вы ищете более высокоуровневую реализацию встроенных клавиатур, обратите внимание на плагин menu. Он упрощает создание интерактивных меню.
К каждой кнопке text
прикреплена строка в качестве данных callback вызова. Если вы не прикрепите данные callback вызова, grammY будет использовать текст кнопки в качестве данных.
Как только пользователь нажмет на кнопку text
, ваш бот получит обновление, содержащее данные callback вызова соответствующей кнопки. Вы можете прослушать данные callback вызова через bot
.
// Сконструируйте клавиатуру.
const inlineKeyboard = new InlineKeyboard().text("клик", "click-payload");
// Отправьте клавиатуру вместе с сообщением.
bot.command("start", async (ctx) => {
await ctx.reply("Любопытно? Нажмите на меня!", {
reply_markup: inlineKeyboard,
});
});
// Подождите события клика с определённым названием
bot.callbackQuery("click-payload", async (ctx) => {
await ctx.answerCallbackQuery({
text: "Вы были очень любопытны!",
});
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Ответы на все callback запросы bot
полезен для
прослушивания событий нажатия определенных кнопок. Вы можете использовать bot
для прослушивания событий любой кнопки.
bot.callbackQuery("click-payload" /* , ... */);
bot.on("callback_query:data", async (ctx) => {
console.log("Неизвестное событие кнопки с payload", ctx.callbackQuery.data);
await ctx.answerCallbackQuery(); // убрать анимацию загрузки
});
2
3
4
5
6
Имеет смысл определить bot
в последнюю очередь, чтобы всегда отвечать на все остальные запросы, которые ваши предыдущие слушатели не обработали. В противном случае некоторые клиенты могут показывать анимацию загрузки до минуты, когда пользователь нажимает кнопку, на которую ваш бот не хочет реагировать.
Пользовательские клавиатуры
Прежде всего: пользовательские клавиатуры иногда называются просто клавиатурами, иногда — ответными клавиатурами. Даже собственная документация Telegram непоследовательна в этом отношении. Простое эмпирическое правило: если это не очевидно из контекста и не называется встроенной клавиатурой, то это, скорее всего, пользовательская клавиатура. Это относится к способу замены системной клавиатуры набором кнопок, которые вы можете определить.
Пересмотрите раздел о пользовательской клавиатуре в статье Telegram Bot Features, написанной командой Telegram.
В grammY есть простой и интуитивно понятный способ создания пользовательских клавиатур, которые ваш бот может использовать для замены системной клавиатуры. Для этого он предоставляет класс Keyboard
.
Как только пользователь нажмет кнопку text
, ваш бот получит отправленный текст в виде обычного текстового сообщения. Помните, что вы можете прослушать текстовое сообщение через bot
или bot
.
Построение пользовательских клавиатур
Вы можете создать собственную клавиатуру, создав новый экземпляр класса Keyboard
, а затем добавив к нему кнопки типа .text()
и другие. Вызовите .row()
, чтобы начать новый ряд кнопок.
Вот пример:
const keyboard = new Keyboard()
.text("Да, это точно").row()
.text("Я не совсем уверен").row()
.text("Не-а. 😈")
.resized();
2
3
4
5
Вы также можете отправлять более мощные кнопки, которые запрашивают номер телефона пользователя, его местоположение или делают другие интересные вещи. Обязательно ознакомьтесь со всеми методами класса Keyboard
.
Если у вас уже есть массив строк, который вы хотите превратить в клавиатуру, вы можете использовать второй, альтернативный стиль создания экземпляров клавиатуры. Класс Keyboard
имеет статические методы, такие как Keyboard
, которые позволяют создавать объекты кнопок. В свою очередь, вы можете создать экземпляр клавиатуры из массива объектов кнопок с помощью Keyboard
.
Таким образом, вы можете построить описанную выше клавиатуру функциональным способом.
const labels = [
"Да, это точно",
"Я не совсем уверен",
"Не-а. 😈",
];
const buttonRows = labels
.map((label) => [Keyboard.text(label)]);
const keyboard = Keyboard.from(buttonRows).resized();
2
3
4
5
6
7
8
Отправка пользовательских клавиатур
Вы можете отправить пользовательскую клавиатуру прямо вместе с сообщением, независимо от того, используете ли вы bot
, ctx
или ctx
:
// Отправить клавиатуру с сообщением
await ctx.reply(text, {
reply_markup: keyboard,
});
2
3
4
Естественно, все остальные методы, отправляющие сообщения, отличные от текстовых, поддерживают те же опции, как указано в Telegram Bot API.
Вы также можете придать клавиатуре одно или несколько дополнительных свойств, вызвав для нее специальные методы. Они не добавляют никаких кнопок, а скорее определяют поведение клавиатуры. Мы уже видели resized
в примере выше — вот еще несколько вещей, которые вы можете сделать.
Постоянные клавиатуры
По умолчанию пользователи видят значок, который позволяет им показывать или скрывать пользовательскую клавиатуру, установленную вашим ботом.
Вы можете вызвать persistent
, если хотите, чтобы пользовательская клавиатура всегда отображалась, когда обычная системная клавиатура скрыта. Таким образом, пользователи всегда будут видеть либо пользовательскую, либо системную клавиатуру.
new Keyboard()
.text("Пропустить")
.persistent();
2
3
Изменение размера пользовательской клавиатуры
Вы можете вызвать resized
, если хотите, чтобы размер пользовательской клавиатуры был изменен в соответствии с содержащимися в ней кнопками. Это позволит сделать клавиатуру меньше. (Обычно клавиатура всегда имеет размер стандартной клавиатуры приложения).
new Keyboard()
.text("Да").row()
.text("Нет")
.resized();
2
3
4
Неважно, вызываете ли вы resized
первым, последним или где-то между ними. Результат всегда будет одинаковым.
Одноразовые пользовательские клавиатуры
Вы можете вызвать one
, если хотите, чтобы пользовательская клавиатура была скрыта сразу после нажатия первой кнопки.
new Keyboard()
.text("Да").row()
.text("Нет")
.oneTime();
2
3
4
Неважно, вызываете ли вы one
первым, последним или где-то между ними. Результат всегда будет одинаковым.
Заполнитель в поле ввода
Вы можете вызвать placeholder
, если хотите, чтобы в поле ввода отображался заполнитель, пока видна пользовательская клавиатура.
new Keyboard()
.text("Да").row()
.text("Нет")
.placeholder("Выбирай сейчас же!");
2
3
4
Неважно, называете ли вы placeholder
первым, последним или где-то между ними. Результат всегда будет одинаковым.
Выборочная отправка пользовательских клавиатур
Вы можете вызвать selected
, если хотите показать пользовательскую клавиатуру только тем пользователям, которые упомянуты (@) в тексте объекта сообщения, и отправителю исходного сообщения в случае, если ваше сообщение является ответом на сообщение.
new Keyboard()
.text("Да").row()
.text("Нет")
.selected();
2
3
4
Неважно, вызовете ли вы selected
первым, последним или где-то между ними. Результат всегда будет одинаковым.
Ответ на нажатие по пользовательской клавиатуре
Как уже говорилось, все, что делают пользовательские клавиатуры — это отправка обычных текстовых сообщений. Ваш бот не сможет отличить обычные текстовые сообщения от сообщений, которые были отправлены нажатием кнопки.
Более того, кнопки всегда будут отправлять именно то сообщение, которое на них написано. Telegram не позволяет создавать кнопки, которые отображают один текст, а отправляют другой. Если вам нужно сделать это, используйте встроенную клавиатуру.
Чтобы обработать нажатие определенной кнопки, вы можете использовать bot
с тем же текстом, который вы поместили на кнопку. Если вы хотите обработать все нажатия на кнопки сразу, используйте bot
и проверьте ctx
, чтобы выяснить, какая кнопка была нажата, или было ли отправлено обычное текстовое сообщение.
Удаление пользовательской клавиатуры
Если не указать one
, как описано выше, пользовательская клавиатура будет оставаться открытой для пользователя (но пользователь может свернуть ее).
Удалить пользовательскую клавиатуру можно только при отправке нового сообщения в чате, так же как и указать новую клавиатуру можно только при отправке сообщения. Передайте { remove
в качестве reply
следующим образом:
await ctx.reply(text, {
reply_markup: { remove_keyboard: true },
});
2
3
Рядом с remove
можно установить значение selective:
, чтобы удалить пользовательскую клавиатуру только для выбранных пользователей. Это работает аналогично выборочной отправке пользовательской клавиатуры.
Краткая информация о плагине
Этот плагин встроен в ядро grammY. Вам не нужно ничего устанавливать, чтобы использовать его. Просто импортируйте все из самого grammY.
Кроме того, документация и ссылка на API этого плагина объединены с основным пакетом.