@zzedbot/yunzhijia 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +326 -0
- package/dist/api.d.ts +31 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +66 -0
- package/dist/api.js.map +1 -0
- package/dist/channel-simple.d.ts +3 -0
- package/dist/channel-simple.d.ts.map +1 -0
- package/dist/channel-simple.js +60 -0
- package/dist/channel-simple.js.map +1 -0
- package/dist/channel.d.ts +34 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/channel.js +409 -0
- package/dist/channel.js.map +1 -0
- package/dist/crypto.d.ts +50 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +54 -0
- package/dist/crypto.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +5 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +14 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +63 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/webhook-server.d.ts +28 -0
- package/dist/webhook-server.d.ts.map +1 -0
- package/dist/webhook-server.js +96 -0
- package/dist/webhook-server.js.map +1 -0
- package/openclaw.plugin.json +36 -0
- package/package.json +24 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zed
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# 🤖 云之家 Channel 插件
|
|
2
|
+
|
|
3
|
+
OpenClaw 金蝶云之家 (YunzhiJia) 消息渠道插件,支持在云之家中集成 OpenClaw AI 能力。
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 📋 简介
|
|
11
|
+
|
|
12
|
+
云之家 Channel 插件允许你在金蝶云之家的群组或私聊中使用 OpenClaw AI 机器人。支持:
|
|
13
|
+
|
|
14
|
+
- ✅ Webhook 消息接收(HmacSHA1 签名验证)
|
|
15
|
+
- ✅ AI 智能回复(基于上下文的对话)
|
|
16
|
+
- ✅ 多账户支持
|
|
17
|
+
- ✅ 群组消息处理
|
|
18
|
+
- ✅ 访问控制(白名单机制)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 🚀 快速开始
|
|
23
|
+
|
|
24
|
+
### 方式一:安装已编译的插件(推荐)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 安装插件到 OpenClaw 扩展目录
|
|
28
|
+
openclaw plugins install <YOUR_WORKSPACE>/projects/yunzhijiachannel
|
|
29
|
+
|
|
30
|
+
# 或手动复制到扩展目录
|
|
31
|
+
cp -r <YOUR_WORKSPACE>/projects/yunzhijiachannel ~/.openclaw/extensions/yunzhijia
|
|
32
|
+
|
|
33
|
+
# 启用插件
|
|
34
|
+
openclaw plugins enable yunzhijia
|
|
35
|
+
|
|
36
|
+
# 重启 Gateway
|
|
37
|
+
openclaw gateway restart
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 方式二:从开发目录链接(开发者)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# 开发模式下,直接链接到开发目录
|
|
44
|
+
openclaw plugins install -l <YOUR_WORKSPACE>/projects/yunzhijiachannel
|
|
45
|
+
|
|
46
|
+
# 重启 Gateway
|
|
47
|
+
openclaw gateway restart
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
> 💡 **说明**:
|
|
51
|
+
> - 生产环境使用 **方式一**,插件安装在 `~/.openclaw/extensions/yunzhijia`
|
|
52
|
+
> - 开发环境使用 **方式二**,直接链接到开发目录 `<YOUR_WORKSPACE>/projects/yunzhijiachannel`
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## ⚙️ 配置
|
|
57
|
+
|
|
58
|
+
### 1. 获取云之家凭证
|
|
59
|
+
|
|
60
|
+
登录 [云之家开放平台](https://open.yunzhijia.com/),创建对话机器人并获取:
|
|
61
|
+
|
|
62
|
+
| 凭证 | 获取位置 |
|
|
63
|
+
|------|---------|
|
|
64
|
+
| `appId` | 应用详情 |
|
|
65
|
+
| `appSecret` | 安全设置 |
|
|
66
|
+
| `token` | 消息配置 |
|
|
67
|
+
| `webhookToken` | Webhook 设置 |
|
|
68
|
+
|
|
69
|
+
### 2. 配置 OpenClaw
|
|
70
|
+
|
|
71
|
+
编辑 `~/.openclaw/openclaw.json`:
|
|
72
|
+
|
|
73
|
+
```json5
|
|
74
|
+
{
|
|
75
|
+
"channels": {
|
|
76
|
+
"yunzhijia": {
|
|
77
|
+
"enabled": true,
|
|
78
|
+
"accounts": {
|
|
79
|
+
"default": {
|
|
80
|
+
"enabled": true,
|
|
81
|
+
"appId": "<YOUR_APP_ID>",
|
|
82
|
+
"appSecret": "<YOUR_APP_SECRET>",
|
|
83
|
+
"token": "<YOUR_TOKEN>",
|
|
84
|
+
"webhookToken": "<YOUR_WEBHOOK_TOKEN>",
|
|
85
|
+
"webhookPort": 18790,
|
|
86
|
+
"webhookHost": "0.0.0.0",
|
|
87
|
+
"dmPolicy": "allowlist",
|
|
88
|
+
"allowFrom": ["<USER_OPENID_1>", "<USER_OPENID_2>"]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"plugins": {
|
|
94
|
+
"allow": ["yunzhijia"],
|
|
95
|
+
"entries": {
|
|
96
|
+
"yunzhijia": {
|
|
97
|
+
"enabled": true
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
> ⚠️ **安全提示**:
|
|
105
|
+
> - 不要将真实密钥提交到 Git
|
|
106
|
+
> - 建议使用环境变量或密钥管理工具
|
|
107
|
+
> - 定期轮换密钥
|
|
108
|
+
|
|
109
|
+
### 3. 配置云之家 Webhook
|
|
110
|
+
|
|
111
|
+
在云之家机器人设置中配置消息接收地址:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
消息接收地址:https://<YOUR_DOMAIN>/yunzhijia/webhook/default
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
> 💡 如果使用内网部署,需要配置外网映射(如 Nginx 反向代理)
|
|
118
|
+
|
|
119
|
+
### 4. 重启 Gateway
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
openclaw gateway restart
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 📖 配置说明
|
|
128
|
+
|
|
129
|
+
### 必需字段
|
|
130
|
+
|
|
131
|
+
| 字段 | 说明 | 示例 |
|
|
132
|
+
|------|------|------|
|
|
133
|
+
| `appId` | 云之家应用 ID | `app_12345` |
|
|
134
|
+
| `appSecret` | 应用密钥(用于签名验证) | `abc123...` |
|
|
135
|
+
| `token` | 消息接收 Token | `token_xyz...` |
|
|
136
|
+
| `webhookToken` | Webhook 发送授权码 | `c7d28f...` |
|
|
137
|
+
|
|
138
|
+
### 可选字段
|
|
139
|
+
|
|
140
|
+
| 字段 | 说明 | 默认值 |
|
|
141
|
+
|------|------|--------|
|
|
142
|
+
| `webhookPort` | Webhook 监听端口 | `18790` |
|
|
143
|
+
| `webhookHost` | Webhook 监听地址 | `0.0.0.0` |
|
|
144
|
+
| `webhookPath` | Webhook 路径 | `/yunzhijia/webhook/<accountId>` |
|
|
145
|
+
| `dmPolicy` | DM 策略 (`pairing` \| `allowlist` \| `open`) | `pairing` |
|
|
146
|
+
| `allowFrom` | 允许的用户 OpenID 列表 | `[]` |
|
|
147
|
+
| `groupPolicy` | 群组策略 (`allowlist` \| `open`) | `allowlist` |
|
|
148
|
+
|
|
149
|
+
### 获取用户 OpenID
|
|
150
|
+
|
|
151
|
+
**方法 1**: 查看 Gateway 日志
|
|
152
|
+
```bash
|
|
153
|
+
tail -f /tmp/openclaw/openclaw.log | grep operatorOpenid
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**方法 2**: 用户首次发消息后,从日志中提取 `operatorOpenid` 字段
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 🧪 测试
|
|
161
|
+
|
|
162
|
+
### 1. 本地 Webhook 测试
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
cd <YOUR_WORKSPACE>/projects/yunzhijiachannel
|
|
166
|
+
./test-webhook.sh
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 2. 查看日志
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# 实时日志
|
|
173
|
+
tail -f /tmp/openclaw/openclaw.log | grep yunzhijia
|
|
174
|
+
|
|
175
|
+
# 最近 100 条
|
|
176
|
+
tail -100 /tmp/openclaw/openclaw.log | grep yunzhijia
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 3. 云之家测试
|
|
180
|
+
|
|
181
|
+
1. 在云之家群组中 @机器人
|
|
182
|
+
2. 发送消息:`你好`
|
|
183
|
+
3. 查看是否收到 AI 回复
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 📚 文档导航
|
|
188
|
+
|
|
189
|
+
### 部署与配置
|
|
190
|
+
- [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) - 详细部署指南
|
|
191
|
+
- [docs/PRODUCTION_CONFIG.md](docs/PRODUCTION_CONFIG.md) - 生产环境配置
|
|
192
|
+
|
|
193
|
+
### 技术文档
|
|
194
|
+
- [docs/IMPLEMENTATION.md](docs/IMPLEMENTATION.md) - 实现说明
|
|
195
|
+
- [docs/AI_INTEGRATION_GUIDE.md](docs/AI_INTEGRATION_GUIDE.md) - AI 集成指南
|
|
196
|
+
- [docs/YUNZHIJIA_API.md](docs/YUNZHIJIA_API.md) - 云之家 API 文档
|
|
197
|
+
|
|
198
|
+
### 开发文档
|
|
199
|
+
- [docs/development/](docs/development/) - 开发过程文档
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 🏗️ 项目结构
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
yunzhijiachannel/
|
|
207
|
+
├── src/ # 源代码
|
|
208
|
+
│ ├── channel.ts # Channel 核心实现
|
|
209
|
+
│ ├── webhook-server.ts # Webhook 服务器
|
|
210
|
+
│ ├── crypto.ts # 签名验证
|
|
211
|
+
│ ├── api.ts # 消息发送 API
|
|
212
|
+
│ └── ...
|
|
213
|
+
├── docs/ # 文档目录
|
|
214
|
+
│ ├── DEPLOYMENT.md
|
|
215
|
+
│ ├── PRODUCTION_CONFIG.md
|
|
216
|
+
│ └── ...
|
|
217
|
+
├── package.json # NPM 配置
|
|
218
|
+
├── openclaw.plugin.json # OpenClaw 插件清单
|
|
219
|
+
└── tsconfig.json # TypeScript 配置
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 目录说明
|
|
223
|
+
|
|
224
|
+
| 目录 | 说明 |
|
|
225
|
+
|------|------|
|
|
226
|
+
| `src/` | TypeScript 源代码 |
|
|
227
|
+
| `docs/` | 项目文档 |
|
|
228
|
+
| `dist/` | 编译输出(自动忽略) |
|
|
229
|
+
| `node_modules/` | NPM 依赖(自动忽略) |
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## 🛠️ 开发
|
|
234
|
+
|
|
235
|
+
### 环境要求
|
|
236
|
+
|
|
237
|
+
- Node.js >= 18
|
|
238
|
+
- npm >= 9
|
|
239
|
+
- OpenClaw >= 2026.3.0
|
|
240
|
+
|
|
241
|
+
### 安装依赖
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
cd <YOUR_WORKSPACE>/projects/yunzhijiachannel
|
|
245
|
+
npm install
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### 编译
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
npm run build
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### 开发模式
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
npm run dev
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### 测试
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
npm test
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 🔒 安全最佳实践
|
|
269
|
+
|
|
270
|
+
1. **保护敏感信息**
|
|
271
|
+
- 不要将 `appSecret` 和 `webhookToken` 提交到 Git
|
|
272
|
+
- 使用环境变量或密钥管理工具
|
|
273
|
+
- 定期轮换密钥
|
|
274
|
+
|
|
275
|
+
2. **访问控制**
|
|
276
|
+
- 使用 `allowFrom` 白名单限制用户
|
|
277
|
+
- 配置 `dmPolicy: "allowlist"`
|
|
278
|
+
- 群组启用 `requireMention: true`
|
|
279
|
+
|
|
280
|
+
3. **网络安全**
|
|
281
|
+
- 使用 HTTPS 部署 Webhook
|
|
282
|
+
- 配置防火墙限制访问来源
|
|
283
|
+
- 定期审计日志
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## 🐛 故障排查
|
|
288
|
+
|
|
289
|
+
### 收不到消息
|
|
290
|
+
|
|
291
|
+
1. 检查云之家 Webhook 地址是否正确
|
|
292
|
+
2. 检查外网映射是否正常
|
|
293
|
+
3. 检查防火墙设置
|
|
294
|
+
4. 查看 Gateway 日志
|
|
295
|
+
|
|
296
|
+
### 签名验证失败
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# 检查 appSecret 是否正确
|
|
300
|
+
tail /tmp/openclaw/openclaw.log | grep "Invalid signature"
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### 无法发送回复
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
# 检查 webhookToken 是否正确
|
|
307
|
+
tail /tmp/openclaw/openclaw.log | grep "发送失败"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## 📄 许可证
|
|
313
|
+
|
|
314
|
+
MIT License
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## 🤝 贡献
|
|
319
|
+
|
|
320
|
+
欢迎提交 Issue 和 Pull Request!
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
**版本**: v2.0.0
|
|
325
|
+
**最后更新**: 2026-03-07
|
|
326
|
+
**维护者**: Zed
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { YunzhiJiaSendResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* 发送文本消息
|
|
4
|
+
*/
|
|
5
|
+
export declare function sendTextMessage(params: {
|
|
6
|
+
webhookToken: string;
|
|
7
|
+
content: string;
|
|
8
|
+
notifyParams?: Array<{
|
|
9
|
+
type: string;
|
|
10
|
+
values: string[];
|
|
11
|
+
}>;
|
|
12
|
+
}): Promise<YunzhiJiaSendResult>;
|
|
13
|
+
/**
|
|
14
|
+
* 发送应用类消息
|
|
15
|
+
*/
|
|
16
|
+
export declare function sendAppMessage(params: {
|
|
17
|
+
webhookToken: string;
|
|
18
|
+
content: string;
|
|
19
|
+
param: {
|
|
20
|
+
appName: string;
|
|
21
|
+
title: string;
|
|
22
|
+
content?: string;
|
|
23
|
+
lightAppId?: string;
|
|
24
|
+
thumbUrl?: string;
|
|
25
|
+
webpageUrl?: string;
|
|
26
|
+
customStyle?: 0 | 1 | 2;
|
|
27
|
+
primaryContent?: string;
|
|
28
|
+
contentUrl?: string;
|
|
29
|
+
};
|
|
30
|
+
}): Promise<YunzhiJiaSendResult>;
|
|
31
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAKtD;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC1D,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA8B/B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA8B/B"}
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
const WEBHOOK_BASE_URL = "https://www.yunzhijia.com/gateway/robot/webhook/send";
|
|
3
|
+
const WEBHOOK_DEFAULT_PARAMS = "?yzjtype=12&yzjtoken=";
|
|
4
|
+
/**
|
|
5
|
+
* 发送文本消息
|
|
6
|
+
*/
|
|
7
|
+
export async function sendTextMessage(params) {
|
|
8
|
+
const { webhookToken, content, notifyParams } = params;
|
|
9
|
+
// 使用配置的 yzjtype=12
|
|
10
|
+
const url = `${WEBHOOK_BASE_URL}${WEBHOOK_DEFAULT_PARAMS}${webhookToken}`;
|
|
11
|
+
const payload = { content };
|
|
12
|
+
if (notifyParams) {
|
|
13
|
+
payload.notifyParams = notifyParams;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const response = await axios.post(url, payload, {
|
|
17
|
+
headers: {
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
messageId: `yj_${Date.now()}`,
|
|
23
|
+
success: true,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
28
|
+
return {
|
|
29
|
+
messageId: `yj_${Date.now()}`,
|
|
30
|
+
success: false,
|
|
31
|
+
error: errorMessage,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 发送应用类消息
|
|
37
|
+
*/
|
|
38
|
+
export async function sendAppMessage(params) {
|
|
39
|
+
const { webhookToken, content, param } = params;
|
|
40
|
+
const url = `${WEBHOOK_BASE_URL}?yzjtype=0&yzjtoken=${webhookToken}`;
|
|
41
|
+
const payload = {
|
|
42
|
+
content,
|
|
43
|
+
msgType: 1,
|
|
44
|
+
param,
|
|
45
|
+
};
|
|
46
|
+
try {
|
|
47
|
+
const response = await axios.post(url, payload, {
|
|
48
|
+
headers: {
|
|
49
|
+
"Content-Type": "application/json",
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
messageId: `yj_${Date.now()}`,
|
|
54
|
+
success: true,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
59
|
+
return {
|
|
60
|
+
messageId: `yj_${Date.now()}`,
|
|
61
|
+
success: false,
|
|
62
|
+
error: errorMessage,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,gBAAgB,GAAG,sDAAsD,CAAC;AAChF,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAEvD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAIrC;IACC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAEvD,mBAAmB;IACnB,MAAM,GAAG,GAAG,GAAG,gBAAgB,GAAG,sBAAsB,GAAG,YAAY,EAAE,CAAC;IAE1E,MAAM,OAAO,GAA4B,EAAE,OAAO,EAAE,CAAC;IACrD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CAAC,YAAY,GAAG,YAAY,CAAC;IACtC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE;YAC9C,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE;YAC7B,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE;YAC7B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,YAAY;SACpB,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAcpC;IACC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAEhD,MAAM,GAAG,GAAG,GAAG,gBAAgB,uBAAuB,YAAY,EAAE,CAAC;IAErE,MAAM,OAAO,GAAG;QACd,OAAO;QACP,OAAO,EAAE,CAAC;QACV,KAAK;KACN,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE;YAC9C,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE;YAC7B,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE;YAC7B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,YAAY;SACpB,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-simple.d.ts","sourceRoot":"","sources":["../src/channel-simple.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAiB,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAwD5E,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,iBAAiB,QAGtD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// 简化的云之家 Channel 插件 - 框架版本
|
|
2
|
+
// 完整实现需要参考 Telegram 插件结构
|
|
3
|
+
import { setYunzhiJiaRuntime } from "./runtime.js";
|
|
4
|
+
const yunzhijiaPlugin = {
|
|
5
|
+
id: "yunzhijia",
|
|
6
|
+
meta: {
|
|
7
|
+
id: "yunzhijia",
|
|
8
|
+
label: "金蝶云之家",
|
|
9
|
+
selectionLabel: "金蝶云之家 (Webhook)",
|
|
10
|
+
docsPath: "/channels/yunzhijia",
|
|
11
|
+
blurb: "金蝶云之家企业消息平台",
|
|
12
|
+
aliases: ["yzj"],
|
|
13
|
+
},
|
|
14
|
+
capabilities: {
|
|
15
|
+
chatTypes: ["direct", "group"],
|
|
16
|
+
reactions: false,
|
|
17
|
+
threads: false,
|
|
18
|
+
media: false,
|
|
19
|
+
polls: false,
|
|
20
|
+
nativeCommands: false,
|
|
21
|
+
blockStreaming: false,
|
|
22
|
+
},
|
|
23
|
+
reload: { configPrefixes: ["channels.yunzhijia"] },
|
|
24
|
+
config: {
|
|
25
|
+
listAccountIds: (cfg) => {
|
|
26
|
+
const accounts = cfg.channels?.yunzhijia?.accounts;
|
|
27
|
+
return accounts ? Object.keys(accounts) : ["default"];
|
|
28
|
+
},
|
|
29
|
+
resolveAccount: (cfg, accountId) => {
|
|
30
|
+
const id = accountId ?? "default";
|
|
31
|
+
const accounts = cfg.channels?.yunzhijia?.accounts;
|
|
32
|
+
return accounts?.[id] ?? { accountId: id };
|
|
33
|
+
},
|
|
34
|
+
defaultAccountId: () => "default",
|
|
35
|
+
},
|
|
36
|
+
outbound: {
|
|
37
|
+
deliveryMode: "direct",
|
|
38
|
+
sendText: async ({ to, text }) => {
|
|
39
|
+
// TODO: 实现发送逻辑
|
|
40
|
+
return { channel: "yunzhijia", messageId: `yj_${Date.now()}` };
|
|
41
|
+
},
|
|
42
|
+
sendMedia: async () => {
|
|
43
|
+
throw new Error("媒体消息暂不支持");
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
gateway: {
|
|
47
|
+
startAccount: async (ctx) => {
|
|
48
|
+
ctx.log?.info?.(`[${ctx.accountId}] 云之家插件已加载 (框架版本)`);
|
|
49
|
+
// TODO: 实现 Webhook 服务器
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
ctx.abortSignal?.addEventListener("abort", () => resolve());
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
export default function register(api) {
|
|
57
|
+
setYunzhiJiaRuntime(api.runtime);
|
|
58
|
+
api.registerChannel({ plugin: yunzhijiaPlugin });
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=channel-simple.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-simple.js","sourceRoot":"","sources":["../src/channel-simple.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,yBAAyB;AAGzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,eAAe,GAAkB;IACrC,EAAE,EAAE,WAAW;IACf,IAAI,EAAE;QACJ,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,OAAO;QACd,cAAc,EAAE,iBAAiB;QACjC,QAAQ,EAAE,qBAAqB;QAC/B,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,CAAC,KAAK,CAAC;KACjB;IACD,YAAY,EAAE;QACZ,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC9B,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,KAAK;QACZ,cAAc,EAAE,KAAK;QACrB,cAAc,EAAE,KAAK;KACtB;IACD,MAAM,EAAE,EAAE,cAAc,EAAE,CAAC,oBAAoB,CAAC,EAAE;IAClD,MAAM,EAAE;QACN,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE;YACtB,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC;YACnD,OAAO,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACxD,CAAC;QACD,cAAc,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE;YACjC,MAAM,EAAE,GAAG,SAAS,IAAI,SAAS,CAAC;YAClC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC;YACnD,OAAO,QAAQ,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QAC7C,CAAC;QACD,gBAAgB,EAAE,GAAG,EAAE,CAAC,SAAS;KAClC;IACD,QAAQ,EAAE;QACR,YAAY,EAAE,QAAQ;QACtB,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YAC/B,eAAe;YACf,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC;QACjE,CAAC;QACD,SAAS,EAAE,KAAK,IAAI,EAAE;YACpB,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;QAC9B,CAAC;KACF;IACD,OAAO,EAAE;QACP,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC1B,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,SAAS,mBAAmB,CAAC,CAAC;YACtD,uBAAuB;YACvB,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBACnC,GAAG,CAAC,WAAW,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9D,CAAC,CAAC,CAAC;QACL,CAAC;KACF;CACF,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAsB;IACrD,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACjC,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ChannelPlugin } from "openclaw/plugin-sdk";
|
|
2
|
+
export interface YunzhiJiaAccount {
|
|
3
|
+
accountId: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
appId: string;
|
|
7
|
+
appSecret: string;
|
|
8
|
+
token: string;
|
|
9
|
+
webhookToken?: string;
|
|
10
|
+
encodingAesKey?: string;
|
|
11
|
+
webhookPath?: string;
|
|
12
|
+
webhookPort?: number;
|
|
13
|
+
webhookHost?: string;
|
|
14
|
+
config: {
|
|
15
|
+
dmPolicy?: "pairing" | "allowlist" | "open" | "disabled";
|
|
16
|
+
allowFrom?: string[];
|
|
17
|
+
groupPolicy?: "open" | "allowlist" | "disabled";
|
|
18
|
+
groupAllowFrom?: string[];
|
|
19
|
+
groups?: Record<string, {
|
|
20
|
+
requireMention?: boolean;
|
|
21
|
+
groupPolicy?: "open" | "allowlist";
|
|
22
|
+
}>;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface YunzhiJiaProbe {
|
|
26
|
+
ok: boolean;
|
|
27
|
+
appInfo?: {
|
|
28
|
+
name?: string;
|
|
29
|
+
id?: string;
|
|
30
|
+
};
|
|
31
|
+
error?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare const yunzhijiaPlugin: ChannelPlugin;
|
|
34
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAWL,KAAK,aAAa,EAEnB,MAAM,qBAAqB,CAAC;AAW7B,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE;QACN,QAAQ,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;QACzD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;QAChD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,cAAc,CAAC,EAAE,OAAO,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;SAAE,CAAC,CAAC;KAC3F,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAC;KACb,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+DD,eAAO,MAAM,eAAe,EAAE,aAgX7B,CAAC"}
|