@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
@@ -0,0 +1,665 @@
1
+ /**
2
+ * 会议管理模块
3
+ * API 章节:十七 - 会议
4
+ * 包含:预约会议、会议统计、会中控制、网络研讨会、会议室等
5
+ */
6
+
7
+ const WeComSDK = require('../../sdk');
8
+
9
+ class Meeting extends WeComSDK {
10
+ constructor(config) {
11
+ super(config);
12
+ }
13
+
14
+ // ========== 预约会议基础管理 ==========
15
+
16
+ /**
17
+ * 创建预约会议
18
+ * @param {object} params 会议参数
19
+ */
20
+ async createMeeting(params) {
21
+ const { topic, startTime, endTime, organizers, guests, meetingType, password, settings } = params;
22
+ return this.post('/meeting/create', {
23
+ topic,
24
+ meeting_start_time: Math.floor(new Date(startTime).getTime() / 1000),
25
+ meeting_end_time: Math.floor(new Date(endTime).getTime() / 1000),
26
+ organizers,
27
+ guests,
28
+ meeting_type: meetingType || 1,
29
+ password,
30
+ settings: settings || {}
31
+ });
32
+ }
33
+
34
+ /**
35
+ * 修改预约会议
36
+ * @param {string} meetingId 会议 id
37
+ * @param {object} params 更新参数
38
+ */
39
+ async updateMeeting(meetingId, { topic, startTime, endTime, guests, password, settings }) {
40
+ return this.post('/meeting/update', {
41
+ meeting_id: meetingId,
42
+ topic,
43
+ meeting_start_time: startTime ? Math.floor(new Date(startTime).getTime() / 1000) : undefined,
44
+ meeting_end_time: endTime ? Math.floor(new Date(endTime).getTime() / 1000) : undefined,
45
+ guests,
46
+ password,
47
+ settings
48
+ });
49
+ }
50
+
51
+ /**
52
+ * 取消预约会议
53
+ * @param {string} meetingId 会议 id
54
+ */
55
+ async cancelMeeting(meetingId) {
56
+ return this.post('/meeting/cancel', { meeting_id: meetingId });
57
+ }
58
+
59
+ /**
60
+ * 获取会议详情
61
+ * @param {string} meetingId 会议 id
62
+ */
63
+ async getMeetingDetail(meetingId) {
64
+ return this.post('/meeting/get', { meeting_id: meetingId });
65
+ }
66
+
67
+ /**
68
+ * 获取成员会议 ID 列表
69
+ * @param {string} userId 成员 userid
70
+ * @param {number} startTime 开始时间戳
71
+ * @param {number} endTime 结束时间戳
72
+ */
73
+ async getUserMeetingIds(userId, startTime, endTime) {
74
+ return this.post('/meeting/user_meeting_list', {
75
+ userid: userId,
76
+ meeting_start_time: startTime,
77
+ meeting_end_time: endTime
78
+ });
79
+ }
80
+
81
+ // ========== 会议统计管理 ==========
82
+
83
+ /**
84
+ * 获取会议发起记录
85
+ * @param {number} startTime 开始时间戳
86
+ * @param {number} endTime 结束时间戳
87
+ * @param {number} cursor 分页游标
88
+ * @param {number} size 每页数量
89
+ */
90
+ async getMeetingRecord(startTime, endTime, cursor = 0, size = 100) {
91
+ return this.post('/meeting/get_meeting_record', {
92
+ start_time: startTime,
93
+ end_time: endTime,
94
+ cursor,
95
+ size
96
+ });
97
+ }
98
+
99
+ // ========== 预约会议高级管理 ==========
100
+
101
+ /**
102
+ * 创建预约会议(高级)
103
+ * @param {object} params 会议参数
104
+ */
105
+ async createMeetingAdvanced(params) {
106
+ const {
107
+ topic, startTime, endTime, meetingType, password,
108
+ hosts, organizers, recurrenceType, recurrenceUntil,
109
+ attendees, allowIn, allowOut, mute, settings
110
+ } = params;
111
+
112
+ const meetingInfo = {
113
+ topic,
114
+ meeting_start_time: Math.floor(new Date(startTime).getTime() / 1000),
115
+ meeting_end_time: Math.floor(new Date(endTime).getTime() / 1000),
116
+ meeting_type: meetingType || 1,
117
+ password,
118
+ hosts,
119
+ organizers
120
+ };
121
+
122
+ if (recurrenceType) {
123
+ meetingInfo.recurrence_type = recurrenceType;
124
+ meetingInfo.recurrence_until = recurrenceUntil;
125
+ }
126
+
127
+ if (attendees) meetingInfo.attendees = attendees;
128
+
129
+ meetingInfo.settings = settings || {
130
+ allow_in: allowIn !== undefined ? allowIn : true,
131
+ allow_out: allowOut !== undefined ? allowOut : true,
132
+ mute: mute !== undefined ? mute : 1
133
+ };
134
+
135
+ return this.post('/meeting/create', meetingInfo);
136
+ }
137
+
138
+ /**
139
+ * 获取会议受邀成员列表
140
+ * @param {string} meetingId 会议 id
141
+ */
142
+ async getMeetingAttendees(meetingId) {
143
+ return this.post('/meeting/get_attendees', { meeting_id: meetingId });
144
+ }
145
+
146
+ /**
147
+ * 更新会议受邀成员列表
148
+ * @param {string} meetingId 会议 id
149
+ * @param {object} params 参数
150
+ */
151
+ async updateMeetingAttendees(meetingId, { attendees, updateScope }) {
152
+ return this.post('/meeting/update_attendees', {
153
+ meeting_id: meetingId,
154
+ attendees,
155
+ update_scope: updateScope
156
+ });
157
+ }
158
+
159
+ /**
160
+ * 获取用户专属参会链接
161
+ * @param {string} meetingId 会议 id
162
+ * @param {string} userId 用户 userid
163
+ */
164
+ async getUserMeetingJoinLink(meetingId, userId) {
165
+ return this.post('/meeting/get_user_meeting_link', {
166
+ meeting_id: meetingId,
167
+ userid: userId
168
+ });
169
+ }
170
+
171
+ /**
172
+ * 获取实时会中成员列表
173
+ * @param {string} meetingId 会议 id
174
+ */
175
+ async getMeetingMembers(meetingId) {
176
+ return this.post('/meeting/get_meeting_members', { meeting_id: meetingId });
177
+ }
178
+
179
+ // ========== 会中控制管理 ==========
180
+
181
+ /**
182
+ * 管理会中设置
183
+ * @param {string} meetingId 会议 id
184
+ * @param {object} settings 设置参数
185
+ */
186
+ async updateMeetingSettings(meetingId, settings) {
187
+ return this.post('/meeting/update_meeting', {
188
+ meeting_id: meetingId,
189
+ settings
190
+ });
191
+ }
192
+
193
+ /**
194
+ * 管理联席主持人
195
+ * @param {string} meetingId 会议 id
196
+ * @param {string[]} userIds 成员 userid 列表
197
+ * @param {number} type 1-添加 2-删除
198
+ */
199
+ async manageCoHost(meetingId, userIds, type = 1) {
200
+ return this.post('/meeting/set_co_host', {
201
+ meeting_id: meetingId,
202
+ userid: userIds,
203
+ type
204
+ });
205
+ }
206
+
207
+ /**
208
+ * 静音成员
209
+ * @param {string} meetingId 会议 id
210
+ * @param {string[]} userIds 成员 userid 列表
211
+ * @param {boolean} muteAll 是否全员静音
212
+ */
213
+ async muteMember(meetingId, userIds, muteAll = false) {
214
+ return this.post('/meeting/mute_member', {
215
+ meeting_id: meetingId,
216
+ userid: userIds,
217
+ mute_all: muteAll
218
+ });
219
+ }
220
+
221
+ /**
222
+ * 关闭或开启成员视频
223
+ * @param {string} meetingId 会议 id
224
+ * @param {string} userId 成员 userid
225
+ * @param {boolean} muteVideo 是否关闭视频
226
+ */
227
+ async updateMemberVideo(meetingId, userId, muteVideo = true) {
228
+ return this.post('/meeting/mute_video', {
229
+ meeting_id: meetingId,
230
+ userid: userId,
231
+ mute_video: muteVideo
232
+ });
233
+ }
234
+
235
+ /**
236
+ * 关闭成员屏幕共享
237
+ * @param {string} meetingId 会议 id
238
+ * @param {string} userId 成员 userid
239
+ */
240
+ async stopMemberScreenShare(meetingId, userId) {
241
+ return this.post('/meeting/stop_screen_share', {
242
+ meeting_id: meetingId,
243
+ userid: userId
244
+ });
245
+ }
246
+
247
+ /**
248
+ * 管理等候室成员
249
+ * @param {string} meetingId 会议 id
250
+ * @param {string} userId 成员 userid
251
+ * @param {number} type 1-进入等候室 2-移出等候室 3-进入会议
252
+ */
253
+ async manageWaitingRoom(meetingId, userId, type) {
254
+ return this.post('/meeting/waiting_room', {
255
+ meeting_id: meetingId,
256
+ userid: userId,
257
+ type
258
+ });
259
+ }
260
+
261
+ /**
262
+ * 移出成员
263
+ * @param {string} meetingId 会议 id
264
+ * @param {string[]} userIds 成员 userid 列表
265
+ */
266
+ async kickMember(meetingId, userIds) {
267
+ return this.post('/meeting/kick', {
268
+ meeting_id: meetingId,
269
+ userid: userIds
270
+ });
271
+ }
272
+
273
+ /**
274
+ * 结束会议
275
+ * @param {string} meetingId 会议 id
276
+ */
277
+ async endMeeting(meetingId) {
278
+ return this.post('/meeting/end', { meeting_id: meetingId });
279
+ }
280
+
281
+ // ========== 网络研讨会管理 ==========
282
+
283
+ /**
284
+ * 创建网络研讨会
285
+ * @param {object} params 研讨会参数
286
+ */
287
+ async createWebinar(params) {
288
+ const { topic, startTime, endTime, password, hosts, guests, settings } = params;
289
+ return this.post('/meeting/webinar/create', {
290
+ topic,
291
+ meeting_start_time: Math.floor(new Date(startTime).getTime() / 1000),
292
+ meeting_end_time: Math.floor(new Date(endTime).getTime() / 1000),
293
+ password,
294
+ hosts,
295
+ guests,
296
+ settings: settings || {}
297
+ });
298
+ }
299
+
300
+ /**
301
+ * 修改网络研讨会
302
+ * @param {string} webinarId 研讨会 id
303
+ * @param {object} params 更新参数
304
+ */
305
+ async updateWebinar(webinarId, params) {
306
+ return this.post('/meeting/webinar/update', {
307
+ webinar_id: webinarId,
308
+ ...params
309
+ });
310
+ }
311
+
312
+ /**
313
+ * 取消网络研讨会
314
+ * @param {string} webinarId 研讨会 id
315
+ */
316
+ async cancelWebinar(webinarId) {
317
+ return this.post('/meeting/webinar/cancel', { webinar_id: webinarId });
318
+ }
319
+
320
+ /**
321
+ * 获取网络研讨会详情
322
+ * @param {string} webinarId 研讨会 id
323
+ */
324
+ async getWebinarDetail(webinarId) {
325
+ return this.post('/meeting/webinar/get', { webinar_id: webinarId });
326
+ }
327
+
328
+ // ========== 会议室管理 (Rooms) ==========
329
+
330
+ /**
331
+ * 预定 Rooms 会议室
332
+ * @param {string} roomId 会议室 id
333
+ * @param {number} startTime 开始时间戳
334
+ * @param {number} endTime 结束时间戳
335
+ * @param {string} userId 预定人 userid
336
+ */
337
+ async bookRoom(roomId, startTime, endTime, userId) {
338
+ return this.post('/meeting/rooms/book', {
339
+ room_id: roomId,
340
+ start_time: startTime,
341
+ end_time: endTime,
342
+ userid: userId
343
+ });
344
+ }
345
+
346
+ /**
347
+ * 释放 Rooms 会议室
348
+ * @param {string} roomId 会议室 id
349
+ * @param {string} meetingId 会议 id
350
+ */
351
+ async releaseRoom(roomId, meetingId) {
352
+ return this.post('/meeting/rooms/release', {
353
+ room_id: roomId,
354
+ meeting_id: meetingId
355
+ });
356
+ }
357
+
358
+ /**
359
+ * 获取 Rooms 会议室列表
360
+ * @param {number} offset 偏移量
361
+ * @param {number} size 每页数量
362
+ */
363
+ async getRoomsList(offset = 0, size = 100) {
364
+ return this.post('/meeting/rooms/list', { offset, limit: size });
365
+ }
366
+
367
+ /**
368
+ * 获取 Rooms 会议室详情
369
+ * @param {string} roomId 会议室 id
370
+ */
371
+ async getRoomDetail(roomId) {
372
+ return this.post('/meeting/rooms/get', { room_id: roomId });
373
+ }
374
+
375
+ /**
376
+ * 呼叫 Rooms 会议室
377
+ * @param {string} roomId 会议室 id
378
+ * @param {string} userId 呼叫人 userid
379
+ */
380
+ async callRoom(roomId, userId) {
381
+ return this.post('/meeting/rooms/call', {
382
+ room_id: roomId,
383
+ userid: userId
384
+ });
385
+ }
386
+
387
+ /**
388
+ * 取消呼叫 Rooms 会议室
389
+ * @param {string} roomId 会议室 id
390
+ */
391
+ async cancelCallRoom(roomId) {
392
+ return this.post('/meeting/rooms/cancel', { room_id: roomId });
393
+ }
394
+
395
+ // ========== 录制管理 ==========
396
+
397
+ /**
398
+ * 获取会议录制列表
399
+ * @param {string} meetingId 会议 id
400
+ */
401
+ async getMeetingRecordings(meetingId) {
402
+ return this.post('/meeting/record/get_list', { meeting_id: meetingId });
403
+ }
404
+
405
+ /**
406
+ * 获取会议录制地址
407
+ * @param {string} meetingId 会议 id
408
+ */
409
+ async getMeetingRecordingUrl(meetingId) {
410
+ return this.post('/meeting/record/get_url', { meeting_id: meetingId });
411
+ }
412
+
413
+ /**
414
+ * 删除会议录制
415
+ * @param {string} meetingId 会议 id
416
+ */
417
+ async deleteMeetingRecording(meetingId) {
418
+ return this.post('/meeting/record/delete', { meeting_id: meetingId });
419
+ }
420
+
421
+ /**
422
+ * 修改会议录制共享设置
423
+ * @param {string} meetingId 会议 id
424
+ * @param {number} shareType 共享类型
425
+ */
426
+ async updateRecordingShare(meetingId, shareType) {
427
+ return this.post('/meeting/record/set_share', {
428
+ meeting_id: meetingId,
429
+ share_type: shareType
430
+ });
431
+ }
432
+
433
+ // ========== 会议投票管理 ==========
434
+
435
+ /**
436
+ * 创建会议投票主题
437
+ * @param {string} meetingId 会议 ID
438
+ * @param {object} vote 投票配置
439
+ */
440
+ async createMeetingVote(meetingId, vote) {
441
+ return this.post('/meeting/vote/create', {
442
+ meeting_id: meetingId,
443
+ vote
444
+ });
445
+ }
446
+
447
+ /**
448
+ * 修改会议投票主题
449
+ * @param {string} meetingId 会议 ID
450
+ * @param {string} voteId 投票 ID
451
+ * @param {object} vote 投票配置
452
+ */
453
+ async updateMeetingVote(meetingId, voteId, vote) {
454
+ return this.post('/meeting/vote/update', {
455
+ meeting_id: meetingId,
456
+ vote_id: voteId,
457
+ vote
458
+ });
459
+ }
460
+
461
+ /**
462
+ * 获取会议投票列表
463
+ * @param {string} meetingId 会议 ID
464
+ */
465
+ async getMeetingVoteList(meetingId) {
466
+ return this.post('/meeting/vote/list', { meeting_id: meetingId });
467
+ }
468
+
469
+ /**
470
+ * 获取会议投票详情
471
+ * @param {string} meetingId 会议 ID
472
+ * @param {string} voteId 投票 ID
473
+ */
474
+ async getMeetingVoteDetail(meetingId, voteId) {
475
+ return this.post('/meeting/vote/get', {
476
+ meeting_id: meetingId,
477
+ vote_id: voteId
478
+ });
479
+ }
480
+
481
+ /**
482
+ * 删除会议投票
483
+ * @param {string} meetingId 会议 ID
484
+ * @param {string} voteId 投票 ID
485
+ */
486
+ async deleteMeetingVote(meetingId, voteId) {
487
+ return this.post('/meeting/vote/delete', {
488
+ meeting_id: meetingId,
489
+ vote_id: voteId
490
+ });
491
+ }
492
+
493
+ /**
494
+ * 发起会议投票
495
+ * @param {string} meetingId 会议 ID
496
+ * @param {string} voteId 投票 ID
497
+ */
498
+ async startMeetingVote(meetingId, voteId) {
499
+ return this.post('/meeting/vote/start', {
500
+ meeting_id: meetingId,
501
+ vote_id: voteId
502
+ });
503
+ }
504
+
505
+ /**
506
+ * 结束会议投票
507
+ * @param {string} meetingId 会议 ID
508
+ * @param {string} voteId 投票 ID
509
+ */
510
+ async endMeetingVote(meetingId, voteId) {
511
+ return this.post('/meeting/vote/end', {
512
+ meeting_id: meetingId,
513
+ vote_id: voteId
514
+ });
515
+ }
516
+
517
+ // ========== 会议布局和背景管理 ==========
518
+
519
+ /**
520
+ * 获取布局模板列表
521
+ */
522
+ async getLayoutTemplateList() {
523
+ return this.post('/meeting/layout/list', {});
524
+ }
525
+
526
+ /**
527
+ * 添加会议基础布局
528
+ * @param {object} layout 布局配置
529
+ */
530
+ async addBasicLayout(layout) {
531
+ return this.post('/meeting/layout/add', layout);
532
+ }
533
+
534
+ /**
535
+ * 添加会议高级布局
536
+ * @param {object} layout 布局配置
537
+ */
538
+ async addAdvancedLayout(layout) {
539
+ return this.post('/meeting/layout/add_advanced', layout);
540
+ }
541
+
542
+ /**
543
+ * 修改会议基础布局
544
+ * @param {string} layoutId 布局 ID
545
+ * @param {object} layout 布局配置
546
+ */
547
+ async updateBasicLayout(layoutId, layout) {
548
+ return this.post('/meeting/layout/update', {
549
+ layout_id: layoutId,
550
+ ...layout
551
+ });
552
+ }
553
+
554
+ /**
555
+ * 设置会议默认布局
556
+ * @param {string} meetingId 会议 ID
557
+ * @param {string} layoutId 布局 ID
558
+ */
559
+ async setDefaultLayout(meetingId, layoutId) {
560
+ return this.post('/meeting/layout/set_default', {
561
+ meeting_id: meetingId,
562
+ layout_id: layoutId
563
+ });
564
+ }
565
+
566
+ /**
567
+ * 获取会议布局列表
568
+ * @param {string} meetingId 会议 ID
569
+ */
570
+ async getMeetingLayoutList(meetingId) {
571
+ return this.post('/meeting/layout/get_list', { meeting_id: meetingId });
572
+ }
573
+
574
+ /**
575
+ * 获取用户布局
576
+ * @param {string} userId 用户 ID
577
+ */
578
+ async getUserLayout(userId) {
579
+ return this.post('/meeting/layout/get_user_layout', { userid: userId });
580
+ }
581
+
582
+ /**
583
+ * 批量删除布局
584
+ * @param {string[]} layoutIds 布局 ID 列表
585
+ */
586
+ async batchDeleteLayout(layoutIds) {
587
+ return this.post('/meeting/layout/batch_delete', { layout_ids: layoutIds });
588
+ }
589
+
590
+ /**
591
+ * 添加会议背景
592
+ * @param {string} filePath 背景文件路径
593
+ * @param {string} type 背景类型: default, custom
594
+ */
595
+ async addMeetingBackground(filePath, type = 'custom') {
596
+ return this.uploadFile(filePath, 'media', { type });
597
+ }
598
+
599
+ /**
600
+ * 获取会议背景列表
601
+ */
602
+ async getMeetingBackgroundList() {
603
+ return this.post('/meeting/background/list', {});
604
+ }
605
+
606
+ /**
607
+ * 设置会议默认背景
608
+ * @param {string} backgroundId 背景 ID
609
+ */
610
+ async setDefaultBackground(backgroundId) {
611
+ return this.post('/meeting/background/set_default', { background_id: backgroundId });
612
+ }
613
+
614
+ /**
615
+ * 删除会议背景
616
+ * @param {string} backgroundId 背景 ID
617
+ */
618
+ async deleteMeetingBackground(backgroundId) {
619
+ return this.post('/meeting/background/delete', { background_id: backgroundId });
620
+ }
621
+
622
+ // ========== MRA会议室连接器管理 ==========
623
+
624
+ /**
625
+ * 获取 MRA 状态信息
626
+ * @param {string} deviceId 设备 ID
627
+ */
628
+ async getMraStatus(deviceId) {
629
+ return this.post('/meeting/mra/status', { device_id: deviceId });
630
+ }
631
+
632
+ /**
633
+ * 切换 MRA 默认布局
634
+ * @param {string} deviceId 设备 ID
635
+ * @param {string} layoutId 布局 ID
636
+ */
637
+ async switchMraLayout(deviceId, layoutId) {
638
+ return this.post('/meeting/mra/switch_layout', {
639
+ device_id: deviceId,
640
+ layout_id: layoutId
641
+ });
642
+ }
643
+
644
+ /**
645
+ * 设置 MRA 举手或手放下
646
+ * @param {string} deviceId 设备 ID
647
+ * @param {number} handStatus 举手状态: 0-放下 1-举手
648
+ */
649
+ async setMraHand(deviceId, handStatus) {
650
+ return this.post('/meeting/mra/hand', {
651
+ device_id: deviceId,
652
+ hand_status: handStatus
653
+ });
654
+ }
655
+
656
+ /**
657
+ * 挂断 MRA 呼叫
658
+ * @param {string} deviceId 设备 ID
659
+ */
660
+ async hangupMra(deviceId) {
661
+ return this.post('/meeting/mra/hangup', { device_id: deviceId });
662
+ }
663
+ }
664
+
665
+ module.exports = Meeting;