スラッシュコマンド
カスタムスラッシュコマンドを使用すると、メッセージ入力欄に/somethingと入力してサービスを呼び出すことができます。AntimatterはコマンドをURLに送信し、応答をそのユーザー本人のみに表示するか、チャンネル全体に表示するかを選択できます。
スラッシュコマンドの動作
- ユーザーが
/weather Parisと入力して送信します。テキストは投稿されません。 - Antimatterは、コマンドのURLにHTTPリクエストを送信します。リクエストには、入力したユーザー、場所、トリガー文字列の後のテキストが含まれます。
- サービスは、リクエストのタイムアウト(デフォルトは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"} を送信します。method は POST の場合は P、GET の場合は G です。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 | ワークスペースの ID と URL 名。 |
root_id | スレッドの返信欄で実行された場合のスレッド。 |
trigger_id | 応答でダイアログを開くことを可能にします (ダイアログ を参照)。有効期間は短時間のみです。 |
response_url | 後でさらに応答を投稿するための URL (遅延応答 を参照)。 |
user_mentions, user_mentions_ids, channel_mentions, channel_mentions_ids | テキスト内で言及されているユーザーと公開チャンネル。チャンネルは#channel-nameまたは~channel-nameのいずれかの形式で記述されている場合もカウントされます。 |
response_urlを構築します。応答
JSON (Content-Type: application/json) で 200 を返します:
{
"response_type": "in_channel",
"text": "Paris: 18 °C, light rain",
"attachments": []
}
| フィールド | 意味 |
|---|---|
response_type | ephemeral (デフォルト): コマンドを実行したユーザーのみ応答を確認でき、リロード後は保持されません。in_channel: 応答がチャンネルに投稿されます。 |
text, attachments | メッセージ。Webhook と同様に、Markdown テキストと 添付ファイル、ボタン、メニューを含みます。 |
username, icon_url | オーバーライドが許可されている場合に表示する名前と画像。コマンド自身の設定が優先されます。 |
channel_id | 応答を別のチャンネルに投稿します。そのユーザーはメンバーである必要があります。 |
goto_location | コマンド実行後に開く URL。 |
props, type | Webhook と同様に、追加プロパティとカスタム投稿タイプ。 |
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)でそれを許可する必要があります。
遅延応答
タイムアウトを超える時間がかかる作業については、まず即座に応答します(例:一時的な「処理中です…」)。その後、実際の応答を response_url に POST します。応答と同じ JSON を受け取り、コマンドから 30 分以内に最大 5 回まで機能します。
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のようになります。ユーザー、チャンネル、コミュニティを受け取り、{"Item", "Hint", "HelpText"}の JSON リストを返します。
Named… 系の変種(AddNamedTextArgument など)は --name value フラグを追加します。これらの候補は、両方の Web インターフェースに表示されます。
コマンドを入力している間、Fusionはコマンドとその各引数をブロックとして表示し、入力中のブロックにはヘルプテキストを表示してハイライトします。引数はAutocompleteDataから取得され、それが存在しない場合はヒントから取得されます。@[username]... #[channel]のようなヒントでは、@で始まる単語はユーザー引数に、#で始まる単語はチャンネル引数に割り当てられ、順序は問いません。...は引数が繰り返し可能であることを示し、最後の引数は残りのテキストを受け取ります。
引数内のチャンネル
コマンドの引数では、@はユーザーを、#はチャンネルを提案し#channel-nameとして補完し、~は~channel-nameとして補完します。AntimatterのWebインターフェースとモバイルアプリは#を使用してチャンネルリンクを記述するため、チャンネルを受け取るコマンドは両方の形式を受け入れる必要があります。組み込みの/join、/mute、/inviteはこれに対応しており、そのヒントは#[channel]となっています。