@zhin.js/adapter-dingtalk 1.0.1
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/CHANGELOG.md +25 -0
- package/LICENSE +21 -0
- package/README.md +365 -0
- package/lib/index.d.ts +65 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +499 -0
- package/lib/index.js.map +1 -0
- package/package.json +56 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @zhin.js/adapter-dingtalk
|
|
2
|
+
|
|
3
|
+
## 1.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- cda76be: fix: add adapters
|
|
8
|
+
|
|
9
|
+
## 1.0.0 (2024-11-19)
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
- **adapter-dingtalk**: 初始版本发布
|
|
14
|
+
- **adapter-dingtalk**: 支持企业内部机器人
|
|
15
|
+
- **adapter-dingtalk**: 支持接收文本、图片、文件、语音、视频等消息类型
|
|
16
|
+
- **adapter-dingtalk**: 支持发送文本、Markdown、链接等消息类型
|
|
17
|
+
- **adapter-dingtalk**: 支持 @ 提醒功能
|
|
18
|
+
- **adapter-dingtalk**: 实现签名验证,确保安全性
|
|
19
|
+
- **adapter-dingtalk**: 自动管理 access_token
|
|
20
|
+
- **adapter-dingtalk**: 提供用户信息、部门用户等 API 接口
|
|
21
|
+
- **adapter-dingtalk**: 支持发送工作通知
|
|
22
|
+
|
|
23
|
+
### Changes
|
|
24
|
+
|
|
25
|
+
- **adapter-dingtalk**: 使用 fetch 替代 axios,减少依赖
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 凉菜
|
|
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,365 @@
|
|
|
1
|
+
# @zhin.js/adapter-dingtalk
|
|
2
|
+
|
|
3
|
+
Zhin.js 钉钉适配器,支持企业内部机器人和钉钉开放平台机器人开发。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @zhin.js/adapter-dingtalk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 配置
|
|
12
|
+
|
|
13
|
+
### 基础配置
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { DingTalkBotConfig } from '@zhin.js/adapter-dingtalk';
|
|
17
|
+
|
|
18
|
+
const config: DingTalkBotConfig = {
|
|
19
|
+
context: 'dingtalk',
|
|
20
|
+
name: 'my-dingtalk-bot',
|
|
21
|
+
appKey: 'YOUR_APP_KEY', // 钉钉应用 AppKey
|
|
22
|
+
appSecret: 'YOUR_APP_SECRET', // 钉钉应用 AppSecret
|
|
23
|
+
webhookPath: '/dingtalk/webhook', // Webhook 路径
|
|
24
|
+
robotCode: 'YOUR_ROBOT_CODE' // 机器人编码(可选)
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 完整配置
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
const config: DingTalkBotConfig = {
|
|
32
|
+
context: 'dingtalk',
|
|
33
|
+
name: 'my-dingtalk-bot',
|
|
34
|
+
appKey: 'YOUR_APP_KEY',
|
|
35
|
+
appSecret: 'YOUR_APP_SECRET',
|
|
36
|
+
webhookPath: '/dingtalk/webhook',
|
|
37
|
+
robotCode: 'YOUR_ROBOT_CODE',
|
|
38
|
+
|
|
39
|
+
// API 配置
|
|
40
|
+
apiBaseUrl: 'https://oapi.dingtalk.com' // 自定义API地址(可选)
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 配置参数说明
|
|
45
|
+
|
|
46
|
+
- `appKey` (必需): 钉钉应用的 AppKey,在开发者后台获取
|
|
47
|
+
- `appSecret` (必需): 钉钉应用的 AppSecret,在开发者后台获取
|
|
48
|
+
- `webhookPath` (必需): Webhook 路径,如 `/dingtalk/webhook`
|
|
49
|
+
- `robotCode` (可选): 机器人编码,用于发送消息时识别机器人身份
|
|
50
|
+
- `apiBaseUrl` (可选): 自定义 API 基础地址,默认为 `https://oapi.dingtalk.com`
|
|
51
|
+
|
|
52
|
+
## 获取配置信息
|
|
53
|
+
|
|
54
|
+
### 创建钉钉企业内部应用
|
|
55
|
+
|
|
56
|
+
1. **访问钉钉开放平台**
|
|
57
|
+
- 登录 [钉钉开放平台](https://open.dingtalk.com/)
|
|
58
|
+
- 进入「应用开发」→「企业内部开发」
|
|
59
|
+
|
|
60
|
+
2. **创建应用**
|
|
61
|
+
- 点击「创建应用」
|
|
62
|
+
- 选择「企业内部开发」→「机器人」
|
|
63
|
+
- 填写应用基本信息(应用名称、应用描述、应用图标等)
|
|
64
|
+
|
|
65
|
+
3. **获取应用凭证**
|
|
66
|
+
- 在应用详情页面找到「开发管理」
|
|
67
|
+
- 获取 **AppKey** 和 **AppSecret**
|
|
68
|
+
- 记录这些信息用于配置
|
|
69
|
+
|
|
70
|
+
### 配置机器人
|
|
71
|
+
|
|
72
|
+
1. **配置机器人能力**
|
|
73
|
+
- 在应用详情页面,进入「机器人配置」
|
|
74
|
+
- 启用「消息接收」功能
|
|
75
|
+
- 获取机器人的 **RobotCode**(机器人编码)
|
|
76
|
+
|
|
77
|
+
2. **配置消息接收地址**
|
|
78
|
+
- 在「消息接收」设置中配置接收地址
|
|
79
|
+
- 设置请求 URL:`https://yourdomain.com/dingtalk/webhook`
|
|
80
|
+
- 钉钉会通过该地址推送消息事件
|
|
81
|
+
|
|
82
|
+
3. **配置权限**
|
|
83
|
+
- 在「权限管理」中申请所需权限:
|
|
84
|
+
- `通讯录只读权限` - 读取通讯录信息
|
|
85
|
+
- `企业通讯录个人信息读权限` - 获取用户详细信息
|
|
86
|
+
- `消息通知` - 发送工作通知
|
|
87
|
+
- 其他业务需要的权限
|
|
88
|
+
|
|
89
|
+
4. **发布应用**
|
|
90
|
+
- 完成配置后,发布应用
|
|
91
|
+
- 在企业工作台添加应用
|
|
92
|
+
- 员工可在钉钉中找到并使用该机器人
|
|
93
|
+
|
|
94
|
+
### 创建群机器人(Webhook 机器人)
|
|
95
|
+
|
|
96
|
+
如果只需要简单的群聊机器人功能:
|
|
97
|
+
|
|
98
|
+
1. **在群聊中添加机器人**
|
|
99
|
+
- 进入钉钉群聊
|
|
100
|
+
- 点击群设置 → 「智能群助手」
|
|
101
|
+
- 选择「添加机器人」→「自定义机器人」
|
|
102
|
+
|
|
103
|
+
2. **配置 Webhook**
|
|
104
|
+
- 输入机器人名称
|
|
105
|
+
- 获取 Webhook 地址
|
|
106
|
+
- 配置安全设置(加签或关键词)
|
|
107
|
+
|
|
108
|
+
3. **使用限制**
|
|
109
|
+
- 群机器人只能在对应群聊中使用
|
|
110
|
+
- 功能相对简单,适合轻量级场景
|
|
111
|
+
|
|
112
|
+
## 使用示例
|
|
113
|
+
|
|
114
|
+
### 配置文件(zhin.config.ts)
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { defineConfig } from 'zhin.js'
|
|
118
|
+
|
|
119
|
+
export default defineConfig({
|
|
120
|
+
bots: [
|
|
121
|
+
{
|
|
122
|
+
name: 'dingtalk-bot',
|
|
123
|
+
context: 'dingtalk',
|
|
124
|
+
appKey: 'dingxxxxxxxxxx',
|
|
125
|
+
appSecret: 'your-app-secret',
|
|
126
|
+
webhookPath: '/dingtalk/webhook',
|
|
127
|
+
robotCode: 'dingxxxxxxxxxxxxxxxx'
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
plugins: [
|
|
131
|
+
'http', // HTTP 服务(必需,提供 webhook 接口)
|
|
132
|
+
'adapter-dingtalk', // 钉钉适配器
|
|
133
|
+
// 其他插件...
|
|
134
|
+
]
|
|
135
|
+
})
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 接收和发送消息
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { addCommand, MessageCommand, useLogger } from 'zhin.js'
|
|
142
|
+
|
|
143
|
+
const logger = useLogger()
|
|
144
|
+
|
|
145
|
+
// 定义命令
|
|
146
|
+
addCommand(new MessageCommand('hello <name:text>')
|
|
147
|
+
.action(async (message, result) => {
|
|
148
|
+
logger.info(`收到来自 ${result.params.name} 的问候`)
|
|
149
|
+
return `你好,${result.params.name}!欢迎使用钉钉机器人。`
|
|
150
|
+
})
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
// 监听所有消息
|
|
154
|
+
import { onMessage } from 'zhin.js'
|
|
155
|
+
|
|
156
|
+
onMessage(async (message) => {
|
|
157
|
+
logger.info(`收到消息:${message.$raw}`)
|
|
158
|
+
logger.info(`发送者:${message.$sender.name}`)
|
|
159
|
+
logger.info(`会话类型:${message.$channel.type}`)
|
|
160
|
+
})
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 使用 @ 功能
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
addCommand(new MessageCommand('notify <...users:at>')
|
|
167
|
+
.action(async (message, result) => {
|
|
168
|
+
const users = result.params.users
|
|
169
|
+
return [
|
|
170
|
+
{ type: 'text', data: { content: '通知以下用户:\n' } },
|
|
171
|
+
...users.map(user => ({
|
|
172
|
+
type: 'at',
|
|
173
|
+
data: { id: user.data.id, name: user.data.name }
|
|
174
|
+
})),
|
|
175
|
+
{ type: 'text', data: { content: '\n请注意查看!' } }
|
|
176
|
+
]
|
|
177
|
+
})
|
|
178
|
+
)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### 发送富文本消息
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
addCommand(new MessageCommand('info')
|
|
185
|
+
.action(async (message) => {
|
|
186
|
+
return [
|
|
187
|
+
{
|
|
188
|
+
type: 'markdown',
|
|
189
|
+
data: {
|
|
190
|
+
title: '系统信息',
|
|
191
|
+
content: `
|
|
192
|
+
# 系统信息
|
|
193
|
+
|
|
194
|
+
## 基本信息
|
|
195
|
+
- **服务器**: 运行正常
|
|
196
|
+
- **版本**: v1.0.0
|
|
197
|
+
- **状态**: ✅ 在线
|
|
198
|
+
|
|
199
|
+
## 功能列表
|
|
200
|
+
1. 消息接收与发送
|
|
201
|
+
2. 命令解析
|
|
202
|
+
3. @ 提醒功能
|
|
203
|
+
`
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
})
|
|
208
|
+
)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## 消息类型支持
|
|
212
|
+
|
|
213
|
+
### 接收消息类型
|
|
214
|
+
|
|
215
|
+
- ✅ **文本消息** (`text`) - 普通文本和 @ 提醒
|
|
216
|
+
- ✅ **图片消息** (`picture`) - 图片文件
|
|
217
|
+
- ✅ **文件消息** (`file`) - 各类文件
|
|
218
|
+
- ✅ **语音消息** (`audio`) - 音频文件
|
|
219
|
+
- ✅ **视频消息** (`video`) - 视频文件
|
|
220
|
+
- ✅ **富文本消息** (`richText`) - 富文本内容
|
|
221
|
+
- ✅ **Markdown 消息** (`markdown`) - Markdown 格式
|
|
222
|
+
|
|
223
|
+
### 发送消息类型
|
|
224
|
+
|
|
225
|
+
- ✅ **文本消息** - 支持 @ 提醒
|
|
226
|
+
- ✅ **图片消息** - 通过 URL 发送
|
|
227
|
+
- ✅ **Markdown 消息** - 富文本展示
|
|
228
|
+
- ✅ **链接消息** - 卡片式链接
|
|
229
|
+
- ❌ **撤回消息** - 钉钉机器人不支持撤回
|
|
230
|
+
|
|
231
|
+
## API 方法
|
|
232
|
+
|
|
233
|
+
### 获取用户信息
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const bot = app.adapters.get('dingtalk')?.bots.get('dingtalk-bot')
|
|
237
|
+
if (bot) {
|
|
238
|
+
const userInfo = await bot.getUserInfo('user-id')
|
|
239
|
+
console.log(userInfo)
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 获取部门用户列表
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
const users = await bot.getDepartmentUsers(1) // 部门 ID
|
|
247
|
+
console.log(users)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### 发送工作通知
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
await bot.sendWorkNotice(
|
|
254
|
+
['user1', 'user2'], // 用户 ID 列表
|
|
255
|
+
{
|
|
256
|
+
msgtype: 'text',
|
|
257
|
+
text: { content: '这是一条工作通知' }
|
|
258
|
+
}
|
|
259
|
+
)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## 安全说明
|
|
263
|
+
|
|
264
|
+
### 签名验证
|
|
265
|
+
|
|
266
|
+
钉钉会在 Webhook 请求的 Header 中携带签名信息:
|
|
267
|
+
- `timestamp`: 时间戳
|
|
268
|
+
- `sign`: 签名值
|
|
269
|
+
|
|
270
|
+
适配器会自动验证签名,确保请求来自钉钉服务器。
|
|
271
|
+
|
|
272
|
+
### Token 管理
|
|
273
|
+
|
|
274
|
+
适配器会自动管理 access_token:
|
|
275
|
+
- 首次连接时获取 token
|
|
276
|
+
- Token 过期前 5 分钟自动刷新
|
|
277
|
+
- 所有 API 请求自动携带有效 token
|
|
278
|
+
|
|
279
|
+
## 最佳实践
|
|
280
|
+
|
|
281
|
+
### 1. 配置环境变量
|
|
282
|
+
|
|
283
|
+
不要在代码中硬编码敏感信息:
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
export default defineConfig({
|
|
287
|
+
bots: [{
|
|
288
|
+
name: 'dingtalk-bot',
|
|
289
|
+
context: 'dingtalk',
|
|
290
|
+
appKey: process.env.DINGTALK_APP_KEY!,
|
|
291
|
+
appSecret: process.env.DINGTALK_APP_SECRET!,
|
|
292
|
+
webhookPath: '/dingtalk/webhook',
|
|
293
|
+
robotCode: process.env.DINGTALK_ROBOT_CODE
|
|
294
|
+
}]
|
|
295
|
+
})
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### 2. 错误处理
|
|
299
|
+
|
|
300
|
+
处理可能的错误情况:
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
onMessage(async (message) => {
|
|
304
|
+
try {
|
|
305
|
+
// 处理消息逻辑
|
|
306
|
+
} catch (error) {
|
|
307
|
+
logger.error('处理消息失败:', error)
|
|
308
|
+
await message.$reply('抱歉,处理消息时出现错误')
|
|
309
|
+
}
|
|
310
|
+
})
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### 3. 消息限流
|
|
314
|
+
|
|
315
|
+
注意钉钉的 API 调用频率限制,避免过于频繁的请求。
|
|
316
|
+
|
|
317
|
+
### 4. 日志记录
|
|
318
|
+
|
|
319
|
+
开启详细日志,便于排查问题:
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
export default defineConfig({
|
|
323
|
+
log_level: 'debug', // 开发环境使用 debug
|
|
324
|
+
// ... 其他配置
|
|
325
|
+
})
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## 常见问题
|
|
329
|
+
|
|
330
|
+
### Q: Webhook 收不到消息?
|
|
331
|
+
|
|
332
|
+
A: 检查以下几点:
|
|
333
|
+
1. Webhook URL 是否可以从公网访问
|
|
334
|
+
2. 钉钉后台的消息接收地址是否配置正确
|
|
335
|
+
3. 应用是否已经发布并添加到工作台
|
|
336
|
+
4. 检查服务器日志是否有错误信息
|
|
337
|
+
|
|
338
|
+
### Q: 发送消息失败?
|
|
339
|
+
|
|
340
|
+
A: 可能的原因:
|
|
341
|
+
1. AppKey 或 AppSecret 配置错误
|
|
342
|
+
2. access_token 获取失败
|
|
343
|
+
3. 机器人编码(robotCode)配置错误
|
|
344
|
+
4. 网络问题或 API 限流
|
|
345
|
+
|
|
346
|
+
### Q: @ 功能不生效?
|
|
347
|
+
|
|
348
|
+
A: 确保:
|
|
349
|
+
1. 使用正确的用户 ID 格式
|
|
350
|
+
2. @ 的用户在当前会话中
|
|
351
|
+
3. 消息格式正确包含 at 字段
|
|
352
|
+
|
|
353
|
+
## 相关链接
|
|
354
|
+
|
|
355
|
+
- [钉钉开放平台](https://open.dingtalk.com/)
|
|
356
|
+
- [钉钉机器人开发文档](https://open.dingtalk.com/document/robots/robot-overview)
|
|
357
|
+
- [Zhin.js 官方文档](https://github.com/zhinjs/zhin)
|
|
358
|
+
|
|
359
|
+
## 许可证
|
|
360
|
+
|
|
361
|
+
MIT License
|
|
362
|
+
|
|
363
|
+
## 贡献
|
|
364
|
+
|
|
365
|
+
欢迎提交 Issue 和 Pull Request!
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Bot, Adapter, Message, SendOptions } from "zhin.js";
|
|
2
|
+
declare module '@zhin.js/types' {
|
|
3
|
+
interface RegisteredAdapters {
|
|
4
|
+
dingtalk: Adapter<DingTalkBot>;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export interface DingTalkBotConfig extends Bot.Config {
|
|
8
|
+
context: 'dingtalk';
|
|
9
|
+
name: string;
|
|
10
|
+
appKey: string;
|
|
11
|
+
appSecret: string;
|
|
12
|
+
webhookPath: string;
|
|
13
|
+
robotCode?: string;
|
|
14
|
+
apiBaseUrl?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface DingTalkMessage {
|
|
17
|
+
msgtype?: string;
|
|
18
|
+
text?: {
|
|
19
|
+
content?: string;
|
|
20
|
+
};
|
|
21
|
+
msgId?: string;
|
|
22
|
+
createAt?: number;
|
|
23
|
+
conversationType?: string;
|
|
24
|
+
conversationId?: string;
|
|
25
|
+
senderId?: string;
|
|
26
|
+
senderNick?: string;
|
|
27
|
+
senderCorpId?: string;
|
|
28
|
+
sessionWebhook?: string;
|
|
29
|
+
chatbotCorpId?: string;
|
|
30
|
+
chatbotUserId?: string;
|
|
31
|
+
isAdmin?: boolean;
|
|
32
|
+
senderStaffId?: string;
|
|
33
|
+
atUsers?: Array<{
|
|
34
|
+
dingtalkId?: string;
|
|
35
|
+
staffId?: string;
|
|
36
|
+
}>;
|
|
37
|
+
content?: any;
|
|
38
|
+
}
|
|
39
|
+
export declare class DingTalkBot implements Bot<DingTalkMessage, DingTalkBotConfig> {
|
|
40
|
+
$config: DingTalkBotConfig;
|
|
41
|
+
$connected?: boolean;
|
|
42
|
+
private router;
|
|
43
|
+
private accessToken;
|
|
44
|
+
private baseURL;
|
|
45
|
+
private sessionWebhooks;
|
|
46
|
+
constructor(router: any, $config: DingTalkBotConfig);
|
|
47
|
+
private request;
|
|
48
|
+
private setupWebhookRoute;
|
|
49
|
+
private handleWebhook;
|
|
50
|
+
private verifySignature;
|
|
51
|
+
private handleEvent;
|
|
52
|
+
private ensureAccessToken;
|
|
53
|
+
private refreshAccessToken;
|
|
54
|
+
$formatMessage(msg: DingTalkMessage): Message<DingTalkMessage>;
|
|
55
|
+
private parseMessageContent;
|
|
56
|
+
$sendMessage(options: SendOptions): Promise<string>;
|
|
57
|
+
$recallMessage(id: string): Promise<void>;
|
|
58
|
+
private formatSendContent;
|
|
59
|
+
$connect(): Promise<void>;
|
|
60
|
+
$disconnect(): Promise<void>;
|
|
61
|
+
getUserInfo(userId: string): Promise<any>;
|
|
62
|
+
getDepartmentUsers(deptId: number): Promise<any[]>;
|
|
63
|
+
sendWorkNotice(userIdList: string[], content: any): Promise<boolean>;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,GAAG,EAEH,OAAO,EAEP,OAAO,EACP,WAAW,EAKd,MAAM,SAAS,CAAC;AAKjB,OAAO,QAAQ,gBAAgB,CAAA;IAC3B,UAAU,kBAAkB;QACxB,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;KACjC;CACJ;AAKD,MAAM,WAAW,iBAAkB,SAAQ,GAAG,CAAC,MAAM;IACjD,OAAO,EAAE,UAAU,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AAGD,MAAM,WAAW,eAAe;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE;QACH,OAAO,CAAC,EAAE,MAAM,CAAA;KACnB,CAAA;IACD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,KAAK,CAAC;QACZ,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,OAAO,CAAC,EAAE,MAAM,CAAA;KACnB,CAAC,CAAA;IACF,OAAO,CAAC,EAAE,GAAG,CAAA;CAChB;AAgCD,qBAAa,WAAY,YAAW,GAAG,CAAC,eAAe,EAAE,iBAAiB,CAAC;IAOvC,OAAO,EAAE,iBAAiB;IAN1D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,eAAe,CAAiC;gBAE5C,MAAM,EAAE,GAAG,EAAS,OAAO,EAAE,iBAAiB;YAa5C,OAAO;IAgCrB,OAAO,CAAC,iBAAiB;YAMX,aAAa;IAmC3B,OAAO,CAAC,eAAe;YAaT,WAAW;YAiBX,iBAAiB;YAUjB,kBAAkB;IAgChC,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAoC9D,OAAO,CAAC,mBAAmB;IAmGrB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IA6CnD,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK/C,OAAO,CAAC,iBAAiB;IAgHnB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAezB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAc5B,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAqBzC,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAqBlD,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC;CAsB7E"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { usePlugin, Adapter, registerAdapter, Message, segment, useContext } from "zhin.js";
|
|
2
|
+
import { createHmac } from 'crypto';
|
|
3
|
+
const plugin = usePlugin();
|
|
4
|
+
// ================================================================================================
|
|
5
|
+
// DingTalkBot 类
|
|
6
|
+
// ================================================================================================
|
|
7
|
+
export class DingTalkBot {
|
|
8
|
+
$config;
|
|
9
|
+
$connected;
|
|
10
|
+
router;
|
|
11
|
+
accessToken;
|
|
12
|
+
baseURL;
|
|
13
|
+
sessionWebhooks = new Map(); // conversationId -> webhook
|
|
14
|
+
constructor(router, $config) {
|
|
15
|
+
this.$config = $config;
|
|
16
|
+
this.router = router;
|
|
17
|
+
this.$connected = false;
|
|
18
|
+
this.accessToken = { token: '', expires_in: 0, timestamp: 0 };
|
|
19
|
+
// 设置 API 基础 URL
|
|
20
|
+
this.baseURL = $config.apiBaseUrl || 'https://oapi.dingtalk.com';
|
|
21
|
+
// 设置 webhook 路由
|
|
22
|
+
this.setupWebhookRoute();
|
|
23
|
+
}
|
|
24
|
+
// 封装 fetch 请求方法
|
|
25
|
+
async request(path, options = {}) {
|
|
26
|
+
await this.ensureAccessToken();
|
|
27
|
+
const { method = 'GET', params = {}, body } = options;
|
|
28
|
+
// 添加 access_token 到查询参数
|
|
29
|
+
const urlParams = new URLSearchParams({
|
|
30
|
+
...params,
|
|
31
|
+
access_token: this.accessToken.token
|
|
32
|
+
});
|
|
33
|
+
const url = `${this.baseURL}${path}?${urlParams.toString()}`;
|
|
34
|
+
const fetchOptions = {
|
|
35
|
+
method,
|
|
36
|
+
headers: {
|
|
37
|
+
'Content-Type': 'application/json; charset=utf-8'
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
if (body && method === 'POST') {
|
|
41
|
+
fetchOptions.body = JSON.stringify(body);
|
|
42
|
+
}
|
|
43
|
+
const response = await fetch(url, fetchOptions);
|
|
44
|
+
return await response.json();
|
|
45
|
+
}
|
|
46
|
+
setupWebhookRoute() {
|
|
47
|
+
this.router.post(this.$config.webhookPath, (ctx) => {
|
|
48
|
+
this.handleWebhook(ctx);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async handleWebhook(ctx) {
|
|
52
|
+
try {
|
|
53
|
+
const body = ctx.request.body;
|
|
54
|
+
const headers = ctx.request.headers;
|
|
55
|
+
// 钉钉签名验证
|
|
56
|
+
const timestamp = headers['timestamp'];
|
|
57
|
+
const sign = headers['sign'];
|
|
58
|
+
if (timestamp && sign) {
|
|
59
|
+
if (!this.verifySignature(timestamp, sign)) {
|
|
60
|
+
plugin.logger.warn('Invalid signature in webhook');
|
|
61
|
+
ctx.status = 403;
|
|
62
|
+
ctx.body = { code: -1, msg: 'Forbidden' };
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const event = body;
|
|
67
|
+
// 处理消息事件
|
|
68
|
+
if (event.msgtype) {
|
|
69
|
+
await this.handleEvent(event);
|
|
70
|
+
}
|
|
71
|
+
ctx.status = 200;
|
|
72
|
+
ctx.body = { code: 0, msg: 'success' };
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
plugin.logger.error('Webhook error:', error);
|
|
76
|
+
ctx.status = 500;
|
|
77
|
+
ctx.body = { code: -1, msg: 'Internal Server Error' };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
verifySignature(timestamp, sign) {
|
|
81
|
+
try {
|
|
82
|
+
const stringToSign = `${timestamp}\n${this.$config.appSecret}`;
|
|
83
|
+
const hmac = createHmac('sha256', this.$config.appSecret);
|
|
84
|
+
hmac.update(stringToSign);
|
|
85
|
+
const calculatedSign = hmac.digest('base64');
|
|
86
|
+
return calculatedSign === sign;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
plugin.logger.error('Signature verification error:', error);
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async handleEvent(event) {
|
|
94
|
+
// 存储会话 webhook(用于回复消息)
|
|
95
|
+
if (event.sessionWebhook && event.conversationId) {
|
|
96
|
+
this.sessionWebhooks.set(event.conversationId, event.sessionWebhook);
|
|
97
|
+
}
|
|
98
|
+
// 处理消息事件
|
|
99
|
+
const message = this.$formatMessage(event);
|
|
100
|
+
plugin.dispatch('message.receive', message);
|
|
101
|
+
plugin.logger.info(`${this.$config.name} recv ${message.$channel.type}(${message.$channel.id}): ${segment.raw(message.$content)}`);
|
|
102
|
+
plugin.dispatch(`message.${message.$channel.type}.receive`, message);
|
|
103
|
+
}
|
|
104
|
+
// ================================================================================================
|
|
105
|
+
// Token 管理
|
|
106
|
+
// ================================================================================================
|
|
107
|
+
async ensureAccessToken() {
|
|
108
|
+
const now = Date.now();
|
|
109
|
+
// 提前 5 分钟刷新 token
|
|
110
|
+
if (this.accessToken.token && now < (this.accessToken.timestamp + (this.accessToken.expires_in - 300) * 1000)) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
await this.refreshAccessToken();
|
|
114
|
+
}
|
|
115
|
+
async refreshAccessToken() {
|
|
116
|
+
try {
|
|
117
|
+
const baseURL = this.$config.apiBaseUrl || 'https://oapi.dingtalk.com';
|
|
118
|
+
const params = new URLSearchParams({
|
|
119
|
+
appkey: this.$config.appKey,
|
|
120
|
+
appsecret: this.$config.appSecret
|
|
121
|
+
});
|
|
122
|
+
const url = `${baseURL}/gettoken?${params.toString()}`;
|
|
123
|
+
const response = await fetch(url);
|
|
124
|
+
const data = await response.json();
|
|
125
|
+
if (data.errcode === 0) {
|
|
126
|
+
this.accessToken = {
|
|
127
|
+
token: data.access_token,
|
|
128
|
+
expires_in: data.expires_in,
|
|
129
|
+
timestamp: Date.now()
|
|
130
|
+
};
|
|
131
|
+
plugin.logger.debug('Access token refreshed successfully');
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
throw new Error(`Failed to get access token: ${data.errmsg}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
plugin.logger.error('Failed to refresh access token:', error);
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// ================================================================================================
|
|
143
|
+
// 消息格式化
|
|
144
|
+
// ================================================================================================
|
|
145
|
+
$formatMessage(msg) {
|
|
146
|
+
const content = this.parseMessageContent(msg);
|
|
147
|
+
// 确定聊天类型: '1'为单聊, '2'为群聊
|
|
148
|
+
const chatType = msg.conversationType === '2' ? 'group' : 'private';
|
|
149
|
+
return Message.from(msg, {
|
|
150
|
+
$id: msg.msgId || Date.now().toString(),
|
|
151
|
+
$adapter: 'dingtalk',
|
|
152
|
+
$bot: this.$config.name,
|
|
153
|
+
$sender: {
|
|
154
|
+
id: msg.senderId || msg.senderStaffId || 'unknown',
|
|
155
|
+
name: msg.senderNick || msg.senderId || 'Unknown User'
|
|
156
|
+
},
|
|
157
|
+
$channel: {
|
|
158
|
+
id: msg.conversationId || 'unknown',
|
|
159
|
+
type: chatType
|
|
160
|
+
},
|
|
161
|
+
$content: content,
|
|
162
|
+
$raw: JSON.stringify(msg),
|
|
163
|
+
$timestamp: msg.createAt || Date.now(),
|
|
164
|
+
$recall: async () => {
|
|
165
|
+
await this.$recallMessage(msg.msgId || '');
|
|
166
|
+
},
|
|
167
|
+
$reply: async (content) => {
|
|
168
|
+
return await this.$sendMessage({
|
|
169
|
+
context: 'dingtalk',
|
|
170
|
+
bot: this.$config.name,
|
|
171
|
+
id: msg.conversationId || msg.senderId || 'unknown',
|
|
172
|
+
type: chatType,
|
|
173
|
+
content: content
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
parseMessageContent(msg) {
|
|
179
|
+
const content = [];
|
|
180
|
+
if (!msg.msgtype) {
|
|
181
|
+
return content;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
switch (msg.msgtype) {
|
|
185
|
+
case 'text':
|
|
186
|
+
if (msg.text?.content) {
|
|
187
|
+
content.push(segment('text', { content: msg.text.content }));
|
|
188
|
+
// 处理 @提及
|
|
189
|
+
if (msg.atUsers && msg.atUsers.length > 0) {
|
|
190
|
+
for (const atUser of msg.atUsers) {
|
|
191
|
+
content.push(segment('at', {
|
|
192
|
+
id: atUser.dingtalkId || atUser.staffId,
|
|
193
|
+
name: atUser.dingtalkId || atUser.staffId
|
|
194
|
+
}));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
case 'picture':
|
|
200
|
+
if (msg.content) {
|
|
201
|
+
content.push(segment('image', {
|
|
202
|
+
url: msg.content.downloadCode || msg.content.pictureDownloadCode,
|
|
203
|
+
file: msg.content.downloadCode || msg.content.pictureDownloadCode
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
break;
|
|
207
|
+
case 'file':
|
|
208
|
+
if (msg.content) {
|
|
209
|
+
content.push(segment('file', {
|
|
210
|
+
file: msg.content.downloadCode,
|
|
211
|
+
name: msg.content.fileName,
|
|
212
|
+
size: msg.content.fileSize
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
case 'audio':
|
|
217
|
+
if (msg.content) {
|
|
218
|
+
content.push(segment('audio', {
|
|
219
|
+
file: msg.content.downloadCode,
|
|
220
|
+
duration: msg.content.duration
|
|
221
|
+
}));
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
case 'video':
|
|
225
|
+
if (msg.content) {
|
|
226
|
+
content.push(segment('video', {
|
|
227
|
+
file: msg.content.downloadCode,
|
|
228
|
+
duration: msg.content.duration,
|
|
229
|
+
size: msg.content.videoSize
|
|
230
|
+
}));
|
|
231
|
+
}
|
|
232
|
+
break;
|
|
233
|
+
case 'richText':
|
|
234
|
+
// 富文本消息处理(简化)
|
|
235
|
+
if (msg.content?.richText) {
|
|
236
|
+
for (const item of msg.content.richText) {
|
|
237
|
+
if (item.text) {
|
|
238
|
+
content.push(segment('text', { content: item.text }));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
break;
|
|
243
|
+
case 'markdown':
|
|
244
|
+
if (msg.content?.text) {
|
|
245
|
+
content.push(segment('markdown', {
|
|
246
|
+
content: msg.content.text,
|
|
247
|
+
title: msg.content.title
|
|
248
|
+
}));
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
default:
|
|
252
|
+
content.push(segment('text', { content: `[不支持的消息类型: ${msg.msgtype}]` }));
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
plugin.logger.error('Failed to parse message content:', error);
|
|
258
|
+
content.push(segment('text', { content: '[消息解析失败]' }));
|
|
259
|
+
}
|
|
260
|
+
return content;
|
|
261
|
+
}
|
|
262
|
+
// ================================================================================================
|
|
263
|
+
// 消息发送
|
|
264
|
+
// ================================================================================================
|
|
265
|
+
async $sendMessage(options) {
|
|
266
|
+
const conversationId = options.id;
|
|
267
|
+
const content = this.formatSendContent(options.content);
|
|
268
|
+
try {
|
|
269
|
+
// 优先使用会话 webhook 发送消息(更快,更准确)
|
|
270
|
+
const sessionWebhook = this.sessionWebhooks.get(conversationId);
|
|
271
|
+
if (sessionWebhook) {
|
|
272
|
+
const response = await fetch(sessionWebhook, {
|
|
273
|
+
method: 'POST',
|
|
274
|
+
headers: {
|
|
275
|
+
'Content-Type': 'application/json; charset=utf-8'
|
|
276
|
+
},
|
|
277
|
+
body: JSON.stringify(content)
|
|
278
|
+
});
|
|
279
|
+
const data = await response.json();
|
|
280
|
+
if (data.errcode !== 0) {
|
|
281
|
+
throw new Error(`Failed to send message via session webhook: ${data.errmsg}`);
|
|
282
|
+
}
|
|
283
|
+
plugin.logger.debug('Message sent via session webhook');
|
|
284
|
+
return data.msgId || Date.now().toString();
|
|
285
|
+
}
|
|
286
|
+
// 否则使用普通机器人发送接口
|
|
287
|
+
const data = await this.request('/robot/send', {
|
|
288
|
+
method: 'POST',
|
|
289
|
+
body: {
|
|
290
|
+
...content,
|
|
291
|
+
robotCode: this.$config.robotCode
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
if (data.errcode !== 0) {
|
|
295
|
+
throw new Error(`Failed to send message: ${data.errmsg}`);
|
|
296
|
+
}
|
|
297
|
+
plugin.logger.debug('Message sent successfully');
|
|
298
|
+
return data.msgId || Date.now().toString();
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
plugin.logger.error('Failed to send message:', error);
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
async $recallMessage(id) {
|
|
306
|
+
// 钉钉机器人不支持撤回消息
|
|
307
|
+
plugin.logger.warn('DingTalk robot does not support message recall');
|
|
308
|
+
}
|
|
309
|
+
formatSendContent(content) {
|
|
310
|
+
if (typeof content === 'string') {
|
|
311
|
+
return {
|
|
312
|
+
msgtype: 'text',
|
|
313
|
+
text: { content }
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
if (Array.isArray(content)) {
|
|
317
|
+
const textParts = [];
|
|
318
|
+
const atMobiles = [];
|
|
319
|
+
const atUserIds = [];
|
|
320
|
+
let hasMedia = false;
|
|
321
|
+
let mediaContent = null;
|
|
322
|
+
for (const item of content) {
|
|
323
|
+
if (typeof item === 'string') {
|
|
324
|
+
textParts.push(item);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
const segment = item;
|
|
328
|
+
switch (segment.type) {
|
|
329
|
+
case 'text':
|
|
330
|
+
textParts.push(segment.data.content || segment.data.text || '');
|
|
331
|
+
break;
|
|
332
|
+
case 'at':
|
|
333
|
+
const userId = segment.data.id || segment.data.userId;
|
|
334
|
+
if (userId) {
|
|
335
|
+
atUserIds.push(userId);
|
|
336
|
+
textParts.push(`@${segment.data.name || userId} `);
|
|
337
|
+
}
|
|
338
|
+
break;
|
|
339
|
+
case 'image':
|
|
340
|
+
if (!hasMedia) {
|
|
341
|
+
hasMedia = true;
|
|
342
|
+
mediaContent = {
|
|
343
|
+
msgtype: 'picture',
|
|
344
|
+
picture: {
|
|
345
|
+
picURL: segment.data.url || segment.data.file
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
break;
|
|
350
|
+
case 'markdown':
|
|
351
|
+
if (!hasMedia) {
|
|
352
|
+
hasMedia = true;
|
|
353
|
+
mediaContent = {
|
|
354
|
+
msgtype: 'markdown',
|
|
355
|
+
markdown: {
|
|
356
|
+
title: segment.data.title || '消息',
|
|
357
|
+
text: segment.data.content || segment.data.text
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
case 'link':
|
|
363
|
+
if (!hasMedia) {
|
|
364
|
+
hasMedia = true;
|
|
365
|
+
mediaContent = {
|
|
366
|
+
msgtype: 'link',
|
|
367
|
+
link: {
|
|
368
|
+
title: segment.data.title || '链接',
|
|
369
|
+
text: segment.data.text || segment.data.content || '',
|
|
370
|
+
messageUrl: segment.data.url,
|
|
371
|
+
picUrl: segment.data.picUrl
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
// 优先发送媒体内容
|
|
380
|
+
if (hasMedia && mediaContent) {
|
|
381
|
+
return mediaContent;
|
|
382
|
+
}
|
|
383
|
+
// 否则发送文本内容
|
|
384
|
+
const result = {
|
|
385
|
+
msgtype: 'text',
|
|
386
|
+
text: {
|
|
387
|
+
content: textParts.join('')
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
// 添加 @ 信息
|
|
391
|
+
if (atUserIds.length > 0) {
|
|
392
|
+
result.at = {
|
|
393
|
+
atUserIds,
|
|
394
|
+
isAtAll: false
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
return result;
|
|
398
|
+
}
|
|
399
|
+
return {
|
|
400
|
+
msgtype: 'text',
|
|
401
|
+
text: {
|
|
402
|
+
content: String(content)
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
// ================================================================================================
|
|
407
|
+
// Bot 生命周期
|
|
408
|
+
// ================================================================================================
|
|
409
|
+
async $connect() {
|
|
410
|
+
try {
|
|
411
|
+
// 获取 access token
|
|
412
|
+
await this.refreshAccessToken();
|
|
413
|
+
this.$connected = true;
|
|
414
|
+
plugin.logger.info(`DingTalk bot connected: ${this.$config.name}`);
|
|
415
|
+
plugin.logger.info(`Webhook URL: ${this.$config.webhookPath}`);
|
|
416
|
+
}
|
|
417
|
+
catch (error) {
|
|
418
|
+
plugin.logger.error('Failed to connect DingTalk bot:', error);
|
|
419
|
+
throw error;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
async $disconnect() {
|
|
423
|
+
try {
|
|
424
|
+
this.$connected = false;
|
|
425
|
+
plugin.logger.info('DingTalk bot disconnected');
|
|
426
|
+
}
|
|
427
|
+
catch (error) {
|
|
428
|
+
plugin.logger.error('Error disconnecting DingTalk bot:', error);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
// ================================================================================================
|
|
432
|
+
// 工具方法
|
|
433
|
+
// ================================================================================================
|
|
434
|
+
// 获取用户信息
|
|
435
|
+
async getUserInfo(userId) {
|
|
436
|
+
try {
|
|
437
|
+
const data = await this.request('/topapi/v2/user/get', {
|
|
438
|
+
method: 'POST',
|
|
439
|
+
body: {
|
|
440
|
+
userid: userId
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
if (data.errcode === 0) {
|
|
444
|
+
return data.result;
|
|
445
|
+
}
|
|
446
|
+
throw new Error(`Failed to get user info: ${data.errmsg}`);
|
|
447
|
+
}
|
|
448
|
+
catch (error) {
|
|
449
|
+
plugin.logger.error('Failed to get user info:', error);
|
|
450
|
+
return null;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
// 获取部门用户列表
|
|
454
|
+
async getDepartmentUsers(deptId) {
|
|
455
|
+
try {
|
|
456
|
+
const data = await this.request('/topapi/user/listid', {
|
|
457
|
+
method: 'POST',
|
|
458
|
+
body: {
|
|
459
|
+
dept_id: deptId
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
if (data.errcode === 0) {
|
|
463
|
+
return data.result.userid_list || [];
|
|
464
|
+
}
|
|
465
|
+
throw new Error(`Failed to get department users: ${data.errmsg}`);
|
|
466
|
+
}
|
|
467
|
+
catch (error) {
|
|
468
|
+
plugin.logger.error('Failed to get department users:', error);
|
|
469
|
+
return [];
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
// 发送工作通知
|
|
473
|
+
async sendWorkNotice(userIdList, content) {
|
|
474
|
+
try {
|
|
475
|
+
const data = await this.request('/topapi/message/corpconversation/asyncsend_v2', {
|
|
476
|
+
method: 'POST',
|
|
477
|
+
body: {
|
|
478
|
+
agent_id: this.$config.robotCode,
|
|
479
|
+
userid_list: userIdList.join(','),
|
|
480
|
+
msg: content
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
if (data.errcode === 0) {
|
|
484
|
+
plugin.logger.debug('Work notice sent successfully');
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
throw new Error(`Failed to send work notice: ${data.errmsg}`);
|
|
488
|
+
}
|
|
489
|
+
catch (error) {
|
|
490
|
+
plugin.logger.error('Failed to send work notice:', error);
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
// 注册适配器(需要 router)
|
|
496
|
+
useContext('router', (router) => {
|
|
497
|
+
registerAdapter(new Adapter('dingtalk', (config) => new DingTalkBot(router, config)));
|
|
498
|
+
});
|
|
499
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zhin.js/adapter-dingtalk",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "zhin adapter for DingTalk (钉钉)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./lib/index.js",
|
|
7
|
+
"types": "./lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"import": "./lib/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"zhin",
|
|
16
|
+
"adapter",
|
|
17
|
+
"dingtalk",
|
|
18
|
+
"钉钉"
|
|
19
|
+
],
|
|
20
|
+
"author": "lc-cn",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"url": "git+https://github.com/zhinjs/zhin.git",
|
|
24
|
+
"type": "git",
|
|
25
|
+
"directory": "plugins/adapters/dingtalk"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"typescript": "^5.3.0",
|
|
29
|
+
"@types/node": "^22.9.0",
|
|
30
|
+
"@types/koa": "^2.15.0"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"zhin.js": "1.0.16",
|
|
34
|
+
"@zhin.js/types": "1.0.5",
|
|
35
|
+
"@zhin.js/http": "1.0.7"
|
|
36
|
+
},
|
|
37
|
+
"peerDependenciesMeta": {
|
|
38
|
+
"@zhin.js/types": {
|
|
39
|
+
"optional": true
|
|
40
|
+
},
|
|
41
|
+
"@zhin.js/http": {
|
|
42
|
+
"optional": false
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"lib",
|
|
47
|
+
"node",
|
|
48
|
+
"README.md",
|
|
49
|
+
"CHANGELOG.md"
|
|
50
|
+
],
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "pnpm build:node",
|
|
53
|
+
"clean": "rm -rf lib",
|
|
54
|
+
"build:node": "tsc"
|
|
55
|
+
}
|
|
56
|
+
}
|