@jiexiaoyin/wecom-api 0.0.2

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.
Files changed (58) hide show
  1. package/README.md +228 -0
  2. package/config.example.json +7 -0
  3. package/config.js +76 -0
  4. package/docs/approval-templates.example.json +11 -0
  5. package/docs/nginx-mirror.md +193 -0
  6. package/openclaw.plugin.json +15 -0
  7. package/package.json +34 -0
  8. package/plugin.cjs +172 -0
  9. package/plugin.ts +136 -0
  10. package/skills/wecom-api/SKILL.md +40 -0
  11. package/skills/wecom-api/index.js +288 -0
  12. package/skills/wecom-api/openclaw.plugin.json +10 -0
  13. package/src/callback-helper.js +198 -0
  14. package/src/config.cjs +286 -0
  15. package/src/core/permission.js +479 -0
  16. package/src/crypto.js +130 -0
  17. package/src/index.js +199 -0
  18. package/src/modules/addressbook/index.js +413 -0
  19. package/src/modules/addressbook_cache/index.js +365 -0
  20. package/src/modules/advanced/index.js +159 -0
  21. package/src/modules/app/index.js +102 -0
  22. package/src/modules/approval/index.js +146 -0
  23. package/src/modules/auth/index.js +103 -0
  24. package/src/modules/callback/index.js +1180 -0
  25. package/src/modules/chain/index.js +193 -0
  26. package/src/modules/checkin/index.js +142 -0
  27. package/src/modules/checkin_rules/index.js +251 -0
  28. package/src/modules/contact/index.js +481 -0
  29. package/src/modules/contact_stats/index.js +349 -0
  30. package/src/modules/custom/index.js +140 -0
  31. package/src/modules/customer/index.js +51 -0
  32. package/src/modules/disk/index.js +245 -0
  33. package/src/modules/document/index.js +282 -0
  34. package/src/modules/hr/index.js +93 -0
  35. package/src/modules/intelligence/index.js +346 -0
  36. package/src/modules/kf/index.js +74 -0
  37. package/src/modules/live/index.js +122 -0
  38. package/src/modules/media/index.js +183 -0
  39. package/src/modules/meeting/index.js +665 -0
  40. package/src/modules/message/index.js +402 -0
  41. package/src/modules/messenger/index.js +208 -0
  42. package/src/modules/moments/index.js +161 -0
  43. package/src/modules/msgaudit/index.js +24 -0
  44. package/src/modules/notify/index.js +81 -0
  45. package/src/modules/oceanengine/index.js +199 -0
  46. package/src/modules/openchat/index.js +197 -0
  47. package/src/modules/phone/index.js +45 -0
  48. package/src/modules/room/index.js +178 -0
  49. package/src/modules/schedule/index.js +246 -0
  50. package/src/modules/school/index.js +199 -0
  51. package/src/modules/security/index.js +223 -0
  52. package/src/modules/sensitive/index.js +170 -0
  53. package/src/modules/thirdparty/index.js +145 -0
  54. package/src/sdk/index.js +269 -0
  55. package/src/utils/callback-helper.js +198 -0
  56. package/test/callback-crypto.test.js +55 -0
  57. package/test/crypto.test.js +85 -0
  58. package/test/permission.test.js +115 -0
package/src/index.js ADDED
@@ -0,0 +1,199 @@
1
+ /**
2
+ * 企业微信插件 - 统一入口
3
+ *
4
+ * 模块清单(共32个)
5
+ */
6
+
7
+ const Approval = require('./modules/approval');
8
+ const Contact = require('./modules/contact');
9
+ const CheckIn = require('./modules/checkin');
10
+ const Disk = require('./modules/disk');
11
+ const Custom = require('./modules/custom');
12
+ const Live = require('./modules/live');
13
+ const Intelligence = require('./modules/intelligence');
14
+ const AddressBook = require('./modules/addressbook');
15
+ const Message = require('./modules/message');
16
+ const App = require('./modules/app');
17
+ const Media = require('./modules/media');
18
+ const Schedule = require('./modules/schedule');
19
+ const Meeting = require('./modules/meeting');
20
+ const Document = require('./modules/document');
21
+ const Chain = require('./modules/chain');
22
+ const Phone = require('./modules/phone');
23
+ const Security = require('./modules/security');
24
+ const Auth = require('./modules/auth');
25
+ const HR = require('./modules/hr');
26
+ const Room = require('./modules/room');
27
+ const Advanced = require('./modules/advanced');
28
+ const Notify = require('./modules/notify');
29
+ const ThirdParty = require('./modules/thirdparty');
30
+ const Moments = require('./modules/moments');
31
+ const OceanEngine = require('./modules/oceanengine');
32
+ const Messenger = require('./modules/messenger');
33
+ const ContactStats = require('./modules/contact_stats');
34
+ const Customer = require('./modules/customer');
35
+ const Sensitive = require('./modules/sensitive');
36
+ const CheckInRules = require('./modules/checkin_rules');
37
+ const School = require('./modules/school');
38
+ const OpenChat = require('./modules/openchat');
39
+ const Callback = require('./modules/callback');
40
+ const Permission = require('./core/permission');
41
+
42
+ class WeComPlugin {
43
+ constructor(config) {
44
+ this.config = config;
45
+
46
+ // 核心办公
47
+ this.approval = new Approval(config);
48
+ this.contact = new Contact(config);
49
+ this.checkin = new CheckIn(config);
50
+ this.disk = new Disk(config);
51
+ this.custom = new Custom(config);
52
+ this.live = new Live(config);
53
+ this.intelligence = new Intelligence(config);
54
+
55
+ // 协作增强
56
+ this.addressbook = new AddressBook(config);
57
+ this.message = new Message(config);
58
+ this.app = new App(config);
59
+ this.media = new Media(config);
60
+ this.customer = new Customer(config);
61
+
62
+ // 协作效率
63
+ this.schedule = new Schedule(config);
64
+ this.meeting = new Meeting(config);
65
+ this.document = new Document(config);
66
+
67
+ // 高级功能
68
+ this.chain = new Chain(config);
69
+ this.phone = new Phone(config);
70
+ this.security = new Security(config);
71
+
72
+ // 身份与验证
73
+ this.auth = new Auth(config);
74
+
75
+ // 人事与场地
76
+ this.hr = new HR(config);
77
+ this.room = new Room(config);
78
+
79
+ // 高级功能扩展
80
+ this.advanced = new Advanced(config);
81
+ this.notify = new Notify(config);
82
+
83
+ // 补充模块
84
+ this.thirdparty = new ThirdParty(config);
85
+ this.moments = new Moments(config);
86
+ this.oceanengine = new OceanEngine(config);
87
+ this.messenger = new Messenger(config);
88
+ this.contactstats = new ContactStats(config);
89
+ this.sensitive = new Sensitive(config);
90
+ this.checkinrules = new CheckInRules(config);
91
+ this.school = new School(config);
92
+ this.openchat = new OpenChat(config);
93
+
94
+ // 回调处理(非 API 模块,直接实例化)
95
+ this.callback = new Callback(config);
96
+
97
+ // 权限控制(依赖 addressbook 模块)
98
+ this.permission = new Permission(config, this.addressbook);
99
+ }
100
+
101
+ getConfig() {
102
+ return { corpId: this.config.corpId, agentId: this.config.agentId };
103
+ }
104
+
105
+ async testConnection() {
106
+ try {
107
+ const token = await this.approval.getAccessToken();
108
+ return { success: true, message: '连接成功', token };
109
+ } catch (error) {
110
+ return { success: false, message: error.message };
111
+ }
112
+ }
113
+
114
+ getModules() {
115
+ return [
116
+ 'approval', 'contact', 'checkin', 'disk', 'custom', 'live', 'intelligence',
117
+ 'addressbook', 'message', 'app', 'media', 'schedule', 'meeting', 'document',
118
+ 'chain', 'phone', 'security', 'auth', 'hr', 'room', 'advanced', 'notify',
119
+ 'thirdparty', 'moments', 'oceanengine', 'messenger', 'contactstats', 'sensitive',
120
+ 'checkinrules', 'school', 'openchat'
121
+ ];
122
+ }
123
+
124
+ // ========== 权限控制 ==========
125
+
126
+ /**
127
+ * 获取用户角色
128
+ * @param {string} userId 用户ID
129
+ * @returns {Promise<string>} 角色名
130
+ */
131
+ async getUserRole(userId) {
132
+ return this.permission.getUserRole(userId);
133
+ }
134
+
135
+ /**
136
+ * 检查用户是否有权限
137
+ * @param {string} userId 用户ID
138
+ * @param {string} module 模块名
139
+ * @param {string} action 操作名
140
+ * @returns {Promise<boolean>}
141
+ */
142
+ async checkPermission(userId, module, action) {
143
+ return this.permission.checkPermission(userId, module, action);
144
+ }
145
+
146
+ /**
147
+ * 权限检查,失败则抛出异常
148
+ * @param {string} userId 用户ID
149
+ * @param {string} module 模块名
150
+ * @param {string} action 操作名
151
+ */
152
+ async requirePermission(userId, module, action) {
153
+ return this.permission.requirePermission(userId, module, action);
154
+ }
155
+
156
+ /**
157
+ * 获取用户数据权限范围
158
+ * @param {string} userId 用户ID
159
+ * @param {string} module 模块名
160
+ * @returns {Promise<Object>}
161
+ */
162
+ async getDataScope(userId, module) {
163
+ return this.permission.getDataScope(userId, module);
164
+ }
165
+
166
+ /**
167
+ * 根据权限过滤数据
168
+ * @param {Array} data 数据列表
169
+ * @param {string} userId 用户ID
170
+ * @param {string} dataField 数据字段名
171
+ * @returns {Promise<Array>}
172
+ */
173
+ async filterData(data, userId, dataField) {
174
+ return this.permission.filterData(data, userId, dataField);
175
+ }
176
+
177
+ /**
178
+ * 获取权限矩阵
179
+ */
180
+ getPermissionMatrix() {
181
+ return this.permission.getPermissionMatrix();
182
+ }
183
+
184
+ /**
185
+ * 获取角色定义
186
+ */
187
+ static getRoles() {
188
+ return Permission.getRoles();
189
+ }
190
+
191
+ /**
192
+ * 清除权限缓存
193
+ */
194
+ clearPermissionCache() {
195
+ this.permission.clearCache();
196
+ }
197
+ }
198
+
199
+ module.exports = WeComPlugin;
@@ -0,0 +1,413 @@
1
+ /**
2
+ * 通讯录管理模块
3
+ * API 章节:三 - 通讯录管理
4
+ * 包含:成员管理、部门管理、标签管理、异步导入导出
5
+ */
6
+
7
+ const WeComSDK = require('../../sdk');
8
+
9
+ class AddressBook extends WeComSDK {
10
+ constructor(config) {
11
+ super(config);
12
+ }
13
+
14
+ // ========== 成员管理 ==========
15
+
16
+ /**
17
+ * 创建成员
18
+ * @param {object} params 成员参数
19
+ */
20
+ async createUser(params) {
21
+ const { userId, name, mobile, email, departments, position, gender, avatar, enable } = params;
22
+ return this.post('/user/create', {
23
+ userid: userId,
24
+ name,
25
+ mobile,
26
+ email,
27
+ department: departments,
28
+ position,
29
+ gender: gender || 0,
30
+ avatar,
31
+ enable: enable !== undefined ? enable : 1
32
+ });
33
+ }
34
+
35
+ /**
36
+ * 读取成员
37
+ * @param {string} userId 成员 userid
38
+ */
39
+ async getUser(userId) {
40
+ return this.post('/user/get', { userid: userId });
41
+ }
42
+
43
+ /**
44
+ * 更新成员
45
+ * @param {object} params 成员参数
46
+ */
47
+ async updateUser(params) {
48
+ const { userId, name, mobile, email, departments, position, gender, avatar, enable } = params;
49
+ return this.post('/user/update', {
50
+ userid: userId,
51
+ name,
52
+ mobile,
53
+ email,
54
+ department: departments,
55
+ position,
56
+ gender,
57
+ avatar,
58
+ enable
59
+ });
60
+ }
61
+
62
+ /**
63
+ * 删除成员
64
+ * @param {string} userId 成员 userid
65
+ */
66
+ async deleteUser(userId) {
67
+ return this.post('/user/delete', { userid: userId });
68
+ }
69
+
70
+ /**
71
+ * 批量删除成员
72
+ * @param {string[]} userIds 成员 userid 列表
73
+ */
74
+ async batchDeleteUsers(userIds) {
75
+ return this.post('/user/batchdelete', { useridlist: userIds });
76
+ }
77
+
78
+ /**
79
+ * 获取部门成员
80
+ * @param {number} departmentId 部门 id
81
+ * @param {boolean} fetchChild 是否递归获取子部门成员
82
+ */
83
+ async getDepartmentUsers(departmentId, fetchChild = false) {
84
+ return this.get('/user/simplelist', {
85
+ department_id: departmentId,
86
+ fetch_child: fetchChild ? 1 : 0
87
+ });
88
+ }
89
+
90
+ /**
91
+ * 获取部门成员详情
92
+ * @param {number} departmentId 部门 id
93
+ * @param {boolean} fetchChild 是否递归获取子部门成员
94
+ */
95
+ async getDepartmentUsersDetail(departmentId, fetchChild = false) {
96
+ return this.get('/user/list', {
97
+ department_id: departmentId,
98
+ fetch_child: fetchChild ? 1 : 0
99
+ });
100
+ }
101
+
102
+ /**
103
+ * userid 与 openid 互换
104
+ * @param {string} openId openid
105
+ * @param {string} userId userid
106
+ */
107
+ async convertToUserId(openId, userId) {
108
+ return this.post('/user/convert_to_userid', { openid: openId, userid: userId });
109
+ }
110
+
111
+ /**
112
+ * 手机号获取 userid
113
+ * @param {string} mobile 手机号
114
+ */
115
+ async getUserIdByMobile(mobile) {
116
+ return this.post('/user/getuserid3', { mobile });
117
+ }
118
+
119
+ /**
120
+ * 邮箱获取 userid
121
+ * @param {string} email 邮箱
122
+ */
123
+ async getUserIdByEmail(email) {
124
+ return this.post('/user/getuserid4', { email });
125
+ }
126
+
127
+ /**
128
+ * 邀请成员
129
+ * @param {string} userId 成员 userid
130
+ */
131
+ async inviteUser(userId) {
132
+ return this.post('/invite/user', { userid: userId });
133
+ }
134
+
135
+ /**
136
+ * 获取加入企业二维码
137
+ * @param {number} sizeType 二维码尺寸类型
138
+ */
139
+ async getJoinQrCode(sizeType = 1) {
140
+ return this.post('/invite/get_qrcode', { size_type: sizeType });
141
+ }
142
+
143
+ /**
144
+ * 获取成员 ID 列表
145
+ * @param {number} departmentId 部门 id
146
+ */
147
+ async getUserIdList(departmentId) {
148
+ return this.get('/user/list_id', { department_id: departmentId });
149
+ }
150
+
151
+ // ========== 用户ID转换 ==========
152
+
153
+ /**
154
+ * tmp_external_userid 的转换
155
+ * 将外部联系人临时 ID 转换为永久 external_userid
156
+ * @param {string} tmpExternalUserId 外部联系人临时 ID
157
+ */
158
+ async convertTmpExternalUserId(tmpExternalUserId) {
159
+ return this.post('/externalcontact/convert_to_external_userid', {
160
+ tmp_external_userid: tmpExternalUserId
161
+ });
162
+ }
163
+
164
+ // ========== 成员扩展属性 ==========
165
+
166
+ /**
167
+ * 获取成员扩展属性
168
+ * @param {string} userId 成员 userid
169
+ */
170
+ async getUserExtAttr(userId) {
171
+ return this.post('/user/get', { userid: userId });
172
+ }
173
+
174
+ /**
175
+ * 设置成员扩展属性
176
+ * @param {string} userId 成员 userid
177
+ * @param {object[]} extAttr 扩展属性列表
178
+ */
179
+ async setUserExtAttr(userId, extAttr) {
180
+ return this.post('/user/update', {
181
+ userid: userId,
182
+ extattr: extAttr
183
+ });
184
+ }
185
+
186
+ // ========== 部门管理 ==========
187
+
188
+ /**
189
+ * 创建部门
190
+ * @param {string} name 部门名称
191
+ * @param {number} parentId 父部门 id
192
+ * @param {number} order 排序
193
+ */
194
+ async createDepartment(name, parentId = 1, order = 0) {
195
+ return this.post('/department/create', {
196
+ name,
197
+ parentid: parentId,
198
+ order
199
+ });
200
+ }
201
+
202
+ /**
203
+ * 更新部门
204
+ * @param {number} departmentId 部门 id
205
+ * @param {object} params 更新参数
206
+ */
207
+ async updateDepartment(departmentId, { name, parentId, order }) {
208
+ return this.post('/department/update', {
209
+ id: departmentId,
210
+ name,
211
+ parentid: parentId,
212
+ order
213
+ });
214
+ }
215
+
216
+ /**
217
+ * 删除部门
218
+ * @param {number} departmentId 部门 id
219
+ */
220
+ async deleteDepartment(departmentId) {
221
+ return this.post('/department/delete', { id: departmentId });
222
+ }
223
+
224
+ /**
225
+ * 获取部门列表
226
+ * @param {number} departmentId 部门 id,不填则获取全部
227
+ */
228
+ async getDepartmentList(departmentId) {
229
+ return this.post('/department/list', { id: departmentId });
230
+ }
231
+
232
+ /**
233
+ * 获取子部门 ID 列表
234
+ * @param {number} departmentId 部门 id
235
+ */
236
+ async getSubDepartmentIds(departmentId) {
237
+ return this.post('/department/list_id', { id: departmentId });
238
+ }
239
+
240
+ /**
241
+ * 获取单个部门详情
242
+ * @param {number} departmentId 部门 id
243
+ */
244
+ async getDepartmentDetail(departmentId) {
245
+ return this.get('/department/get', { id: departmentId });
246
+ }
247
+
248
+ // ========== 标签管理 ==========
249
+
250
+ /**
251
+ * 创建标签
252
+ * @param {string} tagName 标签名称
253
+ * @param {number} tagId 标签 id(可选)
254
+ */
255
+ async createTag(tagName, tagId) {
256
+ return this.post('/tag/create', {
257
+ tagname: tagName,
258
+ tagid: tagId
259
+ });
260
+ }
261
+
262
+ /**
263
+ * 更新标签名字
264
+ * @param {number} tagId 标签 id
265
+ * @param {string} tagName 新标签名
266
+ */
267
+ async updateTag(tagId, tagName) {
268
+ return this.post('/tag/update', {
269
+ tagid: tagId,
270
+ tagname: tagName
271
+ });
272
+ }
273
+
274
+ /**
275
+ * 删除标签
276
+ * @param {number} tagId 标签 id
277
+ */
278
+ async deleteTag(tagId) {
279
+ return this.post('/tag/delete', { tagid: tagId });
280
+ }
281
+
282
+ /**
283
+ * 获取标签成员
284
+ * @param {number} tagId 标签 id
285
+ */
286
+ async getTagUsers(tagId) {
287
+ return this.post('/tag/get', { tagid: tagId });
288
+ }
289
+
290
+ /**
291
+ * 增加标签成员
292
+ * @param {number} tagId 标签 id
293
+ * @param {string[]} userIds 成员 userid 列表
294
+ * @param {number[]} departmentIds 部门 id 列表
295
+ */
296
+ async addTagUsers(tagId, userIds = [], departmentIds = []) {
297
+ return this.post('/tag/addtagusers', {
298
+ tagid: tagId,
299
+ userlist: userIds,
300
+ partylist: departmentIds
301
+ });
302
+ }
303
+
304
+ /**
305
+ * 删除标签成员
306
+ * @param {number} tagId 标签 id
307
+ * @param {string[]} userIds 成员 userid 列表
308
+ * @param {number[]} departmentIds 部门 id 列表
309
+ */
310
+ async removeTagUsers(tagId, userIds = [], departmentIds = []) {
311
+ return this.post('/tag/deltagusers', {
312
+ tagid: tagId,
313
+ userlist: userIds,
314
+ partylist: departmentIds
315
+ });
316
+ }
317
+
318
+ /**
319
+ * 获取标签列表
320
+ */
321
+ async getTagList() {
322
+ return this.post('/tag/list', {});
323
+ }
324
+
325
+ // ========== 异步导入 ==========
326
+
327
+ /**
328
+ * 增量更新成员
329
+ * @param {string} mediaId 文件 id
330
+ * @param {boolean} toInvite 是否邀请
331
+ */
332
+ async syncUsers(mediaId, toInvite = true) {
333
+ return this.post('/user/syncuser', {
334
+ media_id: mediaId,
335
+ to_invite: toInvite ? 1 : 0
336
+ });
337
+ }
338
+
339
+ /**
340
+ * 全量覆盖成员
341
+ * @param {string} mediaId 文件 id
342
+ * @param {boolean} toInvite 是否邀请
343
+ */
344
+ async replaceUsers(mediaId, toInvite = true) {
345
+ return this.post('/user/replaceuser', {
346
+ media_id: mediaId,
347
+ to_invite: toInvite ? 1 : 0
348
+ });
349
+ }
350
+
351
+ /**
352
+ * 全量覆盖部门
353
+ * @param {string} mediaId 文件 id
354
+ */
355
+ async replaceDepartments(mediaId) {
356
+ return this.post('/department/replaceparty', { media_id: mediaId });
357
+ }
358
+
359
+ /**
360
+ * 获取异步任务结果
361
+ * @param {string} jobId 任务 id
362
+ */
363
+ async getAsyncJobResult(jobId) {
364
+ return this.post('/getresult', { jobid: jobId });
365
+ }
366
+
367
+ // ========== 异步导出 ==========
368
+
369
+ /**
370
+ * 导出成员
371
+ * @param {number} departmentId 部门 id
372
+ * @param {number} departmentIds 部门 id 列表
373
+ */
374
+ async exportUsers(departmentId = 1, departmentIds = []) {
375
+ return this.post('/export/simple_user', {
376
+ department_id: departmentId,
377
+ department_ids: departmentIds
378
+ });
379
+ }
380
+
381
+ /**
382
+ * 导出成员详情
383
+ * @param {number} departmentId 部门 id
384
+ */
385
+ async exportUsersDetail(departmentId = 1) {
386
+ return this.post('/export/user', { department_id: departmentId });
387
+ }
388
+
389
+ /**
390
+ * 导出部门
391
+ */
392
+ async exportDepartments() {
393
+ return this.post('/export/party', {});
394
+ }
395
+
396
+ /**
397
+ * 导出标签成员
398
+ * @param {number} tagId 标签 id
399
+ */
400
+ async exportTagUsers(tagId) {
401
+ return this.post('/export/tag_users', { tagid: tagId });
402
+ }
403
+
404
+ /**
405
+ * 获取导出结果
406
+ * @param {string} jobId 任务 id
407
+ */
408
+ async getExportResult(jobId) {
409
+ return this.post('/export/getresult', { jobid: jobId });
410
+ }
411
+ }
412
+
413
+ module.exports = AddressBook;