Interactions API: слэш-команды
Interactions — это Discord-style слэш-команды: пользователь начинает вводить /, видит список
команд бота с подсказками, выбирает нужную, заполняет параметры — и бот получает структурированный
запрос вместо того, чтобы разбирать текст сообщения. Сюда же относятся клики по кнопкам/меню на
сообщениях бота и заполнение модальных окон — все три сценария используют один и тот же жизненный
цикл «interaction → ответ бота».
Interactions обслуживает отдельный gRPC-сервис — InteractionsApi. Он логически разбит на две
части с разными правами вызова:
| Часть | Кто вызывает | Аутентификация |
|---|---|---|
Регистрация команд (RegisterCommand, UpdateCommand, DeleteCommand, GetBotCommands) | Владелец бота или сам бот | Оба варианта: пользовательский вход (владелец) либо токен бота с intent'ом ApplicationCommands |
Выполнение (ExecuteCommand, RequestAutocomplete, InvokeMessageComponent, SubmitModal) | Любой участник группы (обычно — сам клиент Voice, когда пользователь вводит команду) | Обычный пользовательский вход — это действие человека, не бота |
Библиотеке для ботов из этого сервиса обычно нужна только регистрация команд — сам бот не
«выполняет» команды, он лишь регистрирует их при старте, а затем получает уже готовый,
структурированный InteractionCreated через Gateway и отвечает через
BotsApi (см. ниже).
Регистрация команд
RegisterCommand {
bot_id: "<id бота>"
name: "weather"
description: "Показать погоду в городе"
options: [
{ name: "city", description: "Город", type: STRING, required: true, autocomplete: true }
]
default_member_permissions: 0
}
Типы параметров команды (CommandOptionType): STRING, INTEGER, BOOLEAN, USER, CHANNEL,
ROLE, NUMBER, SUB_COMMAND, SUB_COMMAND_GROUP. Параметр с autocomplete: true не имеет
статичного списка choices — вместо этого сервер будет присылать боту запрос RequestAutocomplete
по мере ввода пользователем текста в это поле, а бот должен ответить динамическим списком
подсказок (см. ниже про типы ответа).
UpdateCommand/DeleteCommand работают предсказуемо — обновляют/удаляют ранее
зарегистрированную команду по command_id. GetBotCommands возвращает все команды конкретного
бота. Команды сейчас глобальные для бота — действуют во всех группах, где он состоит, отдельной
регистрации на каждую группу не требуется.
Типичный паттерн — синхронизировать список команд при запуске бота: получить уже
зарегистрированные (GetBotCommands), сравнить с тем, что описано в коде, создать недостающие,
обновить изменившиеся, удалить лишние. Так разработчику бота достаточно объявить команды в коде —
без отдельного шага «выложить команды в консоли администратора».
Жизненный цикл одного interaction
- Пользователь вызывает слэш-команду / кликает кнопку / отправляет форму модального окна.
- Сервер создаёт короткоживущую сущность interaction'а и присылает боту событие
InteractionCreatedчерез топикinteraction-eventsGateway (адресно, этому конкретному боту). - У бота есть ограниченное окно времени, чтобы ответить через
BotsApi.RespondToInteraction:- 10 секунд — для слэш-команд, кликов по компонентам, сабмитов модальных окон;
- 3 секунды — для запросов автодополнения (
RequestAutocomplete). Если бот не успевает — interaction считается просроченным, попытка ответить на него позже вернёт ошибкуFailedPrecondition.
- Если ответ требует времени (например, боту нужно сходить во внешний API), он может сначала
отправить «отложенный» ответ (
DEFERRED_CHANNEL_MESSAGE/DEFERRED_UPDATE_MESSAGE) в пределах тех же 10 секунд, а затем прислать содержательный ответ уже черезSendInteractionFollowup— на это даётся 15 минут с момента первого ответа («followup window»).
Полезная нагрузка InteractionCreated
{
"interactionId": "...",
"invokingUserId": "...",
"channelId": "...",
"groupId": "...",
"type": "ApplicationCommand",
"data": {
"commandName": "weather",
"options": { "city": "Berlin" },
"customId": null,
"values": null,
"focusedOption": null,
"modalFields": null
}
}
type — один из четырёх видов, определяющий, какие поля data заполнены:
type | Что произошло | Заполненные поля data |
|---|---|---|
ApplicationCommand | Вызвана слэш-команда | commandName, options |
MessageComponent | Клик по кнопке/пункту меню на сообщении бота | customId, values (для меню с несколькими вариантами) |
ModalSubmit | Отправлена форма модального окна | customId (id модального окна), modalFields (значения полей по их customId) |
ApplicationCommandAutocomplete | Пользователь печатает в поле с autocomplete: true | commandName, options (уже введённые значения других полей), focusedOption (какое поле сейчас в фокусе) |
Ответ бота
RespondToInteraction {
interaction_id: "..."
kind: CHANNEL_MESSAGE
content: "В Berlin сейчас +12°C"
components_json: null // опционально, см. "Компоненты и модальные окна"
modal_json: null
autocomplete_choices: []
ephemeral: false
}
Вид ответа (kind, он же InteractionResponseKind):
| Значение | Когда используется |
|---|---|
CHANNEL_MESSAGE | Обычный ответ — новое сообщение в канал |
DEFERRED_CHANNEL_MESSAGE | «Думаю…» — подтверждает получение, реальный ответ придёт позже через SendInteractionFollowup |
UPDATE_MESSAGE | Только для ответа на клик по компоненту — редактирует то самое сообщение, на котором был клик, вместо создания нового |
DEFERRED_UPDATE_MESSAGE | То же, но с отложенным редактированием |
MODAL | Открывает у пользователя модальное окно (modal_json, см. «Компоненты и модальные окна») — доступно только в ответ на слэш-команду или клик по компоненту, не на сабмит другого модального окна |
AUTOCOMPLETE_RESULT | Ответ на ApplicationCommandAutocomplete — список подсказок (autocomplete_choices) |
ephemeral: true означает, что ответ увидит только сам вызвавший команду пользователь (остальные
участники канала — нет). Работает только для CHANNEL_MESSAGE/DEFERRED_CHANNEL_MESSAGE.
Если kind — CHANNEL_MESSAGE (не эфемерный), результат действительно создаёт настоящее
сообщение в канале — оно попадёт в историю чата, на него распространяются UpdateMessage/
DeleteMessage из BotsApi, а рядом с ним показывается Discord-style пометка «использовал(а)
/имя-команды».