Skip to content

Commit

Permalink
feat: 添加webhook相关调用方式
Browse files Browse the repository at this point in the history
  • Loading branch information
feilongproject committed Sep 15, 2024
1 parent a345b49 commit d8a8c70
Show file tree
Hide file tree
Showing 13 changed files with 936 additions and 15 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ QQ 机器人 SDK,基于 [官方 SDK](https://github.com/tencent-connect/bot-no
npm i qq-bot-sdk --registry=https://registry.npmjs.org
```

## 引用
## `webhook` 方式使用(新增)

详情请见 `example`[`webhook`](/example/webhook) 使用案例

## `websocket` 方式引用

> 可参见[example](/example)中样例
Expand All @@ -31,6 +35,10 @@ const ws = createWebsocket(testConfigWs); // 创建ws实例(用于接收消息

# 对比优化内容

## 新增 `webhook` 方式调用

详情请见 `example`[`webhook`](/example/webhook) 使用案例

## 新增群消息订阅事件

```js
Expand Down
5 changes: 4 additions & 1 deletion example/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// 以下仅为用法示意,详情请参照文档:https://bot.q.qq.com/wiki/develop/nodesdk/
/**
* 以下仅为用法示意,详情请参照文档:https://bot.q.qq.com/wiki/develop/nodesdk/
* 其中对官方逻辑扩展,添加了诸多功能,修复了许多问题
*/
const { createOpenAPI, createWebsocket, AvailableIntentsEventsEnum } = require('qq-bot-sdk');

const testConfigWs = {
Expand Down
25 changes: 16 additions & 9 deletions example/package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
{
"name": "example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"example": "node index.js"
},
"author": "",
"license": "ISC"
"name": "example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"example": "node index.js",
"example:webhook": "node webhook/index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"@types/koa-router": "^7.4.8",
"koa": "^2.15.3",
"koa-body": "^6.0.1",
"koa-router": "^13.0.1"
}
}
9 changes: 9 additions & 0 deletions example/webhook/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# 简介

基于官方文档 https://bot.q.qq.com/wiki/develop/api-v2/dev-prepare/interface-framework/event-emit.html 实现

此案例中 `web` 服务基于 `koa2` + `koa-router` + `koa-body``http` 服务, 官方需要使用 `https` 协议 `443`端口(其余端口亲测无法验证), 因此需要 `nginx` 设置 `ssl` 反代, `nginx` 代理设置详见同级目录下的 `nginx.conf`

> `webhook` 相关功能需要在设置了 `secret` 情况下使用,此时仍要设置 `token`
详细流程详见 `index.js` 代码内解释
68 changes: 68 additions & 0 deletions example/webhook/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* 基于官方文档 https://bot.q.qq.com/wiki/develop/api-v2/dev-prepare/interface-framework/event-emit.html
* nginx 代理设置详见同级目录下的 nginx.conf
* 注意:webhook 相关功能需要在设置了 secret 情况下使用,此时仍要设置 token
*/
const { createOpenAPI } = require('qq-bot-sdk');

const Koa = require("koa");
const { koaBody } = require("koa-body");
const Router = require("koa-router");


const client = createOpenAPI({
appID: "",
token: "", // 如果不使用 websocket 可留空
secret: "", // 如果使用 webhook 必填
}); // 创建 client


const PORT = 2333; // 定义 web 的端口, 需要与 nginx.conf 内端口一致
const app = new Koa(); // 定义 koa 实例
const router = new Router(); // 定义路由
app.use(async (ctx, next) => {
let rawData = '';
ctx.req.on('data', chunk => rawData += chunk);
ctx.req.on('end', () => ctx.request.rawBody = rawData);
await next();
}); // 对 body 进行验证需要原数据 (格式化后无法使用)

router.post("/webhook", async (ctx, next) => {
const sign = ctx.req.headers["x-signature-ed25519"]; // 获取服务器传来的 sign
const timestamp = ctx.req.headers["x-signature-timestamp"]; // 获取服务器传来的 timestamp
const rawBody = ctx.request.rawBody; // 获取原数据用来进行验证
const isValid = client.webhookApi.validSign(timestamp, rawBody, sign); // 进行验证, 通过后才可继续执行下一步操作
if (!isValid) {
ctx.status = 400;
ctx.body = { msg: "invalid signature" };
return;
}// 没有通过验证就一边玩去

const body = ctx.request.body;

if (body.op == 13) return ctx.body = {
plain_token: body.d.plain_token,
signature: client.webhookApi.getSign(body.d.event_ts, body.d.plain_token),
}; // 当 op = 13 进行 webhook 验证

/**
*
* 此处已经正式通过验证, 你可以对数据做出相应的处理(如回复消息), 数据格式遵从 websocket 接收到的格式
*
*/
console.log(body);


}); // 监听对应的url

app.use(async (ctx, next) => {
await next();
ctx.status = ctx.body?.status || ctx.status || 200;
}); // 返回的 body 里面如果有 status 时, 则返回的 status 设置为与之相同的值
app.use(koaBody({ multipart: true })); // 使用 koaBody
app.use(router.routes()); // 使用路由
app.use(router.allowedMethods()); // 使用路由
app.listen(PORT, async () => {
console.log("webhook 服务运行中......");
}); // 正式监听相应的端口

28 changes: 28 additions & 0 deletions example/webhook/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
server {
listen 443 ssl; # 监听 443 端口,并设置 ssl
server_name bot.example.com; # 这里设置对应的域名

ssl_certificate /path/to/it.crt; # 设置证书 公钥
ssl_certificate_key /path/to/it.key; # 设置证书 私钥

location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods *;

if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}

proxy_pass http://127.0.0.1:2333; # 设置代理的域名,需要与 index.js 里面的 PORT 相同
proxy_redirect off;
proxy_set_header Host $host; # 传递域名
proxy_set_header X-Real-IP $remote_addr; # 传递ip
proxy_set_header X-Scheme $scheme; # 传递协议
}
}
Loading

0 comments on commit d8a8c70

Please sign in to comment.