@webex/plugin-meetings 3.1.0 → 3.3.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/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/common/errors/{reconnection-in-progress.js → reconnection-not-started.js} +27 -15
- package/dist/common/errors/reconnection-not-started.js.map +1 -0
- package/dist/constants.js +12 -3
- package/dist/constants.js.map +1 -1
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +7 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +10 -0
- package/dist/locus-info/index.js.map +1 -1
- package/dist/media/properties.js +102 -57
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +6 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +543 -467
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +27 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/util.js +9 -16
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting/voicea-meeting.js +37 -49
- package/dist/meeting/voicea-meeting.js.map +1 -1
- package/dist/meeting-info/util.js +304 -267
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +334 -298
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/index.js +6 -27
- package/dist/meetings/index.js.map +1 -1
- package/dist/reachability/index.js +6 -0
- package/dist/reachability/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +138 -109
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/request.js +3 -27
- package/dist/roap/request.js.map +1 -1
- package/dist/statsAnalyzer/index.js +4 -0
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +3 -0
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/types/common/errors/reconnection-not-started.d.ts +13 -0
- package/dist/{constants.d.ts → types/constants.d.ts} +11 -2
- package/dist/types/index.d.ts +19 -0
- package/dist/{media → types/media}/properties.d.ts +26 -2
- package/dist/{meeting → types/meeting}/in-meeting-actions.d.ts +6 -0
- package/dist/{meeting → types/meeting}/index.d.ts +5 -6
- package/dist/{meeting → types/meeting}/locusMediaRequest.d.ts +1 -0
- package/dist/{meeting → types/meeting}/util.d.ts +3 -0
- package/dist/{meeting → types/meeting}/voicea-meeting.d.ts +3 -2
- package/dist/{meeting-info → types/meeting-info}/index.d.ts +1 -1
- package/dist/{meeting-info → types/meeting-info}/meeting-info-v2.d.ts +1 -1
- package/dist/types/meeting-info/util.d.ts +49 -0
- package/dist/types/meeting-info/utilv2.d.ts +65 -0
- package/dist/{meetings → types/meetings}/index.d.ts +1 -16
- package/dist/{reconnection-manager → types/reconnection-manager}/index.d.ts +4 -14
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/common/errors/reconnection-not-started.ts +25 -0
- package/src/constants.ts +12 -4
- package/src/index.ts +30 -0
- package/src/locus-info/controlsUtils.ts +11 -0
- package/src/locus-info/index.ts +16 -0
- package/src/media/properties.ts +67 -15
- package/src/meeting/in-meeting-actions.ts +12 -0
- package/src/meeting/index.ts +121 -98
- package/src/meeting/locusMediaRequest.ts +31 -0
- package/src/meeting/util.ts +9 -16
- package/src/meeting/voicea-meeting.ts +44 -46
- package/src/meeting-info/util.ts +241 -233
- package/src/meeting-info/utilv2.ts +250 -244
- package/src/meetings/index.ts +8 -25
- package/src/reachability/index.ts +3 -0
- package/src/reconnection-manager/index.ts +128 -105
- package/src/roap/request.ts +1 -24
- package/src/statsAnalyzer/index.ts +4 -0
- package/src/statsAnalyzer/mqaUtil.ts +5 -0
- package/test/unit/spec/locus-info/controlsUtils.js +20 -0
- package/test/unit/spec/locus-info/index.js +21 -0
- package/test/unit/spec/media/properties.ts +145 -140
- package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
- package/test/unit/spec/meeting/index.js +243 -97
- package/test/unit/spec/meeting/locusMediaRequest.ts +49 -0
- package/test/unit/spec/meeting/utils.js +3 -10
- package/test/unit/spec/meeting/voicea-meeting.ts +5 -14
- package/test/unit/spec/meetings/index.js +27 -8
- package/test/unit/spec/reconnection-manager/index.js +127 -39
- package/test/unit/spec/roap/request.ts +0 -37
- package/test/unit/spec/stats-analyzer/index.js +11 -0
- package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
- package/dist/common/errors/reconnection-in-progress.js.map +0 -1
- package/dist/index.d.ts +0 -7
- package/dist/meeting-info/util.d.ts +0 -2
- package/dist/meeting-info/utilv2.d.ts +0 -2
- package/src/common/errors/reconnection-in-progress.ts +0 -8
- /package/dist/{annotation → types/annotation}/annotation.types.d.ts +0 -0
- /package/dist/{annotation → types/annotation}/constants.d.ts +0 -0
- /package/dist/{annotation → types/annotation}/index.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/breakout.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/collection.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/edit-lock-error.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/events.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/index.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/request.d.ts +0 -0
- /package/dist/{breakouts → types/breakouts}/utils.d.ts +0 -0
- /package/dist/{common → types/common}/browser-detection.d.ts +0 -0
- /package/dist/{common → types/common}/collection.d.ts +0 -0
- /package/dist/{common → types/common}/config.d.ts +0 -0
- /package/dist/{common → types/common}/errors/captcha-error.d.ts +0 -0
- /package/dist/{common → types/common}/errors/intent-to-join.d.ts +0 -0
- /package/dist/{common → types/common}/errors/join-meeting.d.ts +0 -0
- /package/dist/{common → types/common}/errors/media.d.ts +0 -0
- /package/dist/{common → types/common}/errors/no-meeting-info.d.ts +0 -0
- /package/dist/{common → types/common}/errors/parameter.d.ts +0 -0
- /package/dist/{common → types/common}/errors/password-error.d.ts +0 -0
- /package/dist/{common → types/common}/errors/permission.d.ts +0 -0
- /package/dist/{common → types/common}/errors/reclaim-host-role-errors.d.ts +0 -0
- /package/dist/{common → types/common}/errors/reconnection.d.ts +0 -0
- /package/dist/{common → types/common}/errors/stats.d.ts +0 -0
- /package/dist/{common → types/common}/errors/webex-errors.d.ts +0 -0
- /package/dist/{common → types/common}/errors/webex-meetings-error.d.ts +0 -0
- /package/dist/{common → types/common}/events/events-scope.d.ts +0 -0
- /package/dist/{common → types/common}/events/events.d.ts +0 -0
- /package/dist/{common → types/common}/events/trigger-proxy.d.ts +0 -0
- /package/dist/{common → types/common}/events/util.d.ts +0 -0
- /package/dist/{common → types/common}/logs/logger-config.d.ts +0 -0
- /package/dist/{common → types/common}/logs/logger-proxy.d.ts +0 -0
- /package/dist/{common → types/common}/logs/request.d.ts +0 -0
- /package/dist/{common → types/common}/queue.d.ts +0 -0
- /package/dist/{config.d.ts → types/config.d.ts} +0 -0
- /package/dist/{controls-options-manager → types/controls-options-manager}/constants.d.ts +0 -0
- /package/dist/{controls-options-manager → types/controls-options-manager}/enums.d.ts +0 -0
- /package/dist/{controls-options-manager → types/controls-options-manager}/index.d.ts +0 -0
- /package/dist/{controls-options-manager → types/controls-options-manager}/types.d.ts +0 -0
- /package/dist/{controls-options-manager → types/controls-options-manager}/util.d.ts +0 -0
- /package/dist/{interceptors → types/interceptors}/index.d.ts +0 -0
- /package/dist/{interceptors → types/interceptors}/locusRetry.d.ts +0 -0
- /package/dist/{interpretation → types/interpretation}/collection.d.ts +0 -0
- /package/dist/{interpretation → types/interpretation}/index.d.ts +0 -0
- /package/dist/{interpretation → types/interpretation}/siLanguage.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/controlsUtils.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/embeddedAppsUtils.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/fullState.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/hostUtils.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/index.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/infoUtils.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/mediaSharesUtils.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/parser.d.ts +0 -0
- /package/dist/{locus-info → types/locus-info}/selfUtils.d.ts +0 -0
- /package/dist/{media → types/media}/MediaConnectionAwaiter.d.ts +0 -0
- /package/dist/{media → types/media}/index.d.ts +0 -0
- /package/dist/{media → types/media}/util.d.ts +0 -0
- /package/dist/{mediaQualityMetrics → types/mediaQualityMetrics}/config.d.ts +0 -0
- /package/dist/{meeting → types/meeting}/muteState.d.ts +0 -0
- /package/dist/{meeting → types/meeting}/request.d.ts +0 -0
- /package/dist/{meeting → types/meeting}/request.type.d.ts +0 -0
- /package/dist/{meeting → types/meeting}/state.d.ts +0 -0
- /package/dist/{meeting-info → types/meeting-info}/collection.d.ts +0 -0
- /package/dist/{meeting-info → types/meeting-info}/request.d.ts +0 -0
- /package/dist/{meetings → types/meetings}/collection.d.ts +0 -0
- /package/dist/{meetings → types/meetings}/meetings.types.d.ts +0 -0
- /package/dist/{meetings → types/meetings}/request.d.ts +0 -0
- /package/dist/{meetings → types/meetings}/util.d.ts +0 -0
- /package/dist/{member → types/member}/index.d.ts +0 -0
- /package/dist/{member → types/member}/types.d.ts +0 -0
- /package/dist/{member → types/member}/util.d.ts +0 -0
- /package/dist/{members → types/members}/collection.d.ts +0 -0
- /package/dist/{members → types/members}/index.d.ts +0 -0
- /package/dist/{members → types/members}/request.d.ts +0 -0
- /package/dist/{members → types/members}/types.d.ts +0 -0
- /package/dist/{members → types/members}/util.d.ts +0 -0
- /package/dist/{metrics → types/metrics}/constants.d.ts +0 -0
- /package/dist/{metrics → types/metrics}/index.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/mediaRequestManager.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/receiveSlot.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/receiveSlotManager.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/remoteMedia.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/remoteMediaGroup.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/remoteMediaManager.d.ts +0 -0
- /package/dist/{multistream → types/multistream}/sendSlotManager.d.ts +0 -0
- /package/dist/{networkQualityMonitor → types/networkQualityMonitor}/index.d.ts +0 -0
- /package/dist/{personal-meeting-room → types/personal-meeting-room}/index.d.ts +0 -0
- /package/dist/{personal-meeting-room → types/personal-meeting-room}/request.d.ts +0 -0
- /package/dist/{personal-meeting-room → types/personal-meeting-room}/util.d.ts +0 -0
- /package/dist/{reachability → types/reachability}/clusterReachability.d.ts +0 -0
- /package/dist/{reachability → types/reachability}/index.d.ts +0 -0
- /package/dist/{reachability → types/reachability}/request.d.ts +0 -0
- /package/dist/{reachability → types/reachability}/util.d.ts +0 -0
- /package/dist/{reactions → types/reactions}/constants.d.ts +0 -0
- /package/dist/{reactions → types/reactions}/reactions.d.ts +0 -0
- /package/dist/{reactions → types/reactions}/reactions.type.d.ts +0 -0
- /package/dist/{recording-controller → types/recording-controller}/enums.d.ts +0 -0
- /package/dist/{recording-controller → types/recording-controller}/index.d.ts +0 -0
- /package/dist/{recording-controller → types/recording-controller}/util.d.ts +0 -0
- /package/dist/{roap → types/roap}/index.d.ts +0 -0
- /package/dist/{roap → types/roap}/request.d.ts +0 -0
- /package/dist/{roap → types/roap}/turnDiscovery.d.ts +0 -0
- /package/dist/{rtcMetrics → types/rtcMetrics}/constants.d.ts +0 -0
- /package/dist/{rtcMetrics → types/rtcMetrics}/index.d.ts +0 -0
- /package/dist/{statsAnalyzer → types/statsAnalyzer}/global.d.ts +0 -0
- /package/dist/{statsAnalyzer → types/statsAnalyzer}/index.d.ts +0 -0
- /package/dist/{statsAnalyzer → types/statsAnalyzer}/mqaUtil.d.ts +0 -0
- /package/dist/{transcription → types/transcription}/index.d.ts +0 -0
- /package/dist/{webinar → types/webinar}/collection.d.ts +0 -0
- /package/dist/{webinar → types/webinar}/index.d.ts +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import {type MeetingTranscriptPayload} from '@webex/internal-plugin-voicea';
|
|
2
|
+
|
|
1
3
|
export const getSpeaker = (members, csis = []) =>
|
|
2
4
|
Object.values(members).find((member: any) => {
|
|
3
5
|
const memberCSIs = member.participant.status.csis ?? [];
|
|
@@ -31,43 +33,16 @@ export const getSpeakerFromProxyOrStore = ({csisKey, meetingMembers, transcriptD
|
|
|
31
33
|
return {speaker, needsCaching};
|
|
32
34
|
};
|
|
33
35
|
|
|
34
|
-
export const processNewCaptions = ({
|
|
36
|
+
export const processNewCaptions = ({
|
|
37
|
+
data,
|
|
38
|
+
meeting,
|
|
39
|
+
}: {
|
|
40
|
+
data: MeetingTranscriptPayload;
|
|
41
|
+
meeting: any;
|
|
42
|
+
}) => {
|
|
35
43
|
const {transcriptId} = data;
|
|
36
44
|
const transcriptData = meeting.transcription;
|
|
37
45
|
|
|
38
|
-
if (data.isFinal) {
|
|
39
|
-
transcriptData.interimCaptions[transcriptId].forEach((interimId) => {
|
|
40
|
-
const interimTranscriptIndex = transcriptData.captions.findIndex(
|
|
41
|
-
(transcript) => transcript.id === interimId
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
if (interimTranscriptIndex !== -1) {
|
|
45
|
-
transcriptData.captions.splice(interimTranscriptIndex, 1);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
delete transcriptData.interimCaptions[transcriptId];
|
|
49
|
-
const csisKey = data.transcript?.csis[0];
|
|
50
|
-
|
|
51
|
-
const {needsCaching, speaker} = getSpeakerFromProxyOrStore({
|
|
52
|
-
meetingMembers: meeting.members.membersCollection.members,
|
|
53
|
-
transcriptData,
|
|
54
|
-
csisKey,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
if (needsCaching) {
|
|
58
|
-
transcriptData.speakerProxy[csisKey] = speaker;
|
|
59
|
-
}
|
|
60
|
-
const captionData = {
|
|
61
|
-
id: transcriptId,
|
|
62
|
-
isFinal: data.isFinal,
|
|
63
|
-
translations: data.translations,
|
|
64
|
-
text: data.transcript?.text,
|
|
65
|
-
currentSpokenLanguage: data.transcript?.transcript_language_code,
|
|
66
|
-
timestamp: data.timestamp,
|
|
67
|
-
speaker,
|
|
68
|
-
};
|
|
69
|
-
transcriptData.captions.push(captionData);
|
|
70
|
-
}
|
|
71
46
|
const {transcripts = []} = data;
|
|
72
47
|
const transcriptsPerCsis = new Map();
|
|
73
48
|
|
|
@@ -80,8 +55,11 @@ export const processNewCaptions = ({data, meeting}) => {
|
|
|
80
55
|
|
|
81
56
|
const newCaption = `${transcriptsPerCsis.get(csisMember)?.text ?? ''} ${text}`.trim();
|
|
82
57
|
|
|
83
|
-
|
|
84
|
-
|
|
58
|
+
transcriptsPerCsis.set(csisMember, {
|
|
59
|
+
...transcript,
|
|
60
|
+
text: newCaption,
|
|
61
|
+
currentSpokenLanguage,
|
|
62
|
+
});
|
|
85
63
|
}
|
|
86
64
|
const interimTranscriptionIds = [];
|
|
87
65
|
|
|
@@ -91,31 +69,51 @@ export const processNewCaptions = ({data, meeting}) => {
|
|
|
91
69
|
transcriptData,
|
|
92
70
|
csisKey: key,
|
|
93
71
|
});
|
|
72
|
+
const {speakerId} = speaker;
|
|
73
|
+
const interimId = `${transcriptId}_${speakerId}`;
|
|
94
74
|
|
|
95
75
|
if (needsCaching) {
|
|
96
76
|
transcriptData.speakerProxy[key] = speaker;
|
|
97
77
|
}
|
|
98
|
-
|
|
99
|
-
const interimId = `${transcriptId}_${speakerId}`;
|
|
78
|
+
|
|
100
79
|
const captionData = {
|
|
101
80
|
id: interimId,
|
|
102
81
|
isFinal: data.isFinal,
|
|
103
82
|
translations: value.translations,
|
|
104
83
|
text: value.text,
|
|
105
|
-
currentCaptionLanguage:
|
|
84
|
+
currentCaptionLanguage:
|
|
85
|
+
meeting.transcription?.languageOptions?.currentCaptionLanguage ||
|
|
86
|
+
value.currentSpokenLanguage,
|
|
87
|
+
currentSpokenLanguage:
|
|
88
|
+
meeting.transcription?.languageOptions?.currentSpokenLanguage ||
|
|
89
|
+
data.transcripts[0]?.transcript_language_code,
|
|
106
90
|
timestamp: value?.timestamp,
|
|
107
91
|
speaker,
|
|
108
92
|
};
|
|
109
93
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
94
|
+
if (!data.isFinal) {
|
|
95
|
+
const interimTranscriptIndex = transcriptData.captions.findIndex(
|
|
96
|
+
(transcript) => transcript.id === interimId
|
|
97
|
+
);
|
|
113
98
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
99
|
+
if (interimTranscriptIndex !== -1) {
|
|
100
|
+
transcriptData.captions.splice(interimTranscriptIndex, 1);
|
|
101
|
+
}
|
|
117
102
|
|
|
118
|
-
|
|
103
|
+
interimTranscriptionIds.push(interimId);
|
|
104
|
+
} else {
|
|
105
|
+
transcriptData.interimCaptions[transcriptId].forEach((innerInterimId) => {
|
|
106
|
+
const interimTranscriptIndex = transcriptData.captions.findIndex(
|
|
107
|
+
(transcript) => transcript.id === innerInterimId
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
if (interimTranscriptIndex !== -1) {
|
|
111
|
+
transcriptData.captions.splice(interimTranscriptIndex, 1);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
delete transcriptData.interimCaptions[transcriptId];
|
|
115
|
+
captionData.id = transcriptId;
|
|
116
|
+
}
|
|
119
117
|
transcriptData.captions.push(captionData);
|
|
120
118
|
}
|
|
121
119
|
transcriptData.interimCaptions[transcriptId] = interimTranscriptionIds;
|
package/src/meeting-info/util.ts
CHANGED
|
@@ -33,282 +33,290 @@ import {
|
|
|
33
33
|
UUID_REG,
|
|
34
34
|
} from '../constants';
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
/**
|
|
37
|
+
* @class MeetingInfoUtil
|
|
38
|
+
*/
|
|
39
|
+
export default class MeetingInfoUtil {
|
|
40
|
+
static extractDestination(destination, type) {
|
|
41
|
+
let dest = destination;
|
|
42
|
+
|
|
43
|
+
if (type === _LOCUS_ID_) {
|
|
44
|
+
if (!(destination && destination.url)) {
|
|
45
|
+
throw new ParameterError(
|
|
46
|
+
'You cannot create a meeting by locus without a locus.url defined'
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
dest = destination.url;
|
|
44
50
|
}
|
|
45
|
-
|
|
51
|
+
|
|
52
|
+
return dest;
|
|
46
53
|
}
|
|
47
54
|
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
static getParsedUrl(link) {
|
|
56
|
+
try {
|
|
57
|
+
let parsedUrl = url.parse(link);
|
|
58
|
+
|
|
59
|
+
if (!parsedUrl) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
// hack for links such as <company>.webex.com/meet/<user> without a protocol
|
|
63
|
+
if (!parsedUrl.protocol) {
|
|
64
|
+
parsedUrl = url.parse(`${HTTPS_PROTOCOL}${link}`);
|
|
65
|
+
}
|
|
50
66
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
return parsedUrl;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
LoggerProxy.logger.warn(
|
|
70
|
+
`Meeting-info:util#getParsedUrl --> unable to parse the URL, error: ${error}`
|
|
71
|
+
);
|
|
54
72
|
|
|
55
|
-
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
// hack for links such as <company>.webex.com/meet/<user> without a protocol
|
|
59
|
-
if (!parsedUrl.protocol) {
|
|
60
|
-
parsedUrl = url.parse(`${HTTPS_PROTOCOL}${link}`);
|
|
73
|
+
return null;
|
|
61
74
|
}
|
|
75
|
+
}
|
|
62
76
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Helper function to check if a string matches a known meeting link pattern
|
|
79
|
+
* @param {String} value string to parse and see if it matches a meeting link
|
|
80
|
+
* @returns {Boolean}
|
|
81
|
+
*/
|
|
82
|
+
static isMeetingLink(value: string) {
|
|
83
|
+
const parsedUrl = this.getParsedUrl(value);
|
|
84
|
+
let hostNameBool;
|
|
85
|
+
let pathNameBool;
|
|
86
|
+
if (parsedUrl) {
|
|
87
|
+
hostNameBool = parsedUrl.hostname && parsedUrl.hostname.includes(WEBEX_DOT_COM);
|
|
88
|
+
pathNameBool =
|
|
89
|
+
parsedUrl.pathname &&
|
|
90
|
+
(parsedUrl.pathname.includes(`/${MEET}`) ||
|
|
91
|
+
parsedUrl.pathname.includes(`/${MEET_M}`) ||
|
|
92
|
+
parsedUrl.pathname.includes(`/${JOIN}`));
|
|
93
|
+
}
|
|
68
94
|
|
|
69
|
-
return
|
|
95
|
+
return hostNameBool && pathNameBool;
|
|
70
96
|
}
|
|
71
|
-
};
|
|
72
97
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const pathNameBool =
|
|
82
|
-
parsedUrl.pathname &&
|
|
83
|
-
(parsedUrl.pathname.includes(`/${MEET}`) ||
|
|
84
|
-
parsedUrl.pathname.includes(`/${MEET_M}`) ||
|
|
85
|
-
parsedUrl.pathname.includes(`/${JOIN}`));
|
|
86
|
-
|
|
87
|
-
return hostNameBool && pathNameBool;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
MeetingInfoUtil.isConversationUrl = (value, webex) => {
|
|
91
|
-
const clusterId = webex.internal.services.getClusterId(value);
|
|
92
|
-
|
|
93
|
-
if (clusterId) {
|
|
94
|
-
return clusterId.endsWith(CONVERSATION_SERVICE);
|
|
98
|
+
static isConversationUrl(value, webex) {
|
|
99
|
+
const clusterId = webex.internal.services.getClusterId(value);
|
|
100
|
+
|
|
101
|
+
if (clusterId) {
|
|
102
|
+
return clusterId.endsWith(CONVERSATION_SERVICE);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return false;
|
|
95
106
|
}
|
|
96
107
|
|
|
97
|
-
|
|
98
|
-
|
|
108
|
+
static convertLinkToSip(value) {
|
|
109
|
+
const parsedUrl = this.getParsedUrl(value);
|
|
99
110
|
|
|
100
|
-
|
|
101
|
-
|
|
111
|
+
if (!parsedUrl) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
let user;
|
|
102
115
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
let user;
|
|
116
|
+
if (parsedUrl.pathname) {
|
|
117
|
+
const userIndex = parsedUrl.pathname.lastIndexOf('/');
|
|
107
118
|
|
|
108
|
-
|
|
109
|
-
|
|
119
|
+
user = parsedUrl.pathname.substring(userIndex + 1);
|
|
120
|
+
}
|
|
121
|
+
if (!user) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
let company;
|
|
110
125
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (!user) {
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
let company;
|
|
126
|
+
if (parsedUrl.hostname) {
|
|
127
|
+
const companyIndex = parsedUrl.hostname.lastIndexOf(`.${WEBEX_DOT_COM}`);
|
|
117
128
|
|
|
118
|
-
|
|
119
|
-
|
|
129
|
+
company = parsedUrl.hostname.substring(0, companyIndex).replace(WWW_DOT, '');
|
|
130
|
+
}
|
|
131
|
+
if (!company) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
120
134
|
|
|
121
|
-
company
|
|
122
|
-
}
|
|
123
|
-
if (!company) {
|
|
124
|
-
return null;
|
|
135
|
+
return `${user}@${company}.${WEBEX_DOT_COM}`;
|
|
125
136
|
}
|
|
126
137
|
|
|
127
|
-
|
|
128
|
-
|
|
138
|
+
static isSipUri(sipString) {
|
|
139
|
+
// TODO: lets remove regex from this equation and user URI matchers and such
|
|
140
|
+
// have not found a great sip uri parser library as of now
|
|
141
|
+
const sipUri = DIALER_REGEX.SIP_ADDRESS.exec(sipString);
|
|
129
142
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// have not found a great sip uri parser library as of now
|
|
133
|
-
const sipUri = DIALER_REGEX.SIP_ADDRESS.exec(sipString);
|
|
143
|
+
return sipUri;
|
|
144
|
+
}
|
|
134
145
|
|
|
135
|
-
|
|
136
|
-
|
|
146
|
+
static isPhoneNumber(phoneNumber) {
|
|
147
|
+
const isValidNumber = DIALER_REGEX.PHONE_NUMBER.test(phoneNumber);
|
|
137
148
|
|
|
138
|
-
|
|
139
|
-
|
|
149
|
+
return isValidNumber;
|
|
150
|
+
}
|
|
140
151
|
|
|
141
|
-
|
|
142
|
-
};
|
|
152
|
+
static getHydraId(destination) {
|
|
153
|
+
const {type, id, cluster} = deconstructHydraId(destination);
|
|
143
154
|
|
|
144
|
-
|
|
145
|
-
|
|
155
|
+
if (id && UUID_REG.test(id)) {
|
|
156
|
+
if (type === _ROOM_) {
|
|
157
|
+
return {room: true, destination: id, cluster};
|
|
158
|
+
}
|
|
159
|
+
if (type === _PEOPLE_) {
|
|
160
|
+
return {people: true, destination: id, cluster};
|
|
161
|
+
}
|
|
146
162
|
|
|
147
|
-
|
|
148
|
-
if (type === _ROOM_) {
|
|
149
|
-
return {room: true, destination: id, cluster};
|
|
150
|
-
}
|
|
151
|
-
if (type === _PEOPLE_) {
|
|
152
|
-
return {people: true, destination: id, cluster};
|
|
163
|
+
return {};
|
|
153
164
|
}
|
|
154
165
|
|
|
155
166
|
return {};
|
|
156
167
|
}
|
|
157
168
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
throw err;
|
|
175
|
-
});
|
|
169
|
+
static getSipUriFromHydraPersonId(destination, webex) {
|
|
170
|
+
return webex.people
|
|
171
|
+
.get(destination)
|
|
172
|
+
.then((res) => {
|
|
173
|
+
if (res.emails && res.emails.length) {
|
|
174
|
+
return res.emails[0];
|
|
175
|
+
}
|
|
176
|
+
throw new ParameterError('Hydra Id Lookup was an invalid hydra person id.');
|
|
177
|
+
})
|
|
178
|
+
.catch((err) => {
|
|
179
|
+
LoggerProxy.logger.error(
|
|
180
|
+
`Meeting-info:util#MeetingInfoUtil.getSipUriFromHydraPersonId --> getSipUriFromHydraPersonId ${err} `
|
|
181
|
+
);
|
|
182
|
+
throw err;
|
|
183
|
+
});
|
|
184
|
+
}
|
|
176
185
|
|
|
177
|
-
|
|
178
|
-
|
|
186
|
+
static async generateOptions(from) {
|
|
187
|
+
const {destination, type, webex} = from;
|
|
179
188
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (MeetingInfoUtil.isMeetingLink(destination)) {
|
|
190
|
-
LoggerProxy.logger.warn(
|
|
191
|
-
'Meeting-info:util#generateOptions --> WARN, use of Meeting Link is deprecated, please use a SIP URI instead'
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
options.type = _MEETING_LINK_;
|
|
195
|
-
options.destination = destination;
|
|
196
|
-
} else if (MeetingInfoUtil.isSipUri(destination)) {
|
|
197
|
-
options.type = _SIP_URI_;
|
|
198
|
-
options.destination = destination;
|
|
199
|
-
} else if (MeetingInfoUtil.isPhoneNumber(destination)) {
|
|
200
|
-
options.type = _SIP_URI_;
|
|
201
|
-
options.destination = destination;
|
|
202
|
-
} else if (MeetingInfoUtil.isConversationUrl(destination, webex)) {
|
|
203
|
-
options.type = _CONVERSATION_URL_;
|
|
204
|
-
options.destination = destination;
|
|
205
|
-
} else if (hydraId.people) {
|
|
206
|
-
options.type = _SIP_URI_;
|
|
207
|
-
|
|
208
|
-
return MeetingInfoUtil.getSipUriFromHydraPersonId(hydraId.destination, webex).then((res) => {
|
|
209
|
-
options.destination = res;
|
|
210
|
-
|
|
211
|
-
// Since hydra person ids require a unique case in which they are
|
|
212
|
-
// entirely converted to a SIP URI, we need to set a flag for detecting
|
|
213
|
-
// this type of destination.
|
|
214
|
-
options.wasHydraPerson = true;
|
|
215
|
-
|
|
216
|
-
return Promise.resolve(options);
|
|
217
|
-
});
|
|
218
|
-
} else if (hydraId.room) {
|
|
219
|
-
options.type = _CONVERSATION_URL_;
|
|
220
|
-
try {
|
|
221
|
-
await webex.internal.services.waitForCatalog('postauth');
|
|
189
|
+
if (type) {
|
|
190
|
+
return {
|
|
191
|
+
destination,
|
|
192
|
+
type,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
const options: any = {};
|
|
196
|
+
const hydraId = this.getHydraId(destination);
|
|
222
197
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
},
|
|
227
|
-
webex
|
|
198
|
+
if (this.isMeetingLink(destination)) {
|
|
199
|
+
LoggerProxy.logger.warn(
|
|
200
|
+
'Meeting-info:util#generateOptions --> WARN, use of Meeting Link is deprecated, please use a SIP URI instead'
|
|
228
201
|
);
|
|
229
202
|
|
|
230
|
-
options.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
203
|
+
options.type = _MEETING_LINK_;
|
|
204
|
+
options.destination = destination;
|
|
205
|
+
} else if (this.isSipUri(destination)) {
|
|
206
|
+
options.type = _SIP_URI_;
|
|
207
|
+
options.destination = destination;
|
|
208
|
+
} else if (this.isPhoneNumber(destination)) {
|
|
209
|
+
options.type = _SIP_URI_;
|
|
210
|
+
options.destination = destination;
|
|
211
|
+
} else if (this.isConversationUrl(destination, webex)) {
|
|
212
|
+
options.type = _CONVERSATION_URL_;
|
|
213
|
+
options.destination = destination;
|
|
214
|
+
} else if (hydraId.people) {
|
|
215
|
+
options.type = _SIP_URI_;
|
|
216
|
+
|
|
217
|
+
return this.getSipUriFromHydraPersonId(hydraId.destination, webex).then((res) => {
|
|
218
|
+
options.destination = res;
|
|
219
|
+
|
|
220
|
+
// Since hydra person ids require a unique case in which they are
|
|
221
|
+
// entirely converted to a SIP URI, we need to set a flag for detecting
|
|
222
|
+
// this type of destination.
|
|
223
|
+
options.wasHydraPerson = true;
|
|
224
|
+
|
|
225
|
+
return Promise.resolve(options);
|
|
226
|
+
});
|
|
227
|
+
} else if (hydraId.room) {
|
|
228
|
+
options.type = _CONVERSATION_URL_;
|
|
229
|
+
try {
|
|
230
|
+
await webex.internal.services.waitForCatalog('postauth');
|
|
231
|
+
|
|
232
|
+
const serviceUrl = webex.internal.services.getServiceUrlFromClusterId(
|
|
233
|
+
{
|
|
234
|
+
cluster: hydraId.cluster,
|
|
235
|
+
},
|
|
236
|
+
webex
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
options.destination = hydraId.destination
|
|
240
|
+
? `${serviceUrl}/conversations/${hydraId.destination}`
|
|
241
|
+
: serviceUrl;
|
|
242
|
+
} catch (e) {
|
|
243
|
+
LoggerProxy.logger.error(`Meeting-info:util#generateOptions --> ${e}`);
|
|
244
|
+
throw e;
|
|
245
|
+
}
|
|
246
|
+
} else {
|
|
247
|
+
throw new ParameterError(
|
|
248
|
+
'MeetingInfo is fetched with the meeting link, SIP URI, phone number, Hydra people ID, or a conversation URL.'
|
|
249
|
+
);
|
|
236
250
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
'MeetingInfo is fetched with the meeting link, SIP URI, phone number, Hydra people ID, or a conversation URL.'
|
|
240
|
-
);
|
|
251
|
+
|
|
252
|
+
return Promise.resolve(options);
|
|
241
253
|
}
|
|
242
254
|
|
|
243
|
-
|
|
244
|
-
|
|
255
|
+
/**
|
|
256
|
+
* Helper function to build up a correct locus url depending on the value passed
|
|
257
|
+
* @param {String} type One of [SIP_URI, PERSONAL_ROOM, MEETING_ID, CONVERSATION_URL, LOCUS_ID, MEETING_LINK]
|
|
258
|
+
* @param {Object} value ?? value.value
|
|
259
|
+
* @returns {Object} returns an object with {resource, method}
|
|
260
|
+
*/
|
|
261
|
+
static getResourceUrl(type: string, value: any) {
|
|
262
|
+
let resource = `/${LOCI}/${MEETINGINFO}`;
|
|
263
|
+
let method = HTTP_VERBS.GET;
|
|
264
|
+
let uri = null;
|
|
265
|
+
|
|
266
|
+
switch (type) {
|
|
267
|
+
case _SIP_URI_:
|
|
268
|
+
case _PERSONAL_ROOM_:
|
|
269
|
+
case _MEETING_ID_:
|
|
270
|
+
resource = `/${LOCI}/${MEETINGINFO}/${encodeURIComponent(
|
|
271
|
+
value
|
|
272
|
+
)}?${TYPE}=${type}&${USE_URI_LOOKUP_FALSE}`;
|
|
273
|
+
break;
|
|
274
|
+
case _CONVERSATION_URL_:
|
|
275
|
+
method = HTTP_VERBS.PUT;
|
|
276
|
+
break;
|
|
277
|
+
case _LOCUS_ID_:
|
|
278
|
+
uri = `${value}/${MEETINGINFO}`;
|
|
279
|
+
method = HTTP_VERBS.PUT;
|
|
280
|
+
break;
|
|
281
|
+
case _MEETING_LINK_:
|
|
282
|
+
resource = `$/${LOCI}/${MEETINGINFO}/${btoa(
|
|
283
|
+
value
|
|
284
|
+
)}?${TYPE}=${_MEETING_LINK_}&${USE_URI_LOOKUP_FALSE}`;
|
|
285
|
+
break;
|
|
286
|
+
default:
|
|
287
|
+
}
|
|
245
288
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
*/
|
|
252
|
-
MeetingInfoUtil.getResourceUrl = (type: string, value: any) => {
|
|
253
|
-
let resource = `/${LOCI}/${MEETINGINFO}`;
|
|
254
|
-
let method = HTTP_VERBS.GET;
|
|
255
|
-
let uri = null;
|
|
256
|
-
|
|
257
|
-
switch (type) {
|
|
258
|
-
case _SIP_URI_:
|
|
259
|
-
case _PERSONAL_ROOM_:
|
|
260
|
-
case _MEETING_ID_:
|
|
261
|
-
resource = `/${LOCI}/${MEETINGINFO}/${encodeURIComponent(
|
|
262
|
-
value
|
|
263
|
-
)}?${TYPE}=${type}&${USE_URI_LOOKUP_FALSE}`;
|
|
264
|
-
break;
|
|
265
|
-
case _CONVERSATION_URL_:
|
|
266
|
-
method = HTTP_VERBS.PUT;
|
|
267
|
-
break;
|
|
268
|
-
case _LOCUS_ID_:
|
|
269
|
-
uri = `${value}/${MEETINGINFO}`;
|
|
270
|
-
method = HTTP_VERBS.PUT;
|
|
271
|
-
break;
|
|
272
|
-
case _MEETING_LINK_:
|
|
273
|
-
resource = `$/${LOCI}/${MEETINGINFO}/${btoa(
|
|
274
|
-
value
|
|
275
|
-
)}?${TYPE}=${_MEETING_LINK_}&${USE_URI_LOOKUP_FALSE}`;
|
|
276
|
-
break;
|
|
277
|
-
default:
|
|
289
|
+
return {
|
|
290
|
+
uri,
|
|
291
|
+
resource,
|
|
292
|
+
method,
|
|
293
|
+
};
|
|
278
294
|
}
|
|
279
295
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
resource,
|
|
283
|
-
method,
|
|
284
|
-
};
|
|
285
|
-
};
|
|
286
|
-
|
|
287
|
-
MeetingInfoUtil.getRequestParams = (resourceOptions, type, value, api) => {
|
|
288
|
-
let requestParams: any = {
|
|
289
|
-
method: resourceOptions.method,
|
|
290
|
-
api,
|
|
291
|
-
resource: resourceOptions.resource,
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
if (resourceOptions.method === HTTP_VERBS.GET) {
|
|
295
|
-
// for handling URL redirections
|
|
296
|
-
requestParams.resource = requestParams.resource.concat(`&${ALTERNATE_REDIRECT_TRUE}`);
|
|
297
|
-
} else if (type !== _LOCUS_ID_) {
|
|
298
|
-
// locus id check is a PUT not sure why
|
|
299
|
-
requestParams.resource = requestParams.resource.concat(`?${ALTERNATE_REDIRECT_TRUE}`);
|
|
300
|
-
requestParams.body = {
|
|
301
|
-
value,
|
|
302
|
-
lookupType: type,
|
|
303
|
-
};
|
|
304
|
-
} else if (type === _LOCUS_ID_) {
|
|
305
|
-
requestParams = {
|
|
296
|
+
static getRequestParams(resourceOptions, type, value, api) {
|
|
297
|
+
let requestParams: any = {
|
|
306
298
|
method: resourceOptions.method,
|
|
307
|
-
|
|
299
|
+
api,
|
|
300
|
+
resource: resourceOptions.resource,
|
|
308
301
|
};
|
|
309
|
-
}
|
|
310
302
|
|
|
311
|
-
|
|
312
|
-
|
|
303
|
+
if (resourceOptions.method === HTTP_VERBS.GET) {
|
|
304
|
+
// for handling URL redirections
|
|
305
|
+
requestParams.resource = requestParams.resource.concat(`&${ALTERNATE_REDIRECT_TRUE}`);
|
|
306
|
+
} else if (type !== _LOCUS_ID_) {
|
|
307
|
+
// locus id check is a PUT not sure why
|
|
308
|
+
requestParams.resource = requestParams.resource.concat(`?${ALTERNATE_REDIRECT_TRUE}`);
|
|
309
|
+
requestParams.body = {
|
|
310
|
+
value,
|
|
311
|
+
lookupType: type,
|
|
312
|
+
};
|
|
313
|
+
} else if (type === _LOCUS_ID_) {
|
|
314
|
+
requestParams = {
|
|
315
|
+
method: resourceOptions.method,
|
|
316
|
+
uri: resourceOptions.uri,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
313
319
|
|
|
314
|
-
|
|
320
|
+
return requestParams;
|
|
321
|
+
}
|
|
322
|
+
}
|