Боты и интерактивные сообщения

Аккаунт бота — это пользователь, созданный для программы. Он имеет собственное имя, аватар и токены, а рядом с его именем отображается метка BOT. На этой странице также описаны интерактивные элементы сообщений: кнопки, меню и диалоги, которые могут использовать любые интеграции.

Зачем нужен аккаунт бота

  • Его сообщения исходят от чётко определённой личности с меткой БОТ, а не от учётной записи коллеги.
  • Его токены продолжают работать, даже если человек, создавший бота, сменит роль или покинет рабочее пространство (если на сервере не отключены боты деактивированных владельцев, см. ниже).
  • Боты не могут входить в систему по паролю и никогда не видят веб-приложение.

Приложения создают собственных ботов, таких как боты Todo или Playbooks, через API плагина (EnsureBotUser).

Включение аккаунтов ботов

Системный администратор включает Включить создание учетной записи бота в Системная консоль › Интеграции › Аккаунты ботов (ServiceSettings.EnableBotAccountCreation, AM_SERVICESETTINGS_ENABLEBOTACCOUNTCREATION). По умолчанию эта опция выключена. Создавать ботов могут только системные администраторы, если только они не предоставят это право другим ролям в настройках разрешений.

На той же странице опция Отключить учетные записи ботов когда их владелец деактивирован (ServiceSettings.DisableBotsWhenOwnerIsDeactivated, включена по умолчанию) отключает бота, когда учётная запись его владельца деактивируется.

Создание бота

  1. Откройте свой аватар в правом верхнем углу, затем выберите Интеграции › Аккаунты ботов, а затем Добавить учетную запись бота.
  2. Введите Имя пользователя (строчные буквы, цифры, точки, дефисы и подчёркивания), а при необходимости — Значок бота, Отображаемое имя и Описание.
  3. Выберите Роль: Участник или Системный администратор для бота, управляющего сервером. Выдавайте боту только те права, которые ему действительно необходимы.
  4. Отметьте сообщения:каналы, чтобы бот мог публиковать сообщения во всех публичных каналах, или сообщения:всем, чтобы он мог публиковать сообщения во всех каналах, включая закрытые и личные сообщения, даже не являясь их участником.
  5. Установите срок действия токена по умолчанию, затем выберите Создать аккаунт бота.
  6. Скопируйте отображаемый токен доступа. Он не будет показан повторно.

Позже, на строке бота, кнопка Создать новый токен добавляет новый токен; каждый токен можно отключить или удалить. Токены ботов работают даже тогда, когда личные токены доступа отключены для пользователей.

С помощью API:

# create the bot (you become its owner)
curl -X POST https://chat.example.com/api/v4/bots \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"username": "deploy-bot", "display_name": "Deploy", "description": "Posts deployments"}'

# give it a token
curl -X POST https://chat.example.com/api/v4/users/$BOT_USER_ID/tokens \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"description": "deploy pipeline"}'

Из командной строки, войдя как администратор (не в локальном режиме): amctl bot create deploy-bot --display-name Deploy --with-token --expires-in 90d. Другие конечные точки: GET /api/v4/bots, PUT /api/v4/bots/{bot_user_id}, POST /api/v4/bots/{bot_user_id}/disable и /enable, POST /api/v4/bots/{bot_user_id}/assign/{user_id} для смены владельца.

Добавление бота в сообщества и каналы

Новый бот не состоит ни в одном сообществе. Добавьте его, как обычного участника, через управление участниками сообщества или с помощью API:

curl -X POST https://chat.example.com/api/v4/teams/$TEAM_ID/members \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"team_id": "'$TEAM_ID'", "user_id": "'$BOT_USER_ID'"}'

curl -X POST https://chat.example.com/api/v4/channels/$CHANNEL_ID/members \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"user_id": "'$BOT_USER_ID'"}'

Бот с правом сообщения:каналы или сообщения:всем может публиковать сообщения, не являясь участником канала, но получает события WebSocket только для тех каналов, в которых он состоит.

Публикация сообщений от имени бота

Используйте токен бота в любом запросе к API; чаще всего применяется POST /api/v4/posts (см. Основные ресурсы). Чтобы написать кому-то напрямую, сначала откройте канал личных сообщений:

# returns the channel; use its "id" as channel_id
curl -X POST https://chat.example.com/api/v4/channels/direct \
  -H "Authorization: Bearer $BOT_TOKEN" -H 'Content-Type: application/json' \
  -d '["'$BOT_USER_ID'", "'$USER_ID'"]'

Чтобы реагировать на сообщения пользователей, подключитесь к WebSocket с токеном бота и обрабатывайте события posted, которые вас интересуют. Игнорируйте собственные сообщения бота, чтобы избежать циклов.

Сообщение, видимое только одному человеку (эфемерное сообщение), отправляется с помощью POST /api/v4/posts/ephemeral и тела {"user_id", "post": {"channel_id", "message"}}. Для этого требуется право create_post_ephemeral, которое по умолчанию имеют только системные администраторы. Интеграции обычно отправляют эфемерные сообщения в качестве ответов на команды с косой чертой и нажатия кнопок.

Интерактивные сообщения: кнопки и меню

Любое сообщение с вложениями может содержать действия: кнопки и меню для выбора. Они работают в сообщениях, отправленных через API, вебхуки и в ответах на команды с косой чертой. Когда кто-то использует действие, Antimatter вызывает URL вашей интеграции.

{
  "channel_id": "…",
  "message": "Deploy **api 2.4.0** to production?",
  "props": {
    "attachments": [{
      "actions": [
        {
          "id": "approve",
          "type": "button",
          "name": "Approve",
          "style": "primary",
          "integration": {"url": "https://deploy.example.com/actions", "context": {"release": "2.4.0", "action": "approve"}}
        },
        {
          "id": "env",
          "type": "select",
          "name": "Pick an environment",
          "options": [{"text": "Staging", "value": "staging"}, {"text": "Production", "value": "production"}],
          "integration": {"url": "https://deploy.example.com/actions", "context": {"release": "2.4.0", "action": "env"}}
        }
      ]
    }]
  }
}
  • type: button или select.
  • id: буквы, цифры, дефисы и подчёркивания; должен быть уникальным для каждого действия в сообщении. Если поле не указано, идентификатор генерируется автоматически.
  • style (для кнопок): default, primary, success, good, warning, danger или цвет в шестнадцатеричном формате.
  • options (для меню) или data_source: users или channels для выбора пользователя или канала. default_option задаёт значение по умолчанию.
  • integration.url: адрес, на который отправляется запрос при нажатии. Приложение (плагин) может использовать собственный маршрут, например /plugins/com.example.deploy/actions. integration.context — это ваши данные: они возвращаются вместе с запросом, но не отображаются клиентам.

Запрос, который получает ваше приложение

{
  "user_id": "…",
  "user_name": "priya",
  "channel_id": "…",
  "channel_name": "releases",
  "team_id": "…",
  "team_domain": "lumen-labs",
  "post_id": "…",
  "trigger_id": "…",
  "type": "button",
  "context": {"release": "2.4.0", "action": "approve"}
}

Для меню значение type равно select, а context.selected_option содержит выбранное значение.

Ваш ответ

{
  "update": {"message": "Deploy of **api 2.4.0** approved by @priya", "props": {}},
  "ephemeral_text": "Done. The deploy starts in a minute."
}
  • update: заменяет текст и свойства сообщения, например, чтобы удалить кнопки после их использования (пустое значение props).
  • ephemeral_text: сообщение, которое видит только тот, кто нажал.
  • goto_location: URL для открытия.
  • Пустое тело ответа ничего не меняет.

Сервер ожидает ответа в течение времени, разрешённого параметром Таймаут запроса на интеграцию (по умолчанию 30 секунд). Адреса интеграций в частных сетях должны быть разрешены системным администратором, как и в случае с вебхуками.

Диалоги

Диалог — это форма, которая открывается поверх чата. Открыть его можно только в ответ на действие пользователя (команду с косой чертой или нажатие кнопки), так как для этого требуется trigger_id из этого запроса. trigger_id действителен в течение времени, заданного в Integration request timeout.

curl -X POST https://chat.example.com/api/v4/actions/dialogs/open \
  -H 'Content-Type: application/json' \
  -d '{
    "trigger_id": "'$TRIGGER_ID'",
    "url": "https://deploy.example.com/dialog",
    "dialog": {
      "callback_id": "new-release",
      "title": "New release",
      "introduction_text": "Fill in the release details.",
      "submit_label": "Create",
      "notify_on_cancel": false,
      "state": "anything you want back",
      "elements": [
        {"display_name": "Version", "name": "version", "type": "text", "placeholder": "2.4.0"},
        {"display_name": "Notes", "name": "notes", "type": "textarea", "optional": true},
        {"display_name": "Environment", "name": "env", "type": "select",
         "options": [{"text": "Staging", "value": "staging"}, {"text": "Production", "value": "production"}]},
        {"display_name": "Owner", "name": "owner", "type": "select", "data_source": "users"},
        {"display_name": "Notify the channel", "name": "notify", "type": "bool", "default": "true"}
      ]
    }
  }'
Тип элементаЧто отображается
textОднострочное поле. subtype: text, email, number, password, tel или url. min_length и max_length задают ограничения на длину.
textareaМногострочное поле.
selectСписок: options, либо data_source со значением users, channels или dynamic (с указанием data_source_url). multiselect позволяет выбрать несколько значений.
boolФлажок.
radioОдин выбор из списка options.
date, datetimeДата или дата и время.

Каждый элемент принимает параметры display_name, name, help_text, placeholder, default и optional.

При отправке формы Antimatter выполняет POST-запрос на url диалога:

{
  "type": "dialog_submission",
  "callback_id": "new-release",
  "state": "anything you want back",
  "user_id": "…",
  "channel_id": "…",
  "team_id": "…",
  "submission": {"version": "2.4.0", "notes": "", "env": "staging", "owner": "…", "notify": true},
  "cancelled": false
}

Ответьте пустым телом, чтобы закрыть диалог, или оставьте его открытым и укажите, что не так:

{"errors": {"version": "This version already exists."}}

{"error": "…"} отображает сообщение для всей формы. Если задан notify_on_cancel, при закрытии диалога отправляется "cancelled": true. Диалоги в приложениях работают так же: метод OpenInteractiveDialog API плагинов принимает тот же запрос.