@webex/plugin-meetings 3.11.0 → 3.12.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/dist/aiEnableRequest/index.js +184 -0
- package/dist/aiEnableRequest/index.js.map +1 -0
- package/dist/aiEnableRequest/utils.js +36 -0
- package/dist/aiEnableRequest/utils.js.map +1 -0
- package/dist/annotation/index.js +14 -5
- package/dist/annotation/index.js.map +1 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/config.js +5 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +28 -6
- package/dist/constants.js.map +1 -1
- package/dist/hashTree/constants.js +3 -1
- package/dist/hashTree/constants.js.map +1 -1
- package/dist/hashTree/hashTree.js +18 -0
- package/dist/hashTree/hashTree.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +709 -380
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/hashTree/types.js +4 -2
- package/dist/hashTree/types.js.map +1 -1
- package/dist/hashTree/utils.js +10 -0
- package/dist/hashTree/utils.js.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/interceptors/constant.js +12 -0
- package/dist/interceptors/constant.js.map +1 -0
- package/dist/interceptors/dataChannelAuthToken.js +290 -0
- package/dist/interceptors/dataChannelAuthToken.js.map +1 -0
- package/dist/interceptors/index.js +7 -0
- package/dist/interceptors/index.js.map +1 -1
- package/dist/interceptors/utils.js +27 -0
- package/dist/interceptors/utils.js.map +1 -0
- package/dist/interpretation/index.js +2 -2
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +5 -3
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +217 -79
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +1 -0
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/locus-info/types.js.map +1 -1
- package/dist/media/MediaConnectionAwaiter.js +57 -1
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/properties.js +4 -2
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +7 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1082 -861
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +50 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +133 -3
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +100 -45
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/index.js +10 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +10 -0
- package/dist/member/util.js.map +1 -1
- package/dist/metrics/constants.js +2 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +9 -60
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +11 -0
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/reachability/index.js +18 -10
- package/dist/reachability/index.js.map +1 -1
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.js +0 -1
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/types/aiEnableRequest/index.d.ts +5 -0
- package/dist/types/aiEnableRequest/utils.d.ts +2 -0
- package/dist/types/config.d.ts +3 -0
- package/dist/types/constants.d.ts +23 -1
- package/dist/types/hashTree/constants.d.ts +1 -0
- package/dist/types/hashTree/hashTree.d.ts +7 -0
- package/dist/types/hashTree/hashTreeParser.d.ts +99 -14
- package/dist/types/hashTree/types.d.ts +3 -0
- package/dist/types/hashTree/utils.d.ts +6 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/interceptors/constant.d.ts +5 -0
- package/dist/types/interceptors/dataChannelAuthToken.d.ts +43 -0
- package/dist/types/interceptors/index.d.ts +2 -1
- package/dist/types/interceptors/utils.d.ts +1 -0
- package/dist/types/locus-info/index.d.ts +21 -2
- package/dist/types/locus-info/types.d.ts +1 -0
- package/dist/types/media/MediaConnectionAwaiter.d.ts +10 -1
- package/dist/types/media/properties.d.ts +2 -1
- package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
- package/dist/types/meeting/index.d.ts +38 -6
- package/dist/types/meeting/request.d.ts +16 -1
- package/dist/types/meeting/request.type.d.ts +5 -0
- package/dist/types/meeting/util.d.ts +31 -0
- package/dist/types/meetings/index.d.ts +4 -2
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/util.d.ts +5 -0
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/multistream/mediaRequestManager.d.ts +0 -23
- package/dist/types/reactions/reactions.type.d.ts +1 -0
- package/dist/types/webinar/utils.d.ts +6 -0
- package/dist/webinar/index.js +260 -90
- package/dist/webinar/index.js.map +1 -1
- package/dist/webinar/utils.js +25 -0
- package/dist/webinar/utils.js.map +1 -0
- package/package.json +24 -23
- package/src/aiEnableRequest/README.md +84 -0
- package/src/aiEnableRequest/index.ts +170 -0
- package/src/aiEnableRequest/utils.ts +25 -0
- package/src/annotation/index.ts +27 -7
- package/src/config.ts +3 -0
- package/src/constants.ts +29 -1
- package/src/hashTree/constants.ts +1 -0
- package/src/hashTree/hashTree.ts +17 -0
- package/src/hashTree/hashTreeParser.ts +627 -249
- package/src/hashTree/types.ts +4 -0
- package/src/hashTree/utils.ts +9 -0
- package/src/index.ts +8 -1
- package/src/interceptors/constant.ts +6 -0
- package/src/interceptors/dataChannelAuthToken.ts +170 -0
- package/src/interceptors/index.ts +2 -1
- package/src/interceptors/utils.ts +16 -0
- package/src/interpretation/index.ts +2 -2
- package/src/locus-info/controlsUtils.ts +11 -0
- package/src/locus-info/index.ts +231 -61
- package/src/locus-info/selfUtils.ts +1 -0
- package/src/locus-info/types.ts +1 -0
- package/src/media/MediaConnectionAwaiter.ts +41 -1
- package/src/media/properties.ts +3 -1
- package/src/meeting/in-meeting-actions.ts +12 -0
- package/src/meeting/index.ts +205 -44
- package/src/meeting/request.ts +42 -0
- package/src/meeting/request.type.ts +6 -0
- package/src/meeting/util.ts +160 -2
- package/src/meetings/index.ts +135 -41
- package/src/member/index.ts +10 -0
- package/src/member/util.ts +12 -0
- package/src/metrics/constants.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +4 -54
- package/src/multistream/remoteMediaManager.ts +13 -0
- package/src/reachability/index.ts +9 -0
- package/src/reactions/reactions.type.ts +1 -0
- package/src/reconnection-manager/index.ts +0 -1
- package/src/webinar/index.ts +162 -5
- package/src/webinar/utils.ts +16 -0
- package/test/unit/spec/aiEnableRequest/index.ts +981 -0
- package/test/unit/spec/aiEnableRequest/utils.ts +130 -0
- package/test/unit/spec/annotation/index.ts +69 -7
- package/test/unit/spec/hashTree/hashTree.ts +66 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +1869 -189
- package/test/unit/spec/interceptors/dataChannelAuthToken.ts +210 -0
- package/test/unit/spec/interceptors/utils.ts +75 -0
- package/test/unit/spec/locus-info/controlsUtils.js +29 -0
- package/test/unit/spec/locus-info/index.js +383 -46
- package/test/unit/spec/media/MediaConnectionAwaiter.ts +41 -1
- package/test/unit/spec/media/properties.ts +12 -3
- package/test/unit/spec/meeting/in-meeting-actions.ts +8 -2
- package/test/unit/spec/meeting/index.js +716 -115
- package/test/unit/spec/meeting/request.js +70 -0
- package/test/unit/spec/meeting/utils.js +438 -26
- package/test/unit/spec/meetings/index.js +652 -31
- package/test/unit/spec/member/index.js +28 -4
- package/test/unit/spec/member/util.js +65 -27
- package/test/unit/spec/multistream/mediaRequestManager.ts +2 -85
- package/test/unit/spec/multistream/remoteMediaManager.ts +30 -0
- package/test/unit/spec/reachability/index.ts +23 -0
- package/test/unit/spec/reconnection-manager/index.js +4 -8
- package/test/unit/spec/webinar/index.ts +348 -36
- package/test/unit/spec/webinar/utils.ts +39 -0
|
@@ -32,6 +32,7 @@ interface IInMeetingActions {
|
|
|
32
32
|
canLowerAllHands?: boolean;
|
|
33
33
|
canLowerSomeoneElsesHand?: boolean;
|
|
34
34
|
bothLeaveAndEndMeetingAvailable?: boolean;
|
|
35
|
+
requireHostEndMeetingBeforeLeave?: boolean;
|
|
35
36
|
canEnableClosedCaption?: boolean;
|
|
36
37
|
canStartTranscribing?: boolean;
|
|
37
38
|
canStopTranscribing?: boolean;
|
|
@@ -117,6 +118,8 @@ interface IInMeetingActions {
|
|
|
117
118
|
canMoveToLobby?: boolean;
|
|
118
119
|
canEnablePollingQA?: boolean;
|
|
119
120
|
canDisablePollingQA?: boolean;
|
|
121
|
+
canAttendeeRequestAiAssistantEnabled?: boolean;
|
|
122
|
+
isAttendeeRequestAiAssistantDeclinedAll?: boolean;
|
|
120
123
|
}
|
|
121
124
|
|
|
122
125
|
/**
|
|
@@ -169,6 +172,8 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
169
172
|
|
|
170
173
|
bothLeaveAndEndMeetingAvailable = null;
|
|
171
174
|
|
|
175
|
+
requireHostEndMeetingBeforeLeave = null;
|
|
176
|
+
|
|
172
177
|
canEnableClosedCaption = null;
|
|
173
178
|
|
|
174
179
|
canStartTranscribing = null;
|
|
@@ -337,6 +342,10 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
337
342
|
|
|
338
343
|
canDisablePollingQA = null;
|
|
339
344
|
|
|
345
|
+
canAttendeeRequestAiAssistantEnabled = null;
|
|
346
|
+
|
|
347
|
+
isAttendeeRequestAiAssistantDeclinedAll = null;
|
|
348
|
+
|
|
340
349
|
/**
|
|
341
350
|
* Returns all meeting action options
|
|
342
351
|
* @returns {Object}
|
|
@@ -364,6 +373,7 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
364
373
|
canLowerAllHands: this.canLowerAllHands,
|
|
365
374
|
canLowerSomeoneElsesHand: this.canLowerSomeoneElsesHand,
|
|
366
375
|
bothLeaveAndEndMeetingAvailable: this.bothLeaveAndEndMeetingAvailable,
|
|
376
|
+
requireHostEndMeetingBeforeLeave: this.requireHostEndMeetingBeforeLeave,
|
|
367
377
|
canEnableClosedCaption: this.canEnableClosedCaption,
|
|
368
378
|
canStartTranscribing: this.canStartTranscribing,
|
|
369
379
|
canStopTranscribing: this.canStopTranscribing,
|
|
@@ -448,6 +458,8 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
448
458
|
canMoveToLobby: this.canMoveToLobby,
|
|
449
459
|
canEnablePollingQA: this.canEnablePollingQA,
|
|
450
460
|
canDisablePollingQA: this.canDisablePollingQA,
|
|
461
|
+
canAttendeeRequestAiAssistantEnabled: this.canAttendeeRequestAiAssistantEnabled,
|
|
462
|
+
isAttendeeRequestAiAssistantDeclinedAll: this.isAttendeeRequestAiAssistantDeclinedAll,
|
|
451
463
|
});
|
|
452
464
|
|
|
453
465
|
/**
|
package/src/meeting/index.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
CALL_DIAGNOSTIC_CONFIG,
|
|
14
14
|
RtcMetrics,
|
|
15
15
|
} from '@webex/internal-plugin-metrics';
|
|
16
|
-
import {ClientEvent as RawClientEvent} from '@webex/event-dictionary-ts';
|
|
16
|
+
import type {ClientEvent as RawClientEvent} from '@webex/event-dictionary-ts';
|
|
17
17
|
|
|
18
18
|
import {
|
|
19
19
|
ConnectionState,
|
|
@@ -33,6 +33,8 @@ import {
|
|
|
33
33
|
InboundAudioIssueSubTypes,
|
|
34
34
|
} from '@webex/internal-media-core';
|
|
35
35
|
|
|
36
|
+
import {DataChannelTokenType} from '@webex/internal-plugin-llm';
|
|
37
|
+
|
|
36
38
|
import {
|
|
37
39
|
LocalStream,
|
|
38
40
|
LocalCameraStream,
|
|
@@ -55,6 +57,7 @@ import {
|
|
|
55
57
|
isBrowserMediaError,
|
|
56
58
|
isBrowserMediaErrorName,
|
|
57
59
|
} from '@webex/internal-plugin-metrics/src/call-diagnostic/call-diagnostic-metrics.util';
|
|
60
|
+
import {CapabilityState, WebCapabilities} from '@webex/web-capabilities';
|
|
58
61
|
import {processNewCaptions} from './voicea-meeting';
|
|
59
62
|
|
|
60
63
|
import {
|
|
@@ -178,8 +181,9 @@ import JoinForbiddenError from '../common/errors/join-forbidden-error';
|
|
|
178
181
|
import {ReachabilityMetrics} from '../reachability/reachability.types';
|
|
179
182
|
import {SetStageOptions, SetStageVideoLayout, UnsetStageVideoLayout} from './request.type';
|
|
180
183
|
import {Invitee} from './type';
|
|
181
|
-
import {DataSet} from '../hashTree/hashTreeParser';
|
|
184
|
+
import {DataSet, Metadata} from '../hashTree/hashTreeParser';
|
|
182
185
|
import {LocusDTO} from '../locus-info/types';
|
|
186
|
+
import AIEnableRequest from '../aiEnableRequest';
|
|
183
187
|
|
|
184
188
|
// default callback so we don't call an undefined function, but in practice it should never be used
|
|
185
189
|
const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
|
|
@@ -249,6 +253,7 @@ export type AddMediaOptions = {
|
|
|
249
253
|
remoteMediaManagerConfig?: RemoteMediaManagerConfiguration; // applies only to multistream meetings
|
|
250
254
|
bundlePolicy?: BundlePolicy; // applies only to multistream meetings
|
|
251
255
|
allowMediaInLobby?: boolean; // allows adding media when in the lobby
|
|
256
|
+
allowPublishMediaInLobby?: boolean; // allows publishing media when in the lobby, if not specified, default value false is used
|
|
252
257
|
additionalMediaOptions?: AdditionalMediaOptions; // allows adding additional options like send/receive audio/video
|
|
253
258
|
};
|
|
254
259
|
|
|
@@ -574,6 +579,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
574
579
|
breakouts: any;
|
|
575
580
|
simultaneousInterpretation: any;
|
|
576
581
|
annotation: any;
|
|
582
|
+
aiEnableRequest: any;
|
|
577
583
|
webinar: any;
|
|
578
584
|
conversationUrl: string;
|
|
579
585
|
callStateForMetrics: CallStateForMetrics;
|
|
@@ -622,6 +628,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
622
628
|
keepAliveTimerId: NodeJS.Timeout;
|
|
623
629
|
lastVideoLayoutInfo: any;
|
|
624
630
|
locusInfo: any;
|
|
631
|
+
// this group of properties is populated via updateMeetingObject() that's registered as a callback with LocusInfo
|
|
632
|
+
isUserUnadmitted?: boolean;
|
|
633
|
+
joinedWith?: any;
|
|
634
|
+
selfId?: string;
|
|
635
|
+
roles: any[];
|
|
636
|
+
// ... there is more ... see SelfUtils.parse()
|
|
637
|
+
// end of the group
|
|
625
638
|
locusMediaRequest?: LocusMediaRequest;
|
|
626
639
|
mediaProperties: MediaProperties;
|
|
627
640
|
mediaRequestManagers: {
|
|
@@ -656,7 +669,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
656
669
|
endCallInitJoinReq: any;
|
|
657
670
|
endJoinReqResp: any;
|
|
658
671
|
endLocalSDPGenRemoteSDPRecvDelay: any;
|
|
659
|
-
joinedWith: any;
|
|
660
672
|
locusId: any;
|
|
661
673
|
startCallInitJoinReq: any;
|
|
662
674
|
startJoinReqResp: any;
|
|
@@ -671,12 +683,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
671
683
|
permissionTokenReceivedLocalTime: number;
|
|
672
684
|
resourceId: any;
|
|
673
685
|
resourceUrl: string;
|
|
674
|
-
selfId: string;
|
|
675
686
|
state: any;
|
|
676
687
|
localAudioStreamMuteStateHandler: () => void;
|
|
677
688
|
localVideoStreamMuteStateHandler: () => void;
|
|
678
689
|
localOutputTrackChangeHandler: () => void;
|
|
679
|
-
|
|
690
|
+
localConstraintsChangeHandler: () => void;
|
|
680
691
|
environment: string;
|
|
681
692
|
namespace = MEETINGS;
|
|
682
693
|
allowMediaInLobby: boolean;
|
|
@@ -893,6 +904,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
893
904
|
*/
|
|
894
905
|
// @ts-ignore
|
|
895
906
|
this.simultaneousInterpretation = new SimultaneousInterpretation({}, {parent: this.webex});
|
|
907
|
+
|
|
908
|
+
// @ts-ignore
|
|
909
|
+
this.aiEnableRequest = new AIEnableRequest({}, {parent: this.webex});
|
|
910
|
+
|
|
896
911
|
/**
|
|
897
912
|
* @instance
|
|
898
913
|
* @type {Annotation}
|
|
@@ -1542,6 +1557,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1542
1557
|
}
|
|
1543
1558
|
};
|
|
1544
1559
|
|
|
1560
|
+
this.localConstraintsChangeHandler = () => {
|
|
1561
|
+
if (!this.isMultistream) {
|
|
1562
|
+
this.mediaProperties.webrtcMediaConnection?.updatePreferredBitrateKbps();
|
|
1563
|
+
}
|
|
1564
|
+
};
|
|
1565
|
+
|
|
1545
1566
|
/**
|
|
1546
1567
|
* Promise that exists if SDP offer has been generated, and resolves once sdp answer is received.
|
|
1547
1568
|
* @instance
|
|
@@ -2951,6 +2972,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2951
2972
|
);
|
|
2952
2973
|
});
|
|
2953
2974
|
|
|
2975
|
+
this.locusInfo.on(
|
|
2976
|
+
LOCUSINFO.EVENTS.CONTROLS_AI_SUMMARY_NOTIFICATION_UPDATED,
|
|
2977
|
+
({aiSummaryNotification}) => {
|
|
2978
|
+
Trigger.trigger(
|
|
2979
|
+
this,
|
|
2980
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
2981
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_AI_SUMMARY_NOTIFICATION_UPDATED,
|
|
2982
|
+
{aiSummaryNotification}
|
|
2983
|
+
);
|
|
2984
|
+
}
|
|
2985
|
+
);
|
|
2986
|
+
|
|
2954
2987
|
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_WEBCAST_CHANGED, ({state}) => {
|
|
2955
2988
|
Trigger.trigger(
|
|
2956
2989
|
this,
|
|
@@ -3402,6 +3435,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3402
3435
|
this.recordingController.setLocusUrl(this.locusUrl);
|
|
3403
3436
|
this.controlsOptionsManager.setLocusUrl(this.locusUrl, !!isMainLocus);
|
|
3404
3437
|
this.webinar.locusUrlUpdate(url);
|
|
3438
|
+
// @ts-ignore
|
|
3439
|
+
this.webex.internal.llm.setRefreshHandler(() => this.refreshDataChannelToken());
|
|
3405
3440
|
|
|
3406
3441
|
Trigger.trigger(
|
|
3407
3442
|
this,
|
|
@@ -3432,6 +3467,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3432
3467
|
this.breakouts.breakoutServiceUrlUpdate(payload?.services?.breakout?.url);
|
|
3433
3468
|
this.annotation.approvalUrlUpdate(payload?.services?.approval?.url);
|
|
3434
3469
|
this.simultaneousInterpretation.approvalUrlUpdate(payload?.services?.approval?.url);
|
|
3470
|
+
this.aiEnableRequest.approvalUrlUpdate(payload?.services?.approval?.url);
|
|
3435
3471
|
});
|
|
3436
3472
|
}
|
|
3437
3473
|
|
|
@@ -3529,6 +3565,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3529
3565
|
// @ts-ignore - config coming from registerPlugin
|
|
3530
3566
|
if (datachannelUrl && this.config.enableAutomaticLLM) {
|
|
3531
3567
|
this.updateLLMConnection();
|
|
3568
|
+
if (this.webinar.isJoinPracticeSessionDataChannel()) {
|
|
3569
|
+
this.webinar.updatePSDataChannel();
|
|
3570
|
+
}
|
|
3532
3571
|
}
|
|
3533
3572
|
}
|
|
3534
3573
|
|
|
@@ -3761,6 +3800,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3761
3800
|
);
|
|
3762
3801
|
});
|
|
3763
3802
|
|
|
3803
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.SELF_ID_CHANGED, (payload) => {
|
|
3804
|
+
this.aiEnableRequest.selfParticipantIdUpdate(payload.selfId);
|
|
3805
|
+
});
|
|
3806
|
+
|
|
3764
3807
|
this.locusInfo.on(LOCUSINFO.EVENTS.SELF_MEETING_INTERPRETATION_CHANGED, (payload) => {
|
|
3765
3808
|
const targetChanged = this.simultaneousInterpretation.updateSelfInterpretation(payload);
|
|
3766
3809
|
Trigger.trigger(
|
|
@@ -4263,6 +4306,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4263
4306
|
bothLeaveAndEndMeetingAvailable: MeetingUtil.bothLeaveAndEndMeetingAvailable(
|
|
4264
4307
|
this.userDisplayHints
|
|
4265
4308
|
),
|
|
4309
|
+
requireHostEndMeetingBeforeLeave: MeetingUtil.requireHostEndMeetingBeforeLeave(
|
|
4310
|
+
this.userDisplayHints
|
|
4311
|
+
),
|
|
4266
4312
|
canEnableClosedCaption: MeetingUtil.canEnableClosedCaption(this.userDisplayHints),
|
|
4267
4313
|
canStartTranscribing: MeetingUtil.canStartTranscribing(this.userDisplayHints),
|
|
4268
4314
|
canStopTranscribing: MeetingUtil.canStopTranscribing(this.userDisplayHints),
|
|
@@ -4521,6 +4567,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4521
4567
|
requiredHints: [DISPLAY_HINTS.DISABLE_ATTENDEE_START_POLLING_QA],
|
|
4522
4568
|
displayHints: this.userDisplayHints,
|
|
4523
4569
|
}),
|
|
4570
|
+
canAttendeeRequestAiAssistantEnabled: MeetingUtil.canAttendeeRequestAiAssistantEnabled(
|
|
4571
|
+
this.userDisplayHints,
|
|
4572
|
+
this.roles
|
|
4573
|
+
),
|
|
4574
|
+
isAttendeeRequestAiAssistantDeclinedAll:
|
|
4575
|
+
MeetingUtil.attendeeRequestAiAssistantDeclinedAll(this.userDisplayHints),
|
|
4524
4576
|
}) || changed;
|
|
4525
4577
|
}
|
|
4526
4578
|
if (changed) {
|
|
@@ -4592,7 +4644,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4592
4644
|
mediaId: string;
|
|
4593
4645
|
host: object;
|
|
4594
4646
|
selfId: string;
|
|
4595
|
-
dataSets: DataSet[];
|
|
4647
|
+
dataSets: DataSet[]; // only sent by Locus when hash trees are used
|
|
4648
|
+
metadata: Metadata; // only sent by Locus when hash trees are used
|
|
4596
4649
|
}) {
|
|
4597
4650
|
const mtgLocus: any = data.locus;
|
|
4598
4651
|
|
|
@@ -4608,6 +4661,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4608
4661
|
trigger: 'join-response',
|
|
4609
4662
|
locus: mtgLocus,
|
|
4610
4663
|
dataSets: data.dataSets,
|
|
4664
|
+
metadata: data.metadata,
|
|
4611
4665
|
});
|
|
4612
4666
|
}
|
|
4613
4667
|
|
|
@@ -4817,6 +4871,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4817
4871
|
this.localVideoStreamMuteStateHandler
|
|
4818
4872
|
);
|
|
4819
4873
|
oldStream?.off(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
4874
|
+
oldStream?.off(LocalStreamEventNames.ConstraintsChange, this.localConstraintsChangeHandler);
|
|
4820
4875
|
|
|
4821
4876
|
// we don't update this.mediaProperties.mediaDirection.sendVideo, because we always keep it as true to avoid extra SDP exchanges
|
|
4822
4877
|
this.mediaProperties.setLocalVideoStream(localStream);
|
|
@@ -4832,6 +4887,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4832
4887
|
this.localVideoStreamMuteStateHandler
|
|
4833
4888
|
);
|
|
4834
4889
|
localStream?.on(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
4890
|
+
localStream?.on(LocalStreamEventNames.ConstraintsChange, this.localConstraintsChangeHandler);
|
|
4835
4891
|
|
|
4836
4892
|
if (!this.isMultistream || !localStream) {
|
|
4837
4893
|
// for multistream WCME automatically un-publishes the old stream when we publish a new one
|
|
@@ -4966,6 +5022,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4966
5022
|
this.localVideoStreamMuteStateHandler
|
|
4967
5023
|
);
|
|
4968
5024
|
videoStream?.off(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
5025
|
+
videoStream?.off(LocalStreamEventNames.ConstraintsChange, this.localConstraintsChangeHandler);
|
|
4969
5026
|
|
|
4970
5027
|
shareAudioStream?.off(StreamEventNames.Ended, this.handleShareAudioStreamEnded);
|
|
4971
5028
|
shareAudioStream?.off(
|
|
@@ -5379,6 +5436,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5379
5436
|
let joined = false;
|
|
5380
5437
|
let joinResponse = prevJoinResponse;
|
|
5381
5438
|
|
|
5439
|
+
/* Before we do anything, check if RTCPeerConnection is available. Normally this is checked
|
|
5440
|
+
by addMediaInternal() itself when creating the media connection, but since joinWithMedia()
|
|
5441
|
+
is a convenience method that does both join() and addMedia(), we want to fail fast here
|
|
5442
|
+
in case WebRTC is not available at all.
|
|
5443
|
+
*/
|
|
5444
|
+
if (WebCapabilities.supportsRTCPeerConnection() === CapabilityState.NOT_CAPABLE) {
|
|
5445
|
+
// throw the same error that would be thrown by addMediaInternal()
|
|
5446
|
+
throw new Errors.WebrtcApiNotAvailableError(
|
|
5447
|
+
'RTCPeerConnection API is not available in this environment'
|
|
5448
|
+
);
|
|
5449
|
+
}
|
|
5450
|
+
|
|
5382
5451
|
try {
|
|
5383
5452
|
let turnServerInfo;
|
|
5384
5453
|
let turnDiscoverySkippedReason;
|
|
@@ -5449,7 +5518,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5449
5518
|
// if this was the first attempt, let's do a retry
|
|
5450
5519
|
let shouldRetry = !isRetry;
|
|
5451
5520
|
|
|
5452
|
-
if (
|
|
5521
|
+
if (
|
|
5522
|
+
CallDiagnosticUtils.isSdpOfferCreationError(error) ||
|
|
5523
|
+
CallDiagnosticUtils.isWebrtcApiNotAvailableError(error)
|
|
5524
|
+
) {
|
|
5453
5525
|
// errors related to offer creation (for example missing H264 codec) will happen again no matter how many times we try,
|
|
5454
5526
|
// so there is no point doing a retry
|
|
5455
5527
|
shouldRetry = false;
|
|
@@ -5765,7 +5837,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5765
5837
|
this.isReactionsSupported()
|
|
5766
5838
|
) {
|
|
5767
5839
|
const member = this.members.membersCollection.get(e.data.sender.participantId);
|
|
5768
|
-
if (!member) {
|
|
5840
|
+
if (!member && !this.locusInfo?.info?.isWebinar) {
|
|
5769
5841
|
// @ts-ignore -- fix type
|
|
5770
5842
|
LoggerProxy.logger.warn(
|
|
5771
5843
|
`Meeting:index#processRelayEvent --> Skipping handling of ${REACTION_RELAY_TYPES.REACTION} for ${this.id}. participantId ${e.data.sender.participantId} does not exist in membersCollection.`
|
|
@@ -5773,7 +5845,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5773
5845
|
break;
|
|
5774
5846
|
}
|
|
5775
5847
|
|
|
5776
|
-
const
|
|
5848
|
+
const name = (member && member.name) || e.data.sender.displayName;
|
|
5777
5849
|
const processedReaction: ProcessedReaction = {
|
|
5778
5850
|
reaction: e.data.reaction,
|
|
5779
5851
|
sender: {
|
|
@@ -6161,6 +6233,49 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6161
6233
|
}
|
|
6162
6234
|
}
|
|
6163
6235
|
|
|
6236
|
+
/**
|
|
6237
|
+
* Disconnects and cleans up the default LLM session listeners/timers.
|
|
6238
|
+
* @param {Object} options
|
|
6239
|
+
* @param {boolean} [options.removeOnlineListener=true] removes the one-time online listener
|
|
6240
|
+
* @param {boolean} [options.throwOnError=true] rethrows disconnect errors when true
|
|
6241
|
+
* @returns {Promise<void>}
|
|
6242
|
+
*/
|
|
6243
|
+
private cleanupLLMConneciton = async ({
|
|
6244
|
+
removeOnlineListener = true,
|
|
6245
|
+
throwOnError = true,
|
|
6246
|
+
}: {
|
|
6247
|
+
removeOnlineListener?: boolean;
|
|
6248
|
+
throwOnError?: boolean;
|
|
6249
|
+
} = {}): Promise<void> => {
|
|
6250
|
+
try {
|
|
6251
|
+
// @ts-ignore - Fix type
|
|
6252
|
+
await this.webex.internal.llm.disconnectLLM({
|
|
6253
|
+
code: 3050,
|
|
6254
|
+
reason: 'done (permanent)',
|
|
6255
|
+
});
|
|
6256
|
+
} catch (error) {
|
|
6257
|
+
LoggerProxy.logger.error(
|
|
6258
|
+
'Meeting:index#cleanupLLMConneciton --> Failed to disconnect default LLM session',
|
|
6259
|
+
error
|
|
6260
|
+
);
|
|
6261
|
+
|
|
6262
|
+
if (throwOnError) {
|
|
6263
|
+
throw error;
|
|
6264
|
+
}
|
|
6265
|
+
} finally {
|
|
6266
|
+
if (removeOnlineListener) {
|
|
6267
|
+
// @ts-ignore - Fix type
|
|
6268
|
+
this.webex.internal.llm.off('online', this.handleLLMOnline);
|
|
6269
|
+
}
|
|
6270
|
+
// @ts-ignore - fix types
|
|
6271
|
+
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
|
6272
|
+
// @ts-ignore - Fix type
|
|
6273
|
+
this.webex.internal.llm.off(LOCUS_LLM_EVENT, this.processLocusLLMEvent);
|
|
6274
|
+
|
|
6275
|
+
this.clearLLMHealthCheckTimer();
|
|
6276
|
+
}
|
|
6277
|
+
};
|
|
6278
|
+
|
|
6164
6279
|
/**
|
|
6165
6280
|
* Connects to low latency mercury and reconnects if the address has changed
|
|
6166
6281
|
* It will also disconnect if called when the meeting has ended
|
|
@@ -6169,15 +6284,26 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6169
6284
|
*/
|
|
6170
6285
|
async updateLLMConnection() {
|
|
6171
6286
|
// @ts-ignore - Fix type
|
|
6172
|
-
const {
|
|
6287
|
+
const {
|
|
6288
|
+
url = undefined,
|
|
6289
|
+
info: {datachannelUrl = undefined} = {},
|
|
6290
|
+
self: {datachannelToken = undefined} = {},
|
|
6291
|
+
} = this.locusInfo || {};
|
|
6173
6292
|
|
|
6174
6293
|
const isJoined = this.isJoined();
|
|
6175
6294
|
|
|
6295
|
+
// @ts-ignore
|
|
6296
|
+
const currentToken = this.webex.internal.llm.getDatachannelToken(DataChannelTokenType.Default);
|
|
6297
|
+
|
|
6298
|
+
const finalToken = currentToken ?? datachannelToken;
|
|
6299
|
+
|
|
6300
|
+
if (!currentToken && datachannelToken) {
|
|
6301
|
+
// @ts-ignore
|
|
6302
|
+
this.webex.internal.llm.setDatachannelToken(datachannelToken, DataChannelTokenType.Default);
|
|
6303
|
+
}
|
|
6304
|
+
|
|
6176
6305
|
// webinar panelist should use new data channel in practice session
|
|
6177
|
-
const dataChannelUrl =
|
|
6178
|
-
this.webinar.isJoinPracticeSessionDataChannel() && practiceSessionDatachannelUrl
|
|
6179
|
-
? practiceSessionDatachannelUrl
|
|
6180
|
-
: datachannelUrl;
|
|
6306
|
+
const dataChannelUrl = datachannelUrl;
|
|
6181
6307
|
|
|
6182
6308
|
// @ts-ignore - Fix type
|
|
6183
6309
|
if (this.webex.internal.llm.isConnected()) {
|
|
@@ -6190,21 +6316,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6190
6316
|
) {
|
|
6191
6317
|
return undefined;
|
|
6192
6318
|
}
|
|
6193
|
-
|
|
6194
|
-
await this.webex.internal.llm.disconnectLLM(
|
|
6195
|
-
isJoined
|
|
6196
|
-
? {
|
|
6197
|
-
code: 3050,
|
|
6198
|
-
reason: 'done (permanent)',
|
|
6199
|
-
}
|
|
6200
|
-
: undefined
|
|
6201
|
-
);
|
|
6202
|
-
// @ts-ignore - Fix type
|
|
6203
|
-
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
|
6204
|
-
// @ts-ignore - Fix type
|
|
6205
|
-
this.webex.internal.llm.off(LOCUS_LLM_EVENT, this.processLocusLLMEvent);
|
|
6206
|
-
|
|
6207
|
-
this.clearLLMHealthCheckTimer();
|
|
6319
|
+
await this.cleanupLLMConneciton({removeOnlineListener: false});
|
|
6208
6320
|
}
|
|
6209
6321
|
|
|
6210
6322
|
if (!isJoined) {
|
|
@@ -6213,7 +6325,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6213
6325
|
|
|
6214
6326
|
// @ts-ignore - Fix type
|
|
6215
6327
|
return this.webex.internal.llm
|
|
6216
|
-
.registerAndConnect(url, dataChannelUrl)
|
|
6328
|
+
.registerAndConnect(url, dataChannelUrl, finalToken)
|
|
6217
6329
|
.then((registerAndConnectResult) => {
|
|
6218
6330
|
// @ts-ignore - Fix type
|
|
6219
6331
|
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
|
@@ -7417,7 +7529,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7417
7529
|
*/
|
|
7418
7530
|
private async waitForMediaConnectionConnected(): Promise<void> {
|
|
7419
7531
|
try {
|
|
7420
|
-
await this.mediaProperties.waitForMediaConnectionConnected();
|
|
7532
|
+
await this.mediaProperties.waitForMediaConnectionConnected(this.correlationId);
|
|
7421
7533
|
} catch (error) {
|
|
7422
7534
|
const {iceConnected} = error;
|
|
7423
7535
|
|
|
@@ -8010,6 +8122,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
8010
8122
|
remoteMediaManagerConfig,
|
|
8011
8123
|
bundlePolicy = 'max-bundle',
|
|
8012
8124
|
additionalMediaOptions = {},
|
|
8125
|
+
allowPublishMediaInLobby = false,
|
|
8013
8126
|
} = options;
|
|
8014
8127
|
|
|
8015
8128
|
const {
|
|
@@ -8030,7 +8143,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
8030
8143
|
const ipver = MeetingUtil.getIpVersion(this.webex); // used just for metrics
|
|
8031
8144
|
|
|
8032
8145
|
// If the user is unjoined or guest waiting in lobby dont allow the user to addMedia
|
|
8033
|
-
// @ts-ignore - isUserUnadmitted coming from SelfUtil
|
|
8034
8146
|
if (this.isUserUnadmitted && !this.wirelessShare && !this.allowMediaInLobby) {
|
|
8035
8147
|
throw new UserInLobbyError();
|
|
8036
8148
|
}
|
|
@@ -8075,7 +8187,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
8075
8187
|
this.brbState = createBrbState(this, false);
|
|
8076
8188
|
|
|
8077
8189
|
try {
|
|
8078
|
-
|
|
8190
|
+
// if we're in a lobby and allowPublishMediaInLobby==false, we don't want to
|
|
8191
|
+
// setup local streams for publishing, because if we ever end up admitted to the meeting
|
|
8192
|
+
// but Locus event about it for us is delayed or missed, others could see/hear our user's video/audio
|
|
8193
|
+
// while the user would still think they're in the lobby
|
|
8194
|
+
if (allowPublishMediaInLobby || !this.isUserUnadmitted) {
|
|
8195
|
+
await this.setUpLocalStreamReferences(localStreams);
|
|
8196
|
+
}
|
|
8079
8197
|
|
|
8080
8198
|
this.setMercuryListener();
|
|
8081
8199
|
|
|
@@ -8543,12 +8661,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
8543
8661
|
LoggerProxy.logger.log('Meeting:index#leave --> Leaving a meeting');
|
|
8544
8662
|
|
|
8545
8663
|
return MeetingUtil.leaveMeeting(this, options)
|
|
8546
|
-
.then((leave) => {
|
|
8664
|
+
.then(async (leave) => {
|
|
8547
8665
|
// CA team recommends submitting this *after* locus /leave
|
|
8548
8666
|
submitLeaveMetric();
|
|
8549
8667
|
|
|
8550
8668
|
this.meetingFiniteStateMachine.leave();
|
|
8551
|
-
this.clearMeetingData();
|
|
8669
|
+
await this.clearMeetingData();
|
|
8552
8670
|
|
|
8553
8671
|
// upload logs on leave irrespective of meeting delete
|
|
8554
8672
|
Trigger.trigger(
|
|
@@ -9407,10 +9525,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
9407
9525
|
});
|
|
9408
9526
|
|
|
9409
9527
|
return MeetingUtil.endMeetingForAll(this)
|
|
9410
|
-
.then((end) => {
|
|
9528
|
+
.then(async (end) => {
|
|
9411
9529
|
this.meetingFiniteStateMachine.end();
|
|
9412
9530
|
|
|
9413
|
-
this.clearMeetingData();
|
|
9531
|
+
await this.clearMeetingData();
|
|
9414
9532
|
// upload logs on leave irrespective of meeting delete
|
|
9415
9533
|
Trigger.trigger(
|
|
9416
9534
|
this,
|
|
@@ -9458,7 +9576,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
9458
9576
|
* @public
|
|
9459
9577
|
* @memberof Meeting
|
|
9460
9578
|
*/
|
|
9461
|
-
clearMeetingData = () => {
|
|
9579
|
+
clearMeetingData = async () => {
|
|
9462
9580
|
this.audio = null;
|
|
9463
9581
|
this.video = null;
|
|
9464
9582
|
this.screenShareFloorState = ScreenShareFloorStatus.RELEASED;
|
|
@@ -9474,12 +9592,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
9474
9592
|
|
|
9475
9593
|
this.annotation.deregisterEvents();
|
|
9476
9594
|
|
|
9477
|
-
|
|
9478
|
-
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
|
9479
|
-
// @ts-ignore - Fix type
|
|
9480
|
-
this.webex.internal.llm.off(LOCUS_LLM_EVENT, this.processLocusLLMEvent);
|
|
9481
|
-
|
|
9482
|
-
this.clearLLMHealthCheckTimer();
|
|
9595
|
+
await this.cleanupLLMConneciton({throwOnError: false});
|
|
9483
9596
|
};
|
|
9484
9597
|
|
|
9485
9598
|
/**
|
|
@@ -10179,4 +10292,52 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
10179
10292
|
cancelSipCallOut(participantId: string) {
|
|
10180
10293
|
return this.meetingRequest.cancelSipCallOut(participantId);
|
|
10181
10294
|
}
|
|
10295
|
+
|
|
10296
|
+
/**
|
|
10297
|
+
* Method to get new data
|
|
10298
|
+
* @returns {Promise}
|
|
10299
|
+
*/
|
|
10300
|
+
public async refreshDataChannelToken() {
|
|
10301
|
+
const isPracticeSession = this.webinar.isJoinPracticeSessionDataChannel();
|
|
10302
|
+
const dataChannelTokenType = this.getDataChannelTokenType();
|
|
10303
|
+
|
|
10304
|
+
try {
|
|
10305
|
+
const res = await this.meetingRequest.fetchDatachannelToken({
|
|
10306
|
+
locusUrl: this.locusUrl,
|
|
10307
|
+
requestingParticipantId: this.members.selfId,
|
|
10308
|
+
isPracticeSession,
|
|
10309
|
+
});
|
|
10310
|
+
|
|
10311
|
+
return {
|
|
10312
|
+
body: {
|
|
10313
|
+
datachannelToken: res.body.datachannelToken,
|
|
10314
|
+
dataChannelTokenType,
|
|
10315
|
+
},
|
|
10316
|
+
};
|
|
10317
|
+
} catch (e) {
|
|
10318
|
+
const msg = e?.message || String(e);
|
|
10319
|
+
|
|
10320
|
+
LoggerProxy.logger.warn(
|
|
10321
|
+
`Meeting:index#refreshDataChannelToken --> DataChannel token refresh failed (likely locus changed or participant left): ${msg}`,
|
|
10322
|
+
{statusCode: e?.statusCode}
|
|
10323
|
+
);
|
|
10324
|
+
|
|
10325
|
+
return null;
|
|
10326
|
+
}
|
|
10327
|
+
}
|
|
10328
|
+
|
|
10329
|
+
/**
|
|
10330
|
+
* Determines the current data channel token type based on the meeting state.
|
|
10331
|
+
*
|
|
10332
|
+
* variant should be used when connecting to the LLM data channel.
|
|
10333
|
+
*
|
|
10334
|
+
* @returns {DataChannelTokenType} The token type representing the current session mode.
|
|
10335
|
+
*/
|
|
10336
|
+
public getDataChannelTokenType(): DataChannelTokenType {
|
|
10337
|
+
if (this.webinar.isJoinPracticeSessionDataChannel()) {
|
|
10338
|
+
return DataChannelTokenType.PracticeSession;
|
|
10339
|
+
}
|
|
10340
|
+
|
|
10341
|
+
return DataChannelTokenType.Default;
|
|
10342
|
+
}
|
|
10182
10343
|
}
|
package/src/meeting/request.ts
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
ToggleReactionsOptions,
|
|
34
34
|
PostMeetingDataConsentOptions,
|
|
35
35
|
SynchronizeVideoLayout,
|
|
36
|
+
fetchDataChannelTokenOptions,
|
|
36
37
|
} from './request.type';
|
|
37
38
|
import MeetingUtil from './util';
|
|
38
39
|
import {AnnotationInfo} from '../annotation/annotation.types';
|
|
@@ -1126,4 +1127,45 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
1126
1127
|
throw err;
|
|
1127
1128
|
}
|
|
1128
1129
|
}
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* Sends a request to retrieve the datachannel authorization token for a participant.
|
|
1133
|
+
*
|
|
1134
|
+
* For regular meeting data channel:
|
|
1135
|
+
* GET /locus/api/v1/loci/{uuid:lid}/participant/{uuid:pid}/datachannel/token
|
|
1136
|
+
*
|
|
1137
|
+
* For practice session data channel:
|
|
1138
|
+
* GET /locus/api/v1/loci/{uuid:lid}/participant/{uuid:pid}/practiceSession/datachannel/token
|
|
1139
|
+
*
|
|
1140
|
+
* @param {string} locusUrl - The locus url.
|
|
1141
|
+
* @param {string} requestingParticipantId - The participant UUID.
|
|
1142
|
+
* @param {boolean} [isPracticeSession=false] - Whether to get the practice session token.
|
|
1143
|
+
* @returns {Promise<{datachannelToken: string}>}
|
|
1144
|
+
*/
|
|
1145
|
+
public async fetchDatachannelToken({
|
|
1146
|
+
locusUrl,
|
|
1147
|
+
requestingParticipantId,
|
|
1148
|
+
isPracticeSession = false,
|
|
1149
|
+
}: fetchDataChannelTokenOptions) {
|
|
1150
|
+
if (!locusUrl || !requestingParticipantId) {
|
|
1151
|
+
return Promise.reject(new Error('locusUrl and participantId are required'));
|
|
1152
|
+
}
|
|
1153
|
+
const practicePrefix = isPracticeSession ? '/practiceSession' : '';
|
|
1154
|
+
|
|
1155
|
+
const uri = `${locusUrl}/${PARTICIPANT}/${requestingParticipantId}${practicePrefix}/datachannel/token`;
|
|
1156
|
+
|
|
1157
|
+
// @ts-ignore
|
|
1158
|
+
return this.locusDeltaRequest({
|
|
1159
|
+
method: HTTP_VERBS.GET,
|
|
1160
|
+
uri,
|
|
1161
|
+
}).catch((err) => {
|
|
1162
|
+
LoggerProxy.logger.warn(
|
|
1163
|
+
`Meeting:request#fetchDatachannelToken --> Failed to retrieve ${
|
|
1164
|
+
isPracticeSession ? 'practice session ' : ''
|
|
1165
|
+
}datachannel token: ${err?.message || err}`
|
|
1166
|
+
);
|
|
1167
|
+
|
|
1168
|
+
return null;
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1129
1171
|
}
|
|
@@ -88,4 +88,10 @@ export type UnsetStageVideoLayout = {
|
|
|
88
88
|
overrideDefault: false;
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
+
export type fetchDataChannelTokenOptions = {
|
|
92
|
+
locusUrl: string;
|
|
93
|
+
requestingParticipantId: string;
|
|
94
|
+
isPracticeSession: boolean;
|
|
95
|
+
};
|
|
96
|
+
|
|
91
97
|
export type SynchronizeVideoLayout = SetStageVideoLayout | UnsetStageVideoLayout;
|