From b85f7ba316df2fd64780da3f315c2c30a07c70e1 Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 22:57:10 +0800 Subject: [PATCH 01/13] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E9=9D=99=E6=80=81=E8=B5=84=E6=BA=90=E8=8E=B7=E5=8F=96=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=8Crecvd=5Fapi=20=E5=A2=9E=E5=8A=A0=E5=A4=B4?= =?UTF-8?q?=E5=83=8Furl=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Closes: #198 --- README.md | 52 ++++++++++++++-- package.json | 3 + pnpm-lock.yaml | 95 ++++++++++++++++++++++++++++++ src/config/const.js | 5 +- src/middleware/loginCheck.js | 2 +- src/route/index.js | 1 + src/route/resouces.js | 39 ++++++++++++ src/service/msgUploader.js | 35 +++++++++-- src/utils/index.js | 13 ++-- src/utils/msg.js | 11 +++- src/utils/res.js | 14 +++++ src/wechaty/init.js | 11 ++-- typings/global.d.ts | 6 ++ typings/{extend.d.ts => hono.d.ts} | 0 typings/lodash.d.ts | 6 ++ 15 files changed, 270 insertions(+), 23 deletions(-) create mode 100644 src/route/resouces.js create mode 100644 src/utils/res.js rename typings/{extend.d.ts => hono.d.ts} (100%) create mode 100644 typings/lodash.d.ts diff --git a/README.md b/README.md index 36e57b7..bb3fa35 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ | 接收文件 | ✅ | | | 接收公众号推文链接 | ✅ | | | 接收系统通知 | ✅ 上线通知 / 掉线通知 / 异常通知 | | +| [头像获取](https://github.com/danni-cool/wechatbot-webhook?tab=readme-ov-file#1-%E5%A4%B4%E5%83%8F%E8%8E%B7%E5%8F%96-api) | ✅ | | | [快捷回复](https://github.com/danni-cool/wechatbot-webhook?tab=readme-ov-file#2-%E6%94%B6%E6%B6%88%E6%81%AF-api) | ✅ | ✅ | | **<群管理>** | | | | **<好友管理>** | | | @@ -410,12 +411,11 @@ curl --location 'https://your.recvdapi.com' \ #### token 配置说明 > 除了在 docker 启动时配置token,在默认缺省 token 的情况,会默认生成一个写入 `.env` 文件中 -#### `/login?token=[YOUR_PERSONAL_TOKEN]` - -- **描述**:获取登录二维码接口。 +#### 3.1 获取登录二维码接口 +- **地址**:`/login` - **methods**: `GET` - **query**: token - +- **example**: http://localhost:3001/login?token=[YOUR_PERSONAL_TOKEN] **status**: `200` ##### 登录成功 @@ -430,15 +430,55 @@ curl --location 'https://your.recvdapi.com' \ 展示微信登录扫码页面 -#### `/healthz?token=[YOUR_PERSONAL_TOKEN]` +#### 3.2 健康检测接口 + +可以主动轮询该接口,检查服务是否正常运行 -- **描述**:健康检测接口。 +- **地址**:`/healthz` - **methods**: `GET` - **query**: token - **status**: `200` +- **example**: http://localhost:3001/healthz?token=[YOUR_PERSONAL_TOKEN] 微信已登录, 返回纯文本 `healthy`,否则返回 `unHealthy` +#### 3.3 获取静态资源接口 + +从 2.8.0 版本开始,可以通过本接口访问到头像等静态资源,具体见 [recvd_api 数据结构示例的 avatar 字段](docs/recvdApi.example.md#formdatasource) + +注意所有上报 recvd_api 的静态资源地址不会默认带上 token, 需要自己拼接,否则会返回 401 错误, 另外,**请确保自己微信已登录,需要通过登录态去获取资源** + +- **地址**:`/resouces` +- **methods**: `GET` +- **query**: + - token: 登录token + - media: encode过的相对路径,比如 `/avatar/1234567890.jpg` encode为 `avatar%2F1234567890.jpg` +- **status**: `200` `404` `401` + +- **example**:http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxgetheadimg%3Fseq%3D83460%26username%3D%40%4086815a%26skey%3D&token=[YOUR_PERSONAL_TOKEN] + +##### status: `200` + +成功获取资源, 返回静态资源文件 + +##### status: `404` + +获取资源失败 + +##### status: `401` 未携带登录token + +```json +{"success":false, "message":"Unauthorized: Access is denied due to invalid credentials."} +``` + +##### status: `401` 微信登录态已过期 + +```json +{ + "success": false, "message": "you must login first" +} +``` + ## 🌟 Star History diff --git a/package.json b/package.json index 8a32393..ceb8b6b 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "form-data": "^4.0.0", "gerror": "^1.0.16", "hono": "^3.11.11", + "lodash.clonedeep": "^4.5.0", "log4js": "^6.9.1", "mime": "^3.0.0", "node-fetch-commonjs": "^3.3.2", @@ -64,6 +65,8 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.2", "husky": "^8.0.3", + "i": "^0.3.7", + "npm": "^10.5.0", "prettier": "^3.1.1", "tsc-files": "^1.1.4", "typescript": "^5.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9538783..4d5c3b0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,6 +40,9 @@ importers: hono: specifier: ^3.11.11 version: 3.11.11 + lodash.clonedeep: + specifier: ^4.5.0 + version: 4.5.0 log4js: specifier: ^6.9.1 version: 6.9.1 @@ -86,6 +89,12 @@ importers: husky: specifier: ^8.0.3 version: 8.0.3 + i: + specifier: ^0.3.7 + version: 0.3.7 + npm: + specifier: ^10.5.0 + version: 10.5.0 prettier: specifier: ^3.1.1 version: 3.1.1 @@ -2147,6 +2156,11 @@ packages: hasBin: true dev: true + /i@0.3.7: + resolution: {integrity: sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==} + engines: {node: '>=0.4'} + dev: true + /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -2452,6 +2466,10 @@ packages: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} dev: false + /lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + dev: false + /lodash.defaults@4.2.0: resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} dev: false @@ -2631,6 +2649,83 @@ packages: resolution: {integrity: sha512-XdkOuXGx0DTwlqb0DWTcDqelgU/F3YyZ+PTRaecpDVpkYskcnh3OeUYKfvjcRQ2D1diTIGxi/a3eHVjW5yPupQ==} dev: false + /npm@10.5.0: + resolution: {integrity: sha512-Ejxwvfh9YnWVU2yA5FzoYLTW52vxHCz+MHrOFg9Cc8IFgF/6f5AGPAvb5WTay5DIUP1NIfN3VBZ0cLlGO0Ys+A==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + dev: true + bundledDependencies: + - '@isaacs/string-locale-compare' + - '@npmcli/arborist' + - '@npmcli/config' + - '@npmcli/fs' + - '@npmcli/map-workspaces' + - '@npmcli/package-json' + - '@npmcli/promise-spawn' + - '@npmcli/run-script' + - '@sigstore/tuf' + - abbrev + - archy + - cacache + - chalk + - ci-info + - cli-columns + - cli-table3 + - columnify + - fastest-levenshtein + - fs-minipass + - glob + - graceful-fs + - hosted-git-info + - ini + - init-package-json + - is-cidr + - json-parse-even-better-errors + - libnpmaccess + - libnpmdiff + - libnpmexec + - libnpmfund + - libnpmhook + - libnpmorg + - libnpmpack + - libnpmpublish + - libnpmsearch + - libnpmteam + - libnpmversion + - make-fetch-happen + - minimatch + - minipass + - minipass-pipeline + - ms + - node-gyp + - nopt + - normalize-package-data + - npm-audit-report + - npm-install-checks + - npm-package-arg + - npm-pick-manifest + - npm-profile + - npm-registry-fetch + - npm-user-validate + - npmlog + - p-map + - pacote + - parse-conflict-json + - proc-log + - qrcode-terminal + - read + - semver + - spdx-expression-parse + - ssri + - supports-color + - tar + - text-table + - tiny-relative-date + - treeverse + - validate-npm-package-name + - which + - write-file-atomic + /nth-check@1.0.2: resolution: {integrity: sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==} dependencies: diff --git a/src/config/const.js b/src/config/const.js index e0ec497..d43cd72 100644 --- a/src/config/const.js +++ b/src/config/const.js @@ -1,11 +1,14 @@ const path = require('path') +const { PORT } = process.env const config = { /** * 上报消息的api群成员缓存多久(单位:ms) * @type {number} */ - roomCachedTime: 1000 * 60 * 5 + roomCachedTime: 1000 * 60 * 5, + /** 服务启动地址 */ + localUrl: `http://localhost:${PORT}` } const { homeEnvCfg, homeMemoryCardPath } = process.env diff --git a/src/middleware/loginCheck.js b/src/middleware/loginCheck.js index d85aec3..f812d9b 100644 --- a/src/middleware/loginCheck.js +++ b/src/middleware/loginCheck.js @@ -8,7 +8,7 @@ module.exports.loginCheck = async (c, next) => { c.status(401) return c.json({ success: false, - message: 'you must login first before sending messages' + message: 'you must login first' }) } diff --git a/src/route/index.js b/src/route/index.js index b920fd7..5efd50d 100644 --- a/src/route/index.js +++ b/src/route/index.js @@ -21,4 +21,5 @@ module.exports = function registerRoute({ app, bot }) { require('./msg')({ app, bot }) require('./login')({ app, bot }) + require('./resouces')({ app, bot }) } diff --git a/src/route/resouces.js b/src/route/resouces.js new file mode 100644 index 0000000..b50a3b5 --- /dev/null +++ b/src/route/resouces.js @@ -0,0 +1,39 @@ +const { downloadFile } = require('../utils/index') +const middleware = require('../middleware') +/** + * 注册login路由和处理上报逻辑 + * @param {Object} param + * @param {import('hono').Hono} param.app + * @param {import('wechaty').Wechaty} param.bot + */ +module.exports = function registerResourceAgentRoute({ app, bot }) { + app.get( + '/resouces', + middleware.loginCheck, + /** @param {import('hono').Context} c */ + async (c) => { + // 暂时不考虑其他puppet的情况 + const cookie = + // @ts-ignore 私有变量 + bot.__puppet._memory.payload['\rpuppet\nPUPPET-WECHAT4U'].COOKIE + const mediaUrl = c.req.query('media') + const fullResouceUrl = `https://wx2.qq.com${decodeURIComponent( + mediaUrl || '' + )}` + + const { buffer, contentType } = await downloadFile(fullResouceUrl, { + Cookie: Object.entries(cookie).reduce( + (pre, next) => (pre += `${next[0]}=${next[1]};`), + '' + ) + }) + if (buffer) { + contentType && c.header('Content-Type', contentType) + return c.body(buffer) + } else { + c.status(404) + return c.json({ success: false, message: '获取资源失败' }) + } + } + ) +} diff --git a/src/service/msgUploader.js b/src/service/msgUploader.js index 41bf9a7..7613b0d 100644 --- a/src/service/msgUploader.js +++ b/src/service/msgUploader.js @@ -5,7 +5,7 @@ const FormData = require('form-data') const { LOCAL_RECVD_MSG_API, RECVD_MSG_API } = process.env const { MSG_TYPE_ENUM } = require('../config/const') const cacheTool = require('../service/cache') - +const cloneDeep = require('lodash.cloneDeep') /** * 收到消息上报接受url * @typedef {{type:'text'|'fileUrl'}} baseMsgInterface @@ -39,7 +39,7 @@ async function sendMsg2RecvdApi(msg) { // 有webhookurl才发送 if (!webhookUrl) return - /** @type {import('wechaty/impls').RoomInterface & {payload: { memberList: {id:string,name:string,alias:string|undefined}[]}}} */ + /** @type {roomInfoForUpload} */ //@ts-expect-errors 强制as配合 ts-expect-errors 实用更佳 const roomInfo = msg.room() @@ -59,6 +59,8 @@ async function sendMsg2RecvdApi(msg) { }) } roomInfo.payload.memberList = roomMemberInfo.map((item) => ({ + // @ts-expect-error wechaty定义问题,数据在payload里 + avatar: Utils.getAssetsAgentUrl(item.payload.avatar), // @ts-expect-error wechaty定义问题,数据在payload里 id: item.payload.id, // @ts-expect-error wechaty定义问题,数据在payload里 @@ -74,11 +76,32 @@ async function sendMsg2RecvdApi(msg) { } const source = { - /** room的话解析群成员信息,原始信息不会带 */ - room: roomInfo ?? '', - to: msg.to() ?? '', + room: cloneDeep(roomInfo || {}), + /** @type { import('wechaty').Message['to'] } */ + // @ts-ignore + to: cloneDeep(msg.to() || {}), + from: cloneDeep(msg.talker() || {}) + } + + // @ts-ignore + if (source.to && source.to.payload?.avatar) { + // @ts-ignore + source.to.payload.avatar = Utils.getAssetsAgentUrl(source.to.payload.avatar) + } + + // @ts-ignore + if (source.from.payload?.avatar) { // @ts-ignore - from: msg.talker() ?? '' + source.from.payload.avatar = Utils.getAssetsAgentUrl( + // @ts-ignore + source.from.payload.avatar + ) + } + + if (source.room.payload?.avatar) { + source.room.payload.avatar = Utils.getAssetsAgentUrl( + source.room.payload.avatar + ) } // let passed = true diff --git a/src/utils/index.js b/src/utils/index.js index 826afbc..9f4e19f 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -2,31 +2,34 @@ const { FileBox } = require('file-box') const MIME = require('mime') const { logger } = require('./log') const { URL } = require('url') + /** * 下载媒体文件转化为Buffer * @param {string} fileUrl - * @returns {Promise<{buffer?: Buffer, fileName?: string, fileNameAlias?: string}>} + * @returns {Promise<{buffer?: Buffer, fileName?: string, fileNameAlias?: string, contentType?: null | string}>} */ -const downloadFile = async (fileUrl) => { +const downloadFile = async (fileUrl, headers = {}) => { try { - const response = await fetch(fileUrl) + const response = await fetch(fileUrl, { headers }) if (response.ok) { const buffer = Buffer.from(await response.arrayBuffer()) // 使用自定义文件名,解决URL无文件后缀名时,文件被微信解析成不正确的后缀问题 let { fileName, query } = getFileInfoFromUrl(fileUrl) + let contentType = response.headers.get('content-type') // deal with unValid Url format like https://pangji-home.com/Fi5DimeGHBLQ3KcELn3DolvENjVU if (fileName === '') { // 有些资源文件链接是不会返回文件后缀的 例如 https://pangji-home.com/Fi5DimeGHBLQ3KcELn3DolvENjVU 其实是一张图片 //@ts-expect-errors 不考虑无content-type的情况 - const extName = MIME.getExtension(response.headers.get('content-type')) + const extName = MIME.getExtension(contentType) fileName = `${Date.now()}.${extName}` } return { buffer, fileName, + contentType, fileNameAlias: query?.$alias } } @@ -194,6 +197,8 @@ module.exports = { ...require('./nextTick.js'), ...require('./paramsValid.js'), ...require('./log.js'), + ...require('./res'), + downloadFile, getMediaFromUrl, getBufferFile, generateToken, diff --git a/src/utils/msg.js b/src/utils/msg.js index ad54b0f..fbf0ad5 100644 --- a/src/utils/msg.js +++ b/src/utils/msg.js @@ -1,4 +1,6 @@ const { MSG_TYPE_ENUM, legacySystemMsgStrMap } = require('../config/const') +const { getAssetsAgentUrl } = require('./res') +const cloneDeep = require('lodash.cloneDeep') class CommonMsg { /** * @param {commonMsgPayload} payload @@ -108,8 +110,15 @@ class SystemEvent extends CommonMsg { * @param {systemEventPayload} payload */ constructor(payload) { + const payloadClone = cloneDeep(payload) + if (payloadClone.user?.payload) { + payloadClone.user.payload.avatar = getAssetsAgentUrl( + payloadClone.user.payload.avatar + ) + } + super({ - text: JSON.stringify(payload), + text: JSON.stringify(payloadClone), type: legacySystemMsgStrMap[payload.event], isSystemEvent: true }) diff --git a/src/utils/res.js b/src/utils/res.js new file mode 100644 index 0000000..fff957f --- /dev/null +++ b/src/utils/res.js @@ -0,0 +1,14 @@ +const { + config: { localUrl } +} = require('../config/const') + +/** + * 将相对资源路径转为代理获取资源路径 + * @param {string} relativePath + * @returns {string} + */ +module.exports.getAssetsAgentUrl = (relativePath) => { + if (!relativePath) return '' + + return `${localUrl}/resouces?media=${encodeURIComponent(relativePath)}` +} diff --git a/src/wechaty/init.js b/src/wechaty/init.js index 1d090dc..504673e 100644 --- a/src/wechaty/init.js +++ b/src/wechaty/init.js @@ -4,8 +4,11 @@ const { SystemEvent } = require('../utils/msg.js') const Service = require('../service') const Utils = require('../utils/index') const chalk = require('chalk') -const { PORT } = process.env -const { memoryCardName, logOutUnofficialCodeList } = require('../config/const') +const { + memoryCardName, + logOutUnofficialCodeList, + config: { localUrl } +} = require('../config/const') const token = Service.initLoginApiToken() const cacheTool = require('../service/cache') const bot = @@ -31,7 +34,7 @@ module.exports = function init() { Utils.logger.info( [ 'Or Access the URL to login: ' + - chalk.cyan(`http://localhost:${PORT}/login?token=${token}`) + chalk.cyan(`${localUrl}/login?token=${token}`) ].join('\n') ) }) @@ -42,7 +45,7 @@ module.exports = function init() { Utils.logger.info( '💬 ' + `你的推消息 api 为:${chalk.cyan( - `http://localhost:${PORT}/webhook/msg/v2?token=${token}` + `${localUrl}/webhook/msg/v2?token=${token}` )}` ) Utils.logger.info( diff --git a/typings/global.d.ts b/typings/global.d.ts index 96bc4be..07af426 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -150,3 +150,9 @@ type commonMsgPayload = { room?: import('wechaty').Room | '' file?: string | (import('file-box').FileBoxInterface & { _name: string }) } + +type roomInfoForUpload = import('wechaty/impls').RoomInterface & { + payload: { + memberList: { id: string; name: string; alias: string | undefined }[] + } +} diff --git a/typings/extend.d.ts b/typings/hono.d.ts similarity index 100% rename from typings/extend.d.ts rename to typings/hono.d.ts diff --git a/typings/lodash.d.ts b/typings/lodash.d.ts new file mode 100644 index 0000000..342274b --- /dev/null +++ b/typings/lodash.d.ts @@ -0,0 +1,6 @@ +declare module 'lodash.cloneDeep' { + // 定义 cloneDeep 函数,接受任意类型的参数,并返回相同的类型 + function cloneDeep(value: T): T + // commonjs 导出 + export = cloneDeep +} From 7933e1d3183c14c50af2d385c695ee7d8bafde65 Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:00:27 +0800 Subject: [PATCH 02/13] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0doc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb3fa35..8c48711 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ | 接收文件 | ✅ | | | 接收公众号推文链接 | ✅ | | | 接收系统通知 | ✅ 上线通知 / 掉线通知 / 异常通知 | | -| [头像获取](https://github.com/danni-cool/wechatbot-webhook?tab=readme-ov-file#1-%E5%A4%B4%E5%83%8F%E8%8E%B7%E5%8F%96-api) | ✅ | | +| [头像获取](/docs/recvdApi.example.md#2-formdatasource-string) | ✅ | | | [快捷回复](https://github.com/danni-cool/wechatbot-webhook?tab=readme-ov-file#2-%E6%94%B6%E6%B6%88%E6%81%AF-api) | ✅ | ✅ | | **<群管理>** | | | | **<好友管理>** | | | From bc975a5e1ea95d713f1ecef189f03cada4fba3c5 Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:02:25 +0800 Subject: [PATCH 03/13] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8c48711..77b6274 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ | 接收文件 | ✅ | | | 接收公众号推文链接 | ✅ | | | 接收系统通知 | ✅ 上线通知 / 掉线通知 / 异常通知 | | -| [头像获取](/docs/recvdApi.example.md#2-formdatasource-string) | ✅ | | -| [快捷回复](https://github.com/danni-cool/wechatbot-webhook?tab=readme-ov-file#2-%E6%94%B6%E6%B6%88%E6%81%AF-api) | ✅ | ✅ | +| [头像获取](#33-获取静态资源接口) | ✅ | | +| [快捷回复](#2-%E6%94%B6%E6%B6%88%E6%81%AF-api) | ✅ | ✅ | | **<群管理>** | | | | **<好友管理>** | | | | 接收好友申请 | ✅ | | @@ -444,9 +444,9 @@ curl --location 'https://your.recvdapi.com' \ #### 3.3 获取静态资源接口 -从 2.8.0 版本开始,可以通过本接口访问到头像等静态资源,具体见 [recvd_api 数据结构示例的 avatar 字段](docs/recvdApi.example.md#formdatasource) +从 2.8.0 版本开始,可以通过本接口访问到头像等静态资源,具体见 [recvd_api 数据结构示例的 avatar 字段](/docs/recvdApi.example.md#2-formdatasource-string) -注意所有上报 recvd_api 的静态资源地址不会默认带上 token, 需要自己拼接,否则会返回 401 错误, 另外,**请确保自己微信已登录,需要通过登录态去获取资源** +注意所有上报 recvd_api 的静态资源地址不会默认带上 token, 需要自己拼接,否则会返回 401 错误, 请确保自己微信已登录,需要通过登录态去获取资源 - **地址**:`/resouces` - **methods**: `GET` From 31a4b0ce99fdc365035803fba5899894f442444a Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:04:40 +0800 Subject: [PATCH 04/13] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 77b6274..e3ead76 100644 --- a/README.md +++ b/README.md @@ -485,8 +485,10 @@ curl --location 'https://your.recvdapi.com' \ [![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) ## Contributors - +**Thanks to all our contributors!** + ![](https://contrib.rocks/image?repo=danni-cool/wechatbot-webhook) + ## ⏫ 更新日志 From c8f1d6fcff791273f608ecb93ff02a18990ceb47 Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:05:27 +0800 Subject: [PATCH 05/13] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e3ead76..2d2300d 100644 --- a/README.md +++ b/README.md @@ -485,7 +485,9 @@ curl --location 'https://your.recvdapi.com' \ [![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) ## Contributors + **Thanks to all our contributors!** + ![](https://contrib.rocks/image?repo=danni-cool/wechatbot-webhook) From 949479060dc14815f62f08dae5d4dba47284941d Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:07:15 +0800 Subject: [PATCH 06/13] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2d2300d..6e6991b 100644 --- a/README.md +++ b/README.md @@ -486,11 +486,9 @@ curl --location 'https://your.recvdapi.com' \ ## Contributors -**Thanks to all our contributors!** +Thanks to all our contributors! - -![](https://contrib.rocks/image?repo=danni-cool/wechatbot-webhook) - +![](https://contrib.rocks/image?repo=danni-cool/wechatbot-webhook) ## ⏫ 更新日志 From 478f495f7cae881a26f669999edba8a747a518d1 Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:08:09 +0800 Subject: [PATCH 07/13] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20=E6=8F=90?= =?UTF-8?q?=E4=BA=A4example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/recvdApi.example.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/recvdApi.example.md b/docs/recvdApi.example.md index 64ff03e..40869ca 100644 --- a/docs/recvdApi.example.md +++ b/docs/recvdApi.example.md @@ -73,7 +73,7 @@ "id": "@xxxasdfsf", "payload": { "alias": "", - "avatar": "", + "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 "friend": false, "gender": 1, "id": "@xxx", @@ -98,7 +98,7 @@ "id": "@xxxasdfsf", "payload": { "alias": "", - "avatar": "", + "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 "friend": false, "gender": 1, "id": "@xxx", @@ -125,7 +125,7 @@ "id": "@xxxasdfsf", "payload": { "alias": "", - "avatar": "", + "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 "friend": false, "gender": 1, "id": "@xxx", @@ -166,7 +166,11 @@ "adminIdList": [], "avatar": "xxxx", // 相对路径,应该要配合解密 "memberList": [ - {id: '@xxxx', name:'昵称', alias: '备注名'/** 个人备注名,非群备注名 */ } + { + id: '@xxxx', + avatar: "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 + name:'昵称', + alias: '备注名'/** 个人备注名,非群备注名 */ } ] }, //以下暂不清楚什么用途,如有兴趣,请查阅 wechaty 官网文档 @@ -181,7 +185,7 @@ "payload": { "alias": "", //备注名 - "avatar": "xxx", + "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 "friend": false, "gender": 1, "id": "@xxx", @@ -202,7 +206,7 @@ "payload": { "alias": "", - "avatar": "xxx", + "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 "city": "北京", "friend": true, "gender": 1, From 63b0af138adc5f83ea65576896599e2474db577c Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:16:53 +0800 Subject: [PATCH 08/13] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e6991b..3aaa1fa 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [🚢 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) -开箱即用的微信webhook机器人,通过 http 接口调用即可实现微信消息的发送和接收,作为基于 wechaty 的消息机器人服务在稳定性上做了较多优化。 +一个小小的微信机器人webhook,帮你抹平了很多自己开发的障碍,基于用 http 请求 ## ✨ Features From cca90d52b0c30df013b4244a75383520c2f8c277 Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:17:40 +0800 Subject: [PATCH 09/13] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20update=20doc?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3aaa1fa..0bfc599 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [🚢 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) -一个小小的微信机器人webhook,帮你抹平了很多自己开发的障碍,基于用 http 请求 +一个小小的微信机器人webhook,帮你抹平了很多自己开发的障碍,基于 http 请求 ## ✨ Features From a89b59cde2a109f593c7d7467246e4a85eca05a5 Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:19:21 +0800 Subject: [PATCH 10/13] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/route/resouces.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/route/resouces.js b/src/route/resouces.js index b50a3b5..511dc30 100644 --- a/src/route/resouces.js +++ b/src/route/resouces.js @@ -1,7 +1,7 @@ const { downloadFile } = require('../utils/index') const middleware = require('../middleware') /** - * 注册login路由和处理上报逻辑 + * 通过该接口代理获取微信静态资源 * @param {Object} param * @param {import('hono').Hono} param.app * @param {import('wechaty').Wechaty} param.bot From a506b57be6aecbb14d04f25159506744e1563f51 Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:22:10 +0800 Subject: [PATCH 11/13] =?UTF-8?q?chore:=20=F0=9F=A4=96=20=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- typings/global.d.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/typings/global.d.ts b/typings/global.d.ts index 07af426..402e37f 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -153,6 +153,11 @@ type commonMsgPayload = { type roomInfoForUpload = import('wechaty/impls').RoomInterface & { payload: { - memberList: { id: string; name: string; alias: string | undefined }[] + memberList: { + id: string + name: string + alias: string | undefined + avatar: string + }[] } } From 50711cf8f258fdfba1dc7c7161995581b923c2ca Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:26:45 +0800 Subject: [PATCH 12/13] =?UTF-8?q?chore:=20=F0=9F=A4=96=20=E8=A1=A5?= =?UTF-8?q?=E5=85=85npm=20=E5=8F=91=E5=B8=83=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/publishNPM.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/publishNPM.yml b/.github/workflows/publishNPM.yml index 28aad33..22b835b 100644 --- a/.github/workflows/publishNPM.yml +++ b/.github/workflows/publishNPM.yml @@ -21,6 +21,10 @@ jobs: # 安装 pnpm - name: Install pnpm run: npm install -g pnpm + + # 构建包必要文件 + - name: Build package files + run: pnpm run build:cli # 安装依赖 - name: Install Dependencies From c30ebcf7b473f71b8c8cc27e92c2c220b2734dd6 Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 27 Mar 2024 23:31:38 +0800 Subject: [PATCH 13/13] =?UTF-8?q?style:=20=F0=9F=92=84=20=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=E5=A4=A7=E5=B0=8F=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/msgUploader.js | 2 +- src/utils/msg.js | 2 +- typings/lodash.d.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/service/msgUploader.js b/src/service/msgUploader.js index 7613b0d..f71d431 100644 --- a/src/service/msgUploader.js +++ b/src/service/msgUploader.js @@ -5,7 +5,7 @@ const FormData = require('form-data') const { LOCAL_RECVD_MSG_API, RECVD_MSG_API } = process.env const { MSG_TYPE_ENUM } = require('../config/const') const cacheTool = require('../service/cache') -const cloneDeep = require('lodash.cloneDeep') +const cloneDeep = require('lodash.clonedeep') /** * 收到消息上报接受url * @typedef {{type:'text'|'fileUrl'}} baseMsgInterface diff --git a/src/utils/msg.js b/src/utils/msg.js index fbf0ad5..3203427 100644 --- a/src/utils/msg.js +++ b/src/utils/msg.js @@ -1,6 +1,6 @@ const { MSG_TYPE_ENUM, legacySystemMsgStrMap } = require('../config/const') const { getAssetsAgentUrl } = require('./res') -const cloneDeep = require('lodash.cloneDeep') +const cloneDeep = require('lodash.clonedeep') class CommonMsg { /** * @param {commonMsgPayload} payload diff --git a/typings/lodash.d.ts b/typings/lodash.d.ts index 342274b..d405925 100644 --- a/typings/lodash.d.ts +++ b/typings/lodash.d.ts @@ -1,4 +1,4 @@ -declare module 'lodash.cloneDeep' { +declare module 'lodash.clonedeep' { // 定义 cloneDeep 函数,接受任意类型的参数,并返回相同的类型 function cloneDeep(value: T): T // commonjs 导出