Skip to content

Метод callbackQuery ​

Метод callbackQuery в GramIO используется для обработки обновлений, которые возникают, когда пользователи взаимодействуют с кнопками инлайн-клавиатуры в вашем Telegram боте. Когда пользователь нажимает на кнопку с полезной нагрузкой (callback_data), Telegram отправляет обновление callback_query вашему боту. Этот метод позволяет зарегистрировать обработчик для таких обновлений, давая возможность выполнять действия на основе взаимодействия пользователя.

Основное использование ​

Обработка Callback Query ​

Чтобы использовать метод callbackQuery, вам нужно определить триггер и обработчик. Триггер определяет, когда обработчик должен выполняться на основе полученных callback_data, а обработчик выполняет нужное действие.

ts
const 
someData
= new
CallbackData
("example").
number
("id");
bot
.
callbackQuery
(
someData
, (
context
) => {
return
context
.
send
(`Вы нажали кнопку с ID: ${
context
.
queryData
.
id
}`);
});

В этом примере:

  • someData - это экземпляр CallbackData, определяющий схему для callback data.
  • Метод callbackQuery регистрирует обработчик, который вызывается, когда callback data соответствуют someData.
  • Внутри обработчика context.queryData предоставляет типо-безопасный доступ к callback data.

Типы триггеров ​

Метод callbackQuery поддерживает несколько типов триггеров:

  • Строковый триггер: Обработчик вызывается, если callback_data точно соответствует указанной строке.
ts
bot.callbackQuery("my_callback", (context) => {
    return context.editText("Кнопка нажата!");
});
  • RegExp триггер: Обработчик вызывается, если callback_data соответствует регулярному выражению.
ts
bot.callbackQuery(/my_(.*)/, (context) => {
    const match = context.queryData;
    context.send(`Совпадающие данные: ${match[1]}`);
});
  • Экземпляр CallbackData: Обработчик вызывается, если callback_data соответствуют схеме CallbackData.
ts
const 
someData
= new
CallbackData
("example").
number
("id");
bot
.
callbackQuery
(
someData
, (
context
) => {
context
.
send
(`Data ID: ${
context
.
queryData
.
id
}`);
});

Обработка Callback Data ​

Когда получен callback_query, объект context включает следующие релевантные свойства:

  • context.data: Сырая полезная нагрузка callback_data.
  • context.queryData: Десериализованные данные, если для триггера использовался экземпляр CallbackData.

Пример сценария ​

Рассмотрим сценарий, где вы хотите отправить сообщение с инлайн-клавиатурой и обработать нажатия на кнопки:

ts
const buttonData = new CallbackData("action").number("action_id");

bot.command("start", (context) =>
    context.send("Выберите действие:", {
        reply_markup: new InlineKeyboard().text(
            "Выполнить действие 1",
            buttonData.pack({ action_id: 1 })
        ),
    })
).callbackQuery(buttonData, (context) => {
    context.send(`Вы выбрали действие с ID: ${context.queryData.action_id}`);
});

В этом примере:

  1. Команда /start отправляет сообщение с кнопкой инлайн-клавиатуры.
  2. callback_data кнопки упаковываются с помощью buttonData.pack().
  3. Метод callbackQuery слушает callback_query, которые соответствуют buttonData.
  4. Обработчик отвечает ID выбранного действия.

Миграции схемы и safeUnpack() ​

Кнопки инлайн-клавиатуры остаются в истории Telegram — пользователи могут нажать кнопку спустя дни или недели после её отправки. Если схема CallbackData изменилась между деплоями, старые кнопки могут содержать данные, которые больше не соответствуют схеме.

Что менять безопасно ​

ОперацияБезопасно?Почему
Добавить optional-поле в конец✅ ДаСтарые данные распакуются как undefined / дефолт
Добавить default к существующему optional✅ ДаМеняет только поведение при отсутствующем значении
Добавить required-поле❌ НетВ старых данных нет значения
Удалить поле❌ НетСдвигает позиции всех следующих полей
Поменять порядок полей❌ НетПозиционный формат — значения попадут не в те поля
Сменить тип поля❌ НетДесериализация по другому алгоритму
Переименовать nameId❌ НетcallbackQuery(schema) не матчит старые кнопки

safeUnpack() — для сырых обработчиков callback_query ​

bot.callbackQuery(schema, handler) автоматически фильтрует и распаковывает данные — внутри обработчика ctx.queryData всегда валиден. safeUnpack там не нужен.

safeUnpack() полезен, когда вы обрабатываете callback_query через bot.on() и хотите попробовать несколько схем или корректно обработать устаревшие кнопки:

ts
const v2Schema = new CallbackData("item").number("id").string("tab", { optional: true });

bot.on("callback_query", (ctx) => {
    const result = v2Schema.safeUnpack(ctx.data ?? "");

    if (!result.success) {
        // старая кнопка — схема изменилась или неверный nameId
        return ctx.answerCallbackQuery({ text: "Кнопка устарела, воспользуйтесь новым меню." });
    }

    // result.data типизировано: { id: number; tab: string | undefined }
    return ctx.answerCallbackQuery({ text: `Позиция ${result.data.id}` });
});

Тип возврата — SafeUnpackResult<T>, экспортируется из @gramio/callback-data:

ts
import type { SafeUnpackResult } from "@gramio/callback-data";

function handleData(raw: string): SafeUnpackResult<{ id: number }> {
    return mySchema.safeUnpack(raw);
}