Команди зі скісною рискою

Користувацька команда зі скісною рискою дозволяє користувачам вводити /щось у полі повідомлення, щоб викликати ваш сервіс. Antimatter надсилає команду на ваш URL і відображає вашу відповідь — або лише для цієї людини, або для всього каналу.

Як працює команда зі скісною рискою

  1. Хтось вводить /weather Paris і надсилає. Текст не публікується.
  2. Antimatter надсилає HTTP-запит на URL команди, вказуючи, хто її ввів, де саме, і текст після тригера.
  3. Ваш сервіс відповідає повідомленням у межах часу очікування запиту (за замовчуванням — 30 секунд).
  4. Antimatter відображає відповідь: лише для цієї людини (тимчасово) або в каналі для всіх.

Команди належать до спільноти, і слово-тригер є унікальним у межах цієї спільноти. Вбудовані команди, такі як /join, /msg або /away, не можна замінити. Додатки (плагіни) також можуть реєструвати команди; див. Серверну частину.

Створення команди

Користувацькі команди зі скісною рискою ввімкнені за замовчуванням (Увімкнути користувацькі швидкі команди у Системна консоль › Інтеграції › Управління інтеграцією, ServiceSettings.EnableCommands). Адміністратори спільноти та адміністратори системи можуть створювати їх за замовчуванням.

  1. Натисніть на свій аватар у правому верхньому куті, потім Інтеграції › Швидкі команди, а далі Додати швидку команду.
  2. Заповніть Назву та Опис (відображаються на сторінках інтеграцій).
  3. Введіть Ключове слово без скісної риски та пробілів, наприклад weather.
  4. Введіть URL-адресу запиту та оберіть Метод запиту: ДОПИС (за замовчуванням) або GET.
  5. За бажанням встановіть Ім'я користувача для відповіді та Піктограму відповіді. Вони використовуються лише тоді, коли сервер дозволяє інтеграціям замінювати імена та піктограми (див. Ім'я та піктограма).
  6. Позначте Автозаповнення, щоб команда відображалася у списку, коли користувачі вводять /, разом із Підказкою про автозаповнення (її аргументами, наприклад [city]) та Описом автозаповнення.
  7. Оберіть Зберегти та скопіюйте відображений токен. Ваш сервіс використовує його, щоб перевіряти, що запити надходять з вашого сервера.

Через 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_urlURL для надсилання додаткових відповідей пізніше (див. Відкладені відповіді).
user_mentions, user_mentions_ids, channel_mentions, channel_mentions_idsУчасники та відкриті канали, згадані в тексті, якщо такі є. Канали враховуються незалежно від того, чи записані вони як #channel-name або ~channel-name.
: URL-адреса сайту сервера має бути встановлена, щоб користувацькі команди працювали: Antimatter формує response_url на її основі.

Відповідь

Відповідайте 200 із JSON (Content-Type: application/json):

{
  "response_type": "in_channel",
  "text": "Paris: 18 °C, light rain",
  "attachments": []
}
ПолеЗначення
response_typeephemeral (типово): лише людина, яка виконала команду, бачить відповідь, і вона не зберігається після оновлення сторінки. in_channel: відповідь публікується в каналі.
text, attachmentsПовідомлення, як для вебхуків: текст у Markdown та вкладення, включно з кнопками та меню.
username, icon_urlІм'я та зображення для відображення, якщо дозволено перевизначення. Власні налаштування команди мають пріоритет над цими значеннями.
channel_idПублікуйте відповідь в іншому каналі, учасником якого має бути ця людина.
goto_locationURL, який відкривається після виконання команди.
props, typeДодаткові властивості та власний тип повідомлення, як для вебхуків.
extra_responsesДодаткові відповіді, кожна з тими самими полями, публікуються після першої.
skip_slack_parsingtrue зберігає текст без змін, не перетворюючи посилання та згадки у стилі 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].