Войти

Слэш-команды и кнопки

Бот регистрирует команды через REST, получает INTERACTION_CREATE в шлюзе и отвечает по токену взаимодействия. Для быстрого старта есть примеры на discord.js и discord.py в руководстве для ботов.

Пути ниже указаны относительно https://kli.chat/api/v10. Формы объектов описаны в OpenAPI. Архитектура описана в ADR 0010.

Бот

Команды

МетодПутьЧто делает
GET/applications/{app}/commandsглобальные команды
POST/applications/{app}/commandsсоздать (201) или обновить команду с тем же типом и именем (200, прежний id)
PUT/applications/{app}/commandsзаменить весь список: те же (тип, имя) или тот же id сохраняют id, остальные создаются, лишние удаляются
GET / PATCH / DELETE/applications/{app}/commands/{command}одна команда; PATCH меняет только присланные поля
…/applications/{app}/guilds/{guild}/commands…то же для команд одного сервера — только если бот на нём состоит

Вызывает бот своего приложения (Authorization: Bot klb_…) или владелец приложения (обычный вход). Чужое приложение: бот — 403 50001, человек — 404 10002.

Чтобы проверить регистрацию на одном сервере, укажите ID приложения и сервера в KLICHAT_APP_ID и KLICHAT_GUILD_ID. Бот уже должен быть на сервере.

curl --fail-with-body "https://kli.chat/api/v10/applications/${KLICHAT_APP_ID}/guilds/${KLICHAT_GUILD_ID}/commands" \
  -H "Authorization: Bot ${KLICHAT_BOT_TOKEN}" \
  -H 'Content-Type: application/json' \
  --data '{"name":"эхо","description":"Повторить текст","options":[{"type":3,"name":"текст","description":"Что повторить","required":true}]}'

Ответ — объект команды Discord: id, type, application_id, guild_id?, name, name_localizations, description, description_localizations, options, default_member_permissions (строка или null), dm_permission, contexts (null или список), integration_types, nsfw, version. version — snowflake; меняется, только если команда правда поменялась.

Проверки как у Discord, ошибка — 400 50035 с errors по полям (путь через точку: options.0.name, у PUT — с номером команды: 1.name):

Команды меню (USER, MESSAGE) хранятся, чтобы регистрация у ботов не падала, но клиент их пока не показывает.

INTERACTION_CREATE

Приходит в шлюз без всяких intents (бот с intents: 0 тоже получает). Если у бота шарды, событие получает шард сервера (guild_id >> 22) % num_shards; личка — шард 0.

{"op":0,"t":"INTERACTION_CREATE","s":42,"d":{
  "id":"1553048426941149184","application_id":"1553047201491349504","type":2,"version":1,
  "token":"sBOUfWEYoWCR…86 символов base64url","locale":"ru","guild_locale":"ru",
  "guild_id":"1553047201298411520","channel_id":"1553047201323577344",
  "channel":{"id":"1553047201323577344","type":0,"name":"общий","guild_id":"1553047201298411520","permissions":"665754290618367", …},
  "member":{"user":{"id":"1553047201248079872","username":"member_6345x", …},"roles":[],"joined_at":"…","flags":0,"permissions":"638238686961217", …},
  "app_permissions":"665754290618367","entitlements":[],"context":0,
  "authorizing_integration_owners":{"0":"1553047201298411520"},"attachment_size_limit":26214400,
  "data":{"id":"1553047377396264964","name":"эхо","type":1,
    "options":[{"name":"текст","type":3,"value":"привет"},{"name":"кто","type":6,"value":"1553047200983838720"}],
    "resolved":{"users":{"1553047200983838720":{…}},"members":{"1553047200983838720":{"roles":[],"permissions":"…", …}}}}
}}

Ответ: POST /interactions/{id}/{token}/callback

Передайте id и token из события INTERACTION_CREATE. Заголовок Authorization здесь не нужен. Принимаются JSON или multipart с payload_json и files[n].

typeКомандаКнопкаАвтодополнениеЧто делает
4✓✓сообщение-ответ; flags: 64 — только вызвавшему
5✓✓«бот думает…» (флаг 128); data.flags: 64 — «думает» только у вызвавшего
6✓ничего видимого; @original — сообщение с кнопкой
7✓сразу правит сообщение с кнопкой
8✓data.choices (до 25) уходят клиенту

Например, это тело ответа отправит сообщение, которое увидит только вызвавший команду.

{"type":4,"data":{"content":"Понг!","flags":64}}

Дополнительные сообщения и правка ответа

На путях вебхуков, как у Discord: сервер сначала ищет вебхук с таким id, а не найдя — взаимодействие приложения с этим токеном.

МетодПуть
POST/webhooks/{app}/{token}дополнительное сообщение; ответ — всегда сообщение (как wait=true)
GET / PATCH / DELETE/webhooks/{app}/{token}/messages/@originalответ (или, после 6 и 7, сообщение с кнопкой)
GET / PATCH / DELETE/webhooks/{app}/{token}/messages/{id}сообщение этого взаимодействия

Сообщения ответа

Автор — бот приложения, webhook_id — null.

{"id":"…","type":20,"flags":0,"content":"Понг!","application_id":"1553047201491349504",
 "author":{"id":"1553047201491349505","bot":true, …},
 "interaction_metadata":{"id":"…","type":2,"name":"настройки звук громкость","command_type":1,
   "user":{"id":"…", …},"authorizing_integration_owners":{"0":"…"}},
 "interaction":{"id":"…","type":2,"name":"настройки звук громкость","user":{…}},
 "components":[]}

Кнопки и списки

Отправлять может только бот — в REST (создание и правка сообщения), в ответе на взаимодействие и в дополнительном сообщении. От людей и обычных вебхуков — 400 50035 «Кнопки могут отправлять только приложения».

"components": [
  {"type": 1, "components": [
    {"type": 2, "style": 1, "label": "Да", "custom_id": "yes"},
    {"type": 2, "style": 5, "label": "Сайт", "url": "https://kli.chat"}
  ]},
  {"type": 1, "components": [
    {"type": 3, "custom_id": "цвет", "placeholder": "Цвет", "min_values": 1, "max_values": 2,
     "options": [{"label": "Красный", "value": "red"}, {"label": "Синий", "value": "blue"}]}
  ]}
]

Клиент Кличата

Список команд

GET /api/v1/guilds/{guild}/application-command-index — что показать по «/» на сервере. GET /api/v1/channels/{channel}/application-command-index — в личке с ботом (в канале сервера — то же, что у сервера, в остальных личках — пусто).

{
  "applications": [
    {"id": "1553047201491349504", "name": "Проверочный", "icon": null, "bot_id": "1553047201491349505",
     "bot": {"id": "1553047201491349505", "username": "proverochnyy", "global_name": "Проверочный", "avatar": null, "bot": true, …}},
    {"id": "1550657676906590210", "name": "Кличат Музыка", "icon": null, "bot_id": "1550657676906590209", "bot": {…}}
  ],
  "application_commands": [ApplicationCommand, …]
}

Вызов: POST /api/v1/interactions

{"type": 2, "application_id": "1553047201491349504", "guild_id": "…", "channel_id": "…", "nonce": "1727270000000",
 "data": {"id": "1553047377396264964", "name": "эхо", "type": 1, "options": [
   {"type": 3, "name": "текст", "value": "привет"},
   {"type": 6, "name": "кто", "value": "1553047200983838720"}
 ]}}

Сервер проверяет, создаёт взаимодействие, отдаёт его боту и ждёт первого ответа до 3 секунд:

ОтветКогда
204бот ответил на команду или кнопку; само сообщение придёт событием шлюза
200 {"choices": [{"name", "value"}]}ответ на подсказки
504 {"code": 10062, "message": "Приложение не ответило"}бот не ответил за 3 секунды
400 / 403 {"code", "message", "errors"?}проверка не прошла; message — для человека
429 {"retry_after"}больше 5 вызовов за 5 секунд (подсказки — 20 за 5 секунд)

Тексты отказов: «Нет права использовать команды в этом канале», «Не хватает прав для этой команды», «Команда больше не существует», «Приложения больше нет на этом сервере», «Кнопка больше не работает», «Канал недоступен», «Канал не найден», «Приложение не найдено», «Эта команда работает только на сервере», «Эта команда работает только в личке с ботом», «Команда 18+ работает только в каналах 18+», «Канал 18+: доступен только с 18 лет», «В категории команд нет: выберите канал», «Команды из меню пока не поддерживаются», «Неизвестный тип взаимодействия», «Проверьте значения в команде» (с errors по опциям: options.0.value), «Не удалось разобрать запрос».

Права: USE_APPLICATION_COMMANDS в канале, бот на сервере (кроме встроенной музыки), default_member_permissions. Нажать кнопку можно, если канал виден. Боту вызывать нельзя — 403 20001.

События

Обычные MESSAGE_CREATE/MESSAGE_UPDATE/MESSAGE_DELETE с полями выше. Сообщения «только вам» (флаг 64) приходят только вызвавшему; «бот думает…» — флаг 128 и пустой текст, затем MESSAGE_UPDATE с текстом.

Встроенная музыка

Приложение 1550657676906590210, бот 1550657676906590209. Worker при запуске задаёт команды /играй запрос, /пропустить, /стоп, /пауза, /продолжить, /очередь, /сейчас, /громкость число, /музыка (только на серверах), получает INTERACTION_CREATE подпиской на субъект бота и отвечает через interaction.Builtin. Подсказки и отказы видит только вызвавший; /играй сначала «думает», потом правит ответ. Команды с «!» работают по-прежнему.

Полное описание REST — OpenAPI 3.1. Разделы: вся документация.