@webex/plugin-meetings 3.12.0-next.9 → 3.12.0-next.91

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 (213) hide show
  1. package/AGENTS.md +9 -0
  2. package/dist/aiEnableRequest/index.js +15 -2
  3. package/dist/aiEnableRequest/index.js.map +1 -1
  4. package/dist/breakouts/breakout.js +8 -3
  5. package/dist/breakouts/breakout.js.map +1 -1
  6. package/dist/breakouts/index.js +26 -2
  7. package/dist/breakouts/index.js.map +1 -1
  8. package/dist/config.js +2 -2
  9. package/dist/config.js.map +1 -1
  10. package/dist/constants.js +35 -9
  11. package/dist/constants.js.map +1 -1
  12. package/dist/controls-options-manager/constants.js +11 -1
  13. package/dist/controls-options-manager/constants.js.map +1 -1
  14. package/dist/controls-options-manager/index.js +67 -29
  15. package/dist/controls-options-manager/index.js.map +1 -1
  16. package/dist/controls-options-manager/util.js +91 -0
  17. package/dist/controls-options-manager/util.js.map +1 -1
  18. package/dist/hashTree/constants.js +13 -1
  19. package/dist/hashTree/constants.js.map +1 -1
  20. package/dist/hashTree/hashTreeParser.js +880 -382
  21. package/dist/hashTree/hashTreeParser.js.map +1 -1
  22. package/dist/hashTree/utils.js +42 -0
  23. package/dist/hashTree/utils.js.map +1 -1
  24. package/dist/index.js +7 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/interceptors/dataChannelAuthToken.js +75 -15
  27. package/dist/interceptors/dataChannelAuthToken.js.map +1 -1
  28. package/dist/interceptors/locusRetry.js +23 -8
  29. package/dist/interceptors/locusRetry.js.map +1 -1
  30. package/dist/interpretation/index.js +10 -1
  31. package/dist/interpretation/index.js.map +1 -1
  32. package/dist/interpretation/interpretation.types.js +7 -0
  33. package/dist/interpretation/interpretation.types.js.map +1 -0
  34. package/dist/interpretation/siLanguage.js +1 -1
  35. package/dist/locus-info/controlsUtils.js +4 -1
  36. package/dist/locus-info/controlsUtils.js.map +1 -1
  37. package/dist/locus-info/index.js +303 -88
  38. package/dist/locus-info/index.js.map +1 -1
  39. package/dist/locus-info/infoUtils.js +36 -5
  40. package/dist/locus-info/infoUtils.js.map +1 -1
  41. package/dist/locus-info/types.js +19 -0
  42. package/dist/locus-info/types.js.map +1 -1
  43. package/dist/media/index.js +3 -1
  44. package/dist/media/index.js.map +1 -1
  45. package/dist/media/properties.js +1 -0
  46. package/dist/media/properties.js.map +1 -1
  47. package/dist/meeting/in-meeting-actions.js +5 -1
  48. package/dist/meeting/in-meeting-actions.js.map +1 -1
  49. package/dist/meeting/index.js +1233 -793
  50. package/dist/meeting/index.js.map +1 -1
  51. package/dist/meeting/locusMediaRequest.js +229 -82
  52. package/dist/meeting/locusMediaRequest.js.map +1 -1
  53. package/dist/meeting/muteState.js +10 -1
  54. package/dist/meeting/muteState.js.map +1 -1
  55. package/dist/meeting/request.js +5 -2
  56. package/dist/meeting/request.js.map +1 -1
  57. package/dist/meeting/util.js +35 -2
  58. package/dist/meeting/util.js.map +1 -1
  59. package/dist/meeting-info/meeting-info-v2.js +2 -2
  60. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  61. package/dist/meetings/index.js +231 -118
  62. package/dist/meetings/index.js.map +1 -1
  63. package/dist/meetings/meetings.types.js +6 -1
  64. package/dist/meetings/meetings.types.js.map +1 -1
  65. package/dist/meetings/request.js +39 -0
  66. package/dist/meetings/request.js.map +1 -1
  67. package/dist/meetings/util.js +79 -5
  68. package/dist/meetings/util.js.map +1 -1
  69. package/dist/member/index.js +10 -0
  70. package/dist/member/index.js.map +1 -1
  71. package/dist/member/types.js.map +1 -1
  72. package/dist/member/util.js +30 -0
  73. package/dist/member/util.js.map +1 -1
  74. package/dist/members/index.js +101 -43
  75. package/dist/members/index.js.map +1 -1
  76. package/dist/members/util.js +8 -1
  77. package/dist/members/util.js.map +1 -1
  78. package/dist/metrics/constants.js +5 -1
  79. package/dist/metrics/constants.js.map +1 -1
  80. package/dist/multistream/codec/constants.js +63 -0
  81. package/dist/multistream/codec/constants.js.map +1 -0
  82. package/dist/multistream/mediaRequestManager.js +62 -15
  83. package/dist/multistream/mediaRequestManager.js.map +1 -1
  84. package/dist/multistream/receiveSlot.js +9 -0
  85. package/dist/multistream/receiveSlot.js.map +1 -1
  86. package/dist/reachability/index.js +10 -13
  87. package/dist/reachability/index.js.map +1 -1
  88. package/dist/reachability/reachability.types.js +2 -0
  89. package/dist/reachability/reachability.types.js.map +1 -1
  90. package/dist/reachability/util.js +45 -0
  91. package/dist/reachability/util.js.map +1 -1
  92. package/dist/reactions/reactions.type.js.map +1 -1
  93. package/dist/recording-controller/index.js +1 -3
  94. package/dist/recording-controller/index.js.map +1 -1
  95. package/dist/types/config.d.ts +2 -2
  96. package/dist/types/constants.d.ts +12 -1
  97. package/dist/types/controls-options-manager/constants.d.ts +6 -1
  98. package/dist/types/controls-options-manager/index.d.ts +16 -0
  99. package/dist/types/hashTree/constants.d.ts +2 -0
  100. package/dist/types/hashTree/hashTreeParser.d.ts +146 -17
  101. package/dist/types/hashTree/utils.d.ts +18 -0
  102. package/dist/types/index.d.ts +3 -0
  103. package/dist/types/interceptors/locusRetry.d.ts +4 -4
  104. package/dist/types/interpretation/interpretation.types.d.ts +10 -0
  105. package/dist/types/locus-info/index.d.ts +50 -6
  106. package/dist/types/locus-info/infoUtils.d.ts +8 -0
  107. package/dist/types/locus-info/types.d.ts +21 -1
  108. package/dist/types/media/properties.d.ts +1 -0
  109. package/dist/types/meeting/in-meeting-actions.d.ts +4 -0
  110. package/dist/types/meeting/index.d.ts +94 -7
  111. package/dist/types/meeting/locusMediaRequest.d.ts +12 -0
  112. package/dist/types/meeting/request.d.ts +1 -0
  113. package/dist/types/meeting/util.d.ts +9 -0
  114. package/dist/types/meetings/index.d.ts +30 -18
  115. package/dist/types/meetings/meetings.types.d.ts +15 -0
  116. package/dist/types/meetings/request.d.ts +14 -0
  117. package/dist/types/member/index.d.ts +1 -0
  118. package/dist/types/member/types.d.ts +1 -0
  119. package/dist/types/member/util.d.ts +9 -0
  120. package/dist/types/members/index.d.ts +15 -2
  121. package/dist/types/members/util.d.ts +1 -5
  122. package/dist/types/metrics/constants.d.ts +4 -0
  123. package/dist/types/multistream/codec/constants.d.ts +7 -0
  124. package/dist/types/multistream/mediaRequestManager.d.ts +22 -5
  125. package/dist/types/reachability/index.d.ts +1 -1
  126. package/dist/types/reachability/reachability.types.d.ts +7 -0
  127. package/dist/types/reachability/util.d.ts +17 -0
  128. package/dist/types/reactions/reactions.type.d.ts +3 -0
  129. package/dist/webinar/index.js +305 -159
  130. package/dist/webinar/index.js.map +1 -1
  131. package/package.json +22 -22
  132. package/src/aiEnableRequest/index.ts +16 -0
  133. package/src/breakouts/breakout.ts +3 -1
  134. package/src/breakouts/index.ts +31 -0
  135. package/src/config.ts +2 -2
  136. package/src/constants.ts +20 -3
  137. package/src/controls-options-manager/constants.ts +14 -1
  138. package/src/controls-options-manager/index.ts +87 -28
  139. package/src/controls-options-manager/util.ts +81 -1
  140. package/src/hashTree/constants.ts +16 -0
  141. package/src/hashTree/hashTreeParser.ts +580 -196
  142. package/src/hashTree/utils.ts +36 -0
  143. package/src/index.ts +6 -0
  144. package/src/interceptors/dataChannelAuthToken.ts +88 -12
  145. package/src/interceptors/locusRetry.ts +25 -4
  146. package/src/interpretation/index.ts +27 -9
  147. package/src/interpretation/interpretation.types.ts +11 -0
  148. package/src/locus-info/controlsUtils.ts +3 -1
  149. package/src/locus-info/index.ts +304 -100
  150. package/src/locus-info/infoUtils.ts +41 -6
  151. package/src/locus-info/types.ts +25 -1
  152. package/src/media/index.ts +3 -0
  153. package/src/media/properties.ts +1 -0
  154. package/src/meeting/in-meeting-actions.ts +8 -0
  155. package/src/meeting/index.ts +494 -67
  156. package/src/meeting/locusMediaRequest.ts +106 -6
  157. package/src/meeting/muteState.ts +10 -1
  158. package/src/meeting/request.ts +11 -0
  159. package/src/meeting/util.ts +47 -5
  160. package/src/meeting-info/meeting-info-v2.ts +4 -2
  161. package/src/meetings/index.ts +133 -78
  162. package/src/meetings/meetings.types.ts +19 -0
  163. package/src/meetings/request.ts +43 -0
  164. package/src/meetings/util.ts +97 -1
  165. package/src/member/index.ts +10 -0
  166. package/src/member/types.ts +1 -0
  167. package/src/member/util.ts +29 -0
  168. package/src/members/index.ts +70 -7
  169. package/src/members/util.ts +12 -4
  170. package/src/metrics/constants.ts +4 -0
  171. package/src/multistream/codec/constants.ts +58 -0
  172. package/src/multistream/mediaRequestManager.ts +119 -28
  173. package/src/multistream/receiveSlot.ts +18 -0
  174. package/src/reachability/index.ts +19 -15
  175. package/src/reachability/reachability.types.ts +11 -0
  176. package/src/reachability/util.ts +36 -0
  177. package/src/reactions/reactions.type.ts +3 -0
  178. package/src/recording-controller/index.ts +1 -2
  179. package/src/webinar/index.ts +214 -36
  180. package/test/unit/spec/aiEnableRequest/index.ts +86 -0
  181. package/test/unit/spec/breakouts/breakout.ts +9 -3
  182. package/test/unit/spec/breakouts/index.ts +49 -0
  183. package/test/unit/spec/controls-options-manager/index.js +244 -29
  184. package/test/unit/spec/controls-options-manager/util.js +165 -0
  185. package/test/unit/spec/hashTree/hashTreeParser.ts +1838 -180
  186. package/test/unit/spec/hashTree/utils.ts +125 -1
  187. package/test/unit/spec/interceptors/dataChannelAuthToken.ts +196 -0
  188. package/test/unit/spec/interceptors/locusRetry.ts +205 -4
  189. package/test/unit/spec/interpretation/index.ts +26 -4
  190. package/test/unit/spec/locus-info/controlsUtils.js +172 -57
  191. package/test/unit/spec/locus-info/index.js +499 -81
  192. package/test/unit/spec/locus-info/infoUtils.js +184 -1
  193. package/test/unit/spec/media/index.ts +31 -0
  194. package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
  195. package/test/unit/spec/meeting/index.js +1615 -42
  196. package/test/unit/spec/meeting/locusMediaRequest.ts +302 -4
  197. package/test/unit/spec/meeting/muteState.js +81 -0
  198. package/test/unit/spec/meeting/request.js +12 -0
  199. package/test/unit/spec/meeting/utils.js +157 -1
  200. package/test/unit/spec/meeting-info/meetinginfov2.js +19 -10
  201. package/test/unit/spec/meetings/index.js +363 -36
  202. package/test/unit/spec/meetings/request.js +141 -0
  203. package/test/unit/spec/meetings/utils.js +189 -0
  204. package/test/unit/spec/member/index.js +7 -0
  205. package/test/unit/spec/member/util.js +89 -0
  206. package/test/unit/spec/members/index.js +216 -0
  207. package/test/unit/spec/members/request.js +37 -1
  208. package/test/unit/spec/members/utils.js +63 -0
  209. package/test/unit/spec/multistream/mediaRequestManager.ts +501 -37
  210. package/test/unit/spec/reachability/index.ts +59 -46
  211. package/test/unit/spec/reachability/util.ts +31 -0
  212. package/test/unit/spec/recording-controller/index.js +9 -8
  213. package/test/unit/spec/webinar/index.ts +329 -28
@@ -1,11 +1,13 @@
1
1
  /* eslint-disable valid-jsdoc */
2
2
  import {defer} from 'lodash';
3
- import {Defer, transferEvents} from '@webex/common';
3
+ import {Defer} from '@webex/common';
4
4
  import {EventEmitter} from 'events';
5
5
  import {WebexPlugin} from '@webex/webex-core';
6
6
  import {MEDIA, HTTP_VERBS, ROAP} from '../constants';
7
7
  import LoggerProxy from '../common/logs/logger-proxy';
8
8
  import {ClientMediaPreferences} from '../reachability/reachability.types';
9
+ import Metrics from '../metrics';
10
+ import BEHAVIORAL_METRICS from '../metrics/constants';
9
11
 
10
12
  export type MediaRequestType = 'RoapMessage' | 'LocalMute';
11
13
  export type RequestResult = any;
@@ -37,13 +39,13 @@ export type Request = RoapRequest | LocalMuteRequest;
37
39
  class InternalRequestInfo {
38
40
  public readonly request: Request;
39
41
  private pendingPromises: Defer[];
40
- private sendRequestFn: (request: Request) => Promise<RequestResult>;
42
+ private sendRequestFn: (request: Request, selfUrlRetryCount: number) => Promise<RequestResult>;
41
43
 
42
44
  /** Constructor */
43
45
  constructor(
44
46
  request: Request,
45
47
  pendingPromise: Defer,
46
- sendRequestFn: (request: Request) => Promise<RequestResult>
48
+ sendRequestFn: (request: Request, selfUrlRetryCount: number) => Promise<RequestResult>
47
49
  ) {
48
50
  this.request = request;
49
51
  this.pendingPromises = [pendingPromise];
@@ -69,7 +71,7 @@ class InternalRequestInfo {
69
71
  * is completed (no matter if it succeeded or failed).
70
72
  */
71
73
  public execute(): Promise<void> {
72
- return this.sendRequestFn(this.request)
74
+ return this.sendRequestFn(this.request, 0)
73
75
  .then((result) => {
74
76
  // resolve all the pending promises associated with this request
75
77
  this.pendingPromises.forEach((d) => d.resolve(result));
@@ -91,8 +93,12 @@ export type Config = {
91
93
  correlationId: string;
92
94
  meetingId: string;
93
95
  preferTranscoding: boolean;
96
+ getCurrentSelfUrl: () => string | undefined;
97
+ waitForSelfUrlChange: () => Promise<void>;
94
98
  };
95
99
 
100
+ const MAX_SELF_URL_RETRY_COUNT = 2;
101
+
96
102
  /**
97
103
  * Returns true if the request is triggering confluence creation in the server
98
104
  */
@@ -194,7 +200,13 @@ export class LocusMediaRequest extends WebexPlugin {
194
200
  /**
195
201
  * Prepares the uri and body for the media request to be sent to Locus
196
202
  */
197
- private sendHttpRequest(request: Request) {
203
+ private async sendHttpRequest(request: Request, selfUrlRetryCount = 0) {
204
+ // Resolve selfUrl lazily at send time. Locus rotates it on session
205
+ // transitions (breakout end, move-to, lobby admit) and the value
206
+ // captured upstream in roap/index.ts may be stale by the time we
207
+ // leave the queue. Persist the resolved URL on the request so a
208
+ // retry can detect a further rotation.
209
+ request.selfUrl = this.getCurrentSelfUrl(request);
198
210
  const uri = `${request.selfUrl}/${MEDIA}`;
199
211
 
200
212
  const {audioMuted, videoMuted} = this.getLatestMuteState();
@@ -263,7 +275,21 @@ export class LocusMediaRequest extends WebexPlugin {
263
275
 
264
276
  return result;
265
277
  })
266
- .catch((e) => {
278
+ .catch(async (e) => {
279
+ if (
280
+ e?.statusCode === 409 &&
281
+ (await this.shouldRetryOnSelfUrlChange(request, selfUrlRetryCount))
282
+ ) {
283
+ // In-flight race: selfUrl rotated after we left the queue but
284
+ // before Locus rejected the request. Re-send; getCurrentSelfUrl
285
+ // will pick up the new URL. The returned promise replaces the
286
+ // rejection, so the caller's pendingPromise resolves correctly.
287
+ // Advance the retry count here so the guard in
288
+ // shouldRetryOnSelfUrlChange eventually stops after
289
+ // MAX_SELF_URL_RETRY_COUNT attempts.
290
+ return this.sendHttpRequest(request, selfUrlRetryCount + 1);
291
+ }
292
+
267
293
  if (
268
294
  isRequestAffectingConfluenceState(request) &&
269
295
  this.confluenceState === 'creation in progress'
@@ -301,6 +327,80 @@ export class LocusMediaRequest extends WebexPlugin {
301
327
  return promise;
302
328
  }
303
329
 
330
+ /**
331
+ * Returns the latest selfUrl for this meeting, falling back to the value
332
+ * captured when the request was enqueued.
333
+ */
334
+ private getCurrentSelfUrl(request: Request): string {
335
+ const currentSelfUrl = this.config.getCurrentSelfUrl();
336
+
337
+ if (currentSelfUrl && currentSelfUrl !== request.selfUrl) {
338
+ LoggerProxy.logger.info(
339
+ `Meeting:LocusMediaRequest#getCurrentSelfUrl --> resolved updated selfUrl, using ${currentSelfUrl}`
340
+ );
341
+
342
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.LOCUS_MEDIA_REQUEST_RETRY, {
343
+ correlation_id: this.config.correlationId,
344
+ reason: 'selfUrlUpdatedBeforeMediaRequest',
345
+ });
346
+
347
+ return currentSelfUrl;
348
+ }
349
+
350
+ return request.selfUrl;
351
+ }
352
+
353
+ /**
354
+ * Decides whether a 409 warrants a retry against the meeting's latest
355
+ * selfUrl.
356
+ */
357
+ private async shouldRetryOnSelfUrlChange(
358
+ request: Request,
359
+ selfUrlRetryCount: number
360
+ ): Promise<boolean> {
361
+ if (selfUrlRetryCount >= MAX_SELF_URL_RETRY_COUNT) {
362
+ return false;
363
+ }
364
+
365
+ const roapMessageType =
366
+ request.type === 'RoapMessage' ? request.roapMessage?.messageType : undefined;
367
+
368
+ const currentSelfUrl = this.getCurrentSelfUrl(request);
369
+
370
+ if (!currentSelfUrl || currentSelfUrl === request.selfUrl) {
371
+ await this.config.waitForSelfUrlChange();
372
+
373
+ const latestSelfUrl = this.getCurrentSelfUrl(request);
374
+
375
+ if (!latestSelfUrl || latestSelfUrl === request.selfUrl) {
376
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.LOCUS_MEDIA_REQUEST_RETRY, {
377
+ correlation_id: this.config.correlationId,
378
+ reason: 'selfUrlNotChangedAfterWait',
379
+ retryAttempt: selfUrlRetryCount,
380
+ roapMessageType,
381
+ });
382
+ LoggerProxy.logger.info(
383
+ 'Meeting:LocusMediaRequest#sendHttpRequest --> 409 conflict, no new selfUrl even after waiting'
384
+ );
385
+
386
+ return false;
387
+ }
388
+
389
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.LOCUS_MEDIA_REQUEST_RETRY, {
390
+ correlation_id: this.config.correlationId,
391
+ reason: 'selfUrlChangedAfterWait',
392
+ retryAttempt: selfUrlRetryCount,
393
+ roapMessageType,
394
+ });
395
+ }
396
+
397
+ LoggerProxy.logger.info(
398
+ `Meeting:LocusMediaRequest#sendHttpRequest --> 409 conflict, retrying ${request.type} with updated selfUrl`
399
+ );
400
+
401
+ return true;
402
+ }
403
+
304
404
  /**
305
405
  * Sends a media request to Locus
306
406
  */
@@ -375,7 +375,16 @@ export class MuteState {
375
375
  }
376
376
  if (muted !== undefined) {
377
377
  this.state.server.remoteMute = muted;
378
- this.muteLocalStream(meeting, muted, 'remotelyMuted');
378
+ // BO->Main may replay a stale remoteMute=false from the locus cache.
379
+ // Only enforce the mute on muted=true (also locking client.localMute so a later stale
380
+ // false can't flip isMuted()), and never touch the stream on muted=false — the
381
+ // legitimate server-driven unmute path is LOCAL_UNMUTE_REQUIRED. Always sync client
382
+ // intent back so other participants' tiles still show the mute icon.
383
+ if (muted) {
384
+ this.state.client.localMute = true;
385
+ this.muteLocalStream(meeting, true, 'remotelyMuted');
386
+ }
387
+ this.applyClientStateToServer(meeting);
379
388
  }
380
389
  }
381
390
 
@@ -26,6 +26,7 @@ import {
26
26
  SEND_DTMF_ENDPOINT,
27
27
  _SLIDES_,
28
28
  ANNOTATION,
29
+ INTERPRETATION,
29
30
  } from '../constants';
30
31
  import {
31
32
  SendReactionOptions,
@@ -135,6 +136,7 @@ export default class MeetingRequest extends StatelessWebexPlugin {
135
136
  locale?: string;
136
137
  deviceCapabilities?: Array<string>;
137
138
  liveAnnotationSupported: boolean;
139
+ enableSimultaneousInterpretation: boolean;
138
140
  alias?: string;
139
141
  clientMediaPreferences: ClientMediaPreferences;
140
142
  }) {
@@ -158,6 +160,7 @@ export default class MeetingRequest extends StatelessWebexPlugin {
158
160
  locale,
159
161
  deviceCapabilities = [],
160
162
  liveAnnotationSupported,
163
+ enableSimultaneousInterpretation,
161
164
  clientMediaPreferences,
162
165
  alias,
163
166
  } = options;
@@ -193,6 +196,14 @@ export default class MeetingRequest extends StatelessWebexPlugin {
193
196
  if (liveAnnotationSupported) {
194
197
  deviceCapabilities.push(ANNOTATION.ANNOTATION_ON_SHARE_SUPPORTED);
195
198
  }
199
+ if (enableSimultaneousInterpretation) {
200
+ deviceCapabilities.push(
201
+ INTERPRETATION.CAPABILITIES.HOST_CONTROL_SI_SUPPORTED,
202
+ INTERPRETATION.CAPABILITIES.INTERPRETER_CONTROL_SI_SUPPORTED,
203
+ INTERPRETATION.CAPABILITIES.SI_HANDOVER_SUPPORTED,
204
+ INTERPRETATION.CAPABILITIES.SIGN_INTERPRETER_SUPPORTED
205
+ );
206
+ }
196
207
 
197
208
  // append installationId to device config if it exists
198
209
  // @ts-ignore
@@ -317,6 +317,7 @@ const MeetingUtil = {
317
317
  locale: options.locale,
318
318
  deviceCapabilities: options.deviceCapabilities,
319
319
  liveAnnotationSupported: options.liveAnnotationSupported,
320
+ enableSimultaneousInterpretation: options.enableSimultaneousInterpretation,
320
321
  clientMediaPreferences,
321
322
  alias: options.alias,
322
323
  })
@@ -371,6 +372,7 @@ const MeetingUtil = {
371
372
  meeting.breakouts.cleanUp();
372
373
  meeting.webinar.cleanUp();
373
374
  meeting.simultaneousInterpretation.cleanUp();
375
+ meeting.locusInfo.cleanUp();
374
376
  meeting.locusMediaRequest = undefined;
375
377
 
376
378
  meeting.webex?.internal?.newMetrics?.callDiagnosticMetrics?.clearEventLimitsForCorrelationId(
@@ -845,6 +847,19 @@ const MeetingUtil = {
845
847
  requestBody.sequence = sequence;
846
848
  },
847
849
 
850
+ /**
851
+ * Checks if Locus API response contains a Locus DTO
852
+ *
853
+ * @param {any} response http response from Locus API call
854
+ * @returns {boolean} true if response contains a Locus DTO
855
+ */
856
+ isLocusDtoInAPIResponse(response: any) {
857
+ return (
858
+ response?.body?.locus || // for APIs called on our participant - locus is one of props in the response body
859
+ response?.body?.url // for APIs that act on locus itself (like mute all), the body is the locus
860
+ );
861
+ },
862
+
848
863
  /**
849
864
  * Updates the locus info for the meeting with the locus
850
865
  * information returned from API requests made to Locus
@@ -853,12 +868,13 @@ const MeetingUtil = {
853
868
  * @param {Object} response The response of the http request
854
869
  * @returns {Object}
855
870
  */
856
- updateLocusFromApiResponse: (meeting, response) => {
871
+ updateLocusFromApiResponse: (meeting: any, response: any) => {
857
872
  if (!meeting) {
858
873
  return response;
859
874
  }
860
875
 
861
- if (response?.body?.locus) {
876
+ // locus API responses can come in different shapes:
877
+ if (MeetingUtil.isLocusDtoInAPIResponse(response)) {
862
878
  meeting.locusInfo.handleLocusAPIResponse(meeting, response.body);
863
879
  }
864
880
 
@@ -904,9 +920,20 @@ const MeetingUtil = {
904
920
 
905
921
  const options = buildLocusDeltaRequestOptions(originalOptions);
906
922
 
907
- return meeting
908
- .request(options)
909
- .then((response) => MeetingUtil.updateLocusFromApiResponse(meeting, response));
923
+ return meeting.request(options).then((response) => {
924
+ const requestUri = options?.uri;
925
+ const meetingLocusUrl = meeting.locusUrl;
926
+
927
+ if (!requestUri || !meetingLocusUrl || !requestUri.startsWith(meetingLocusUrl)) {
928
+ LoggerProxy.logger.info(
929
+ `Meeting:util#generateLocusDeltaRequest --> skipping updateLocusFromApiResponse, request uri "${requestUri}" does not match meeting locusUrl "${meetingLocusUrl}"`
930
+ );
931
+
932
+ return response;
933
+ }
934
+
935
+ return MeetingUtil.updateLocusFromApiResponse(meeting, response);
936
+ });
910
937
  };
911
938
 
912
939
  return locusDeltaRequest;
@@ -930,6 +957,21 @@ const MeetingUtil = {
930
957
  attendeeRequestAiAssistantDeclinedAll: (displayHints = []) =>
931
958
  displayHints.includes(DISPLAY_HINTS.ATTENDEE_REQUEST_AI_ASSISTANT_DECLINED_ALL),
932
959
 
960
+ isAnonymizeDisplayNamesEnabled: (displayHints) =>
961
+ displayHints.includes(DISPLAY_HINTS.ANONYMOUS_DISPLAY_NAMES_ENABLED),
962
+
963
+ canViewTheParticipantList: (displayHints, canNotViewTheParticipantList: boolean) => {
964
+ if (!displayHints.includes(DISPLAY_HINTS.VIEW_THE_PARTICIPANT_LIST)) {
965
+ return false;
966
+ }
967
+
968
+ if (canNotViewTheParticipantList) {
969
+ return false;
970
+ }
971
+
972
+ return displayHints.includes(DISPLAY_HINTS.CAN_VIEW_THE_PARTICIPANT_LIST);
973
+ },
974
+
933
975
  selfSupportsFeature: (feature: SELF_POLICY, userPolicies: Record<SELF_POLICY, boolean>) => {
934
976
  if (!userPolicies) {
935
977
  return true;
@@ -19,7 +19,7 @@ const ADHOC_MEETING_DEFAULT_ERROR =
19
19
  const MEETING_IS_IN_PROGRESS_MESSAGE = 'Meeting is in progress';
20
20
  const STATIC_MEETING_LINK_ALREADY_EXISTS_MESSAGE = 'Static meeting link already exists';
21
21
  const FETCH_STATIC_MEETING_LINK = 'Meeting link does not exists for conversation';
22
- const CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES = [423005, 423006];
22
+ const CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES = [423005, 423006, 423008];
23
23
  const CAPTCHA_ERROR_REQUIRES_REGISTRATION_ID_CODES = [423007];
24
24
 
25
25
  const POLICY_ERROR_CODES = [403049, 403104, 403103, 403048, 403102, 403101];
@@ -35,7 +35,9 @@ const JOIN_FORBIDDEN_CODES = [403003];
35
35
  * 403137 - Registration ID verified failure
36
36
  *
37
37
  */
38
- const JOIN_WEBINAR_ERROR_CODES = [403021, 403022, 403024, 403137, 423007, 403026, 403037, 403137];
38
+ const JOIN_WEBINAR_ERROR_CODES = [
39
+ 403021, 403022, 403024, 403137, 423007, 403026, 403037, 403137, 403106,
40
+ ];
39
41
 
40
42
  /**
41
43
  * Error to indicate that wbxappapi requires a password