-
Notifications
You must be signed in to change notification settings - Fork 10
Home
Welcome to the feishu-bot-webhook-action wiki!
边学边做,法力无边
飞书提供的官方github机器人是需要在企业版中,个人版本飞书下如何使用?利用飞书自定义机器人的webhook来实现一下对github仓库的信息变更的监控,同时利用github action的能力,省下对服务器的需求。
开放平台有官方文档自定义机器人使用指南
这里参考的操作为:
- 建立一个群组,在设置-> 群机器人 -> 添加机器人 -> 自定义机器人
- 点击自定义机器人,设置中获取它的 webhook地址
有了这个地址就可以在其他平台post消息到这个地址,实现发送任意信息。
curl -X POST -H "Content-Type: application/json" \
-d '{"msg_type":"text","content":{"text":"request example"}}' \
https://open.feishu.cn/open-apis/bot/v2/hook/****
到这里就可以在飞书群中观察到消息了。
github action 是可以实现CI/CD等各种workflow的,这里利用action来实现监控所有的事件。 比如监控 push, star 事件可以用以下的写法:
on:
push:
branch: [ "main" ]
watch:
types: [started]
这里是所有的 github 事件 github webhook events
由于是希望实现将github的event都发送到飞书中,直接在仓库的设置的webhook中填入机器人的地址是没法看到群内消息出现我们希望的内容的,因为github的消息格式不符合飞书的定义。所以我们需要做一下转换。
为了更加灵活,我们可以定制一个action,而不是直接在workflow的yaml文件中用curl命令来实现消息发送。
创建一个action 参考这里,用js方案来实现比较合适。 工程参考 https://github.com/actions/typescript-action
name: 'Github Events To Feishu Bot Action'
description: 'send message to feishu bot'
author: 'junka'
branding:
icon: 'cloud-snow'
color: 'blue'
inputs:
webhook:
description: 'feishu bot webhook url'
required: true
signkey:
description: 'set when you enable signature verify'
required: false
outputs:
code:
description: 'code from response'
runs:
using: 'node20'
main: 'dist/index.js'
其中input是我们需要配置的信息,通常是配置在secrects中,安装包依赖
npm install @actions/core
npm install @actions/github
我选择使用typescript,(前端门外汉,js/ts随便选了个)。在index.ts 中实现主要逻辑
import * as https from "https";
import * as core from "@actions/core";
import { context } from "@actions/github";
function PostToFeishu(id: string, content: string) {
var options = {
hostname: "open.feishu.cn",
port: 443,
path: `/open-apis/bot/v2/hook/${id}`,
method: "POST",
headers: {
"Content-Type": "application/json",
},
};
var req = https.request(options, (res) => {
res.on("data", (d) => {
process.stdout.write(d);
});
});
req.on("error", (e) => {
console.error(e);
});
req.write(content);
req.end();
}
function PostGithubEvent() {
const webhook = core.getInput("webhook")
? core.getInput("webhook")
: "https://open.feishu.cn/open-apis/bot/v2/hook/xxxx";//替换成你的机器人地址
const payload = context.payload || {}
console.log(payload)
const msg = `{"msg_type":"text","content":{"text":"msg lai le "}}'
PostToFeishu(webhookId, msg);
}
PostGithubEvent();
然后package.json 中配置编译和运行测试命令
"scripts": {
"build": "tsc && ncc build dist/index.js",
"run": "node ./dist/index.js",
ncc指令的意思和其他依赖参看创建一个action 然后在命令行中运行就可以看到消息了。
npm run build
npm run run
到这里的消息是没有签名的,建议开启,在机器人设置界面,可以开启后拷贝出来密钥。 在 https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot 这里有java/go/python的例子。 摸索了一下,用ts代码实现签名
import * as crypto from "crypto";
function sign_with_timestamp(timestamp: number, key: string): string {
const toencstr = `${timestamp}\n${key}`;
const signature = crypto.createHmac("SHA256", toencstr).digest("base64");
return signature;
}
...
function PostGithubEvent() {
...
const signKey = core.getInput("signkey") ? core.getInput("signkey") : "Xbxxxxxxxx";// 替换成你的key
const tm = Math.floor(Date.now() / 1000);//注意时间戳单位s
const sign = sign_with_timestamp(tm, signKey);
const msg = `{
"timestamp": "${tm}",
"sign": "${sign}",
"msg_type": "text",
"content":{"text":"msg lai le "}}`
PostToFeishu(webhookId, msg);
}
必须添加timestamp,sign两个字段,到这里就完成签名校验部分
到这里为止实际上我并没有发送真实有价值的event数据,因为本地不太好调试,我们可以在组织完成消息后再测试。
飞书提供了卡片消息,实现更美观的消息, 使用飞书卡片搭建工具来构建一个消息模板,比如下面的格式
其中有些字段是绑定的变量,发布卡片后可以用卡片id来包裹到我们的消息中去
const color = "blue";
const msg = `{
"timestamp": "${tm}",
"sign": "${sign}",
"msg_type": "interactive",
"card": {
"type": "template",
"data": {
"template_id": "AAqkaaaaaypMLb",
"template_version_name": "1.0.6",
"template_variable": {
"repo": "${repo}",
"eventType": "${eventType}",
"themeColor": "${color}",
"auser": "${actor}",
"avatar": "${avatar}",
"status": "${status}",
"etitle": "${etitle}",
"detailurl": "${detailurl}"
}
}
}
}`
PostToFeishu(webhookId, msg);
template_variable 的key就是我们飞书卡片配置好的变量,value就是我们可以从github包中获取的。 比如对push事件
import { context } from "@actions/github";
etitle = `Commits: ["${context.payload["head_commit"]["id"]}"]("${context.payload["compare"]}")`;
status = context.payload["created"] == true ? "created": (context.payload["forced"] == true? "force updated" : "");
detailurl = context.payload["compare"];
获取了commit号和compare页面信息,填入到对应的字段,后续点击查看详情就能跳转
之后提交代码,release的时可以同步发布到marketplace就可以在其他项目中使用。
估计其他机器人也差不多?由于自定义机器人不支持图片上传,虽然文档写支持,但其实需要一个带token的机器人应用才可以,所以没有实现avatar上传展示。后续考虑开发一个机器人应用而非使用自定义机器人。
代码实现参看,未完工 https://github.com/junka/feishu-bot-webhook-action
- 学习了github action的使用
- 学习了飞书机器人的配置,webhook的含义,签名的代码实现
- 学习了ts开发github action的流程,发布过程
- 学习了github toolkit开发包的使用
- 学习了下飞书机器人卡片消息的配置使用