斜杠命令

自定义斜杠命令允许用户在消息框中输入 /something 来调用您的服务。Antimatter 会将命令发送到您的 URL,并显示您的回复,该回复仅对该用户可见,或对整个频道可见。

斜杠命令的工作原理

  1. 某人输入 /weather Paris 并发送。该文本不会被发布。
  2. Antimatter 向命令的 URL 发送 HTTP 请求,包含输入者、位置以及触发词后的文本。
  3. 您的服务在请求超时时间内(默认为 30 秒)以消息形式回复。
  4. Antimatter 显示回复:仅对该用户可见(临时回复)或在频道内对所有人可见。

命令属于某个社区,且触发词在该社区内是唯一的。内置命令(如 /join、/msg 或 /away)无法被替换。应用(插件)也可以注册命令;请参阅 服务器部分。

创建命令

自定义斜杠命令默认开启(位于 系统控制台 › 集成 › 集成管理 中的 启用自定义斜杠命令,ServiceSettings.EnableCommands)。社区管理员和系统管理员默认可以创建它们。

  1. 打开右上角的头像,然后选择 集成 › 斜杠命令,接着选择 添加斜杠命令。
  2. 填写 标题 和 描述(显示在集成页面上)。
  3. 输入 命令触发词,不带斜杠且不含空格,例如 weather。
  4. 输入请求 URL,并选择请求方式:POST(默认)或 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工作区的 ID 和 URL 名称。
root_id话题,当命令在话题的回复框中执行时。
trigger_id允许您的回复打开对话框(参见 对话框)。它仅在短时间内有效。
response_url用于稍后发布更多回复的 URL(参见 延迟回复)。
user_mentions, user_mentions_ids, channel_mentions, channel_mentions_ids文本中提及的人员和公共频道(如有)。无论频道是以 #channel-name 还是 ~channel-name 的形式书写,均计入在内。
必须设置服务器的 站点 URL 才能运行自定义命令:Antimatter 会基于它构建 response_url。

响应

使用 JSON 返回 200(Content-Type: application/json):

{
  "response_type": "in_channel",
  "text": "Paris: 18 °C, light rain",
  "attachments": []
}
字段含义
response_typeephemeral(默认值):只有执行命令的人能看到回复,且刷新后不会保留。in_channel:回复将发布在频道中。
text, attachments消息内容,与 Webhook 相同:Markdown 文本和 附件,包括按钮和菜单。
username, icon_url要显示的名称和图片(如果允许覆盖)。命令自身的设置优先于这些设置。
channel_id将回复发布到另一个频道,执行者必须是该频道的成员。
goto_location命令执行完毕后要打开的 URL。
props, type额外属性和自定义帖子类型,与 Webhook 相同。
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,并且可以在命令执行后的 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。它接收用户、频道和社区信息,并返回一个 JSON 列表,包含 {"Item", "Hint", "HelpText"}。

Named… 变体(如 AddNamedTextArgument 等)用于添加 --name value 标志。两种 Web 界面都会显示这些建议。

当有人输入命令时,Fusion 会将命令及其每个参数显示为独立的块,当前正在输入的块会高亮显示并附带帮助文本。参数来自 AutocompleteData,若没有该数据,则来自提示符:在类似 @[username]... #[channel] 的提示符中,以 @ 开头的词归入人员参数,以 # 开头的词归入频道参数,顺序不限;... 表示该参数可重复,最后一个参数接收剩余文本。

参数中的频道

在命令参数中,@ 用于建议人员,# 用于建议频道并补全为 #channel-name,~ 则补全为 ~channel-name。Antimatter 的 Web 界面和移动应用使用 # 来书写频道链接,因此接收频道的命令应同时支持这两种形式:内置的 /join、/mute 和 /invite 命令均支持,且它们的提示符显示为 #[channel]。