@webex/calling 0.0.1-next.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 (179) hide show
  1. package/README.md +67 -0
  2. package/dist/module/CallHistory/CallHistory.js +84 -0
  3. package/dist/module/CallHistory/callHistoryFixtures.js +307 -0
  4. package/dist/module/CallHistory/constants.js +9 -0
  5. package/dist/module/CallHistory/types.js +1 -0
  6. package/dist/module/CallSettings/CallSettings.js +65 -0
  7. package/dist/module/CallSettings/UcmBackendConnector.js +100 -0
  8. package/dist/module/CallSettings/WxCallBackendConnector.js +287 -0
  9. package/dist/module/CallSettings/constants.js +11 -0
  10. package/dist/module/CallSettings/testFixtures.js +62 -0
  11. package/dist/module/CallSettings/types.js +1 -0
  12. package/dist/module/CallingClient/CallingClient.js +268 -0
  13. package/dist/module/CallingClient/callRecordFixtures.js +93 -0
  14. package/dist/module/CallingClient/calling/CallerId/index.js +169 -0
  15. package/dist/module/CallingClient/calling/CallerId/types.js +1 -0
  16. package/dist/module/CallingClient/calling/call.js +1649 -0
  17. package/dist/module/CallingClient/calling/callManager.js +274 -0
  18. package/dist/module/CallingClient/calling/index.js +2 -0
  19. package/dist/module/CallingClient/calling/types.js +53 -0
  20. package/dist/module/CallingClient/callingClientFixtures.js +38 -0
  21. package/dist/module/CallingClient/constants.js +122 -0
  22. package/dist/module/CallingClient/line/index.js +110 -0
  23. package/dist/module/CallingClient/line/types.js +14 -0
  24. package/dist/module/CallingClient/registration/index.js +1 -0
  25. package/dist/module/CallingClient/registration/register.js +507 -0
  26. package/dist/module/CallingClient/registration/registerFixtures.js +28 -0
  27. package/dist/module/CallingClient/registration/types.js +1 -0
  28. package/dist/module/CallingClient/types.js +1 -0
  29. package/dist/module/Contacts/ContactsClient.js +487 -0
  30. package/dist/module/Contacts/constants.js +20 -0
  31. package/dist/module/Contacts/contactFixtures.js +284 -0
  32. package/dist/module/Contacts/types.js +10 -0
  33. package/dist/module/Errors/catalog/CallError.js +26 -0
  34. package/dist/module/Errors/catalog/CallingDeviceError.js +18 -0
  35. package/dist/module/Errors/catalog/ExtendedError.js +10 -0
  36. package/dist/module/Errors/catalog/LineError.js +24 -0
  37. package/dist/module/Errors/index.js +2 -0
  38. package/dist/module/Errors/types.js +48 -0
  39. package/dist/module/Events/impl/index.js +19 -0
  40. package/dist/module/Events/types.js +74 -0
  41. package/dist/module/Logger/index.js +114 -0
  42. package/dist/module/Logger/types.js +25 -0
  43. package/dist/module/Metrics/index.js +232 -0
  44. package/dist/module/Metrics/types.js +37 -0
  45. package/dist/module/SDKConnector/index.js +39 -0
  46. package/dist/module/SDKConnector/types.js +1 -0
  47. package/dist/module/SDKConnector/utils.js +12 -0
  48. package/dist/module/Voicemail/BroadworksBackendConnector.js +289 -0
  49. package/dist/module/Voicemail/UcmBackendConnector.js +275 -0
  50. package/dist/module/Voicemail/Voicemail.js +110 -0
  51. package/dist/module/Voicemail/WxCallBackendConnector.js +279 -0
  52. package/dist/module/Voicemail/constants.js +29 -0
  53. package/dist/module/Voicemail/types.js +1 -0
  54. package/dist/module/Voicemail/voicemailFixture.js +449 -0
  55. package/dist/module/common/Utils.js +802 -0
  56. package/dist/module/common/constants.js +40 -0
  57. package/dist/module/common/index.js +1 -0
  58. package/dist/module/common/testUtil.js +938 -0
  59. package/dist/module/common/types.js +57 -0
  60. package/dist/module/index.js +8 -0
  61. package/dist/types/CallHistory/CallHistory.d.ts +19 -0
  62. package/dist/types/CallHistory/CallHistory.d.ts.map +1 -0
  63. package/dist/types/CallHistory/callHistoryFixtures.d.ts +95 -0
  64. package/dist/types/CallHistory/callHistoryFixtures.d.ts.map +1 -0
  65. package/dist/types/CallHistory/constants.d.ts +10 -0
  66. package/dist/types/CallHistory/constants.d.ts.map +1 -0
  67. package/dist/types/CallHistory/types.d.ts +21 -0
  68. package/dist/types/CallHistory/types.d.ts.map +1 -0
  69. package/dist/types/CallSettings/CallSettings.d.ts +20 -0
  70. package/dist/types/CallSettings/CallSettings.d.ts.map +1 -0
  71. package/dist/types/CallSettings/UcmBackendConnector.d.ts +20 -0
  72. package/dist/types/CallSettings/UcmBackendConnector.d.ts.map +1 -0
  73. package/dist/types/CallSettings/WxCallBackendConnector.d.ts +22 -0
  74. package/dist/types/CallSettings/WxCallBackendConnector.d.ts.map +1 -0
  75. package/dist/types/CallSettings/constants.d.ts +12 -0
  76. package/dist/types/CallSettings/constants.d.ts.map +1 -0
  77. package/dist/types/CallSettings/testFixtures.d.ts +16 -0
  78. package/dist/types/CallSettings/testFixtures.d.ts.map +1 -0
  79. package/dist/types/CallSettings/types.d.ts +108 -0
  80. package/dist/types/CallSettings/types.d.ts.map +1 -0
  81. package/dist/types/CallingClient/CallingClient.d.ts +38 -0
  82. package/dist/types/CallingClient/CallingClient.d.ts.map +1 -0
  83. package/dist/types/CallingClient/callRecordFixtures.d.ts +4 -0
  84. package/dist/types/CallingClient/callRecordFixtures.d.ts.map +1 -0
  85. package/dist/types/CallingClient/calling/CallerId/index.d.ts +18 -0
  86. package/dist/types/CallingClient/calling/CallerId/index.d.ts.map +1 -0
  87. package/dist/types/CallingClient/calling/CallerId/types.d.ts +42 -0
  88. package/dist/types/CallingClient/calling/CallerId/types.d.ts.map +1 -0
  89. package/dist/types/CallingClient/calling/call.d.ts +95 -0
  90. package/dist/types/CallingClient/calling/call.d.ts.map +1 -0
  91. package/dist/types/CallingClient/calling/callManager.d.ts +22 -0
  92. package/dist/types/CallingClient/calling/callManager.d.ts.map +1 -0
  93. package/dist/types/CallingClient/calling/index.d.ts +3 -0
  94. package/dist/types/CallingClient/calling/index.d.ts.map +1 -0
  95. package/dist/types/CallingClient/calling/types.d.ts +204 -0
  96. package/dist/types/CallingClient/calling/types.d.ts.map +1 -0
  97. package/dist/types/CallingClient/callingClientFixtures.d.ts +19 -0
  98. package/dist/types/CallingClient/callingClientFixtures.d.ts.map +1 -0
  99. package/dist/types/CallingClient/constants.d.ts +123 -0
  100. package/dist/types/CallingClient/constants.d.ts.map +1 -0
  101. package/dist/types/CallingClient/line/index.d.ts +39 -0
  102. package/dist/types/CallingClient/line/index.d.ts.map +1 -0
  103. package/dist/types/CallingClient/line/types.d.ts +51 -0
  104. package/dist/types/CallingClient/line/types.d.ts.map +1 -0
  105. package/dist/types/CallingClient/registration/index.d.ts +2 -0
  106. package/dist/types/CallingClient/registration/index.d.ts.map +1 -0
  107. package/dist/types/CallingClient/registration/register.d.ts +65 -0
  108. package/dist/types/CallingClient/registration/register.d.ts.map +1 -0
  109. package/dist/types/CallingClient/registration/registerFixtures.d.ts +29 -0
  110. package/dist/types/CallingClient/registration/registerFixtures.d.ts.map +1 -0
  111. package/dist/types/CallingClient/registration/types.d.ts +21 -0
  112. package/dist/types/CallingClient/registration/types.d.ts.map +1 -0
  113. package/dist/types/CallingClient/types.d.ts +30 -0
  114. package/dist/types/CallingClient/types.d.ts.map +1 -0
  115. package/dist/types/Contacts/ContactsClient.d.ts +28 -0
  116. package/dist/types/Contacts/ContactsClient.d.ts.map +1 -0
  117. package/dist/types/Contacts/constants.d.ts +20 -0
  118. package/dist/types/Contacts/constants.d.ts.map +1 -0
  119. package/dist/types/Contacts/contactFixtures.d.ts +281 -0
  120. package/dist/types/Contacts/contactFixtures.d.ts.map +1 -0
  121. package/dist/types/Contacts/types.d.ts +75 -0
  122. package/dist/types/Contacts/types.d.ts.map +1 -0
  123. package/dist/types/Errors/catalog/CallError.d.ts +12 -0
  124. package/dist/types/Errors/catalog/CallError.d.ts.map +1 -0
  125. package/dist/types/Errors/catalog/CallingDeviceError.d.ts +11 -0
  126. package/dist/types/Errors/catalog/CallingDeviceError.d.ts.map +1 -0
  127. package/dist/types/Errors/catalog/ExtendedError.d.ts +7 -0
  128. package/dist/types/Errors/catalog/ExtendedError.d.ts.map +1 -0
  129. package/dist/types/Errors/catalog/LineError.d.ts +11 -0
  130. package/dist/types/Errors/catalog/LineError.d.ts.map +1 -0
  131. package/dist/types/Errors/index.d.ts +3 -0
  132. package/dist/types/Errors/index.d.ts.map +1 -0
  133. package/dist/types/Errors/types.d.ts +61 -0
  134. package/dist/types/Errors/types.d.ts.map +1 -0
  135. package/dist/types/Events/impl/index.d.ts +9 -0
  136. package/dist/types/Events/impl/index.d.ts.map +1 -0
  137. package/dist/types/Events/types.d.ts +284 -0
  138. package/dist/types/Events/types.d.ts.map +1 -0
  139. package/dist/types/Logger/index.d.ts +13 -0
  140. package/dist/types/Logger/index.d.ts.map +1 -0
  141. package/dist/types/Logger/types.d.ts +26 -0
  142. package/dist/types/Logger/types.d.ts.map +1 -0
  143. package/dist/types/Metrics/index.d.ts +6 -0
  144. package/dist/types/Metrics/index.d.ts.map +1 -0
  145. package/dist/types/Metrics/types.d.ts +43 -0
  146. package/dist/types/Metrics/types.d.ts.map +1 -0
  147. package/dist/types/SDKConnector/index.d.ts +13 -0
  148. package/dist/types/SDKConnector/index.d.ts.map +1 -0
  149. package/dist/types/SDKConnector/types.d.ts +129 -0
  150. package/dist/types/SDKConnector/types.d.ts.map +1 -0
  151. package/dist/types/SDKConnector/utils.d.ts +6 -0
  152. package/dist/types/SDKConnector/utils.d.ts.map +1 -0
  153. package/dist/types/Voicemail/BroadworksBackendConnector.d.ts +28 -0
  154. package/dist/types/Voicemail/BroadworksBackendConnector.d.ts.map +1 -0
  155. package/dist/types/Voicemail/UcmBackendConnector.d.ts +35 -0
  156. package/dist/types/Voicemail/UcmBackendConnector.d.ts.map +1 -0
  157. package/dist/types/Voicemail/Voicemail.d.ts +28 -0
  158. package/dist/types/Voicemail/Voicemail.d.ts.map +1 -0
  159. package/dist/types/Voicemail/WxCallBackendConnector.d.ts +24 -0
  160. package/dist/types/Voicemail/WxCallBackendConnector.d.ts.map +1 -0
  161. package/dist/types/Voicemail/constants.d.ts +30 -0
  162. package/dist/types/Voicemail/constants.d.ts.map +1 -0
  163. package/dist/types/Voicemail/types.d.ts +134 -0
  164. package/dist/types/Voicemail/types.d.ts.map +1 -0
  165. package/dist/types/Voicemail/voicemailFixture.d.ts +350 -0
  166. package/dist/types/Voicemail/voicemailFixture.d.ts.map +1 -0
  167. package/dist/types/common/Utils.d.ts +35 -0
  168. package/dist/types/common/Utils.d.ts.map +1 -0
  169. package/dist/types/common/constants.d.ts +41 -0
  170. package/dist/types/common/constants.d.ts.map +1 -0
  171. package/dist/types/common/index.d.ts +2 -0
  172. package/dist/types/common/index.d.ts.map +1 -0
  173. package/dist/types/common/testUtil.d.ts +3612 -0
  174. package/dist/types/common/testUtil.d.ts.map +1 -0
  175. package/dist/types/common/types.d.ts +192 -0
  176. package/dist/types/common/types.d.ts.map +1 -0
  177. package/dist/types/index.d.ts +9 -0
  178. package/dist/types/index.d.ts.map +1 -0
  179. package/package.json +161 -0
@@ -0,0 +1,802 @@
1
+ import * as platform from 'platform';
2
+ import { createCallError } from '../Errors/catalog/CallError';
3
+ import { DEVICE_ERROR_CODE, ERROR_CODE, ERROR_TYPE, CALL_ERROR_CODE, } from '../Errors/types';
4
+ import { ALLOWED_SERVICES, CALLING_BACKEND, HTTP_METHODS, MobiusStatus, SORT, ServiceIndicator, } from './types';
5
+ import log from '../Logger';
6
+ import { createClientError } from '../Errors/catalog/CallingDeviceError';
7
+ import { BYTES_RECEIVED, BYTES_SENT, CALLING_USER_AGENT, CISCO_DEVICE_URL, CODEC_ID, DUMMY_METRICS, IDENTITY_ENDPOINT_RESOURCE, INBOUND_CODEC_MATCH, INBOUND_RTP, JITTER_BUFFER_DELAY, JITTER_BUFFER_EMITTED_COUNT, LOCAL_CANDIDATE_ID, MEDIA_ID, MEDIA_SOURCE, MIME_TYPE, NETWORK_TYPE, OUTBOUND_CODEC_MATCH, OUTBOUND_RTP, PACKETS_DISCARDED, PACKETS_LOST, PACKETS_RECEIVED, PACKETS_SENT, REMOTE_INBOUND_RTP, ROUND_TRIP_TIME_MEASUREMENTS, RTC_CODEC, RTC_ICE_CANDIDATE, RTC_ICE_CANDIDATE_PAIR, RTP_RX_STAT, RTP_TX_STAT, SCIM_ENDPOINT_RESOURCE, SCIM_USER_FILTER, SELECTED_CANDIDATE_PAIR_ID, SPARK_USER_AGENT, TARGET_BIT_RATE, TIMESTAMP, TOTAL_ROUND_TRIP_TIME, TOTAL_SAMPLES_DURATION, TRANSPORT, TYPE, URL_ENDPOINT, UTILS_FILE, } from '../CallingClient/constants';
8
+ import { DEVICES, ITEMS, SETTINGS, VALUES, KEY, TIME, PLACEHOLDER_KEY, XSI_ACTION_ENDPOINT_ORG_URL_PARAM, XSI_ACTION_ENDPOINT, INFER_ID_CONSTANT, BW_XSI_URL, ENTITLEMENT_BASIC, ENTITLEMENT_BROADWORKS_CONN, ENTITLEMENT_STANDARD, NATIVE_WEBEX_TEAMS_CALLING, NATIVE_SIP_CALL_TO_UCM, BW_XSI_ENDPOINT_VERSION, } from './constants';
9
+ import SDKConnector from '../SDKConnector';
10
+ import { LineStatus } from '../CallingClient/line/types';
11
+ import { createLineError } from '../Errors/catalog/LineError';
12
+ export function filterMobiusUris(mobiusServers, defaultMobiusUrl) {
13
+ const logContext = {
14
+ file: UTILS_FILE,
15
+ method: filterMobiusUris.name,
16
+ };
17
+ const urisArrayPrimary = [];
18
+ const urisArrayBackup = [];
19
+ if (mobiusServers?.primary?.uris) {
20
+ log.info('Adding Primary uris', logContext);
21
+ for (const uri of mobiusServers.primary.uris) {
22
+ urisArrayPrimary.push(`${uri}${URL_ENDPOINT}`);
23
+ }
24
+ }
25
+ if (mobiusServers?.backup?.uris) {
26
+ log.info('Adding Backup uris', logContext);
27
+ for (const uri of mobiusServers.backup.uris) {
28
+ urisArrayBackup.push(`${uri}${URL_ENDPOINT}`);
29
+ }
30
+ }
31
+ log.info('Adding Default uri', logContext);
32
+ if (!urisArrayPrimary.length && !urisArrayBackup.length) {
33
+ urisArrayPrimary.push(`${defaultMobiusUrl}${URL_ENDPOINT}`);
34
+ }
35
+ else {
36
+ urisArrayBackup.push(`${defaultMobiusUrl}${URL_ENDPOINT}`);
37
+ }
38
+ const primaryUris = [];
39
+ const backupUris = [];
40
+ for (let i = 0; i < urisArrayPrimary.length; i += 1) {
41
+ if (primaryUris.indexOf(urisArrayPrimary[i]) === -1) {
42
+ primaryUris.push(urisArrayPrimary[i]);
43
+ }
44
+ }
45
+ for (let i = 0; i < urisArrayBackup.length; i += 1) {
46
+ if (backupUris.indexOf(urisArrayBackup[i]) === -1) {
47
+ backupUris.push(urisArrayBackup[i]);
48
+ }
49
+ }
50
+ return { primary: primaryUris, backup: backupUris };
51
+ }
52
+ function updateCallErrorContext(errContext, type, message, correlationId, callError) {
53
+ const errObj = {};
54
+ errObj.context = errContext;
55
+ errObj.type = type;
56
+ errObj.message = message;
57
+ errObj.correlationId = correlationId;
58
+ callError.setCallError(errObj);
59
+ }
60
+ function updateLineErrorContext(errContext, type, message, status, lineError) {
61
+ const errObj = {};
62
+ errObj.context = errContext;
63
+ errObj.type = type;
64
+ errObj.message = message;
65
+ errObj.status = status;
66
+ lineError.setError(errObj);
67
+ }
68
+ function updateErrorContext(errContext, type, message, clientError) {
69
+ const errObj = {};
70
+ errObj.context = errContext;
71
+ errObj.type = type;
72
+ errObj.message = message;
73
+ clientError.setError(errObj);
74
+ }
75
+ export function emitFinalFailure(emitterCb, loggerContext) {
76
+ const clientError = createLineError('', {}, ERROR_TYPE.DEFAULT, LineStatus.INACTIVE);
77
+ updateLineErrorContext(loggerContext, ERROR_TYPE.SERVICE_UNAVAILABLE, 'An unknown error occurred. Wait a moment and try again. Please contact the administrator if the problem persists.', LineStatus.INACTIVE, clientError);
78
+ emitterCb(clientError);
79
+ }
80
+ export async function handleRegistrationErrors(err, emitterCb, loggerContext, restoreRegCb) {
81
+ const lineError = createLineError('', {}, ERROR_TYPE.DEFAULT, LineStatus.INACTIVE);
82
+ const errorCode = err.statusCode;
83
+ let finalError = false;
84
+ log.warn(`Status code: -> ${errorCode}`, loggerContext);
85
+ switch (errorCode) {
86
+ case ERROR_CODE.UNAUTHORIZED: {
87
+ finalError = true;
88
+ log.warn(`401 Unauthorized`, loggerContext);
89
+ updateLineErrorContext(loggerContext, ERROR_TYPE.TOKEN_ERROR, 'User is unauthorized due to an expired token. Sign out, then sign back in.', LineStatus.INACTIVE, lineError);
90
+ emitterCb(lineError, finalError);
91
+ break;
92
+ }
93
+ case ERROR_CODE.INTERNAL_SERVER_ERROR: {
94
+ log.warn(`500 Internal Server Error`, loggerContext);
95
+ updateLineErrorContext(loggerContext, ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred while placing the request. Wait a moment and try again.', LineStatus.INACTIVE, lineError);
96
+ emitterCb(lineError, finalError);
97
+ break;
98
+ }
99
+ case ERROR_CODE.SERVICE_UNAVAILABLE: {
100
+ log.warn(`503 Service Unavailable`, loggerContext);
101
+ updateLineErrorContext(loggerContext, ERROR_TYPE.SERVICE_UNAVAILABLE, 'An error occurred on the server while processing the request. Wait a moment and try again.', LineStatus.INACTIVE, lineError);
102
+ emitterCb(lineError, finalError);
103
+ break;
104
+ }
105
+ case ERROR_CODE.FORBIDDEN: {
106
+ log.warn(`403 Forbidden`, loggerContext);
107
+ const errorBody = err.body;
108
+ if (!errorBody) {
109
+ log.warn('Error response has no body, throwing default error', loggerContext);
110
+ updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, 'An unauthorized action has been received. This action has been blocked. Please contact the administrator if this persists.', LineStatus.INACTIVE, lineError);
111
+ emitterCb(lineError, finalError);
112
+ return finalError;
113
+ }
114
+ const code = errorBody.errorCode;
115
+ log.warn(`Error code found : ${code}`, loggerContext);
116
+ switch (code) {
117
+ case DEVICE_ERROR_CODE.DEVICE_LIMIT_EXCEEDED: {
118
+ const errorMessage = 'User device limit exceeded';
119
+ log.warn(errorMessage, loggerContext);
120
+ if (restoreRegCb) {
121
+ const caller = loggerContext.method || 'handleErrors';
122
+ await restoreRegCb(errorBody, caller);
123
+ }
124
+ break;
125
+ }
126
+ case DEVICE_ERROR_CODE.DEVICE_CREATION_DISABLED: {
127
+ const errorMessage = 'User is not configured for WebRTC calling. Please contact the administrator to resolve this issue.';
128
+ finalError = true;
129
+ updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, errorMessage, LineStatus.INACTIVE, lineError);
130
+ log.warn(errorMessage, loggerContext);
131
+ emitterCb(lineError, true);
132
+ break;
133
+ }
134
+ case DEVICE_ERROR_CODE.DEVICE_CREATION_FAILED: {
135
+ const errorMessage = 'An unknown error occurred while provisioning the device. Wait a moment and try again.';
136
+ updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, errorMessage, LineStatus.INACTIVE, lineError);
137
+ log.warn(errorMessage, loggerContext);
138
+ emitterCb(lineError, finalError);
139
+ break;
140
+ }
141
+ default: {
142
+ const errorMessage = 'An unknown error occurred. Wait a moment and try again. Please contact the administrator if the problem persists.';
143
+ updateLineErrorContext(loggerContext, ERROR_TYPE.FORBIDDEN_ERROR, errorMessage, LineStatus.INACTIVE, lineError);
144
+ log.warn(errorMessage, loggerContext);
145
+ emitterCb(lineError, finalError);
146
+ }
147
+ }
148
+ break;
149
+ }
150
+ case ERROR_CODE.DEVICE_NOT_FOUND: {
151
+ finalError = true;
152
+ log.warn(`404 Device Not Found`, loggerContext);
153
+ updateLineErrorContext(loggerContext, ERROR_TYPE.NOT_FOUND, 'The client has unregistered. Please wait for the client to register before attempting the call. If error persists, sign out, sign back in and attempt the call.', LineStatus.INACTIVE, lineError);
154
+ emitterCb(lineError, finalError);
155
+ break;
156
+ }
157
+ default: {
158
+ updateLineErrorContext(loggerContext, ERROR_TYPE.DEFAULT, 'Unknown error', LineStatus.INACTIVE, lineError);
159
+ log.warn(`Unknown Error`, loggerContext);
160
+ emitterCb(lineError, finalError);
161
+ }
162
+ }
163
+ return finalError;
164
+ }
165
+ export async function handleCallingClientErrors(err, emitterCb, loggerContext) {
166
+ const clientError = createClientError('', {}, ERROR_TYPE.DEFAULT, MobiusStatus.DEFAULT);
167
+ const errorCode = err.statusCode;
168
+ const finalError = false;
169
+ log.warn(`Status code: -> ${errorCode}`, loggerContext);
170
+ switch (errorCode) {
171
+ case ERROR_CODE.INTERNAL_SERVER_ERROR: {
172
+ log.warn(`500 Internal Server Error`, loggerContext);
173
+ updateErrorContext(loggerContext, ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred while placing the request. Wait a moment and try again.', clientError);
174
+ emitterCb(clientError, finalError);
175
+ break;
176
+ }
177
+ default: {
178
+ updateErrorContext(loggerContext, ERROR_TYPE.DEFAULT, 'Unknown error', clientError);
179
+ log.warn(`Unknown Error`, loggerContext);
180
+ emitterCb(clientError, finalError);
181
+ }
182
+ }
183
+ return finalError;
184
+ }
185
+ export async function handleCallErrors(emitterCb, errorLayer, retryCb, correlationId, err, caller, file) {
186
+ const loggerContext = {
187
+ file,
188
+ method: caller,
189
+ };
190
+ const callError = createCallError('', loggerContext, ERROR_TYPE.DEFAULT, '', errorLayer);
191
+ const errorCode = err.statusCode;
192
+ log.warn(`Status code: ->${errorCode}`, loggerContext);
193
+ switch (errorCode) {
194
+ case ERROR_CODE.UNAUTHORIZED: {
195
+ log.warn(`401 Unauthorized`, loggerContext);
196
+ updateCallErrorContext(loggerContext, ERROR_TYPE.TOKEN_ERROR, 'User is unauthorized due to an expired token. Sign out, then sign back in.', correlationId, callError);
197
+ emitterCb(callError);
198
+ break;
199
+ }
200
+ case ERROR_CODE.FORBIDDEN:
201
+ case ERROR_CODE.SERVICE_UNAVAILABLE: {
202
+ const errorBody = err.body;
203
+ if (!errorBody) {
204
+ log.warn('Error response has no body, throwing default error', loggerContext);
205
+ updateCallErrorContext(loggerContext, err.statusCode === 403 ? ERROR_TYPE.FORBIDDEN_ERROR : ERROR_TYPE.SERVICE_UNAVAILABLE, err.statusCode === 403
206
+ ? 'An unauthorized action has been received. This action has been blocked. Please contact the administrator if this persists.'
207
+ : 'An error occurred on the server while processing the request. Wait a moment and try again.', correlationId, callError);
208
+ emitterCb(callError);
209
+ return;
210
+ }
211
+ if (err.headers && 'retry-after' in err.headers && retryCb) {
212
+ const retryInterval = err.headers['retry-after'];
213
+ log.warn(`Retry Interval received: ${retryInterval}`, loggerContext);
214
+ retryCb(retryInterval);
215
+ return;
216
+ }
217
+ const code = errorBody.errorCode;
218
+ let message;
219
+ switch (code) {
220
+ case CALL_ERROR_CODE.INVALID_STATUS_UPDATE: {
221
+ message =
222
+ 'An invalid status update has been received for the call. Wait a moment and try again.';
223
+ break;
224
+ }
225
+ case CALL_ERROR_CODE.DEVICE_NOT_REGISTERED: {
226
+ message =
227
+ 'The client has unregistered. Please wait for the client to register before attempting the call. If error persists, sign out, sign back in and attempt the call.';
228
+ break;
229
+ }
230
+ case CALL_ERROR_CODE.CALL_NOT_FOUND: {
231
+ message = 'Call is not found on the server. Wait a moment and try again.';
232
+ break;
233
+ }
234
+ case CALL_ERROR_CODE.ERROR_PROCESSING: {
235
+ message =
236
+ 'An error occurred while processing the call on the server. Wait a moment and try again.';
237
+ break;
238
+ }
239
+ case CALL_ERROR_CODE.USER_BUSY: {
240
+ message = 'Called user is busy.';
241
+ break;
242
+ }
243
+ case CALL_ERROR_CODE.PARSING_ERROR: {
244
+ message =
245
+ 'An error occurred while parsing the provided information. Wait a moment and try again.';
246
+ break;
247
+ }
248
+ case CALL_ERROR_CODE.NOT_ACCEPTABLE: {
249
+ message =
250
+ 'An error occurred on the server while accepting the call. Wait a moment and try again. Please contact the administrator if this persists.';
251
+ break;
252
+ }
253
+ case CALL_ERROR_CODE.CALL_REJECTED: {
254
+ message =
255
+ 'Call rejected by the server. Wait a moment and try again. Please contact the administrator if this persists.';
256
+ break;
257
+ }
258
+ case CALL_ERROR_CODE.NOT_AVAILABLE: {
259
+ message =
260
+ 'Calling services not available. Wait a moment and try again. Please contact the administrator if this persists.';
261
+ break;
262
+ }
263
+ default: {
264
+ message = 'An unknown error occurred. Wait a moment and try again.';
265
+ }
266
+ }
267
+ updateCallErrorContext(loggerContext, err.statusCode === 403 ? ERROR_TYPE.FORBIDDEN_ERROR : ERROR_TYPE.SERVICE_UNAVAILABLE, message, correlationId, callError);
268
+ emitterCb(callError);
269
+ break;
270
+ }
271
+ case ERROR_CODE.DEVICE_NOT_FOUND: {
272
+ log.warn(`404 Call Not Found`, loggerContext);
273
+ updateCallErrorContext(loggerContext, ERROR_TYPE.NOT_FOUND, 'Call is no longer active. Wait a moment and try again.', correlationId, callError);
274
+ emitterCb(callError);
275
+ break;
276
+ }
277
+ case ERROR_CODE.INTERNAL_SERVER_ERROR: {
278
+ log.warn(`500 Internal Server Error`, loggerContext);
279
+ updateCallErrorContext(loggerContext, ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred in the call. Wait a moment and try again.', correlationId, callError);
280
+ emitterCb(callError);
281
+ break;
282
+ }
283
+ default: {
284
+ log.warn(`Unknown Error`, loggerContext);
285
+ }
286
+ }
287
+ }
288
+ export async function serviceErrorCodeHandler(err, loggerContext) {
289
+ const errorCode = err.statusCode;
290
+ const failureMessage = 'FAILURE';
291
+ switch (errorCode) {
292
+ case ERROR_CODE.BAD_REQUEST: {
293
+ log.warn(`400 Bad request`, loggerContext);
294
+ const errorDetails = {
295
+ statusCode: 400,
296
+ data: {
297
+ error: '400 Bad request',
298
+ },
299
+ message: failureMessage,
300
+ };
301
+ return errorDetails;
302
+ }
303
+ case ERROR_CODE.UNAUTHORIZED: {
304
+ log.warn(`401 User is unauthorised, possible token expiry`, loggerContext);
305
+ const errorDetails = {
306
+ statusCode: 401,
307
+ data: {
308
+ error: 'User is unauthorised, possible token expiry',
309
+ },
310
+ message: failureMessage,
311
+ };
312
+ return errorDetails;
313
+ }
314
+ case ERROR_CODE.FORBIDDEN: {
315
+ log.warn(`403 User request is forbidden`, loggerContext);
316
+ const errorDetails = {
317
+ statusCode: 403,
318
+ data: {
319
+ error: 'User request is forbidden',
320
+ },
321
+ message: failureMessage,
322
+ };
323
+ return errorDetails;
324
+ }
325
+ case ERROR_CODE.DEVICE_NOT_FOUND: {
326
+ log.warn(`404 User info not found`, loggerContext);
327
+ const errorDetails = {
328
+ statusCode: 404,
329
+ data: {
330
+ error: 'User info not found',
331
+ },
332
+ message: failureMessage,
333
+ };
334
+ return errorDetails;
335
+ }
336
+ case ERROR_CODE.REQUEST_TIMEOUT: {
337
+ log.warn(`408 Request to the server timedout`, loggerContext);
338
+ const errorDetails = {
339
+ statusCode: 408,
340
+ data: {
341
+ error: 'Request to the server timedout',
342
+ },
343
+ message: failureMessage,
344
+ };
345
+ return errorDetails;
346
+ }
347
+ case ERROR_CODE.NOT_IMPLEMENTED: {
348
+ log.warn(`501 Not Implemented error occurred`, loggerContext);
349
+ const errorDetails = {
350
+ statusCode: 501,
351
+ data: {
352
+ error: 'Method is not implemented at the backend',
353
+ },
354
+ message: failureMessage,
355
+ };
356
+ return errorDetails;
357
+ }
358
+ case ERROR_CODE.INTERNAL_SERVER_ERROR: {
359
+ log.warn(`500 Internal server error occurred`, loggerContext);
360
+ const errorDetails = {
361
+ statusCode: 500,
362
+ data: {
363
+ error: 'Internal server error occurred',
364
+ },
365
+ message: failureMessage,
366
+ };
367
+ return errorDetails;
368
+ }
369
+ case ERROR_CODE.SERVICE_UNAVAILABLE: {
370
+ log.warn(`503 Unable to establish a connection with the server`, loggerContext);
371
+ const errorDetails = {
372
+ statusCode: 503,
373
+ data: {
374
+ error: 'Unable to establish a connection with the server',
375
+ },
376
+ message: failureMessage,
377
+ };
378
+ return errorDetails;
379
+ }
380
+ default: {
381
+ log.warn(`422 Exception has occurred`, loggerContext);
382
+ const errorDetails = {
383
+ statusCode: 422,
384
+ data: {
385
+ error: '422 Exception has occurred',
386
+ },
387
+ message: failureMessage,
388
+ };
389
+ return errorDetails;
390
+ }
391
+ }
392
+ }
393
+ export function parseMediaQualityStatistics(stats) {
394
+ if (!stats || navigator.userAgent.indexOf('Firefox') !== -1) {
395
+ log.info('RTCStatsReport is null, adding dummy stats', {
396
+ file: UTILS_FILE,
397
+ method: parseMediaQualityStatistics.name,
398
+ });
399
+ return DUMMY_METRICS;
400
+ }
401
+ try {
402
+ let type;
403
+ let id;
404
+ let inboundCodec;
405
+ let outboundCodec;
406
+ const localCandidates = {};
407
+ const candidatePairs = {};
408
+ const codecList = {};
409
+ const rxStat = {};
410
+ const txStat = {};
411
+ const vqPayload = {};
412
+ let jitterBufferDelay = 0;
413
+ let jitterBufferEmittedCount = 0;
414
+ let totalRoundTripTime = 0;
415
+ let roundTripTimeMeasurements = 0;
416
+ let selectedPair = '';
417
+ let bitRate = 0;
418
+ vqPayload.maxJitter = 0;
419
+ vqPayload.VoPktSizeMs = 20;
420
+ stats.forEach((report) => {
421
+ Object.keys(report).forEach((statName) => {
422
+ if (statName !== TIMESTAMP) {
423
+ if (!type || statName === TYPE) {
424
+ type = report[statName];
425
+ }
426
+ else if (!id || statName === MEDIA_ID) {
427
+ id = report[statName];
428
+ }
429
+ else if (id && id.indexOf(RTC_ICE_CANDIDATE_PAIR) !== -1) {
430
+ if (statName === LOCAL_CANDIDATE_ID) {
431
+ candidatePairs[id] = report[statName];
432
+ }
433
+ }
434
+ else if (id && id.indexOf(RTC_ICE_CANDIDATE) !== -1) {
435
+ if (statName === NETWORK_TYPE) {
436
+ localCandidates[id] = report[statName];
437
+ }
438
+ }
439
+ else if (id &&
440
+ (id.indexOf(INBOUND_CODEC_MATCH) !== -1 ||
441
+ id.indexOf(OUTBOUND_CODEC_MATCH) !== -1 ||
442
+ id.indexOf(RTC_CODEC) !== -1)) {
443
+ if (statName === MIME_TYPE) {
444
+ codecList[id] = report[statName];
445
+ }
446
+ }
447
+ else if (type && type === REMOTE_INBOUND_RTP) {
448
+ switch (statName) {
449
+ case TOTAL_ROUND_TRIP_TIME: {
450
+ totalRoundTripTime = report[statName];
451
+ break;
452
+ }
453
+ case ROUND_TRIP_TIME_MEASUREMENTS: {
454
+ roundTripTimeMeasurements = report[statName];
455
+ break;
456
+ }
457
+ default: {
458
+ }
459
+ }
460
+ }
461
+ else if (type && type === INBOUND_RTP) {
462
+ switch (statName) {
463
+ case CODEC_ID: {
464
+ inboundCodec = report[statName];
465
+ break;
466
+ }
467
+ case PACKETS_RECEIVED: {
468
+ rxStat.Pkt = report[statName];
469
+ break;
470
+ }
471
+ case BYTES_RECEIVED: {
472
+ rxStat.Oct = report[statName];
473
+ break;
474
+ }
475
+ case PACKETS_DISCARDED: {
476
+ rxStat.LatePkt = report[statName];
477
+ break;
478
+ }
479
+ case PACKETS_LOST: {
480
+ rxStat.LostPkt = report[statName];
481
+ break;
482
+ }
483
+ case JITTER_BUFFER_DELAY: {
484
+ jitterBufferDelay = report[statName];
485
+ break;
486
+ }
487
+ case JITTER_BUFFER_EMITTED_COUNT: {
488
+ jitterBufferEmittedCount = report[statName];
489
+ break;
490
+ }
491
+ default: {
492
+ }
493
+ }
494
+ }
495
+ else if (type && type === TRANSPORT) {
496
+ switch (statName) {
497
+ case SELECTED_CANDIDATE_PAIR_ID: {
498
+ selectedPair = report[statName];
499
+ break;
500
+ }
501
+ default: {
502
+ }
503
+ }
504
+ }
505
+ else if (type && type === OUTBOUND_RTP) {
506
+ switch (statName) {
507
+ case CODEC_ID: {
508
+ outboundCodec = report[statName];
509
+ break;
510
+ }
511
+ case PACKETS_SENT: {
512
+ txStat.Pkt = report[statName];
513
+ break;
514
+ }
515
+ case BYTES_SENT: {
516
+ txStat.Oct = report[statName];
517
+ break;
518
+ }
519
+ case TARGET_BIT_RATE: {
520
+ bitRate = report[statName];
521
+ break;
522
+ }
523
+ default: {
524
+ }
525
+ }
526
+ }
527
+ else if (type && type === MEDIA_SOURCE) {
528
+ switch (statName) {
529
+ case TOTAL_SAMPLES_DURATION: {
530
+ rxStat.Dur = report[statName];
531
+ txStat.Dur = report[statName];
532
+ break;
533
+ }
534
+ default: {
535
+ }
536
+ }
537
+ }
538
+ }
539
+ });
540
+ });
541
+ if (roundTripTimeMeasurements !== 0) {
542
+ vqPayload.VoOneWayDelayMs = totalRoundTripTime / (2 * roundTripTimeMeasurements);
543
+ }
544
+ else {
545
+ vqPayload.VoOneWayDelayMs = 0;
546
+ }
547
+ vqPayload.hwType = `${platform.os}/${platform.name}-${platform.version}`;
548
+ vqPayload.networkType = localCandidates[candidatePairs[selectedPair]];
549
+ rxStat.AvgJit = jitterBufferDelay / jitterBufferEmittedCount;
550
+ vqPayload.VoRxCodec = codecList[inboundCodec].split('/')[1];
551
+ const txVqPayload = {};
552
+ txVqPayload.VoTxCodec = codecList[outboundCodec].split('/')[1];
553
+ txVqPayload.rtpBitRate = bitRate;
554
+ const byeStats = {};
555
+ rxStat.VQMetrics = vqPayload;
556
+ txStat.VQMetrics = txVqPayload;
557
+ byeStats[RTP_RX_STAT] = rxStat;
558
+ byeStats[RTP_TX_STAT] = txStat;
559
+ log.log(JSON.stringify(byeStats), { file: UTILS_FILE, method: parseMediaQualityStatistics.name });
560
+ return byeStats;
561
+ }
562
+ catch (err) {
563
+ log.warn(`Caught error while parsing RTP stats, ${err}`, {
564
+ file: UTILS_FILE,
565
+ method: parseMediaQualityStatistics.name,
566
+ });
567
+ return DUMMY_METRICS;
568
+ }
569
+ }
570
+ export const waitForMsecs = (msec) => new Promise((resolve) => {
571
+ setTimeout(resolve, msec);
572
+ });
573
+ export function getCallingBackEnd(webex) {
574
+ const entModels = webex.internal.device.features.entitlement.models;
575
+ let callingBackend;
576
+ if (webex.internal.device.callingBehavior === NATIVE_WEBEX_TEAMS_CALLING) {
577
+ for (let i = 0; i < entModels.length; i += 1) {
578
+ if (entModels[i][VALUES][KEY] === ENTITLEMENT_BASIC ||
579
+ entModels[i][VALUES][KEY] === ENTITLEMENT_STANDARD) {
580
+ callingBackend = CALLING_BACKEND.WXC;
581
+ break;
582
+ }
583
+ else if (entModels[i][VALUES][KEY] === ENTITLEMENT_BROADWORKS_CONN) {
584
+ callingBackend = CALLING_BACKEND.BWRKS;
585
+ break;
586
+ }
587
+ }
588
+ }
589
+ else if (webex.internal.device.callingBehavior === NATIVE_SIP_CALL_TO_UCM) {
590
+ callingBackend = CALLING_BACKEND.UCM;
591
+ }
592
+ else {
593
+ callingBackend = CALLING_BACKEND.INVALID;
594
+ }
595
+ return callingBackend;
596
+ }
597
+ export async function getXsiActionEndpoint(webex, loggerContext, callingBackend) {
598
+ try {
599
+ switch (callingBackend) {
600
+ case CALLING_BACKEND.WXC: {
601
+ const userIdResponse = await webex.request({
602
+ uri: `${webex.internal.services._serviceUrls.hydra}/${XSI_ACTION_ENDPOINT_ORG_URL_PARAM}`,
603
+ method: HTTP_METHODS.GET,
604
+ });
605
+ const response = userIdResponse.body;
606
+ const xsiEndpoint = response[ITEMS][0][XSI_ACTION_ENDPOINT];
607
+ return xsiEndpoint;
608
+ }
609
+ case CALLING_BACKEND.BWRKS: {
610
+ const bwTokenResponse = await webex.request({
611
+ uri: `${webex.internal.services._serviceUrls.wdm}/${DEVICES}`,
612
+ method: HTTP_METHODS.GET,
613
+ });
614
+ const response = bwTokenResponse.body;
615
+ let xsiEndpoint = response[DEVICES][0][SETTINGS][BW_XSI_URL];
616
+ if (response[DEVICES][0][SETTINGS][BW_XSI_URL].endsWith(BW_XSI_ENDPOINT_VERSION)) {
617
+ xsiEndpoint = response[DEVICES][0][SETTINGS][BW_XSI_URL].slice(0, -5);
618
+ }
619
+ return xsiEndpoint;
620
+ }
621
+ default: {
622
+ throw new Error('Calling backend is not identified, exiting....');
623
+ }
624
+ }
625
+ }
626
+ catch (err) {
627
+ const errorInfo = err;
628
+ serviceErrorCodeHandler(errorInfo, loggerContext);
629
+ return errorInfo;
630
+ }
631
+ }
632
+ export function getVgActionEndpoint(webex, callingBackend) {
633
+ try {
634
+ if (callingBackend && callingBackend === CALLING_BACKEND.UCM) {
635
+ return webex.internal.services._serviceUrls['ucmgmt-gateway'];
636
+ }
637
+ throw new Error('Calling backend is not identified, exiting....');
638
+ }
639
+ catch (err) {
640
+ const errorInfo = err;
641
+ return errorInfo;
642
+ }
643
+ }
644
+ export function getSortedVoicemailList(voiceMessageList, sortOrder) {
645
+ if (sortOrder === SORT.DESC) {
646
+ voiceMessageList.sort((voiceMail, nextVoiceMail) => nextVoiceMail[TIME][PLACEHOLDER_KEY] - voiceMail[TIME][PLACEHOLDER_KEY]);
647
+ }
648
+ else if (sortOrder === SORT.ASC) {
649
+ voiceMessageList.sort((voiceMail, nextVoiceMail) => voiceMail[TIME][PLACEHOLDER_KEY] - nextVoiceMail[TIME][PLACEHOLDER_KEY]);
650
+ }
651
+ return voiceMessageList;
652
+ }
653
+ async function scimQuery(filter) {
654
+ log.info(`Starting resolution for filter:- ${filter}`, {
655
+ file: UTILS_FILE,
656
+ method: 'scimQuery',
657
+ });
658
+ const sdkConnector = SDKConnector;
659
+ const webex = sdkConnector.getWebex();
660
+ const scimUrl = `${webex.internal.services._serviceUrls.identity}/${IDENTITY_ENDPOINT_RESOURCE}/${SCIM_ENDPOINT_RESOURCE}/${webex.internal.device.orgId}/${SCIM_USER_FILTER}`;
661
+ const query = scimUrl + encodeURIComponent(filter);
662
+ return webex.request({
663
+ uri: query,
664
+ method: HTTP_METHODS.GET,
665
+ headers: {
666
+ [CISCO_DEVICE_URL]: webex.internal.device.url,
667
+ [SPARK_USER_AGENT]: CALLING_USER_AGENT,
668
+ },
669
+ service: ALLOWED_SERVICES.MOBIUS,
670
+ });
671
+ }
672
+ export async function resolveCallerIdDisplay(filter) {
673
+ let resolution;
674
+ const displayResult = {};
675
+ try {
676
+ const response = await scimQuery(filter);
677
+ resolution = response.body;
678
+ log.info(`Number of records found for this user :- ${resolution.totalResults}`, {
679
+ file: UTILS_FILE,
680
+ method: 'resolveCallerIdDisplay',
681
+ });
682
+ }
683
+ catch (err) {
684
+ const res = err;
685
+ log.warn(`Error response: - ${res.statusCode}`, {
686
+ file: UTILS_FILE,
687
+ method: 'resolveCallerIdDisplay',
688
+ });
689
+ }
690
+ if (resolution?.totalResults && resolution.totalResults > 0) {
691
+ const scimResource = resolution.Resources[0];
692
+ displayResult.name = scimResource.displayName;
693
+ const numberObj = scimResource.phoneNumbers.find((num) => num.primary) ||
694
+ scimResource.phoneNumbers.find((num) => num.type.toLowerCase() === 'work');
695
+ if (numberObj) {
696
+ displayResult.num = numberObj.value;
697
+ }
698
+ else if (scimResource.phoneNumbers.length > 0) {
699
+ log.info('Failure to resolve caller information. Setting number as caller ID', {
700
+ file: UTILS_FILE,
701
+ method: 'resolveCallerIdDisplay',
702
+ });
703
+ displayResult.num = scimResource.phoneNumbers[0].value;
704
+ }
705
+ const photo = scimResource.photos?.find((photo) => photo.type === 'thumbnail');
706
+ displayResult.avatarSrc = photo ? photo.value : 'unknown';
707
+ displayResult.id = scimResource.id;
708
+ log.info(`Extracted details:- name: ${displayResult.name} , number: ${displayResult.num}, photo: ${displayResult.avatarSrc}, id: ${displayResult.id}`, {
709
+ file: UTILS_FILE,
710
+ method: 'resolveCallerIdDisplay',
711
+ });
712
+ }
713
+ return displayResult;
714
+ }
715
+ export async function resolveCallerIdByName(name) {
716
+ const displayResult = {};
717
+ const sdkConnector = SDKConnector;
718
+ const webex = sdkConnector.getWebex();
719
+ const searchDirectory = (query) => {
720
+ return webex.people.list({
721
+ displayName: query,
722
+ });
723
+ };
724
+ await searchDirectory(name).then((results) => {
725
+ log.info(`DS Result: ${results}`, {
726
+ file: UTILS_FILE,
727
+ method: 'resolveCallerIdByName',
728
+ });
729
+ if (results && results.items && results.items.length > 0) {
730
+ const resolution = results.items[0];
731
+ displayResult.name = resolution.displayName;
732
+ const id = Buffer.from(resolution.id, 'base64').toString('binary');
733
+ displayResult.id = id.split('/').pop();
734
+ const numObj = resolution.phoneNumbers.find((num) => num.type === 'work');
735
+ if (numObj) {
736
+ displayResult.num = numObj.value;
737
+ }
738
+ else if (resolution.phoneNumbers.length > 0) {
739
+ displayResult.num = resolution.phoneNumbers[0].value;
740
+ }
741
+ displayResult.avatarSrc = resolution.avatar;
742
+ log.info(`Extracted details:- name: ${displayResult.name} , number: ${displayResult.num}, photo: ${displayResult.avatarSrc}, id: ${displayResult.id}`, {
743
+ file: UTILS_FILE,
744
+ method: 'resolveCallerIdByName',
745
+ });
746
+ }
747
+ });
748
+ return displayResult;
749
+ }
750
+ export async function resolveContact(callingPartyInfo) {
751
+ if (callingPartyInfo.userExternalId && callingPartyInfo.userExternalId.$) {
752
+ return resolveCallerIdDisplay(`id eq "${callingPartyInfo.userExternalId.$}"`);
753
+ }
754
+ if (callingPartyInfo.name && callingPartyInfo.name.$) {
755
+ return resolveCallerIdByName(callingPartyInfo.name.$);
756
+ }
757
+ return null;
758
+ }
759
+ export function storeVoicemailList(context, voiceMessageList) {
760
+ const vmEncodedList = Buffer.from(JSON.stringify(voiceMessageList), 'utf8').toString('base64');
761
+ sessionStorage.setItem(context, vmEncodedList.toString());
762
+ }
763
+ export function fetchVoicemailList(context, offset, offsetLimit, loggerContext) {
764
+ let moreVoicemails = false;
765
+ let requiredVoicemailList = [];
766
+ try {
767
+ const voicemailList = JSON.parse(Buffer.from(sessionStorage.getItem(context), 'base64').toString('utf8'));
768
+ log.info(`Length of voicemail list: ${voicemailList.length}`, loggerContext);
769
+ if (voicemailList.length > offset + offsetLimit) {
770
+ moreVoicemails = true;
771
+ }
772
+ requiredVoicemailList = voicemailList.slice(offset, offset + offsetLimit);
773
+ }
774
+ catch (err) {
775
+ log.warn(`Caught exception while fetching voicemail from storage. ${err}`, loggerContext);
776
+ const errorInfo = err;
777
+ serviceErrorCodeHandler(errorInfo, {});
778
+ }
779
+ return { messages: requiredVoicemailList, moreVMAvailable: moreVoicemails };
780
+ }
781
+ export function inferIdFromUuid(id, decodeType) {
782
+ return Buffer.from(`${INFER_ID_CONSTANT}/${decodeType}/${id}`, 'binary').toString('base64');
783
+ }
784
+ function isValidServiceIndicator(indicator) {
785
+ return Object.values(ServiceIndicator).some((v) => v === indicator);
786
+ }
787
+ function isValidServiceDomain(serviceData) {
788
+ const regexp = /^[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,6}$/i;
789
+ const { domain } = serviceData;
790
+ if (!domain) {
791
+ return serviceData.indicator === ServiceIndicator.CALLING;
792
+ }
793
+ return regexp.test(domain);
794
+ }
795
+ export function validateServiceData(serviceData) {
796
+ if (!isValidServiceIndicator(serviceData.indicator)) {
797
+ throw new Error(`Invalid service indicator, Allowed values are: ${Object.values(ServiceIndicator)}`);
798
+ }
799
+ if (!isValidServiceDomain(serviceData)) {
800
+ throw new Error('Invalid service domain.');
801
+ }
802
+ }