@crvouga/mockingbird-service-slack (英语)
本地模拟器。 真正的API合同. 部分 嘲笑鸟。 。 。 .
状态模拟器 偷懒 测试套件: 接通的webhooks, Web API 使用我们的应用程序
和 Socket 模式控制平面 Bolt 需要启动,带有 发件箱 联 合 国
一切的应用"同意"。 一个套房声称,一个警报响起
(单位:千美元)GET /__admin/outbox?webhook=… 或者说 ?channel=…没有真正的工作空间,并驱动
重试路径( 429 为) retry-after, 5xx)和终端设备(no_text, (中文(简体) ), no_service, (中文(简体) ),
channel_not_found) 有命名预设.
- 行动范围: 支助
- Slack没有为这些方法发布维护的OpenAPI:合同(
openapi.yaml)为 手写自Slack记录的线形 和我们的消费者.
安装
npm install -D @crvouga/mockingbird-service-slack
仅限无害环境管理。 节点 22或 Bun 1.2. 无土生属地. 给它服务
npx mockingbird-slack serve, (中文(简体) ), createServer 从 ./server (节点),或 createRuntime 与
任何获取服务器.
使用量
点数每 SLACK_*_WEBHOOK_URL (单位:千美元)SLACK_PIPELINE_ALERT_WEBHOOK_URL, (中文(简体) ),
SLACK_ERX_ALERTS_WEBHOOK_URL, (中文(简体) ), SLACK_BILLING_ALERT_WEBHOOK_URL, (中文(简体) ),
SLACK_CRITICAL_ALERT_WEBHOOK_URL, (中文(简体) ), RECONCILER_SLACK_WEBHOOK_URL,(...)时
http://127.0.0.1:8808/services/T000/B000/<anything>。任何路径都被接受,直到您注册
钩子. 网络 API 调用硬码 https://slack.com/api/…; 指向它们
http://127.0.0.1:8808/api/… (计: @slack/web-api, (中文(简体) ), slackApiUrl: "http://127.0.0.1:8808/api/") (中文(简体) ).
套接字模式中的 Bolt 使用相同 clientOptions.slackApiUrl (复制到
SocketModeReceiver加上一个 xapp- 应用标志. apps.connections.open 返回 a ws:// 網址
有关这一进程.
npx mockingbird-slack serve --port 8808
import { IncomingWebhook } from "@slack/webhook"
import { WebClient } from "@slack/web-api"
import { createServer } from "@crvouga/mockingbird-service-slack/server"
const server = await createServer()
// The app's own Slack clients. Only the URLs they are given change.
const webhook = new IncomingWebhook(`${server.url}/services/T000/B000/XXXX`)
await webhook.send({ text: "reconcile failed", blocks: [{ type: "divider" }] }) // { text: "ok" }
const slack = new WebClient("xoxb-fixture", { slackApiUrl: `${server.url}/api/` })
await slack.chat.postMessage({ channel: "#alerts", text: "deploy finished" }) // { ok: true, ts, … }
// Test controls. Make the next post fail the way Slack does under load; our clients retry at 0/2/8 s.
server.runtime.applyPreset("rate_limited", "default", { count: 1 })
const outbox = await fetch(`${server.url}/__admin/outbox?webhook=/services/T000/B000/XXXX`)
// { messages: [{ text: "reconcile failed", blocks: [...], ts: "1700000000.000001", thread_ts: null, … }] }
await server.close()
路线
| 路线 | 行为 |
|---|---|
POST /services/{T}/{B}/{X} | 来来来来来来来来来来来来来来来来来来来来来去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去去 贾森 {text, blocks?, attachments?, thread_ts?} (或形式) payload=<json>页:1 200 ok (文本/说明). 400 invalid_payload (不是JSON的对象), 400 no_text (无文本、块或附件), 400 invalid_blocks (结构与块 Kit 限制,也在内) attachments[].blocks;见下文, 400 too_many_attachments, (中文(简体) ), 404 no_service (未注册的钩子,一旦注册任何钩子), 404 channel_not_found, (中文(简体) ), 410 channel_is_archived。 。 。 . |
POST /api/chat.postMessage | {channel, text?, blocks?, attachments?, thread_ts?, unfurl_links?} → {ok, channel, ts, message}。 。 。 . channel 是一个id或 #name; 除非 strictChannels。收发箱保存 text, (中文(简体) ), blocks, (中文(简体) ), unfurl_links, (中文(简体) ), thread_ts,以及 workspace (团队编号). 错误 : channel_not_found, (中文(简体) ), no_text, (中文(简体) ), invalid_blocks, (中文(简体) ), invalid_blocks_format, (中文(简体) ), msg_too_long, (中文(简体) ), is_archived。 。 。 . |
POST /api/chat.update | {channel, ts, text?, blocks?} → {ok, channel, ts, text, message} 与 edited· ; message_not_found, (中文(简体) ), cant_update_message (网易新闻). 封口区块被保留. |
POST /api/chat.postEphemeral | {channel, user, text} → {ok, message_ts}· ; user_not_found。在收发箱中录入 ephemeral: true。 。 。 . |
GET|POST /api/chat.getPermalink | channel, (中文(简体) ), message_ts → {ok, channel, permalink} (单位:千美元)https://<domain>.slack.com/archives/C…/p…(三); message_not_found。 。 。 . |
POST /api/reactions.add, (中文(简体) ), /reactions.remove, (中文(简体) ), GET|POST /api/reactions.get | 每个消息( E)channel, (中文(简体) ), timestamp, (中文(简体) ), name(三); already_reacted, (中文(简体) ), no_reaction, (中文(简体) ), message_not_found, (中文(简体) ), no_item_specified。 。 。 . reactions.get 答题 {ok, type: "message", channel, message} 与 reactions[{name, users, count}]。 。 。 . |
GET|POST /api/auth.test | {ok, url, team, user, team_id, user_id, bot_id} 从工作空间设置. |
POST /api/conversations.join | {ok, channel};已经是成员 warning: "already_in_channel"· ; method_not_supported_for_channel_type (非公开), is_archived。 。 。 . |
GET|POST /api/users.info, (中文(简体) ), /users.lookupByEmail | {ok, user} 与 profile.email编号 :real_name· ; user_not_found, (中文(简体) ), users_not_found种子: U0ADA (单位:千美元)[email protected])和那个机器人. |
GET|POST /api/files.info | {ok, file} 与 url_private_download 打开 files.slack.com· ; file_not_found种子: F0REPORT。 。 。 . |
POST /api/views.open | {trigger_id, view} → {ok, view: {id: "V…", hash, state, …}}· ; invalid_arguments。 。 。 . |
POST /api/apps.connections.open | Authorization: Bearer xapp-… (只有标题) {ok, url} 地点 url 实值 ws://<this host>/link/?ticket=…&app_id=…,每张票一张WebSocket;第二次升级或关闭票被拒绝. 丢失的代号 = not_authed; 机器人符号 not_allowed_token_type; 畸形 − invalid_auth; 一个符号 revokedAppTokens → token_revoked; 一个不在此命名空间中的应用符号 appTokens (当清单是非空的) invalid_auth。 。 。 . |
网络安全套 /link/?ticket= | 升级时,一个JSON hello (单位:千美元)type, (中文(简体) ), connection_info.app_id, (中文(简体) ), num_connections, (中文(简体) ), debug_info.approximate_connection_time) (中文(简体) ). 没有推动任何事件。 客户端乒乓球被打平;服务器每2个打平. {envelope_id} 阿克被接受而不回答. disconnect 理由 warning, (中文(简体) ), refresh_requested,以及 link_disabled 匹配 Slack 的信封( 没有重新连接 URL : @slack/[email protected] 电话 apps.connections.open - 再来一次). |
Web API 机构可以是 JSON 或形式编码(结构为 JSON- 以形式字段编码), 如 Slack
接受两者;读取方法也采用查询参数。 认证是 Authorization: Bearer xox… (或 a 个)
token 表单字段: 缺少 {} not_authed除了一个 xoxb-编号 :xoxp-编号 :xoxa- 符号(或
一个在外面 settings.tokens页:1 invalid_auth。逻辑错误为 HTTP 200 {ok: false, error}· ;
a JSON员额无 charset 成功与斯莱克 missing_charset 警告 警告他们.
管理员(超过标准合同)
| 路线 | 效果 |
|---|---|
GET /__admin/outbox?webhook=<path>&channel=<id|#name>&thread_ts=&source=webhook|api&since=&limit= | 每一个消息,最古老的第一: text, (中文(简体) ), blocks, (中文(简体) ), attachments, (中文(简体) ), thread_ts, (中文(简体) ), ts, (中文(简体) ), channel, (中文(简体) ), webhook, (中文(简体) ), method, (中文(简体) ), ephemeral, (中文(简体) ), edited, (中文(简体) ), reactions, (中文(简体) ), unfurl_links, (中文(简体) ), workspace。 。 。 . webhook 带 /services/T/B/X, (中文(简体) ), T/B/X 或一个完整的URL. GET /__admin/outbox/:id 读取一个. |
POST /__admin/hooks | {path, channel?} 或者说 {hooks: [...]}: 注册webhooks(并把它们引导到一个频道). 一旦任何钩子存在,未知钩子就会回答 404 no_service。 。 。 . GET 清单, DELETE [?path=] 移除. |
POST /__admin/channels, (中文(简体) ), /users, (中文(简体) ), /files | 种子工作空间记录{id?, name, is_private?, is_archived?, is_member?}, (中文(简体) ), {id, name?, real_name?, email?}, (中文(简体) ), {id, name?, mimetype?, size?}) (中文(简体) ). GET /__admin/channels, (中文(简体) ), /users, (中文(简体) ), /views 列出它们. |
PUT /__admin/settings | {teamId?, teamName?, teamDomain?, botUserId?, botId?, appId?, tokens?, appTokens?, revokedAppTokens?, socketLifetimeMs?, strictChannels?} 呼叫的命名空间. socketLifetimeMs 关闭打开的 Socket 模式连接 reason: "warning"。 。 。 . |
GET /__admin/socket/connections | 打开并关闭调用命名空间的 Socket 模式套接字 : namespace, (中文(简体) ), appId, (中文(简体) ), ticket, (中文(简体) ), connectedAt, (中文(简体) ), state, (中文(简体) ), reconnectCount永远不给任何标志. |
POST /__admin/socket/disconnect | {reason?: "warning"|"refresh_requested"|"link_disabled", code?: 1000}。发送Slack的 disconnect 信封,然后关闭. code: 1006 放弃 TCP 连接. |
错误预设( E)POST /__admin/faults {"preset": "<name>", "count"?: n, "params"?: {...}}:
| 预设 | 效果 |
|---|---|
rate_limited | 网络呼号 429 rate_limited,网络 API 429 {ok: false, error: "ratelimited"},两者 retry-after (单位:千美元)params.retryAfter,默认值 1 s). |
5xx | 500 internal_error 各地(params.status: 503 给 service_unavailable) (中文(简体) ). |
service_unavailable | 503 service_unavailable 到处都是. |
channel_not_found | 网络呼号 404 channel_not_found; Web API 频道方法 {ok: false, error: "channel_not_found"}。 。 。 . |
no_service | 网络呼号 404 no_service (被吊销的钩子). |
invalid_auth | 网络 API {ok: false, error: "invalid_auth"} (被撤销的令牌). |
connections_open_invalid_auth | apps.connections.open 答题 {ok:false, error:"invalid_auth"} 和薄荷没有票. |
connections_open_429 | apps.connections.open 答题 429 {ok:false, error:"ratelimited"} 与 retry-after (单位:千美元)params.retryAfter,默认值 1. |
connections_open_5xx | apps.connections.open 答题 500 internal_error (单位:千美元)params.status: 503 给 service_unavailable) (中文(简体) ). |
socket_close_after_hello | 下一个套接字模式套接字发送 hello,然后是正常的关闭. |
socket_abnormal_close | 下一个套接字模式套接字发送 hello,然后放弃连接(代码1006). |
socket_hello_latency | 延迟 hello 以 params.latencyMs 毫秒长. HTTP 响应本身没有被延迟. |
命名空间
x-mockingbird-namespace页:1 /__admin/ns/<name> 在 Webhook URL 或 API 基础上,或由
证书 : PUT /__admin/credentials {"credentials": {"xoxb-worker-a": "a", "T000/B000/XXXX": "b"}}
绘制一个bot 令牌或 webhook 的 T/B/X 用于命名空间的路径.
故意不模拟
- 入境事件 API和交互提供. 套接字模式的连接寿命周期是
模拟(
apps.connections.open, (中文(简体) ),hello乒乓球 乒乓球,disconnect所以博尔特可以启动和 关闭; 模拟器不会在连接上推动事件 。 A 类disconnect信封没有 重新连接 URL, 匹配 Slack 的文件形状和@slack/[email protected],哪个 电话apps.connections.open再来一次. - 文件上传和下载 :
files.info答案种子元数据files.slack.comURL( URL) 未送达. - 实际按方法计算的费率限制等级:429次只来自
rate_limited预设. - 公布的会员规则
not_in_channel, (中文(简体) ),chat:write.public范围,以及 触发编号过期views.open。 。 。 . - 信件格式化( mrkdwn 解析、 链接解析、 提及解析): 文本和块是 储存的逐字记录.
- 块 Kit 的限制是 a 最好猜,不是甲骨文验证 (从每个区块的页面)
docs.slack.dev; 每项规则的确切状态和消息Slack返回从未被观察到
现场直播).
blocks和每个attachments[].blocks以invalid_blocks(网页:400 invalid_blocks· ;chat.postMessage, (中文(简体) ),chat.update, (中文(简体) ),chat.postEphemeral数字 :200 {ok: false, error: "invalid_blocks", response_metadata: {messages}},消息是模拟者自己的措辞) 当: 有超过50个块( 在每个阵列中; Slack 是否应用了 50 个内部附件 ) 未经证实)type不是块 Kit 类型; asectiontext超过3000 字符或该字符fields每个超过10件或2000个字符;aheadertext没有plain_text或超过150个字符;context超过10个elements或者说actions25岁以上;ablock_id超过 255 个字符;文本对象为空。 完全限值被接受 并且已逐字存储,被否决的消息则不保存任何信息(更新后留下原件) 然无所动. 必要领域规则(a)section没有text也没有fields,一个image无alt_text),内部元素级验证actions编号 :context编号 :input编号 :rich_text, (中文(简体) ), 其它附件字段没有建模.
API 密码
| 导出 | 仁爱 | 说明 |
|---|---|---|
SlackAPI | 类 | 进程模拟器 : fetch(request), (中文(简体) ), reset(), (中文(简体) ), messages(), (中文(简体) ), state选项: sqlite, (中文(简体) ), now, (中文(简体) ), namespace, (中文(简体) ), settings。 。 。 . |
createRuntime | 函数 | 全面服务合同的仿真器(保健、管理、发包箱、命名空间、证书、预设)。 选项 : settings, (中文(简体) ), clock, (中文(简体) ), seed, (中文(简体) ), adminKey, (中文(简体) ), onLog, (中文(简体) ), sqlite。 。 。 . |
SLACK_PRESETS | 对象 | 每个命名的断层预设. |
SLACK_NAMESPACE | 字符串 | 服务名称, "slack"。 。 。 . |
slackCredential | 函数 | 无记名符号,或者网钩 T/B/X 路径(如何将证书映射到命名空间). |
DEFAULT_SETTINGS, (中文(简体) ), DEFAULT_CHANNELS, (中文(简体) ), DEFAULT_USERS, (中文(简体) ), DEFAULT_FILES | 数值 | 种子工作空间. |
document, (中文(简体) ), operationIds, (中文(简体) ), supportedOperationIds | 数值 | 销售商为OpenAPI合同及其业务代号. |
createServer, (中文(简体) ), serveTarget, (中文(简体) ), DEFAULT_PORT (单位:千美元)./server(中文(简体) ) | 节点 | 服务过来 node:http; 数据 serve CLI目标; 第8808口. |
部分 嘲笑鸟。 。 。 .