@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.
Files changed (206) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/common/errors/{reconnection-in-progress.js → reconnection-not-started.js} +27 -15
  4. package/dist/common/errors/reconnection-not-started.js.map +1 -0
  5. package/dist/constants.js +12 -3
  6. package/dist/constants.js.map +1 -1
  7. package/dist/index.js +80 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/interpretation/index.js +1 -1
  10. package/dist/interpretation/siLanguage.js +1 -1
  11. package/dist/locus-info/controlsUtils.js +7 -1
  12. package/dist/locus-info/controlsUtils.js.map +1 -1
  13. package/dist/locus-info/index.js +10 -0
  14. package/dist/locus-info/index.js.map +1 -1
  15. package/dist/media/properties.js +102 -57
  16. package/dist/media/properties.js.map +1 -1
  17. package/dist/meeting/in-meeting-actions.js +6 -0
  18. package/dist/meeting/in-meeting-actions.js.map +1 -1
  19. package/dist/meeting/index.js +543 -467
  20. package/dist/meeting/index.js.map +1 -1
  21. package/dist/meeting/locusMediaRequest.js +27 -0
  22. package/dist/meeting/locusMediaRequest.js.map +1 -1
  23. package/dist/meeting/util.js +9 -16
  24. package/dist/meeting/util.js.map +1 -1
  25. package/dist/meeting/voicea-meeting.js +37 -49
  26. package/dist/meeting/voicea-meeting.js.map +1 -1
  27. package/dist/meeting-info/util.js +304 -267
  28. package/dist/meeting-info/util.js.map +1 -1
  29. package/dist/meeting-info/utilv2.js +334 -298
  30. package/dist/meeting-info/utilv2.js.map +1 -1
  31. package/dist/meetings/index.js +6 -27
  32. package/dist/meetings/index.js.map +1 -1
  33. package/dist/reachability/index.js +6 -0
  34. package/dist/reachability/index.js.map +1 -1
  35. package/dist/reconnection-manager/index.js +138 -109
  36. package/dist/reconnection-manager/index.js.map +1 -1
  37. package/dist/roap/request.js +3 -27
  38. package/dist/roap/request.js.map +1 -1
  39. package/dist/statsAnalyzer/index.js +4 -0
  40. package/dist/statsAnalyzer/index.js.map +1 -1
  41. package/dist/statsAnalyzer/mqaUtil.js +3 -0
  42. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  43. package/dist/types/common/errors/reconnection-not-started.d.ts +13 -0
  44. package/dist/{constants.d.ts → types/constants.d.ts} +11 -2
  45. package/dist/types/index.d.ts +19 -0
  46. package/dist/{media → types/media}/properties.d.ts +26 -2
  47. package/dist/{meeting → types/meeting}/in-meeting-actions.d.ts +6 -0
  48. package/dist/{meeting → types/meeting}/index.d.ts +5 -6
  49. package/dist/{meeting → types/meeting}/locusMediaRequest.d.ts +1 -0
  50. package/dist/{meeting → types/meeting}/util.d.ts +3 -0
  51. package/dist/{meeting → types/meeting}/voicea-meeting.d.ts +3 -2
  52. package/dist/{meeting-info → types/meeting-info}/index.d.ts +1 -1
  53. package/dist/{meeting-info → types/meeting-info}/meeting-info-v2.d.ts +1 -1
  54. package/dist/types/meeting-info/util.d.ts +49 -0
  55. package/dist/types/meeting-info/utilv2.d.ts +65 -0
  56. package/dist/{meetings → types/meetings}/index.d.ts +1 -16
  57. package/dist/{reconnection-manager → types/reconnection-manager}/index.d.ts +4 -14
  58. package/dist/webinar/index.js +1 -1
  59. package/package.json +22 -22
  60. package/src/common/errors/reconnection-not-started.ts +25 -0
  61. package/src/constants.ts +12 -4
  62. package/src/index.ts +30 -0
  63. package/src/locus-info/controlsUtils.ts +11 -0
  64. package/src/locus-info/index.ts +16 -0
  65. package/src/media/properties.ts +67 -15
  66. package/src/meeting/in-meeting-actions.ts +12 -0
  67. package/src/meeting/index.ts +121 -98
  68. package/src/meeting/locusMediaRequest.ts +31 -0
  69. package/src/meeting/util.ts +9 -16
  70. package/src/meeting/voicea-meeting.ts +44 -46
  71. package/src/meeting-info/util.ts +241 -233
  72. package/src/meeting-info/utilv2.ts +250 -244
  73. package/src/meetings/index.ts +8 -25
  74. package/src/reachability/index.ts +3 -0
  75. package/src/reconnection-manager/index.ts +128 -105
  76. package/src/roap/request.ts +1 -24
  77. package/src/statsAnalyzer/index.ts +4 -0
  78. package/src/statsAnalyzer/mqaUtil.ts +5 -0
  79. package/test/unit/spec/locus-info/controlsUtils.js +20 -0
  80. package/test/unit/spec/locus-info/index.js +21 -0
  81. package/test/unit/spec/media/properties.ts +145 -140
  82. package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
  83. package/test/unit/spec/meeting/index.js +243 -97
  84. package/test/unit/spec/meeting/locusMediaRequest.ts +49 -0
  85. package/test/unit/spec/meeting/utils.js +3 -10
  86. package/test/unit/spec/meeting/voicea-meeting.ts +5 -14
  87. package/test/unit/spec/meetings/index.js +27 -8
  88. package/test/unit/spec/reconnection-manager/index.js +127 -39
  89. package/test/unit/spec/roap/request.ts +0 -37
  90. package/test/unit/spec/stats-analyzer/index.js +11 -0
  91. package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
  92. package/dist/common/errors/reconnection-in-progress.js.map +0 -1
  93. package/dist/index.d.ts +0 -7
  94. package/dist/meeting-info/util.d.ts +0 -2
  95. package/dist/meeting-info/utilv2.d.ts +0 -2
  96. package/src/common/errors/reconnection-in-progress.ts +0 -8
  97. /package/dist/{annotation → types/annotation}/annotation.types.d.ts +0 -0
  98. /package/dist/{annotation → types/annotation}/constants.d.ts +0 -0
  99. /package/dist/{annotation → types/annotation}/index.d.ts +0 -0
  100. /package/dist/{breakouts → types/breakouts}/breakout.d.ts +0 -0
  101. /package/dist/{breakouts → types/breakouts}/collection.d.ts +0 -0
  102. /package/dist/{breakouts → types/breakouts}/edit-lock-error.d.ts +0 -0
  103. /package/dist/{breakouts → types/breakouts}/events.d.ts +0 -0
  104. /package/dist/{breakouts → types/breakouts}/index.d.ts +0 -0
  105. /package/dist/{breakouts → types/breakouts}/request.d.ts +0 -0
  106. /package/dist/{breakouts → types/breakouts}/utils.d.ts +0 -0
  107. /package/dist/{common → types/common}/browser-detection.d.ts +0 -0
  108. /package/dist/{common → types/common}/collection.d.ts +0 -0
  109. /package/dist/{common → types/common}/config.d.ts +0 -0
  110. /package/dist/{common → types/common}/errors/captcha-error.d.ts +0 -0
  111. /package/dist/{common → types/common}/errors/intent-to-join.d.ts +0 -0
  112. /package/dist/{common → types/common}/errors/join-meeting.d.ts +0 -0
  113. /package/dist/{common → types/common}/errors/media.d.ts +0 -0
  114. /package/dist/{common → types/common}/errors/no-meeting-info.d.ts +0 -0
  115. /package/dist/{common → types/common}/errors/parameter.d.ts +0 -0
  116. /package/dist/{common → types/common}/errors/password-error.d.ts +0 -0
  117. /package/dist/{common → types/common}/errors/permission.d.ts +0 -0
  118. /package/dist/{common → types/common}/errors/reclaim-host-role-errors.d.ts +0 -0
  119. /package/dist/{common → types/common}/errors/reconnection.d.ts +0 -0
  120. /package/dist/{common → types/common}/errors/stats.d.ts +0 -0
  121. /package/dist/{common → types/common}/errors/webex-errors.d.ts +0 -0
  122. /package/dist/{common → types/common}/errors/webex-meetings-error.d.ts +0 -0
  123. /package/dist/{common → types/common}/events/events-scope.d.ts +0 -0
  124. /package/dist/{common → types/common}/events/events.d.ts +0 -0
  125. /package/dist/{common → types/common}/events/trigger-proxy.d.ts +0 -0
  126. /package/dist/{common → types/common}/events/util.d.ts +0 -0
  127. /package/dist/{common → types/common}/logs/logger-config.d.ts +0 -0
  128. /package/dist/{common → types/common}/logs/logger-proxy.d.ts +0 -0
  129. /package/dist/{common → types/common}/logs/request.d.ts +0 -0
  130. /package/dist/{common → types/common}/queue.d.ts +0 -0
  131. /package/dist/{config.d.ts → types/config.d.ts} +0 -0
  132. /package/dist/{controls-options-manager → types/controls-options-manager}/constants.d.ts +0 -0
  133. /package/dist/{controls-options-manager → types/controls-options-manager}/enums.d.ts +0 -0
  134. /package/dist/{controls-options-manager → types/controls-options-manager}/index.d.ts +0 -0
  135. /package/dist/{controls-options-manager → types/controls-options-manager}/types.d.ts +0 -0
  136. /package/dist/{controls-options-manager → types/controls-options-manager}/util.d.ts +0 -0
  137. /package/dist/{interceptors → types/interceptors}/index.d.ts +0 -0
  138. /package/dist/{interceptors → types/interceptors}/locusRetry.d.ts +0 -0
  139. /package/dist/{interpretation → types/interpretation}/collection.d.ts +0 -0
  140. /package/dist/{interpretation → types/interpretation}/index.d.ts +0 -0
  141. /package/dist/{interpretation → types/interpretation}/siLanguage.d.ts +0 -0
  142. /package/dist/{locus-info → types/locus-info}/controlsUtils.d.ts +0 -0
  143. /package/dist/{locus-info → types/locus-info}/embeddedAppsUtils.d.ts +0 -0
  144. /package/dist/{locus-info → types/locus-info}/fullState.d.ts +0 -0
  145. /package/dist/{locus-info → types/locus-info}/hostUtils.d.ts +0 -0
  146. /package/dist/{locus-info → types/locus-info}/index.d.ts +0 -0
  147. /package/dist/{locus-info → types/locus-info}/infoUtils.d.ts +0 -0
  148. /package/dist/{locus-info → types/locus-info}/mediaSharesUtils.d.ts +0 -0
  149. /package/dist/{locus-info → types/locus-info}/parser.d.ts +0 -0
  150. /package/dist/{locus-info → types/locus-info}/selfUtils.d.ts +0 -0
  151. /package/dist/{media → types/media}/MediaConnectionAwaiter.d.ts +0 -0
  152. /package/dist/{media → types/media}/index.d.ts +0 -0
  153. /package/dist/{media → types/media}/util.d.ts +0 -0
  154. /package/dist/{mediaQualityMetrics → types/mediaQualityMetrics}/config.d.ts +0 -0
  155. /package/dist/{meeting → types/meeting}/muteState.d.ts +0 -0
  156. /package/dist/{meeting → types/meeting}/request.d.ts +0 -0
  157. /package/dist/{meeting → types/meeting}/request.type.d.ts +0 -0
  158. /package/dist/{meeting → types/meeting}/state.d.ts +0 -0
  159. /package/dist/{meeting-info → types/meeting-info}/collection.d.ts +0 -0
  160. /package/dist/{meeting-info → types/meeting-info}/request.d.ts +0 -0
  161. /package/dist/{meetings → types/meetings}/collection.d.ts +0 -0
  162. /package/dist/{meetings → types/meetings}/meetings.types.d.ts +0 -0
  163. /package/dist/{meetings → types/meetings}/request.d.ts +0 -0
  164. /package/dist/{meetings → types/meetings}/util.d.ts +0 -0
  165. /package/dist/{member → types/member}/index.d.ts +0 -0
  166. /package/dist/{member → types/member}/types.d.ts +0 -0
  167. /package/dist/{member → types/member}/util.d.ts +0 -0
  168. /package/dist/{members → types/members}/collection.d.ts +0 -0
  169. /package/dist/{members → types/members}/index.d.ts +0 -0
  170. /package/dist/{members → types/members}/request.d.ts +0 -0
  171. /package/dist/{members → types/members}/types.d.ts +0 -0
  172. /package/dist/{members → types/members}/util.d.ts +0 -0
  173. /package/dist/{metrics → types/metrics}/constants.d.ts +0 -0
  174. /package/dist/{metrics → types/metrics}/index.d.ts +0 -0
  175. /package/dist/{multistream → types/multistream}/mediaRequestManager.d.ts +0 -0
  176. /package/dist/{multistream → types/multistream}/receiveSlot.d.ts +0 -0
  177. /package/dist/{multistream → types/multistream}/receiveSlotManager.d.ts +0 -0
  178. /package/dist/{multistream → types/multistream}/remoteMedia.d.ts +0 -0
  179. /package/dist/{multistream → types/multistream}/remoteMediaGroup.d.ts +0 -0
  180. /package/dist/{multistream → types/multistream}/remoteMediaManager.d.ts +0 -0
  181. /package/dist/{multistream → types/multistream}/sendSlotManager.d.ts +0 -0
  182. /package/dist/{networkQualityMonitor → types/networkQualityMonitor}/index.d.ts +0 -0
  183. /package/dist/{personal-meeting-room → types/personal-meeting-room}/index.d.ts +0 -0
  184. /package/dist/{personal-meeting-room → types/personal-meeting-room}/request.d.ts +0 -0
  185. /package/dist/{personal-meeting-room → types/personal-meeting-room}/util.d.ts +0 -0
  186. /package/dist/{reachability → types/reachability}/clusterReachability.d.ts +0 -0
  187. /package/dist/{reachability → types/reachability}/index.d.ts +0 -0
  188. /package/dist/{reachability → types/reachability}/request.d.ts +0 -0
  189. /package/dist/{reachability → types/reachability}/util.d.ts +0 -0
  190. /package/dist/{reactions → types/reactions}/constants.d.ts +0 -0
  191. /package/dist/{reactions → types/reactions}/reactions.d.ts +0 -0
  192. /package/dist/{reactions → types/reactions}/reactions.type.d.ts +0 -0
  193. /package/dist/{recording-controller → types/recording-controller}/enums.d.ts +0 -0
  194. /package/dist/{recording-controller → types/recording-controller}/index.d.ts +0 -0
  195. /package/dist/{recording-controller → types/recording-controller}/util.d.ts +0 -0
  196. /package/dist/{roap → types/roap}/index.d.ts +0 -0
  197. /package/dist/{roap → types/roap}/request.d.ts +0 -0
  198. /package/dist/{roap → types/roap}/turnDiscovery.d.ts +0 -0
  199. /package/dist/{rtcMetrics → types/rtcMetrics}/constants.d.ts +0 -0
  200. /package/dist/{rtcMetrics → types/rtcMetrics}/index.d.ts +0 -0
  201. /package/dist/{statsAnalyzer → types/statsAnalyzer}/global.d.ts +0 -0
  202. /package/dist/{statsAnalyzer → types/statsAnalyzer}/index.d.ts +0 -0
  203. /package/dist/{statsAnalyzer → types/statsAnalyzer}/mqaUtil.d.ts +0 -0
  204. /package/dist/{transcription → types/transcription}/index.d.ts +0 -0
  205. /package/dist/{webinar → types/webinar}/collection.d.ts +0 -0
  206. /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 = ({data, meeting}) => {
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
- // eslint-disable-next-line camelcase
84
- transcriptsPerCsis.set(csisMember, {text: newCaption, currentSpokenLanguage});
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
- const {speakerId} = speaker;
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: value.currentSpokenLanguage,
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
- const interimTranscriptIndex = transcriptData.captions.findIndex(
111
- (transcript) => transcript.id === interimId
112
- );
94
+ if (!data.isFinal) {
95
+ const interimTranscriptIndex = transcriptData.captions.findIndex(
96
+ (transcript) => transcript.id === interimId
97
+ );
113
98
 
114
- if (interimTranscriptIndex !== -1) {
115
- transcriptData.captions.splice(interimTranscriptIndex, 1);
116
- }
99
+ if (interimTranscriptIndex !== -1) {
100
+ transcriptData.captions.splice(interimTranscriptIndex, 1);
101
+ }
117
102
 
118
- interimTranscriptionIds.push(interimId);
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;
@@ -33,282 +33,290 @@ import {
33
33
  UUID_REG,
34
34
  } from '../constants';
35
35
 
36
- const MeetingInfoUtil: any = {};
37
-
38
- MeetingInfoUtil.extractDestination = (destination, type) => {
39
- let dest = destination;
40
-
41
- if (type === _LOCUS_ID_) {
42
- if (!(destination && destination.url)) {
43
- throw new ParameterError('You cannot create a meeting by locus without a locus.url defined');
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
- dest = destination.url;
51
+
52
+ return dest;
46
53
  }
47
54
 
48
- return dest;
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
- MeetingInfoUtil.getParsedUrl = (link) => {
52
- try {
53
- let parsedUrl = url.parse(link);
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
- if (!parsedUrl) {
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
- return parsedUrl;
64
- } catch (error) {
65
- LoggerProxy.logger.warn(
66
- `Meeting-info:util#getParsedUrl --> unable to parse the URL, error: ${error}`
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 null;
95
+ return hostNameBool && pathNameBool;
70
96
  }
71
- };
72
97
 
73
- /**
74
- * Helper function to check if a string matches a known meeting link pattern
75
- * @param {String} value string to parse and see if it matches a meeting link
76
- * @returns {Boolean}
77
- */
78
- MeetingInfoUtil.isMeetingLink = (value: string) => {
79
- const parsedUrl = MeetingInfoUtil.getParsedUrl(value);
80
- const hostNameBool = parsedUrl.hostname && parsedUrl.hostname.includes(WEBEX_DOT_COM);
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
- return false;
98
- };
108
+ static convertLinkToSip(value) {
109
+ const parsedUrl = this.getParsedUrl(value);
99
110
 
100
- MeetingInfoUtil.convertLinkToSip = (value) => {
101
- const parsedUrl = MeetingInfoUtil.getParsedUrl(value);
111
+ if (!parsedUrl) {
112
+ return null;
113
+ }
114
+ let user;
102
115
 
103
- if (!parsedUrl) {
104
- return null;
105
- }
106
- let user;
116
+ if (parsedUrl.pathname) {
117
+ const userIndex = parsedUrl.pathname.lastIndexOf('/');
107
118
 
108
- if (parsedUrl.pathname) {
109
- const userIndex = parsedUrl.pathname.lastIndexOf('/');
119
+ user = parsedUrl.pathname.substring(userIndex + 1);
120
+ }
121
+ if (!user) {
122
+ return null;
123
+ }
124
+ let company;
110
125
 
111
- user = parsedUrl.pathname.substring(userIndex + 1);
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
- if (parsedUrl.hostname) {
119
- const companyIndex = parsedUrl.hostname.lastIndexOf(`.${WEBEX_DOT_COM}`);
129
+ company = parsedUrl.hostname.substring(0, companyIndex).replace(WWW_DOT, '');
130
+ }
131
+ if (!company) {
132
+ return null;
133
+ }
120
134
 
121
- company = parsedUrl.hostname.substring(0, companyIndex).replace(WWW_DOT, '');
122
- }
123
- if (!company) {
124
- return null;
135
+ return `${user}@${company}.${WEBEX_DOT_COM}`;
125
136
  }
126
137
 
127
- return `${user}@${company}.${WEBEX_DOT_COM}`;
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
- MeetingInfoUtil.isSipUri = (sipString) => {
131
- // TODO: lets remove regex from this equation and user URI matchers and such
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
- return sipUri;
136
- };
146
+ static isPhoneNumber(phoneNumber) {
147
+ const isValidNumber = DIALER_REGEX.PHONE_NUMBER.test(phoneNumber);
137
148
 
138
- MeetingInfoUtil.isPhoneNumber = (phoneNumber) => {
139
- const isValidNumber = DIALER_REGEX.PHONE_NUMBER.test(phoneNumber);
149
+ return isValidNumber;
150
+ }
140
151
 
141
- return isValidNumber;
142
- };
152
+ static getHydraId(destination) {
153
+ const {type, id, cluster} = deconstructHydraId(destination);
143
154
 
144
- MeetingInfoUtil.getHydraId = (destination) => {
145
- const {type, id, cluster} = deconstructHydraId(destination);
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
- if (id && UUID_REG.test(id)) {
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
- return {};
159
- };
160
-
161
- MeetingInfoUtil.getSipUriFromHydraPersonId = (destination, webex) =>
162
- webex.people
163
- .get(destination)
164
- .then((res) => {
165
- if (res.emails && res.emails.length) {
166
- return res.emails[0];
167
- }
168
- throw new ParameterError('Hydra Id Lookup was an invalid hydra person id.');
169
- })
170
- .catch((err) => {
171
- LoggerProxy.logger.error(
172
- `Meeting-info:util#MeetingInfoUtil.getSipUriFromHydraPersonId --> getSipUriFromHydraPersonId ${err} `
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
- MeetingInfoUtil.generateOptions = async (from) => {
178
- const {destination, type, webex} = from;
186
+ static async generateOptions(from) {
187
+ const {destination, type, webex} = from;
179
188
 
180
- if (type) {
181
- return {
182
- destination,
183
- type,
184
- };
185
- }
186
- const options: any = {};
187
- const hydraId = MeetingInfoUtil.getHydraId(destination);
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
- const serviceUrl = webex.internal.services.getServiceUrlFromClusterId(
224
- {
225
- cluster: hydraId.cluster,
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.destination = hydraId.destination
231
- ? `${serviceUrl}/conversations/${hydraId.destination}`
232
- : serviceUrl;
233
- } catch (e) {
234
- LoggerProxy.logger.error(`Meeting-info:util#generateOptions --> ${e}`);
235
- throw e;
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
- } else {
238
- throw new ParameterError(
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
- return Promise.resolve(options);
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
- * Helper function to build up a correct locus url depending on the value passed
248
- * @param {String} type One of [SIP_URI, PERSONAL_ROOM, MEETING_ID, CONVERSATION_URL, LOCUS_ID, MEETING_LINK]
249
- * @param {Object} value ?? value.value
250
- * @returns {Object} returns an object with {resource, method}
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
- return {
281
- uri,
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
- uri: resourceOptions.uri,
299
+ api,
300
+ resource: resourceOptions.resource,
308
301
  };
309
- }
310
302
 
311
- return requestParams;
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
- export default MeetingInfoUtil;
320
+ return requestParams;
321
+ }
322
+ }