简聊聚合服务代码与文档
-
images/
所有图片文件保存地址,包括每个服务的图标和教程截图,图标以服务名@2x.png
形式命名,教程以服务名-序号.png
形式命名 -
manuals/
所有服务的文字教程地址,每个服务都配有中英文教程,以服务名-语言.md
形式命名,使用 Markdown 格式编写。教程中引用的文件地址以绝对路径表示,如/images/inte-guide/jenkins-1.png
-
src/
源代码目录,每个服务的业务逻辑代码保存在src/services/服务名.coffee
中 -
test/
测试代码目录,每个服务的测试代码保存在test/services/服务名.coffee
中,另有一级子目录test/services/服务名_assets
用于保存每个服务的模拟数据
- 每个服务都需要在代码中配置相关名称,模板,描述等,例如
incoming.coffee
文件中定义的Incoming Webhook
服务
util = require '../util'
module.exports = ->
# 服务标题,可使用中文名
@title = 'Incoming Webhook'
# 服务模板,大部分服务都以 webhook 形式接入简聊,可直接使用 webhook 模板
@template = 'webhook'
# 每个服务的简要描述,显示在聚合列表中,需中英文版本
@summary = util.i18n
zh: 'Incoming Webhook 是使用普通的 HTTP 请求与 JSON 数据从外部向简聊发送消息的简单方案。'
en: 'Incoming Webhook makes use of normal HTTP requests with a JSON payload.'
# 每个服务的详细描述,显示在配置页面中,需中英文版本
@description = util.i18n
zh: 'Incoming Webhook 是使用普通的 HTTP 请求与 JSON 数据从外部向简聊发送消息的简单方案。你可以将 Webook 地址复制到第三方服务,通过简单配置来自定义收取相应的推送消息。'
en: 'Incoming Webhook makes use of normal HTTP requests with a JSON payload. Copy your webhook address to third-party services to configure push notifications.'
# 服务图标,同为绝对路径表示
@iconUrl = util.static 'images/icons/incoming@2x.png'
# 服务需增加的额外字段,如果使用 webhook 模板,需增加 webhookUrl 字段及对应的字段描述
@_fields.push
key: 'webhookUrl'
type: 'text'
readOnly: true
description: util.i18n
zh: '复制 web hook 地址到你的应用中来启用 Incoming Webhook。'
en: 'To start using incoming webhook, copy this url to your application'
# 监听服务事件,处理业务逻辑
@registerEvent 'service.webhook', _receiveWebhook
- 监听事件后,可编写相应的业务逻辑代码,例如监听
service.webhook
事件,当收到来自第三方服务的 webhook 请求时,会将请求体作为参数传入事件的处理方法中
_receiveWebhook = ({query, body}) ->
# 读取请求中的 query, body 对象
payload = _.assign {}
, query or {}
, body or {}
{content, authorName, title, text, redirectUrl, imageUrl} = payload
throw new Error("Title and text can not be empty") unless title?.length or text?.length or content?.length
# 将请求组合成 message 对象
message =
body: content
authorName: authorName
displayType: payload.displayType
# message 对象可以添加附件属性
if title or text or redirectUrl or imageUrl
message.attachments = [
category: 'quote'
data:
title: title
text: text
redirectUrl: redirectUrl
imageUrl: imageUrl
]
# 在方法最后返回 message 对象,API 将此对象包装后推送给客户端
# 如果方法中返回 null, false, undefined,API 将忽略这次请求而不推送任何消息
message
- 支持的事件列表
事件名 | 事件处理方法参数 | 需要的返回值 | 描述 |
---|---|---|---|
integration.create |
包含 integration 属性的 req 对象 |
创建聚合后触发 | |
integration.update |
包含 integration 属性的 req 对象 |
更新聚合后触发 | |
integration.remove |
包含 integration 属性的 req 对象 |
删除聚合后出发 | |
service.webhook |
req 对象 |
如返回 message 对象,则推送消息到客户端 | 当收到 webhook 请求时触发 |
before.integration.create |
包含 integration 属性的 req 对象 |
创建聚合前触发 | |
before.integration.update |
包含 integration 属性的 req 对象 |
更新聚合前触发 | |
before.integration.remove |
包含 integration 属性的 req 对象 |
删除聚合前触发 | |
message.create |
包含 message 属性的 req 对象 |
如返回 message 对象,会发送一条回复消息给消息来源方 | 新消息时触发 |
- 每个服务需要有对应的测试代码,大部分代码可用模拟数据测试,如测试 incoming webhook
should = require 'should'
Promise = require 'bluebird'
loader = require '../../src/loader' # 加载 loader
{req} = require '../util' # 从 util 中取得模拟的 req 对象
$incoming = loader.load 'incoming' # 从 loader 加载对应服务
describe 'Incoming#Webhook', ->
it 'receive webhook', (done) ->
# 模拟 webhook 请求结构体
req.body =
authorName: '路人甲'
title: '你好'
text: '天气不错'
redirectUrl: 'https://jianliao.com/site'
imageUrl: 'https://dn-talk.oss.aliyuncs.com/site/images/workspace-84060cfd.jpg'
$incoming.then (incoming) ->
# 触发 service.webhook 事件
incoming.receiveEvent 'service.webhook', req
.then (message) ->
# 检测返回结果是否正确
message.should.have.properties 'authorName'
message.attachments[0].data.should.have.properties 'title', 'text', 'redirectUrl', 'imageUrl'
.nodeify done