Команды с косой чертой
Пользовательская команда с косой чертой позволяет пользователям вводить /что-то в поле сообщения, чтобы вызвать ваш сервис. Antimatter отправляет команду на ваш URL и отображает ваш ответ — либо только для этого пользователя, либо для всего канала.
Как работает команда с косой чертой
- Пользователь вводит
/weather Parisи отправляет. Текст не публикуется. - Antimatter отправляет HTTP-запрос на URL команды, включая данные о том, кто ввёл команду, где и какой текст следует после ключевого слова.
- Ваш сервис отвечает в пределах тайм-аута запроса (по умолчанию 30 секунд) сообщением.
- Antimatter отображает ответ: только для этого пользователя (эфемерный) или в канале для всех.
Команды принадлежат сообществу, и ключевое слово уникально в пределах сообщества. Встроенные команды, такие как /join, /msg или /away, нельзя заменить. Приложения (плагины) также могут регистрировать команды; см. Серверная часть.
Создание команды
Пользовательские команды с косой чертой включены по умолчанию (Включить пользовательские быстрые команды в Системная консоль › Интеграции › Управление интеграцией, ServiceSettings.EnableCommands). Администраторы сообществ и системные администраторы могут создавать их по умолчанию.
- Откройте свой аватар в правом верхнем углу, затем Интеграции › Слэш-команды, затем Добавить быструю команду.
- Заполните Заголовок и Описание (отображаются на страницах интеграций).
- Введите Ключевое слово, без косой черты и без пробелов, например
weather. - Введите URL запроса и выберите Метод запроса: POST (по умолчанию) или GET.
- При необходимости задайте Имя пользователя для ответа и Значок ответа. Они используются только в том случае, если сервер позволяет интеграциям заменять имена и значки (см. Имя и значок).
- Отметьте Автодополнение, чтобы команда отображалась в списке, когда пользователи вводят
/, с Подсказкой для автодополнения (её аргументами, например[city]) и Описанием для автодополнения. - Выберите Сохранить и скопируйте отображённый токен. Ваш сервис использует его для проверки того, что запросы исходят от вашего сервера.
Через API: POST /api/v4/commands с параметрами {"team_id", "trigger", "url", "method": "P", "display_name", "description", "auto_complete": true, "auto_complete_hint", "auto_complete_desc", "username", "icon_url"}. Значение P означает POST, а G — GET. Запрос PUT /api/v4/commands/{command_id}/regen_token выдаёт новый токен.
Запрос, который получает ваш сервис
Команда POST отправляет тело запроса в формате формы (application/x-www-form-urlencoded); команда GET передаёт те же поля в строке запроса. Токен также находится в заголовке Authorization: Token <token>.
| Поле | Значение |
|---|---|
token | Токен команды. Проверяйте его при каждом запросе. |
command | Триггер с косой чертой, например /weather. |
text | Всё, что следует после триггера, например Paris. |
user_id, user_name | Кто выполнил команду. |
channel_id, channel_name | Где она была выполнена. |
team_id, team_domain | Идентификатор и URL-имя рабочего пространства. |
root_id | Обсуждение, если команда была выполнена в поле ответа к обсуждению. |
trigger_id | Позволяет вашему ответу открыть диалог (см. Диалоги). Действительно только в течение короткого времени. |
response_url | URL для отправки дополнительных ответов позже (см. Отложенные ответы). |
user_mentions, user_mentions_ids, channel_mentions, channel_mentions_ids | Люди и публичные каналы, упомянутые в тексте, если таковые имеются. Каналы учитываются независимо от того, записаны они как #channel-name или ~channel-name. |
response_url на его основе.Ответ
Ответьте 200 с JSON (Content-Type: application/json):
{
"response_type": "in_channel",
"text": "Paris: 18 °C, light rain",
"attachments": []
}
| Поле | Значение |
|---|---|
response_type | ephemeral (по умолчанию): ответ видит только тот, кто выполнил команду, и он не сохраняется после перезагрузки. in_channel: ответ публикуется в канале. |
text, attachments | Сообщение, как для вебхуков: текст в формате Markdown и вложения, включая кнопки и меню. |
username, icon_url | Имя и изображение для отображения, если разрешены переопределения. Настройки самой команды имеют приоритет над этими значениями. |
channel_id | Опубликовать ответ в другом канале, участником которого должен быть пользователь. |
goto_location | URL для открытия после выполнения команды. |
props, type | Дополнительные свойства и пользовательский тип сообщения, как для вебхуков. |
extra_responses | Дополнительные ответы, каждый с теми же полями, публикуемые после первого. |
skip_slack_parsing | true сохраняет текст как есть, без преобразования ссылок и упоминаний в стиле Slack. |
Ответ, не являющийся JSON, отображается как временное сообщение с телом ответа в качестве текста. 204 No Content ничего не отображает. Любой статус вне диапазона 200–299 показывает пользователю ошибку.
Пример сервиса
Минимальный сервис команды на Python, использующий только стандартную библиотеку:
import hmac
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs
TOKEN = "the token shown when you saved the command"
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
body = self.rfile.read(int(self.headers["Content-Length"])).decode()
form = {key: values[0] for key, values in parse_qs(body).items()}
if not hmac.compare_digest(form.get("token", ""), TOKEN):
self.send_response(401)
self.end_headers()
return
answer = {
"response_type": "ephemeral",
"text": f"Hello @{form['user_name']}, you asked for: {form.get('text', '')}",
}
data = json.dumps(answer).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(data)
HTTPServer(("0.0.0.0", 8080), Handler).serve_forever()
Если служба работает по адресу в частной сети, системный администратор должен разрешить её в Разрешить недоверенные внутренние соединения для (ServiceSettings.AllowedUntrustedInternalConnections).
Отложенные ответы
Для задач, которые выполняются дольше, чем время ожидания, сразу отправьте ответ (например, временное сообщение «Работаю над этим…»), а затем отправьте реальный ответ методом POST на response_url. Он принимает тот же JSON, что и обычный ответ, и может быть использован до 5 раз в течение 30 минут после выполнения команды.
curl -X POST "$RESPONSE_URL" -H 'Content-Type: application/json' \
-d '{"response_type": "in_channel", "text": "Report ready: https://reports.example.com/42"}'
Выполнение команды через API
Скрипты и боты могут выполнять любую команду, встроенную или пользовательскую, как если бы они ввели её вручную:
curl -X POST https://chat.example.com/api/v4/commands/execute \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"channel_id": "'$CHANNEL_ID'", "command": "/weather Paris"}'
GET /api/v4/teams/{team_id}/commands/autocomplete возвращает список команд, которые пользователи могут ввести с автодополнением в сообществе.
Автодополнение
Команды, созданные на страницах интеграций, автодополняются с их триггером, подсказкой и описанием. Команды, зарегистрированные приложениями, могут подробно описывать свои подкоманды и аргументы с помощью AutocompleteData, начиная с model.NewAutocompleteData(trigger, hint, helpText):
AddCommand(sub)добавляет подкоманду, которая сама являетсяAutocompleteData.AddTextArgument(helpText, hint, pattern)добавляет аргумент свободного текста.AddStaticListArgument(helpText, required, items)предлагает фиксированный списокAutocompleteListItem{Item, Hint, HelpText}.AddDynamicListArgument(helpText, url, required)запрашивает у вашего приложения предложения по мере ввода текста. URL — это маршрут вашего приложения, например/plugins/com.example.weather/cities. Он получает данные о пользователе, канале и сообществе и возвращает JSON-список{"Item", "Hint", "HelpText"}.
Варианты Named… (AddNamedTextArgument и другие) добавляют флаги вида --name value. Оба веб-интерфейса отображают эти подсказки.
Пока кто-то вводит команду, Fusion отображает команду и каждый из её аргументов в виде блока, при этом вводимый аргумент подсвечивается вместе с текстом справки. Аргументы берутся из AutocompleteData или, если его нет, из подсказки: в подсказке вида @[username]... #[channel] слова, начинающиеся с @, относятся к аргументу «люди», а слова, начинающиеся с #, — к аргументу «каналы», вне зависимости от их порядка; ... означает, что аргумент повторяется, а последний аргумент принимает остальной текст.
Каналы в аргументах
В аргументах команды @ предлагает людей, # предлагает каналы и дополняет их в виде #channel-name, а ~ — в виде ~channel-name. Веб-интерфейс и мобильное приложение Antimatter пишут ссылки на каналы с #, поэтому команда, принимающая канал, должна поддерживать обе формы: встроенные /join, /mute и /invite это делают, а их подсказки содержат #[channel].