@webex/calling 3.3.1 → 3.4.0-next.10

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 (108) hide show
  1. package/dist/CallHistory/CallHistory.js +103 -4
  2. package/dist/CallHistory/CallHistory.js.map +1 -1
  3. package/dist/CallHistory/CallHistory.test.js +143 -0
  4. package/dist/CallHistory/CallHistory.test.js.map +1 -1
  5. package/dist/CallHistory/callHistoryFixtures.js +224 -1
  6. package/dist/CallHistory/callHistoryFixtures.js.map +1 -1
  7. package/dist/CallHistory/constants.js +8 -2
  8. package/dist/CallHistory/constants.js.map +1 -1
  9. package/dist/CallHistory/types.js.map +1 -1
  10. package/dist/CallSettings/UcmBackendConnector.js +1 -1
  11. package/dist/CallSettings/UcmBackendConnector.js.map +1 -1
  12. package/dist/CallSettings/UcmBackendConnector.test.js +1 -1
  13. package/dist/CallSettings/UcmBackendConnector.test.js.map +1 -1
  14. package/dist/CallSettings/constants.js +1 -3
  15. package/dist/CallSettings/constants.js.map +1 -1
  16. package/dist/CallingClient/calling/CallerId/types.js.map +1 -1
  17. package/dist/CallingClient/calling/call.js +5 -3
  18. package/dist/CallingClient/calling/call.js.map +1 -1
  19. package/dist/CallingClient/calling/call.test.js +17 -15
  20. package/dist/CallingClient/calling/call.test.js.map +1 -1
  21. package/dist/CallingClient/constants.js +6 -8
  22. package/dist/CallingClient/constants.js.map +1 -1
  23. package/dist/CallingClient/registration/register.js +18 -13
  24. package/dist/CallingClient/registration/register.js.map +1 -1
  25. package/dist/CallingClient/registration/register.test.js +242 -125
  26. package/dist/CallingClient/registration/register.test.js.map +1 -1
  27. package/dist/Contacts/ContactsClient.js +270 -292
  28. package/dist/Contacts/ContactsClient.js.map +1 -1
  29. package/dist/Contacts/ContactsClient.test.js +109 -12
  30. package/dist/Contacts/ContactsClient.test.js.map +1 -1
  31. package/dist/Contacts/constants.js +3 -1
  32. package/dist/Contacts/constants.js.map +1 -1
  33. package/dist/Contacts/contactFixtures.js +164 -48
  34. package/dist/Contacts/contactFixtures.js.map +1 -1
  35. package/dist/Contacts/types.js.map +1 -1
  36. package/dist/Events/types.js.map +1 -1
  37. package/dist/Metrics/index.js +9 -9
  38. package/dist/Metrics/index.js.map +1 -1
  39. package/dist/Metrics/index.test.js +37 -10
  40. package/dist/Metrics/index.test.js.map +1 -1
  41. package/dist/SDKConnector/types.js.map +1 -1
  42. package/dist/common/Utils.js +12 -10
  43. package/dist/common/Utils.js.map +1 -1
  44. package/dist/common/Utils.test.js +25 -1
  45. package/dist/common/Utils.test.js.map +1 -1
  46. package/dist/common/constants.js +10 -1
  47. package/dist/common/constants.js.map +1 -1
  48. package/dist/common/testUtil.js +24 -6
  49. package/dist/common/testUtil.js.map +1 -1
  50. package/dist/common/types.js +1 -0
  51. package/dist/common/types.js.map +1 -1
  52. package/dist/module/CallHistory/CallHistory.js +57 -3
  53. package/dist/module/CallHistory/callHistoryFixtures.js +215 -0
  54. package/dist/module/CallHistory/constants.js +7 -1
  55. package/dist/module/CallSettings/UcmBackendConnector.js +5 -3
  56. package/dist/module/CallSettings/constants.js +0 -2
  57. package/dist/module/CallingClient/calling/call.js +6 -4
  58. package/dist/module/CallingClient/constants.js +5 -6
  59. package/dist/module/CallingClient/registration/register.js +12 -6
  60. package/dist/module/Contacts/ContactsClient.js +75 -58
  61. package/dist/module/Contacts/constants.js +2 -0
  62. package/dist/module/Contacts/contactFixtures.js +198 -31
  63. package/dist/module/Metrics/index.js +9 -9
  64. package/dist/module/common/Utils.js +10 -9
  65. package/dist/module/common/constants.js +9 -0
  66. package/dist/module/common/testUtil.js +24 -4
  67. package/dist/module/common/types.js +1 -0
  68. package/dist/types/CallHistory/CallHistory.d.ts +1 -0
  69. package/dist/types/CallHistory/CallHistory.d.ts.map +1 -1
  70. package/dist/types/CallHistory/callHistoryFixtures.d.ts +98 -1
  71. package/dist/types/CallHistory/callHistoryFixtures.d.ts.map +1 -1
  72. package/dist/types/CallHistory/constants.d.ts +7 -1
  73. package/dist/types/CallHistory/constants.d.ts.map +1 -1
  74. package/dist/types/CallHistory/types.d.ts +9 -1
  75. package/dist/types/CallHistory/types.d.ts.map +1 -1
  76. package/dist/types/CallSettings/UcmBackendConnector.d.ts.map +1 -1
  77. package/dist/types/CallSettings/constants.d.ts +0 -2
  78. package/dist/types/CallSettings/constants.d.ts.map +1 -1
  79. package/dist/types/CallingClient/calling/CallerId/types.d.ts +1 -23
  80. package/dist/types/CallingClient/calling/CallerId/types.d.ts.map +1 -1
  81. package/dist/types/CallingClient/calling/call.d.ts.map +1 -1
  82. package/dist/types/CallingClient/constants.d.ts +4 -5
  83. package/dist/types/CallingClient/constants.d.ts.map +1 -1
  84. package/dist/types/CallingClient/registration/register.d.ts +1 -0
  85. package/dist/types/CallingClient/registration/register.d.ts.map +1 -1
  86. package/dist/types/Contacts/ContactsClient.d.ts +2 -2
  87. package/dist/types/Contacts/ContactsClient.d.ts.map +1 -1
  88. package/dist/types/Contacts/constants.d.ts +2 -0
  89. package/dist/types/Contacts/constants.d.ts.map +1 -1
  90. package/dist/types/Contacts/contactFixtures.d.ts +99 -39
  91. package/dist/types/Contacts/contactFixtures.d.ts.map +1 -1
  92. package/dist/types/Contacts/types.d.ts +7 -14
  93. package/dist/types/Contacts/types.d.ts.map +1 -1
  94. package/dist/types/Events/types.d.ts +15 -0
  95. package/dist/types/Events/types.d.ts.map +1 -1
  96. package/dist/types/SDKConnector/types.d.ts +1 -5
  97. package/dist/types/SDKConnector/types.d.ts.map +1 -1
  98. package/dist/types/Voicemail/UcmBackendConnector.d.ts +1 -1
  99. package/dist/types/Voicemail/WxCallBackendConnector.d.ts +1 -1
  100. package/dist/types/common/Utils.d.ts +3 -2
  101. package/dist/types/common/Utils.d.ts.map +1 -1
  102. package/dist/types/common/constants.d.ts +9 -0
  103. package/dist/types/common/constants.d.ts.map +1 -1
  104. package/dist/types/common/testUtil.d.ts +20 -4
  105. package/dist/types/common/testUtil.d.ts.map +1 -1
  106. package/dist/types/common/types.d.ts +56 -25
  107. package/dist/types/common/types.d.ts.map +1 -1
  108. package/package.json +7 -7
@@ -259,6 +259,190 @@ export const mockCallHistoryBody = {
259
259
  ],
260
260
  },
261
261
  };
262
+ export const MOCK_CALL_HISTORY_WITH_UCM_LINE_NUMBER = {
263
+ body: {
264
+ statusCode: 200,
265
+ userSessions: [
266
+ {
267
+ id: '123456',
268
+ durationSecs: 438,
269
+ self: {
270
+ id: 'fd2e1234',
271
+ name: 'Mark',
272
+ cucmDN: '1001',
273
+ ucmLineNumber: 1,
274
+ incomingCallProtocols: [],
275
+ callbackInfo: {
276
+ callbackAddress: 'test@cisco.com',
277
+ callbackType: 'EMAIL',
278
+ },
279
+ lookUpInfo: {
280
+ lookupLink: 'https://conv-a.wbx2.com/conversation/api/v1/conversations/98765',
281
+ type: 'CONVERSATION',
282
+ },
283
+ },
284
+ url: 'https://janus-a.wbx2.com/janus/api/v1/history/userSessions/654321',
285
+ sessionId: '123456',
286
+ sessionType: 'SPARK',
287
+ startTime: '2022-08-22T10:45:21.565Z',
288
+ endTime: '2022-08-22T10:53:01.624Z',
289
+ direction: 'OUTGOING',
290
+ disposition: 'INITIATED',
291
+ other: {
292
+ id: '100001',
293
+ name: 'test',
294
+ isPrivate: false,
295
+ callbackAddress: '89998888',
296
+ },
297
+ durationSeconds: 438,
298
+ joinedDurationSeconds: 457,
299
+ participantCount: 2,
300
+ links: {
301
+ locusUrl: 'https://locus-a.wbx2.com/locus/api/v1/loci/786765',
302
+ conversationUrl: 'https://conv-a.wbx2.com/conversation/api/v1/conversations/55443322',
303
+ callbackAddress: '01010101',
304
+ },
305
+ isDeleted: false,
306
+ isPMR: false,
307
+ correlationIds: ['008899'],
308
+ },
309
+ {
310
+ id: '20191817',
311
+ durationSecs: 438,
312
+ self: {
313
+ id: '12131415',
314
+ name: 'Mark',
315
+ cucmDN: '1002',
316
+ ucmLineNumber: 2,
317
+ incomingCallProtocols: [],
318
+ callbackInfo: {
319
+ callbackAddress: 'test@cisco.com',
320
+ callbackType: 'EMAIL',
321
+ },
322
+ lookUpInfo: {
323
+ lookupLink: 'https://conv-a.wbx2.com/conversation/api/v1/conversations/21314151',
324
+ type: 'CONVERSATION',
325
+ },
326
+ },
327
+ url: 'https://janus-a.wbx2.com/janus/api/v1/history/userSessions/100101102',
328
+ sessionId: '20191817',
329
+ sessionType: 'SPARK',
330
+ startTime: '2022-08-30T10:45:21.565Z',
331
+ endTime: '2022-08-30T10:53:01.624Z',
332
+ direction: 'OUTGOING',
333
+ disposition: 'INITIATED',
334
+ other: {
335
+ id: '301302303',
336
+ name: 'test',
337
+ isPrivate: false,
338
+ callbackAddress: '401402403',
339
+ },
340
+ durationSeconds: 438,
341
+ joinedDurationSeconds: 457,
342
+ participantCount: 2,
343
+ links: {
344
+ locusUrl: 'https://locus-a.wbx2.com/locus/api/v1/loci/501502503',
345
+ conversationUrl: 'https://conv-a.wbx2.com/conversation/api/v1/conversations/601602603',
346
+ callbackAddress: '801802803',
347
+ },
348
+ isDeleted: false,
349
+ isPMR: false,
350
+ correlationIds: ['901902903'],
351
+ },
352
+ ],
353
+ },
354
+ };
355
+ export const MOCK_CALL_HISTORY_WITHOUT_UCM_LINE_NUMBER = {
356
+ body: {
357
+ statusCode: 200,
358
+ userSessions: [
359
+ {
360
+ id: '123456',
361
+ durationSecs: 438,
362
+ self: {
363
+ id: 'fd2e1234',
364
+ name: 'Mark',
365
+ cucmDN: '1001',
366
+ incomingCallProtocols: [],
367
+ callbackInfo: {
368
+ callbackAddress: 'test@cisco.com',
369
+ callbackType: 'EMAIL',
370
+ },
371
+ lookUpInfo: {
372
+ lookupLink: 'https://conv-a.wbx2.com/conversation/api/v1/conversations/98765',
373
+ type: 'CONVERSATION',
374
+ },
375
+ },
376
+ url: 'https://janus-a.wbx2.com/janus/api/v1/history/userSessions/654321',
377
+ sessionId: '123456',
378
+ sessionType: 'SPARK',
379
+ startTime: '2022-08-22T10:45:21.565Z',
380
+ endTime: '2022-08-22T10:53:01.624Z',
381
+ direction: 'OUTGOING',
382
+ disposition: 'INITIATED',
383
+ other: {
384
+ id: '100001',
385
+ name: 'test',
386
+ isPrivate: false,
387
+ callbackAddress: '89998888',
388
+ },
389
+ durationSeconds: 438,
390
+ joinedDurationSeconds: 457,
391
+ participantCount: 2,
392
+ links: {
393
+ locusUrl: 'https://locus-a.wbx2.com/locus/api/v1/loci/786765',
394
+ conversationUrl: 'https://conv-a.wbx2.com/conversation/api/v1/conversations/55443322',
395
+ callbackAddress: '01010101',
396
+ },
397
+ isDeleted: false,
398
+ isPMR: false,
399
+ correlationIds: ['008899'],
400
+ },
401
+ {
402
+ id: '20191817',
403
+ durationSecs: 438,
404
+ self: {
405
+ id: '12131415',
406
+ name: 'Mark',
407
+ cucmDN: '1002',
408
+ incomingCallProtocols: [],
409
+ callbackInfo: {
410
+ callbackAddress: 'test@cisco.com',
411
+ callbackType: 'EMAIL',
412
+ },
413
+ lookUpInfo: {
414
+ lookupLink: 'https://conv-a.wbx2.com/conversation/api/v1/conversations/21314151',
415
+ type: 'CONVERSATION',
416
+ },
417
+ },
418
+ url: 'https://janus-a.wbx2.com/janus/api/v1/history/userSessions/100101102',
419
+ sessionId: '20191817',
420
+ sessionType: 'SPARK',
421
+ startTime: '2022-08-30T10:45:21.565Z',
422
+ endTime: '2022-08-30T10:53:01.624Z',
423
+ direction: 'OUTGOING',
424
+ disposition: 'INITIATED',
425
+ other: {
426
+ id: '301302303',
427
+ name: 'test',
428
+ isPrivate: false,
429
+ callbackAddress: '401402403',
430
+ },
431
+ durationSeconds: 438,
432
+ joinedDurationSeconds: 457,
433
+ participantCount: 2,
434
+ links: {
435
+ locusUrl: 'https://locus-a.wbx2.com/locus/api/v1/loci/501502503',
436
+ conversationUrl: 'https://conv-a.wbx2.com/conversation/api/v1/conversations/601602603',
437
+ callbackAddress: '801802803',
438
+ },
439
+ isDeleted: false,
440
+ isPMR: false,
441
+ correlationIds: ['901902903'],
442
+ },
443
+ ],
444
+ },
445
+ };
262
446
  const WEBEX_CALL_SESSION = {
263
447
  id: 'd74d19cc-6aa7-f341-6012-aec433cc6f8d',
264
448
  durationSecs: 438,
@@ -401,3 +585,34 @@ export const ERROR_DETAILS_400 = {
401
585
  },
402
586
  message: 'FAILURE',
403
587
  };
588
+ export const MOCK_LINES_API_CALL_RESPONSE = {
589
+ statusCode: 200,
590
+ data: {
591
+ lines: {
592
+ devices: [
593
+ {
594
+ name: 'CSFheliosucm01',
595
+ model: 503,
596
+ lines: [
597
+ {
598
+ dnorpattern: '+14928000001',
599
+ index: 1,
600
+ label: '',
601
+ },
602
+ {
603
+ dnorpattern: '+14928000003',
604
+ index: 2,
605
+ label: '',
606
+ },
607
+ ],
608
+ },
609
+ ],
610
+ },
611
+ },
612
+ message: 'SUCCESS',
613
+ };
614
+ export const MOCK_LINES_API_CALL_RESPONSE_WITH_NO_LINEDATA = {
615
+ statusCode: 200,
616
+ data: {},
617
+ message: 'SUCCESS',
618
+ };
@@ -1,13 +1,19 @@
1
1
  export const APPLICATION_JSON = 'application/json';
2
2
  export const CALL_HISTORY_FILE = 'CallHistory';
3
3
  export const CONTENT_TYPE = 'Content-Type';
4
+ export const CONFIG = 'config';
4
5
  export const FROM_DATE = '?from';
5
6
  export const HISTORY = 'history';
6
7
  export const LIMIT = 50;
8
+ export const LINES = 'lines';
7
9
  export const NUMBER_OF_DAYS = 10;
10
+ export const ORG_ID = 'orgId';
11
+ export const PEOPLE = 'people';
8
12
  export const RESPONSE_MESSAGE = 'responseMessage';
9
- export const UPDATE_MISSED_CALLS_ENDPOINT = 'setReadState';
10
13
  export const SET_READ_STATE_SUCCESS_MESSAGE = 'Missed calls are read by the user.';
11
14
  export const SUCCESS_MESSAGE = 'SUCCESS';
12
15
  export const STATUS_CODE = 'statusCode';
13
16
  export const USER_SESSIONS = 'userSessions';
17
+ export const UPDATE_MISSED_CALLS_ENDPOINT = 'setReadState';
18
+ export const UNIFIED_COMMUNICATIONS = 'uc';
19
+ export const VERSION_1 = 'v1';
@@ -1,9 +1,9 @@
1
1
  import log from '../Logger';
2
2
  import SDKConnector from '../SDKConnector';
3
3
  import { serviceErrorCodeHandler } from '../common/Utils';
4
- import { FAILURE_MESSAGE, STATUS_CODE, SUCCESS_MESSAGE, UCM_CONNECTOR_FILE, VOICEMAIL, } from '../common/constants';
4
+ import { FAILURE_MESSAGE, STATUS_CODE, SUCCESS_MESSAGE, UCM_CONNECTOR_FILE, VOICEMAIL, WEBEX_API_CONFIG_INT_URL, WEBEX_API_CONFIG_PROD_URL, } from '../common/constants';
5
5
  import { HTTP_METHODS } from '../common/types';
6
- import { CF_ENDPOINT, ORG_ENDPOINT, PEOPLE_ENDPOINT, WEBEX_APIS_INT_URL, WEBEX_APIS_PROD_URL, } from './constants';
6
+ import { CF_ENDPOINT, ORG_ENDPOINT, PEOPLE_ENDPOINT } from './constants';
7
7
  export class UcmBackendConnector {
8
8
  sdkConnector;
9
9
  webex;
@@ -51,7 +51,9 @@ export class UcmBackendConnector {
51
51
  file: UCM_CONNECTOR_FILE,
52
52
  method: this.getCallForwardAlwaysSetting.name,
53
53
  };
54
- const webexApisUrl = this.useProdWebexApis ? WEBEX_APIS_PROD_URL : WEBEX_APIS_INT_URL;
54
+ const webexApisUrl = this.useProdWebexApis
55
+ ? WEBEX_API_CONFIG_PROD_URL
56
+ : WEBEX_API_CONFIG_INT_URL;
55
57
  try {
56
58
  if (directoryNumber) {
57
59
  const resp = await this.webex.request({
@@ -7,5 +7,3 @@ export const CF_ENDPOINT = 'features/callForwarding';
7
7
  export const VM_ENDPOINT = 'features/voicemail';
8
8
  export const CALL_WAITING_ENDPOINT = 'CallWaiting';
9
9
  export const XSI_VERSION = 'v2.0';
10
- export const WEBEX_APIS_INT_URL = 'https://integration.webexapis.com/v1/uc/config';
11
- export const WEBEX_APIS_PROD_URL = 'https://webexapis.com/v1/uc/config';
@@ -1,4 +1,4 @@
1
- import { Event, LocalStreamEventNames, RoapMediaConnection, } from '@webex/internal-media-core';
1
+ import { MediaConnectionEventNames, LocalStreamEventNames, RoapMediaConnection, } from '@webex/internal-media-core';
2
2
  import { createMachine, interpret } from 'xstate';
3
3
  import { v4 as uuid } from 'uuid';
4
4
  import { EffectEvent } from '@webex/web-media-effects';
@@ -6,7 +6,7 @@ import { ERROR_LAYER, ERROR_TYPE } from '../../Errors/types';
6
6
  import { handleCallErrors, parseMediaQualityStatistics } from '../../common/Utils';
7
7
  import { ALLOWED_SERVICES, CallDirection, HTTP_METHODS, } from '../../common/types';
8
8
  import { createCallError } from '../../Errors/catalog/CallError';
9
- import { CALL_ENDPOINT_RESOURCE, CALL_FILE, CALL_HOLD_SERVICE, CALL_STATUS_RESOURCE, CALL_TRANSFER_SERVICE, CALLING_USER_AGENT, CALLS_ENDPOINT_RESOURCE, CISCO_DEVICE_URL, DEFAULT_LOCAL_CALL_ID, DEFAULT_SESSION_TIMER, DEVICES_ENDPOINT_RESOURCE, HOLD_ENDPOINT, INITIAL_SEQ_NUMBER, MEDIA_ENDPOINT_RESOURCE, NOISE_REDUCTION_EFFECT, RESUME_ENDPOINT, SPARK_USER_AGENT, SUPPLEMENTARY_SERVICES_TIMEOUT, TRANSFER_ENDPOINT, } from '../constants';
9
+ import { CALL_ENDPOINT_RESOURCE, CALL_FILE, CALL_HOLD_SERVICE, CALL_STATUS_RESOURCE, CALL_TRANSFER_SERVICE, CALLING_USER_AGENT, CALLS_ENDPOINT_RESOURCE, CISCO_DEVICE_URL, DEFAULT_LOCAL_CALL_ID, DEFAULT_SESSION_TIMER, DEVICES_ENDPOINT_RESOURCE, HOLD_ENDPOINT, ICE_CANDIDATES_TIMEOUT, INITIAL_SEQ_NUMBER, MEDIA_ENDPOINT_RESOURCE, NOISE_REDUCTION_EFFECT, RESUME_ENDPOINT, SPARK_USER_AGENT, SUPPLEMENTARY_SERVICES_TIMEOUT, TRANSFER_ENDPOINT, } from '../constants';
10
10
  import SDKConnector from '../../SDKConnector';
11
11
  import { Eventing } from '../../Events/impl';
12
12
  import { CALL_EVENT_KEYS, MEDIA_CONNECTION_EVENT_KEYS, MOBIUS_MIDCALL_STATE, SUPPLEMENTARY_SERVICES, } from '../../Events/types';
@@ -1186,9 +1186,11 @@ export class Call extends Eventing {
1186
1186
  const mediaConnection = new RoapMediaConnection({
1187
1187
  skipInactiveTransceivers: true,
1188
1188
  iceServers: [],
1189
+ iceCandidatesTimeout: ICE_CANDIDATES_TIMEOUT,
1189
1190
  sdpMunging: {
1190
1191
  convertPort9to0: true,
1191
1192
  addContentSlides: false,
1193
+ copyClineToSessionLevel: true,
1192
1194
  },
1193
1195
  }, {
1194
1196
  localTracks: { audio: localAudioTrack },
@@ -1498,7 +1500,7 @@ export class Call extends Eventing {
1498
1500
  });
1499
1501
  }
1500
1502
  mediaRoapEventsListener() {
1501
- this.mediaConnection.on(Event.ROAP_MESSAGE_TO_SEND, async (event) => {
1503
+ this.mediaConnection.on(MediaConnectionEventNames.ROAP_MESSAGE_TO_SEND, async (event) => {
1502
1504
  log.info(`ROAP message to send (rcv from MEDIA-SDK) :
1503
1505
  \n type: ${event.roapMessage?.messageType}, seq: ${event.roapMessage.seq} , version: ${event.roapMessage.version}`, {});
1504
1506
  log.info(`SDP message to send : \n ${event.roapMessage?.sdp}`, {
@@ -1537,7 +1539,7 @@ export class Call extends Eventing {
1537
1539
  });
1538
1540
  }
1539
1541
  mediaTrackListener() {
1540
- this.mediaConnection.on(Event.REMOTE_TRACK_ADDED, (e) => {
1542
+ this.mediaConnection.on(MediaConnectionEventNames.REMOTE_TRACK_ADDED, (e) => {
1541
1543
  if (e.type === MEDIA_CONNECTION_EVENT_KEYS.MEDIA_TYPE_AUDIO) {
1542
1544
  this.emit(CALL_EVENT_KEYS.REMOTE_MEDIA, e.track);
1543
1545
  }
@@ -1,6 +1,7 @@
1
- export const VERSION = 'beta';
1
+ export const VERSION = 'unknown';
2
+ export const USER_AGENT_VERSION = 'beta';
2
3
  export const REPO_NAME = 'webex-calling';
3
- export const CALLING_USER_AGENT = `${REPO_NAME}/${VERSION}`;
4
+ export const CALLING_USER_AGENT = `${REPO_NAME}/${USER_AGENT_VERSION}`;
4
5
  export const CALL_ENDPOINT_RESOURCE = 'call';
5
6
  export const CALL_STATUS_RESOURCE = 'status';
6
7
  export const CALLS_ENDPOINT_RESOURCE = 'calls';
@@ -42,9 +43,7 @@ export const DUMMY_METRICS = {
42
43
  };
43
44
  export const DUMMY_MOBIUS_URL = 'https://mobius.aintgen-a-1.int.infra.webex.com/api/v1';
44
45
  export const FETCH_NAME = /^[a-zA-Z ]+/;
45
- export const IDENTITY_BROKER = 'https://identitybts.webex.com/';
46
46
  export const IP_ENDPOINT = 'myip';
47
- export const IDENTITY_ENDPOINT_RESOURCE = 'identity';
48
47
  export const INITIAL_SEQ_NUMBER = 1;
49
48
  export const MEDIA_ENDPOINT_RESOURCE = 'media';
50
49
  export const NETWORK_FLAP_TIMEOUT = 2000;
@@ -53,8 +52,6 @@ export const CALL_TRANSFER_SERVICE = 'calltransfer';
53
52
  export const HOLD_ENDPOINT = 'hold';
54
53
  export const TRANSFER_ENDPOINT = 'commit';
55
54
  export const RESUME_ENDPOINT = 'resume';
56
- export const SCIM_ENDPOINT_RESOURCE = 'scim';
57
- export const SCIM_USER_FILTER = 'v1/Users?filter=';
58
55
  export const SPARK_USER_AGENT = 'spark-user-agent';
59
56
  export const REGISTER_RETRY_TIMEOUT = 10000;
60
57
  export const SUPPLEMENTARY_SERVICES_TIMEOUT = 10000;
@@ -110,6 +107,7 @@ export const SEC_TO_MSEC_MFACTOR = 1000;
110
107
  export const MINUTES_TO_SEC_MFACTOR = 60;
111
108
  export const REG_RANDOM_T_FACTOR_UPPER_LIMIT = 10000;
112
109
  export const REG_TRY_BACKUP_TIMER_VAL_IN_SEC = 1200;
110
+ export const REG_TRY_BACKUP_TIMER_VAL_FOR_CC_IN_SEC = 114;
113
111
  export const REG_FAILBACK_429_MAX_RETRIES = 5;
114
112
  export const REGISTER_UTIL = 'registerDevice';
115
113
  export const GET_MOBIUS_SERVERS_UTIL = 'getMobiusServers';
@@ -125,3 +123,4 @@ export const MOBIUS_US_PROD = 'mobius-us-east-1.prod.infra.webex.com';
125
123
  export const MOBIUS_EU_PROD = 'mobius-eu-central-1.prod.infra.webex.com';
126
124
  export const MOBIUS_US_INT = 'mobius-us-east-1.int.infra.webex.com';
127
125
  export const MOBIUS_EU_INT = 'mobius-eu-central-1.int.infra.webex.com';
126
+ export const ICE_CANDIDATES_TIMEOUT = 3000;
@@ -6,8 +6,8 @@ import { getMetricManager } from '../../Metrics';
6
6
  import { getCallManager } from '../calling';
7
7
  import log from '../../Logger';
8
8
  import SDKConnector from '../../SDKConnector';
9
- import { ALLOWED_SERVICES, HTTP_METHODS, RegistrationStatus, } from '../../common/types';
10
- import { CALLING_USER_AGENT, CISCO_DEVICE_URL, DEVICES_ENDPOINT_RESOURCE, SPARK_USER_AGENT, WEBEX_WEB_CLIENT, BASE_REG_RETRY_TIMER_VAL_IN_SEC, BASE_REG_TIMER_MFACTOR, SEC_TO_MSEC_MFACTOR, REG_RANDOM_T_FACTOR_UPPER_LIMIT, REG_TRY_BACKUP_TIMER_VAL_IN_SEC, MINUTES_TO_SEC_MFACTOR, FAILBACK_429_RETRY_UTIL, REG_FAILBACK_429_MAX_RETRIES, FAILBACK_UTIL, REGISTRATION_FILE, DEFAULT_REHOMING_INTERVAL_MIN, DEFAULT_REHOMING_INTERVAL_MAX, DEFAULT_KEEPALIVE_INTERVAL, } from '../constants';
9
+ import { ALLOWED_SERVICES, HTTP_METHODS, RegistrationStatus, ServiceIndicator, } from '../../common/types';
10
+ import { CALLING_USER_AGENT, CISCO_DEVICE_URL, DEVICES_ENDPOINT_RESOURCE, SPARK_USER_AGENT, WEBEX_WEB_CLIENT, BASE_REG_RETRY_TIMER_VAL_IN_SEC, BASE_REG_TIMER_MFACTOR, SEC_TO_MSEC_MFACTOR, REG_RANDOM_T_FACTOR_UPPER_LIMIT, REG_TRY_BACKUP_TIMER_VAL_IN_SEC, MINUTES_TO_SEC_MFACTOR, FAILBACK_429_RETRY_UTIL, REG_FAILBACK_429_MAX_RETRIES, FAILBACK_UTIL, REGISTRATION_FILE, DEFAULT_REHOMING_INTERVAL_MIN, DEFAULT_REHOMING_INTERVAL_MAX, DEFAULT_KEEPALIVE_INTERVAL, REG_TRY_BACKUP_TIMER_VAL_FOR_CC_IN_SEC, } from '../constants';
11
11
  import { LINE_EVENTS } from '../line/types';
12
12
  export class Registration {
13
13
  sdkConnector;
@@ -30,9 +30,11 @@ export class Registration {
30
30
  backupMobiusUris;
31
31
  registerRetry = false;
32
32
  reconnectPending = false;
33
+ isCCFlow = false;
33
34
  constructor(webex, serviceData, mutex, lineEmitter, logLevel) {
34
35
  this.sdkConnector = SDKConnector;
35
36
  this.serviceData = serviceData;
37
+ this.isCCFlow = serviceData.indicator === ServiceIndicator.CONTACT_CENTER;
36
38
  if (!this.sdkConnector.getWebex()) {
37
39
  SDKConnector.setWebex(webex);
38
40
  }
@@ -147,8 +149,11 @@ export class Registration {
147
149
  method: this.startFailoverTimer.name,
148
150
  };
149
151
  let interval = this.getRegRetryInterval(attempt);
150
- if (timeElapsed + interval > REG_TRY_BACKUP_TIMER_VAL_IN_SEC) {
151
- const excessVal = timeElapsed + interval - REG_TRY_BACKUP_TIMER_VAL_IN_SEC;
152
+ const TIMER_THRESHOLD = this.isCCFlow
153
+ ? REG_TRY_BACKUP_TIMER_VAL_FOR_CC_IN_SEC
154
+ : REG_TRY_BACKUP_TIMER_VAL_IN_SEC;
155
+ if (timeElapsed + interval > TIMER_THRESHOLD) {
156
+ const excessVal = timeElapsed + interval - TIMER_THRESHOLD;
152
157
  interval -= excessVal;
153
158
  }
154
159
  let abort;
@@ -409,13 +414,14 @@ export class Registration {
409
414
  startKeepaliveTimer(url, interval) {
410
415
  let keepAliveRetryCount = 0;
411
416
  this.clearKeepaliveTimer();
417
+ const RETRY_COUNT_THRESHOLD = this.isCCFlow ? 4 : 5;
412
418
  this.keepaliveTimer = setInterval(async () => {
413
419
  const logContext = {
414
420
  file: REGISTRATION_FILE,
415
421
  method: this.startKeepaliveTimer.name,
416
422
  };
417
423
  await this.mutex.runExclusive(async () => {
418
- if (this.isDeviceRegistered() && keepAliveRetryCount < 5) {
424
+ if (this.isDeviceRegistered() && keepAliveRetryCount < RETRY_COUNT_THRESHOLD) {
419
425
  try {
420
426
  const res = await this.postKeepAlive(url);
421
427
  log.info(`Sent Keepalive, status: ${res.statusCode}`, logContext);
@@ -434,7 +440,7 @@ export class Registration {
434
440
  }
435
441
  this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.KEEPALIVE_FAILURE, METRIC_TYPE.BEHAVIORAL, clientError);
436
442
  }, { method: this.startKeepaliveTimer.name, file: REGISTRATION_FILE });
437
- if (abort || keepAliveRetryCount >= 5) {
443
+ if (abort || keepAliveRetryCount >= RETRY_COUNT_THRESHOLD) {
438
444
  this.setStatus(RegistrationStatus.INACTIVE);
439
445
  this.clearKeepaliveTimer();
440
446
  this.clearFailbackTimer();
@@ -1,10 +1,10 @@
1
- import { FAILURE_MESSAGE, STATUS_CODE, SUCCESS_MESSAGE } from '../common/constants';
1
+ import { FAILURE_MESSAGE, SCIM_ENTERPRISE_USER, SCIM_WEBEXIDENTITY_USER, STATUS_CODE, SUCCESS_MESSAGE, } from '../common/constants';
2
2
  import { HTTP_METHODS } from '../common/types';
3
3
  import SDKConnector from '../SDKConnector';
4
4
  import log from '../Logger';
5
- import { CONTACTS_FILE, CONTACTS_SCHEMA, CONTACT_FILTER, DEFAULT_GROUP_NAME, ENCRYPT_FILTER, GROUP_FILTER, USERS, encryptedFields, } from './constants';
5
+ import { CONTACTS_FILE, CONTACTS_SCHEMA, CONTACT_FILTER, DEFAULT_GROUP_NAME, ENCRYPT_FILTER, GROUP_FILTER, OR, SCIM_ID_FILTER, USERS, encryptedFields, } from './constants';
6
6
  import { ContactType, GroupType, } from './types';
7
- import { serviceErrorCodeHandler } from '../common/Utils';
7
+ import { scimQuery, serviceErrorCodeHandler } from '../common/Utils';
8
8
  export class ContactsClient {
9
9
  sdkConnector;
10
10
  encryptionKeyUrl;
@@ -128,51 +128,62 @@ export class ContactsClient {
128
128
  });
129
129
  return decryptedContact;
130
130
  }
131
- async fetchContactFromDSS(contactsDataMap) {
132
- const contactList = [];
133
- const dssResult = await this.webex.internal.dss.lookup({ ids: Object.keys(contactsDataMap) });
134
- for (let i = 0; i < dssResult.length; i += 1) {
135
- const contact = dssResult[i];
136
- const contactId = contact.identity;
137
- const { displayName, emails, phoneNumbers, sipAddresses, photos } = contact;
138
- const { department, firstName, identityManager, jobTitle, lastName } = contact.additionalInfo;
139
- const manager = identityManager && identityManager.displayName ? identityManager.displayName : undefined;
140
- const { contactType, avatarUrlDomain, encryptionKeyUrl, ownerId, groups } = contactsDataMap[contactId];
141
- let avatarURL = '';
142
- if (photos.length) {
143
- avatarURL = photos[0].value;
144
- }
145
- const addedPhoneNumbers = contactsDataMap[contactId].phoneNumbers;
146
- if (addedPhoneNumbers) {
147
- const decryptedPhoneNumbers = await this.decryptContactDetail(encryptionKeyUrl, addedPhoneNumbers);
148
- decryptedPhoneNumbers.forEach((number) => phoneNumbers.push(number));
149
- }
150
- const addedSipAddresses = contactsDataMap[contactId].sipAddresses;
151
- if (addedSipAddresses) {
152
- const decryptedSipAddresses = await this.decryptContactDetail(encryptionKeyUrl, addedSipAddresses);
153
- decryptedSipAddresses.forEach((address) => sipAddresses.push(address));
131
+ resolveCloudContacts(contactsDataMap, inputList) {
132
+ const loggerContext = {
133
+ file: CONTACTS_FILE,
134
+ method: 'resolveCloudContacts',
135
+ };
136
+ const finalContactList = [];
137
+ const resolvedList = [];
138
+ try {
139
+ inputList.Resources.forEach((item) => {
140
+ resolvedList.push(item.id);
141
+ });
142
+ Object.values(contactsDataMap).forEach((item) => {
143
+ const isResolved = resolvedList.some((listItem) => listItem === item.contactId);
144
+ if (!isResolved) {
145
+ finalContactList.push({ ...item, resolved: false });
146
+ }
147
+ });
148
+ for (let n = 0; n < inputList.Resources.length; n += 1) {
149
+ const filteredContact = inputList.Resources[n];
150
+ const { displayName, emails, phoneNumbers, photos } = filteredContact;
151
+ let sipAddresses;
152
+ if (filteredContact[SCIM_WEBEXIDENTITY_USER]) {
153
+ sipAddresses = filteredContact[SCIM_WEBEXIDENTITY_USER].sipAddresses;
154
+ }
155
+ const firstName = filteredContact.name?.givenName;
156
+ const lastName = filteredContact.name?.familyName;
157
+ const manager = filteredContact[SCIM_ENTERPRISE_USER]?.manager?.displayName;
158
+ const department = filteredContact[SCIM_ENTERPRISE_USER]?.department;
159
+ const avatarURL = photos?.length ? photos[0].value : '';
160
+ const { contactType, avatarUrlDomain, encryptionKeyUrl, ownerId, groups } = contactsDataMap[inputList.Resources[n].id];
161
+ const cloudContact = {
162
+ avatarUrlDomain,
163
+ avatarURL,
164
+ contactId: inputList.Resources[n].id,
165
+ contactType,
166
+ department,
167
+ displayName,
168
+ emails,
169
+ encryptionKeyUrl,
170
+ firstName,
171
+ groups,
172
+ lastName,
173
+ manager,
174
+ ownerId,
175
+ phoneNumbers,
176
+ sipAddresses,
177
+ resolved: true,
178
+ };
179
+ finalContactList.push(cloudContact);
154
180
  }
155
- const cloudContact = {
156
- avatarUrlDomain,
157
- avatarURL,
158
- contactId,
159
- contactType,
160
- department,
161
- displayName,
162
- emails,
163
- encryptionKeyUrl,
164
- firstName,
165
- groups,
166
- lastName,
167
- manager,
168
- ownerId,
169
- phoneNumbers,
170
- sipAddresses,
171
- title: jobTitle,
172
- };
173
- contactList.push(cloudContact);
174
181
  }
175
- return contactList;
182
+ catch (error) {
183
+ log.warn('Error occurred while parsing resolved contacts', loggerContext);
184
+ return null;
185
+ }
186
+ return finalContactList;
176
187
  }
177
188
  async getContacts() {
178
189
  const loggerContext = {
@@ -180,7 +191,7 @@ export class ContactsClient {
180
191
  method: 'getContacts',
181
192
  };
182
193
  const contactList = [];
183
- const contactsDataMap = {};
194
+ const cloudContactsMap = {};
184
195
  try {
185
196
  const response = await this.webex.request({
186
197
  uri: `${this.webex.internal.services._serviceUrls.contactsService}/${ENCRYPT_FILTER}/${USERS}/${CONTACT_FILTER}`,
@@ -191,19 +202,23 @@ export class ContactsClient {
191
202
  throw new Error(`${response}`);
192
203
  }
193
204
  const { contacts, groups } = responseBody;
194
- for (let i = 0; i < contacts.length; i += 1) {
195
- const contact = contacts[i];
205
+ contacts.map(async (contact) => {
196
206
  if (contact.contactType === ContactType.CUSTOM) {
197
207
  const decryptedContact = await this.decryptContact(contact);
198
208
  contactList.push(decryptedContact);
199
209
  }
200
210
  else if (contact.contactType === ContactType.CLOUD && contact.contactId) {
201
- contactsDataMap[contact.contactId] = contact;
211
+ cloudContactsMap[contact.contactId] = contact;
212
+ }
213
+ });
214
+ if (Object.keys(cloudContactsMap).length) {
215
+ const contactIdList = Object.keys(cloudContactsMap);
216
+ const query = contactIdList.map((item) => `${SCIM_ID_FILTER} "${item}"`).join(OR);
217
+ const result = await scimQuery(query);
218
+ const resolvedContacts = this.resolveCloudContacts(cloudContactsMap, result.body);
219
+ if (resolvedContacts) {
220
+ resolvedContacts.map((item) => contactList.push(item));
202
221
  }
203
- }
204
- if (Object.keys(contactsDataMap).length) {
205
- const cloudContacts = await this.fetchContactFromDSS(contactsDataMap);
206
- contactList.push(...cloudContacts);
207
222
  }
208
223
  await Promise.all(groups.map(async (group, idx) => {
209
224
  groups[idx].displayName = await this.webex.internal.encryption.decryptText(group.encryptionKeyUrl, group.displayName);
@@ -430,10 +445,12 @@ export class ContactsClient {
430
445
  },
431
446
  message: SUCCESS_MESSAGE,
432
447
  };
433
- if (contact.contactType === ContactType.CLOUD) {
434
- const decryptedContacts = await this.fetchContactFromDSS(Object.fromEntries([[newContact.contactId, newContact]]));
435
- if (decryptedContacts.length && decryptedContacts[0]) {
436
- this.contacts?.push(decryptedContacts[0]);
448
+ if (contact.contactType === ContactType.CLOUD && newContact.contactId) {
449
+ const query = `${SCIM_ID_FILTER} "${newContact.contactId}"`;
450
+ const res = await scimQuery(query);
451
+ const resolvedContact = this.resolveCloudContacts(Object.fromEntries([[newContact.contactId, newContact]]), res.body);
452
+ if (resolvedContact) {
453
+ this.contacts?.push(resolvedContact[0]);
437
454
  }
438
455
  }
439
456
  else {
@@ -5,6 +5,8 @@ export const ENCRYPT_FILTER = 'encrypt';
5
5
  export const USERS = 'Users';
6
6
  export const DEFAULT_GROUP_NAME = 'Other contacts';
7
7
  export const CONTACTS_SCHEMA = 'urn:cisco:codev:identity:contact:core:1.0';
8
+ export const SCIM_ID_FILTER = 'id eq';
9
+ export const OR = ' or ';
8
10
  export var encryptedFields;
9
11
  (function (encryptedFields) {
10
12
  encryptedFields["ADDRESS_INFO"] = "addressInfo";