Skip to content
This repository was archived by the owner on Jan 10, 2025. It is now read-only.

Commit fd88f43

Browse files
authored
Dev (#199)
2 parents e6ea08e + c30ebcf commit fd88f43

File tree

17 files changed

+294
-32
lines changed

17 files changed

+294
-32
lines changed

.github/workflows/publishNPM.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ jobs:
2121
# 安装 pnpm
2222
- name: Install pnpm
2323
run: npm install -g pnpm
24+
25+
# 构建包必要文件
26+
- name: Build package files
27+
run: pnpm run build:cli
2428

2529
# 安装依赖
2630
- name: Install Dependencies

README.md

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
[🚢 Docker 镜像](https://hub.docker.com/repository/docker/dannicool/docker-wechatbot-webhook/general) | [📦 NPM包](https://www.npmjs.com/package/wechatbot-webhook)[🔍 FAQ](https://github.com/danni-cool/wechatbot-webhook/issues/72)
1010
</div>
1111

12-
开箱即用的微信webhook机器人,通过 http 接口调用即可实现微信消息的发送和接收,作为基于 wechaty 的消息机器人服务在稳定性上做了较多优化。
12+
一个小小的微信机器人webhook,帮你抹平了很多自己开发的障碍,基于 http 请求
1313

1414
## ✨ Features
1515

@@ -34,7 +34,8 @@
3434
| 接收文件 || |
3535
| 接收公众号推文链接 || |
3636
| 接收系统通知 | ✅ 上线通知 / 掉线通知 / 异常通知 | |
37-
| [快捷回复](https://github.com/danni-cool/wechatbot-webhook?tab=readme-ov-file#2-%E6%94%B6%E6%B6%88%E6%81%AF-api) |||
37+
| [头像获取](#33-获取静态资源接口) || |
38+
| [快捷回复](#2-%E6%94%B6%E6%B6%88%E6%81%AF-api) |||
3839
| **<群管理>** | | |
3940
| **<好友管理>** | | |
4041
| 接收好友申请 || |
@@ -410,12 +411,11 @@ curl --location 'https://your.recvdapi.com' \
410411
#### token 配置说明
411412
> 除了在 docker 启动时配置token,在默认缺省 token 的情况,会默认生成一个写入 `.env` 文件中
412413
413-
#### `/login?token=[YOUR_PERSONAL_TOKEN]`
414-
415-
- **描述**:获取登录二维码接口。
414+
#### 3.1 获取登录二维码接口
415+
- **地址**`/login`
416416
- **methods**: `GET`
417417
- **query**: token
418-
418+
- **example**: http://localhost:3001/login?token=[YOUR_PERSONAL_TOKEN]
419419
**status**: `200`
420420

421421
##### 登录成功
@@ -430,23 +430,65 @@ curl --location 'https://your.recvdapi.com' \
430430

431431
展示微信登录扫码页面
432432

433-
#### `/healthz?token=[YOUR_PERSONAL_TOKEN]`
433+
#### 3.2 健康检测接口
434+
435+
可以主动轮询该接口,检查服务是否正常运行
434436

435-
- **描述**健康检测接口。
437+
- **地址**`/healthz`
436438
- **methods**: `GET`
437439
- **query**: token
438440
- **status**: `200`
441+
- **example**: http://localhost:3001/healthz?token=[YOUR_PERSONAL_TOKEN]
439442

440443
微信已登录, 返回纯文本 `healthy`,否则返回 `unHealthy`
441444

445+
#### 3.3 获取静态资源接口
446+
447+
从 2.8.0 版本开始,可以通过本接口访问到头像等静态资源,具体见 [recvd_api 数据结构示例的 avatar 字段](/docs/recvdApi.example.md#2-formdatasource-string)
448+
449+
注意所有上报 recvd_api 的静态资源地址不会默认带上 token, 需要自己拼接,否则会返回 401 错误, 请确保自己微信已登录,需要通过登录态去获取资源
450+
451+
- **地址**`/resouces`
452+
- **methods**: `GET`
453+
- **query**:
454+
- token: 登录token
455+
- media: encode过的相对路径,比如 `/avatar/1234567890.jpg` encode为 `avatar%2F1234567890.jpg`
456+
- **status**: `200` `404` `401`
457+
458+
- **example**http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxgetheadimg%3Fseq%3D83460%26username%3D%40%4086815a%26skey%3D&token=[YOUR_PERSONAL_TOKEN]
459+
460+
##### status: `200`
461+
462+
成功获取资源, 返回静态资源文件
463+
464+
##### status: `404`
465+
466+
获取资源失败
467+
468+
##### status: `401` 未携带登录token
469+
470+
```json
471+
{"success":false, "message":"Unauthorized: Access is denied due to invalid credentials."}
472+
```
473+
474+
##### status: `401` 微信登录态已过期
475+
476+
```json
477+
{
478+
"success": false, "message": "you must login first"
479+
}
480+
```
481+
442482

443483
## 🌟 Star History
444484

445485
[![Star History Chart](https://api.star-history.com/svg?repos=danni-cool/wechatbot-webhook&type=Date)](https://star-history.com/#danni-cool/wechatbot-webhook&Date)
446486

447487
## Contributors
448488

449-
![](https://contrib.rocks/image?repo=danni-cool/wechatbot-webhook)
489+
Thanks to all our contributors!
490+
491+
<a href="https://github.com/danni-cool/wechatbot-webhook/graphs/contributors">![](https://contrib.rocks/image?repo=danni-cool/wechatbot-webhook)</a>
450492

451493
## ⏫ 更新日志
452494

docs/recvdApi.example.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
"id": "@xxxasdfsf",
7474
"payload": {
7575
"alias": "",
76-
"avatar": "",
76+
"avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密
7777
"friend": false,
7878
"gender": 1,
7979
"id": "@xxx",
@@ -98,7 +98,7 @@
9898
"id": "@xxxasdfsf",
9999
"payload": {
100100
"alias": "",
101-
"avatar": "",
101+
"avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密
102102
"friend": false,
103103
"gender": 1,
104104
"id": "@xxx",
@@ -125,7 +125,7 @@
125125
"id": "@xxxasdfsf",
126126
"payload": {
127127
"alias": "",
128-
"avatar": "",
128+
"avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密
129129
"friend": false,
130130
"gender": 1,
131131
"id": "@xxx",
@@ -166,7 +166,11 @@
166166
"adminIdList": [],
167167
"avatar": "xxxx", // 相对路径,应该要配合解密
168168
"memberList": [
169-
{id: '@xxxx', name:'昵称', alias: '备注名'/** 个人备注名,非群备注名 */ }
169+
{
170+
id: '@xxxx',
171+
avatar: "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密
172+
name:'昵称',
173+
alias: '备注名'/** 个人备注名,非群备注名 */ }
170174
]
171175
},
172176
//以下暂不清楚什么用途,如有兴趣,请查阅 wechaty 官网文档
@@ -181,7 +185,7 @@
181185

182186
"payload": {
183187
"alias": "", //备注名
184-
"avatar": "xxx",
188+
"avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密
185189
"friend": false,
186190
"gender": 1,
187191
"id": "@xxx",
@@ -202,7 +206,7 @@
202206

203207
"payload": {
204208
"alias": "",
205-
"avatar": "xxx",
209+
"avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密
206210
"city": "北京",
207211
"friend": true,
208212
"gender": 1,

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"form-data": "^4.0.0",
4848
"gerror": "^1.0.16",
4949
"hono": "^3.11.11",
50+
"lodash.clonedeep": "^4.5.0",
5051
"log4js": "^6.9.1",
5152
"mime": "^3.0.0",
5253
"node-fetch-commonjs": "^3.3.2",
@@ -64,6 +65,8 @@
6465
"eslint-config-prettier": "^9.1.0",
6566
"eslint-plugin-prettier": "^5.1.2",
6667
"husky": "^8.0.3",
68+
"i": "^0.3.7",
69+
"npm": "^10.5.0",
6770
"prettier": "^3.1.1",
6871
"tsc-files": "^1.1.4",
6972
"typescript": "^5.3.3",

pnpm-lock.yaml

Lines changed: 95 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/config/const.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
const path = require('path')
2+
const { PORT } = process.env
23

34
const config = {
45
/**
56
* 上报消息的api群成员缓存多久(单位:ms)
67
* @type {number}
78
*/
8-
roomCachedTime: 1000 * 60 * 5
9+
roomCachedTime: 1000 * 60 * 5,
10+
/** 服务启动地址 */
11+
localUrl: `http://localhost:${PORT}`
912
}
1013

1114
const { homeEnvCfg, homeMemoryCardPath } = process.env

src/middleware/loginCheck.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports.loginCheck = async (c, next) => {
88
c.status(401)
99
return c.json({
1010
success: false,
11-
message: 'you must login first before sending messages'
11+
message: 'you must login first'
1212
})
1313
}
1414

src/route/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ module.exports = function registerRoute({ app, bot }) {
2121

2222
require('./msg')({ app, bot })
2323
require('./login')({ app, bot })
24+
require('./resouces')({ app, bot })
2425
}

src/route/resouces.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const { downloadFile } = require('../utils/index')
2+
const middleware = require('../middleware')
3+
/**
4+
* 通过该接口代理获取微信静态资源
5+
* @param {Object} param
6+
* @param {import('hono').Hono} param.app
7+
* @param {import('wechaty').Wechaty} param.bot
8+
*/
9+
module.exports = function registerResourceAgentRoute({ app, bot }) {
10+
app.get(
11+
'/resouces',
12+
middleware.loginCheck,
13+
/** @param {import('hono').Context} c */
14+
async (c) => {
15+
// 暂时不考虑其他puppet的情况
16+
const cookie =
17+
// @ts-ignore 私有变量
18+
bot.__puppet._memory.payload['\rpuppet\nPUPPET-WECHAT4U'].COOKIE
19+
const mediaUrl = c.req.query('media')
20+
const fullResouceUrl = `https://wx2.qq.com${decodeURIComponent(
21+
mediaUrl || ''
22+
)}`
23+
24+
const { buffer, contentType } = await downloadFile(fullResouceUrl, {
25+
Cookie: Object.entries(cookie).reduce(
26+
(pre, next) => (pre += `${next[0]}=${next[1]};`),
27+
''
28+
)
29+
})
30+
if (buffer) {
31+
contentType && c.header('Content-Type', contentType)
32+
return c.body(buffer)
33+
} else {
34+
c.status(404)
35+
return c.json({ success: false, message: '获取资源失败' })
36+
}
37+
}
38+
)
39+
}

0 commit comments

Comments
 (0)