@wazo/sdk 0.37.0-rc.5 → 0.37.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/wazo-sdk.js +5 -5
- package/esm/__tests__/api-client.test.js +93 -16
- package/esm/__tests__/web-rtc-client.test.js +153 -54
- package/esm/api/agentd.js +24 -3
- package/esm/api/amid.js +7 -1
- package/esm/api/application.js +24 -3
- package/esm/api/auth.js +24 -3
- package/esm/api/call-logd.js +78 -20
- package/esm/api/calld.js +24 -20
- package/esm/api/chatd.js +24 -3
- package/esm/api/confd.js +24 -3
- package/esm/api/ctid-ng.js +24 -3
- package/esm/api/dird.js +27 -6
- package/esm/api/webhookd.js +7 -1
- package/esm/api-client.js +93 -16
- package/esm/checker/Checker.js +156 -54
- package/esm/checker/checks/aor.js +95 -16
- package/esm/checker/checks/api.js +94 -16
- package/esm/checker/checks/index.js +156 -54
- package/esm/checker/checks/wazo-websocket.js +7 -1
- package/esm/checker/checks/webrtc-transport.js +153 -54
- package/esm/checker/checks/webrtc.js +153 -54
- package/esm/domain/AdHocAPIConference.js +1717 -1640
- package/esm/domain/CallLog.js +71 -19
- package/esm/domain/CallSession.js +1 -18
- package/esm/domain/Contact.js +3 -3
- package/esm/domain/Features.js +93 -16
- package/esm/domain/IndirectTransfer.js +0 -17
- package/esm/domain/Phone/CTIPhone.js +100 -19
- package/esm/domain/Phone/Phone.js +0 -17
- package/esm/domain/Phone/WebRTCPhone.js +51 -36
- package/esm/domain/Recording.js +51 -0
- package/esm/domain/Room.js +0 -17
- package/esm/domain/SwitchboardCall.js +0 -17
- package/esm/domain/__tests__/CallLog.test.js +89 -19
- package/esm/domain/__tests__/CallSession.test.js +1 -18
- package/esm/domain/__tests__/Contact.test.js +3 -3
- package/esm/domain/__tests__/IndirectTransfer.test.js +1 -18
- package/esm/domain/__tests__/Room.test.js +1 -18
- package/esm/domain/__tests__/Session.test.js +7 -0
- package/esm/index.js +3436 -2911
- package/esm/lib/WazoSessionDescriptionHandler.js +28 -10
- package/esm/service/CallApi.js +93 -16
- package/esm/service/IssueReporter.js +7 -1
- package/esm/service/__tests__/IssueReporter.test.js +26 -2
- package/esm/service/getApiClient.js +93 -16
- package/esm/simple/Auth.js +619 -97
- package/esm/simple/Configuration.js +619 -97
- package/esm/simple/Directory.js +93 -16
- package/esm/simple/Phone.js +3261 -2739
- package/esm/simple/Websocket.js +7 -1
- package/esm/simple/index.js +619 -97
- package/esm/simple/room/LocalParticipant.js +619 -97
- package/esm/simple/room/Participant.js +619 -97
- package/esm/simple/room/RemoteParticipant.js +619 -97
- package/esm/simple/room/Room.js +619 -97
- package/esm/simple/room/Stream.js +619 -97
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +619 -97
- package/esm/simple/utils.js +619 -97
- package/esm/utils/__tests__/api-requester.test.js +32 -6
- package/esm/utils/api-requester.js +24 -3
- package/esm/web-rtc-client.js +153 -54
- package/esm/websocket-client.js +7 -1
- package/lib/__tests__/api-client.test.js +93 -16
- package/lib/__tests__/web-rtc-client.test.js +154 -55
- package/lib/api/agentd.js +24 -3
- package/lib/api/amid.js +7 -1
- package/lib/api/application.js +24 -3
- package/lib/api/auth.js +24 -3
- package/lib/api/call-logd.js +78 -20
- package/lib/api/calld.js +24 -20
- package/lib/api/chatd.js +24 -3
- package/lib/api/confd.js +24 -3
- package/lib/api/ctid-ng.js +24 -3
- package/lib/api/dird.js +27 -6
- package/lib/api/webhookd.js +7 -1
- package/lib/api-client.js +93 -16
- package/lib/checker/Checker.js +157 -55
- package/lib/checker/checks/aor.js +95 -16
- package/lib/checker/checks/api.js +94 -16
- package/lib/checker/checks/index.js +157 -55
- package/lib/checker/checks/wazo-websocket.js +7 -1
- package/lib/checker/checks/webrtc-transport.js +154 -55
- package/lib/checker/checks/webrtc.js +154 -55
- package/lib/domain/AdHocAPIConference.js +1717 -1640
- package/lib/domain/CallLog.js +71 -19
- package/lib/domain/CallSession.js +1 -18
- package/lib/domain/Contact.js +3 -3
- package/lib/domain/Features.js +93 -16
- package/lib/domain/IndirectTransfer.js +0 -17
- package/lib/domain/Phone/CTIPhone.js +100 -19
- package/lib/domain/Phone/Phone.js +0 -16
- package/lib/domain/Phone/WebRTCPhone.js +51 -36
- package/lib/domain/Recording.js +57 -0
- package/lib/domain/Room.js +0 -17
- package/lib/domain/SwitchboardCall.js +0 -17
- package/lib/domain/__tests__/CallLog.test.js +89 -19
- package/lib/domain/__tests__/CallSession.test.js +1 -18
- package/lib/domain/__tests__/Contact.test.js +3 -3
- package/lib/domain/__tests__/IndirectTransfer.test.js +1 -18
- package/lib/domain/__tests__/Room.test.js +1 -18
- package/lib/domain/__tests__/Session.test.js +7 -0
- package/lib/index.js +3437 -2912
- package/lib/lib/WazoSessionDescriptionHandler.js +28 -10
- package/lib/service/CallApi.js +93 -16
- package/lib/service/IssueReporter.js +7 -1
- package/lib/service/__tests__/IssueReporter.test.js +26 -2
- package/lib/service/getApiClient.js +93 -16
- package/lib/simple/Auth.js +620 -98
- package/lib/simple/Configuration.js +620 -98
- package/lib/simple/Directory.js +93 -16
- package/lib/simple/Phone.js +3262 -2740
- package/lib/simple/Websocket.js +7 -1
- package/lib/simple/index.js +620 -98
- package/lib/simple/room/LocalParticipant.js +620 -98
- package/lib/simple/room/Participant.js +620 -98
- package/lib/simple/room/RemoteParticipant.js +620 -98
- package/lib/simple/room/Room.js +620 -98
- package/lib/simple/room/Stream.js +620 -98
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +620 -98
- package/lib/simple/utils.js +620 -98
- package/lib/utils/__tests__/api-requester.test.js +32 -6
- package/lib/utils/api-requester.js +24 -3
- package/lib/web-rtc-client.js +154 -55
- package/lib/websocket-client.js +7 -1
- package/package.json +1 -1
- package/src/api-client.js +4 -0
- package/src/checker/checks/aor.js +2 -0
- package/src/checker/checks/api.js +1 -0
- package/src/domain/CallLog.js +18 -11
- package/src/domain/CallSession.js +1 -2
- package/src/domain/Contact.js +3 -3
- package/src/domain/Phone/CTIPhone.js +6 -2
- package/src/domain/Phone/Phone.js +2 -0
- package/src/domain/Phone/WebRTCPhone.js +26 -16
- package/src/domain/Recording.js +48 -0
- package/src/domain/__tests__/CallLog.test.js +19 -0
- package/src/domain/__tests__/Session.test.js +7 -0
- package/src/index.js +6 -0
- package/src/lib/WazoSessionDescriptionHandler.js +21 -9
- package/src/service/IssueReporter.js +7 -1
- package/src/service/__tests__/IssueReporter.test.js +20 -1
- package/src/simple/Phone.js +5 -1
- package/src/simple/index.js +6 -0
- package/src/simple/room/Room.js +18 -15
- package/src/simple/room/Stream.js +1 -4
- package/src/utils/__tests__/api-requester.test.js +9 -4
- package/src/utils/api-requester.js +17 -2
- package/src/web-rtc-client.js +40 -13
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import 'sip.js/lib/api/session-state';
|
|
2
2
|
import moment from 'moment';
|
|
3
|
-
import { jws, b64utoutf8, KEYUTIL } from 'jsrsasign';
|
|
4
3
|
import { Base64 } from 'js-base64';
|
|
4
|
+
import { jws, b64utoutf8, KEYUTIL } from 'jsrsasign';
|
|
5
5
|
import 'events';
|
|
6
6
|
import { jsonToGraphQLQuery } from 'json-to-graphql-query/lib/jsonToGraphQLQuery';
|
|
7
7
|
|
|
@@ -207,2052 +207,2073 @@ class Call {
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
//
|
|
210
|
+
/* eslint-disable no-param-reassign */
|
|
210
211
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
212
|
+
var updateFrom = (instance , from ) => {
|
|
213
|
+
Object.keys(from).forEach(key => {
|
|
214
|
+
// $FlowFixMe
|
|
215
|
+
if (
|
|
216
|
+
(!instance[key] && from[key])
|
|
217
|
+
|| (typeof instance[key] !== 'undefined' && typeof from[key] !== 'undefined' && instance[key] !== from[key])
|
|
218
|
+
) {
|
|
219
|
+
// $FlowFixMe
|
|
220
|
+
instance[key] = from[key];
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
};
|
|
220
224
|
|
|
221
|
-
|
|
225
|
+
/* */
|
|
222
226
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
227
|
+
class BadResponse extends Error {
|
|
228
|
+
static fromResponse(error , status ) {
|
|
229
|
+
return new BadResponse(
|
|
230
|
+
error.message || JSON.stringify(error),
|
|
231
|
+
status,
|
|
232
|
+
error.timestamp,
|
|
233
|
+
error.error_id,
|
|
234
|
+
error.details,
|
|
235
|
+
error,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
229
238
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
239
|
+
static fromText(response , status ) {
|
|
240
|
+
return new BadResponse(response, status);
|
|
241
|
+
}
|
|
235
242
|
|
|
243
|
+
|
|
244
|
+
|
|
236
245
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
243
249
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
250
|
+
constructor(
|
|
251
|
+
message ,
|
|
252
|
+
status ,
|
|
253
|
+
timestamp = null,
|
|
254
|
+
errorId = null,
|
|
255
|
+
details = null,
|
|
256
|
+
error = null,
|
|
257
|
+
) {
|
|
258
|
+
super(message);
|
|
251
259
|
|
|
252
|
-
|
|
253
|
-
|
|
260
|
+
this.timestamp = timestamp;
|
|
261
|
+
this.status = status;
|
|
262
|
+
this.errorId = errorId;
|
|
263
|
+
this.details = details;
|
|
264
|
+
this.error = error;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
254
267
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
268
|
+
/* */
|
|
260
269
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
270
|
+
class ServerError extends BadResponse {
|
|
271
|
+
static fromResponse(error , status ) {
|
|
272
|
+
return new ServerError(
|
|
273
|
+
error.message || JSON.stringify(error),
|
|
274
|
+
status,
|
|
275
|
+
error.timestamp,
|
|
276
|
+
error.error_id,
|
|
277
|
+
error.details,
|
|
278
|
+
);
|
|
269
279
|
}
|
|
270
280
|
|
|
271
|
-
static
|
|
272
|
-
return
|
|
281
|
+
static fromText(response , status ) {
|
|
282
|
+
return new ServerError(response, status);
|
|
273
283
|
}
|
|
284
|
+
}
|
|
274
285
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
286
|
+
/* */
|
|
287
|
+
/* global navigator */
|
|
288
|
+
const isMobile = () => typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
|
|
278
289
|
|
|
279
|
-
|
|
280
|
-
if (!this.extensions) {
|
|
281
|
-
return false;
|
|
282
|
-
}
|
|
290
|
+
/* global window */
|
|
283
291
|
|
|
284
|
-
|
|
285
|
-
|
|
292
|
+
const TRACE = 'trace';
|
|
293
|
+
const DEBUG = 'debug';
|
|
294
|
+
const INFO = 'info';
|
|
295
|
+
const LOG = 'log';
|
|
296
|
+
const WARN = 'warn';
|
|
297
|
+
const ERROR = 'error';
|
|
298
|
+
const CONSOLE_METHODS = [INFO, LOG, WARN, ERROR];
|
|
299
|
+
const LOG_LEVELS = [TRACE, DEBUG, INFO, LOG, WARN, ERROR];
|
|
300
|
+
const CATEGORY_PREFIX = 'logger-category=';
|
|
286
301
|
|
|
287
|
-
|
|
288
|
-
this.id = id;
|
|
289
|
-
this.extensions = extensions;
|
|
290
|
-
this.endpointCustom = endpointCustom || null;
|
|
291
|
-
this.endpointSccp = endpointSccp || null;
|
|
292
|
-
this.endpointSip = endpointSip || null;
|
|
302
|
+
const MAX_REMOTE_RETRY = 100;
|
|
293
303
|
|
|
294
|
-
|
|
295
|
-
|
|
304
|
+
const addLevelsTo = (instance , withMethods = false) => {
|
|
305
|
+
instance.TRACE = TRACE;
|
|
306
|
+
instance.DEBUG = DEBUG;
|
|
307
|
+
instance.INFO = INFO;
|
|
308
|
+
instance.LOG = LOG;
|
|
309
|
+
instance.WARN = WARN;
|
|
310
|
+
instance.ERROR = ERROR;
|
|
311
|
+
|
|
312
|
+
if (withMethods) {
|
|
313
|
+
instance.trace = (...args) => instance.apply(null, [TRACE, ...args]);
|
|
314
|
+
instance.debug = (...args) => instance.apply(null, [DEBUG, ...args]);
|
|
315
|
+
instance.info = (...args) => instance.apply(null, [INFO, ...args]);
|
|
316
|
+
instance.log = (...args) => instance.apply(null, [LOG, ...args]);
|
|
317
|
+
instance.warn = (...args) => instance.apply(null, [WARN, ...args]);
|
|
318
|
+
instance.error = (...args) => instance.apply(null, [ERROR, ...args]);
|
|
296
319
|
}
|
|
297
|
-
}
|
|
298
320
|
|
|
299
|
-
|
|
321
|
+
return instance;
|
|
322
|
+
};
|
|
300
323
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
324
|
+
const safeStringify = (object ) => {
|
|
325
|
+
const result = '{"message": "Not parsable JSON"}';
|
|
326
|
+
try {
|
|
327
|
+
return JSON.stringify(object);
|
|
328
|
+
} catch (e) {
|
|
329
|
+
// Nothing to do
|
|
330
|
+
}
|
|
305
331
|
|
|
306
|
-
|
|
307
|
-
BUSY: 'busy',
|
|
308
|
-
NO_ANSWER: 'noanswer',
|
|
309
|
-
UNCONDITIONAL: 'unconditional',
|
|
332
|
+
return result;
|
|
310
333
|
};
|
|
311
334
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
335
|
+
class IssueReporter {
|
|
336
|
+
|
|
337
|
+
|
|
315
338
|
|
|
316
|
-
|
|
339
|
+
|
|
340
|
+
|
|
317
341
|
|
|
318
|
-
|
|
319
|
-
|
|
342
|
+
|
|
320
343
|
|
|
321
|
-
|
|
344
|
+
|
|
322
345
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
346
|
+
constructor() {
|
|
347
|
+
addLevelsTo(this);
|
|
348
|
+
|
|
349
|
+
this.oldConsoleMethods = null;
|
|
350
|
+
this.enabled = false;
|
|
351
|
+
this.remoteClientConfiguration = null;
|
|
329
352
|
}
|
|
330
353
|
|
|
331
|
-
|
|
332
|
-
|
|
354
|
+
init() {
|
|
355
|
+
this._catchConsole();
|
|
333
356
|
}
|
|
334
357
|
|
|
335
|
-
|
|
336
|
-
this.
|
|
337
|
-
this.enabled = enabled;
|
|
338
|
-
this.key = key;
|
|
358
|
+
configureRemoteClient(configuration = { tag: 'wazo-sdk', host: null, port: null, level: null, extra: {} }) {
|
|
359
|
+
this.remoteClientConfiguration = configuration;
|
|
339
360
|
}
|
|
340
361
|
|
|
341
|
-
|
|
342
|
-
this.
|
|
362
|
+
enable() {
|
|
363
|
+
if (!this.oldConsoleMethods) {
|
|
364
|
+
this.init();
|
|
365
|
+
}
|
|
343
366
|
|
|
344
|
-
|
|
367
|
+
this.enabled = true;
|
|
345
368
|
}
|
|
346
369
|
|
|
347
|
-
|
|
348
|
-
this.enabled =
|
|
349
|
-
|
|
350
|
-
return this;
|
|
370
|
+
disable() {
|
|
371
|
+
this.enabled = false;
|
|
351
372
|
}
|
|
352
373
|
|
|
353
|
-
|
|
354
|
-
|
|
374
|
+
loggerFor(category ) {
|
|
375
|
+
const logger = (level , ...args ) => {
|
|
376
|
+
this.log.apply(this, [level, this._makeCategory(category), ...args]);
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
return addLevelsTo(logger, true);
|
|
355
380
|
}
|
|
356
|
-
}
|
|
357
381
|
|
|
358
|
-
|
|
359
|
-
|
|
382
|
+
removeSlashes(str ) {
|
|
383
|
+
return str.replace(/"/g, "'").replace(/\\/g, '');
|
|
384
|
+
}
|
|
360
385
|
|
|
361
|
-
|
|
386
|
+
log(level , ...args ) {
|
|
387
|
+
if (!this.enabled) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
362
390
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
391
|
+
// Handle category label
|
|
392
|
+
let category = null;
|
|
393
|
+
let extra = {};
|
|
394
|
+
if (args[0].indexOf(CATEGORY_PREFIX) === 0) {
|
|
395
|
+
category = args[0].split('=')[1];
|
|
396
|
+
// eslint-disable-next-line no-param-reassign
|
|
397
|
+
args.splice(0, 1);
|
|
398
|
+
}
|
|
378
399
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
400
|
+
// Handle extra data as object for the last argument
|
|
401
|
+
const lastArg = args[args.length - 1];
|
|
402
|
+
if (lastArg && ((typeof lastArg === 'object' && Object.keys(lastArg).length) || lastArg instanceof Error)) {
|
|
403
|
+
if (lastArg instanceof Error) {
|
|
404
|
+
extra = {
|
|
405
|
+
errorMessage: lastArg.message,
|
|
406
|
+
errorStack: lastArg.stack,
|
|
407
|
+
errorType: lastArg.constructor.name,
|
|
408
|
+
};
|
|
409
|
+
} else {
|
|
410
|
+
extra = lastArg;
|
|
411
|
+
}
|
|
412
|
+
// eslint-disable-next-line no-param-reassign
|
|
413
|
+
args.splice(1, 1);
|
|
414
|
+
}
|
|
393
415
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
416
|
+
const date = moment().format('YYYY-MM-DD HH:mm:ss.SSS');
|
|
417
|
+
const message = args.join(', ');
|
|
418
|
+
let consoleMessage = message;
|
|
407
419
|
|
|
408
|
-
|
|
409
|
-
|
|
420
|
+
if (Object.keys(extra).length) {
|
|
421
|
+
const parsedExtra = safeStringify(extra);
|
|
422
|
+
consoleMessage = `${consoleMessage} (${parsedExtra})`;
|
|
423
|
+
}
|
|
410
424
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const findOption = (options , name ) => options.find(option => option[0] === name);
|
|
425
|
+
if (category) {
|
|
426
|
+
consoleMessage = `[${category}] ${consoleMessage}`;
|
|
427
|
+
}
|
|
415
428
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
const hostOption = findOption(plain.endpoint_section_options, 'media_address');
|
|
429
|
+
// Log the message in the console anyway (but don't console.error on mobile)
|
|
430
|
+
const consoleLevel = isMobile() && level === 'error' ? WARN : level;
|
|
419
431
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
432
|
+
// eslint-disable-next-line
|
|
433
|
+
const oldMethod = this.oldConsoleMethods[consoleLevel] || this.oldConsoleMethods.log;
|
|
434
|
+
oldMethod.apply(oldMethod, [date, consoleMessage]);
|
|
435
|
+
|
|
436
|
+
this._sendToRemoteLogger(level, { date, message, category, ...extra });
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
logRequest(url , options , response , start ) {
|
|
440
|
+
if (!this.enabled) {
|
|
441
|
+
return;
|
|
423
442
|
}
|
|
443
|
+
const { status } = response;
|
|
444
|
+
const duration = new Date() - start;
|
|
424
445
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
446
|
+
let level = TRACE;
|
|
447
|
+
if (status >= 400 && status < 500) {
|
|
448
|
+
level = WARN;
|
|
449
|
+
} else if (status >= 500) {
|
|
450
|
+
level = ERROR;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
this.log(level, this._makeCategory('http'), url, {
|
|
454
|
+
status,
|
|
455
|
+
body: this.removeSlashes(JSON.stringify(options.body)),
|
|
456
|
+
method: options.method,
|
|
457
|
+
headers: options.headers,
|
|
458
|
+
duration,
|
|
438
459
|
});
|
|
439
460
|
}
|
|
440
461
|
|
|
441
|
-
|
|
442
|
-
|
|
462
|
+
// Logs aren't stored anymore
|
|
463
|
+
getLogs() {
|
|
464
|
+
console.warn('IssueReporter\'s logs aren\'t stored anymore. Please use fluentd to store them');
|
|
465
|
+
return [];
|
|
443
466
|
}
|
|
444
467
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
}
|
|
449
|
-
return this.id === line.id;
|
|
468
|
+
getParsedLogs() {
|
|
469
|
+
console.warn('IssueReporter\'s logs aren\'t stored anymore. Please use fluentd to store them');
|
|
470
|
+
return [];
|
|
450
471
|
}
|
|
451
472
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
return this.endpointSectionOptions || this.options || [];
|
|
473
|
+
getReport() {
|
|
474
|
+
return this.getParsedLogs().join('\r\n');
|
|
455
475
|
}
|
|
456
476
|
|
|
457
|
-
|
|
458
|
-
|
|
477
|
+
_catchConsole() {
|
|
478
|
+
this.oldConsoleMethods = {};
|
|
479
|
+
CONSOLE_METHODS.forEach((methodName ) => {
|
|
480
|
+
// eslint-disable-next-line
|
|
481
|
+
this.oldConsoleMethods[methodName] = console[methodName];
|
|
482
|
+
window.console[methodName] = (...args) => {
|
|
483
|
+
// Store message
|
|
484
|
+
try {
|
|
485
|
+
this.log(methodName, args.join(' '));
|
|
486
|
+
// Use old console method to log it normally
|
|
487
|
+
this.oldConsoleMethods[methodName].apply(null, args);
|
|
488
|
+
} catch (e) {
|
|
489
|
+
// Avoid circular structure issues
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
});
|
|
459
493
|
}
|
|
460
494
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
495
|
+
_sendToRemoteLogger(level , payload , retry = 0) {
|
|
496
|
+
if (!this.remoteClientConfiguration || retry >= MAX_REMOTE_RETRY) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
465
499
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
500
|
+
const { tag, host, port, extra, level: minLevel } = this.remoteClientConfiguration;
|
|
501
|
+
if (!minLevel || this._isLevelAbove(minLevel, level)) {
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const isSecure = +port === 443;
|
|
506
|
+
const url = `http${isSecure ? 's' : ''}://${host}${isSecure ? '' : `:${port}`}/${tag}`;
|
|
507
|
+
|
|
508
|
+
realFetch()(url, {
|
|
509
|
+
method: 'POST',
|
|
510
|
+
headers: {
|
|
511
|
+
Accept: 'application/json',
|
|
512
|
+
'Content-Type': 'application/json',
|
|
513
|
+
},
|
|
514
|
+
body: safeStringify({
|
|
515
|
+
level,
|
|
516
|
+
...payload,
|
|
517
|
+
...extra,
|
|
518
|
+
}),
|
|
519
|
+
}).catch(() => {
|
|
520
|
+
setTimeout(() => {
|
|
521
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
522
|
+
payload._retry = retry + 1;
|
|
523
|
+
this._sendToRemoteLogger(level, payload, retry + 1);
|
|
524
|
+
}, 5000 + retry * 1000);
|
|
525
|
+
});
|
|
471
526
|
}
|
|
472
527
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
type,
|
|
480
|
-
host,
|
|
481
|
-
options,
|
|
482
|
-
endpointSectionOptions,
|
|
483
|
-
links,
|
|
484
|
-
trunk,
|
|
485
|
-
line,
|
|
486
|
-
} = {}) {
|
|
487
|
-
this.id = id;
|
|
488
|
-
this.uuid = uuid;
|
|
489
|
-
this.tenantUuid = tenantUuid;
|
|
490
|
-
this.username = username;
|
|
491
|
-
this.secret = secret;
|
|
492
|
-
this.type = type;
|
|
493
|
-
this.host = host;
|
|
494
|
-
this.options = options;
|
|
495
|
-
this.endpointSectionOptions = endpointSectionOptions;
|
|
496
|
-
this.links = links;
|
|
497
|
-
this.trunk = trunk;
|
|
498
|
-
this.line = line;
|
|
528
|
+
_isLevelAbove(level1 , level2 ) {
|
|
529
|
+
const index1 = LOG_LEVELS.indexOf(level1);
|
|
530
|
+
const index2 = LOG_LEVELS.indexOf(level2);
|
|
531
|
+
if (index1 === -1 || index2 === -1) {
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
499
534
|
|
|
500
|
-
|
|
501
|
-
this.type = 'SipLine';
|
|
535
|
+
return index1 > index2;
|
|
502
536
|
}
|
|
503
|
-
}
|
|
504
537
|
|
|
505
|
-
|
|
538
|
+
_makeCategory(category ) {
|
|
539
|
+
return `${CATEGORY_PREFIX}${category}`;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
506
542
|
|
|
507
|
-
|
|
508
|
-
AVAILABLE: 'available',
|
|
509
|
-
UNAVAILABLE: 'unavailable',
|
|
510
|
-
INVISIBLE: 'invisible',
|
|
511
|
-
DISCONNECTED: 'disconnected',
|
|
512
|
-
AWAY: 'away',
|
|
513
|
-
};
|
|
543
|
+
var IssueReporter$1 = new IssueReporter();
|
|
514
544
|
|
|
515
|
-
|
|
516
|
-
AVAILABLE: 'available',
|
|
517
|
-
HOLDING: 'holding',
|
|
518
|
-
RINGING: 'ringing',
|
|
519
|
-
TALKING: 'talking',
|
|
520
|
-
UNAVAILABLE: 'unavailable',
|
|
521
|
-
PROGRESSING: 'progressing',
|
|
522
|
-
};
|
|
545
|
+
/* */
|
|
523
546
|
|
|
524
|
-
|
|
525
|
-
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
|
|
526
550
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
551
|
+
|
|
578
552
|
|
|
579
|
-
|
|
580
|
-
|
|
553
|
+
|
|
581
554
|
|
|
582
555
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
556
|
+
const methods = ['head', 'get', 'post', 'put', 'delete'];
|
|
557
|
+
|
|
558
|
+
const logger$1 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
559
|
+
|
|
560
|
+
// Use a function here to be able to mock it in tests
|
|
561
|
+
const realFetch = () => {
|
|
562
|
+
if (typeof document !== 'undefined') {
|
|
563
|
+
// Browser
|
|
564
|
+
return window.fetch;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (isMobile()) {
|
|
568
|
+
// React native
|
|
569
|
+
return fetch;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// nodejs
|
|
573
|
+
// this package is disable for react-native in package.json because it requires nodejs modules
|
|
574
|
+
// Used to trick the optimizer to avoid requiring `node-fetch/lib/index` directly
|
|
575
|
+
// It causes to require it on browsers when delivered by a nodejs engine (cf: vitejs).
|
|
576
|
+
try {
|
|
577
|
+
// $FlowFixMe
|
|
578
|
+
return require(Math.random() >= 0 ? 'node-fetch/lib/index' : '');
|
|
579
|
+
} catch (e) {
|
|
580
|
+
return fetch;
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
class ApiRequester {
|
|
595
585
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
586
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
class Profile {
|
|
613
|
-
|
|
614
587
|
|
|
615
|
-
|
|
616
588
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
589
|
+
|
|
620
590
|
|
|
621
591
|
|
|
622
|
-
|
|
623
|
-
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
|
|
624
595
|
|
|
625
|
-
|
|
596
|
+
|
|
626
597
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
598
|
+
|
|
599
|
+
|
|
631
600
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
firstName: plain.firstName || plain.firstname || '',
|
|
636
|
-
lastName: plain.lastName || plain.lastname || '',
|
|
637
|
-
email: plain.email,
|
|
638
|
-
lines: plain.lines.map(line => Line.parse(line)),
|
|
639
|
-
username: plain.username,
|
|
640
|
-
mobileNumber: plain.mobile_phone_number || '',
|
|
641
|
-
forwards: [
|
|
642
|
-
ForwardOption.parse(plain.forwards.unconditional, FORWARD_KEYS.UNCONDITIONAL),
|
|
643
|
-
ForwardOption.parse(plain.forwards.noanswer, FORWARD_KEYS.NO_ANSWER),
|
|
644
|
-
ForwardOption.parse(plain.forwards.busy, FORWARD_KEYS.BUSY),
|
|
645
|
-
],
|
|
646
|
-
doNotDisturb: plain.services.dnd.enabled,
|
|
647
|
-
subscriptionType: plain.subscription_type,
|
|
648
|
-
voicemail: plain.voicemail,
|
|
649
|
-
switchboards: plain.switchboards || [],
|
|
650
|
-
agent: plain.agent,
|
|
651
|
-
status: '',
|
|
652
|
-
callPickupTargetUsers: plain.call_pickup_target_users || [],
|
|
653
|
-
onlineCallRecordEnabled: plain.online_call_record_enabled,
|
|
654
|
-
});
|
|
601
|
+
// eslint-disable-next-line
|
|
602
|
+
static successResponseParser(response , isJson ) {
|
|
603
|
+
return response.status === 204 || response.status === 201 || response.status === 200;
|
|
655
604
|
}
|
|
656
605
|
|
|
657
|
-
static
|
|
658
|
-
return
|
|
606
|
+
static defaultParser(response ) {
|
|
607
|
+
return response.json().then((data ) => data);
|
|
659
608
|
}
|
|
660
609
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
username,
|
|
668
|
-
mobileNumber,
|
|
669
|
-
forwards,
|
|
670
|
-
doNotDisturb,
|
|
671
|
-
state,
|
|
672
|
-
subscriptionType,
|
|
673
|
-
voicemail,
|
|
674
|
-
switchboards,
|
|
675
|
-
agent,
|
|
676
|
-
status,
|
|
677
|
-
sipLines,
|
|
678
|
-
callPickupTargetUsers,
|
|
679
|
-
onlineCallRecordEnabled,
|
|
680
|
-
} = {}) {
|
|
681
|
-
this.id = id;
|
|
682
|
-
this.firstName = firstName;
|
|
683
|
-
this.lastName = lastName;
|
|
684
|
-
this.email = email;
|
|
685
|
-
this.lines = lines;
|
|
686
|
-
this.username = username;
|
|
687
|
-
this.mobileNumber = mobileNumber;
|
|
688
|
-
this.forwards = forwards;
|
|
689
|
-
this.doNotDisturb = doNotDisturb;
|
|
690
|
-
this.state = state;
|
|
691
|
-
this.voicemail = voicemail;
|
|
692
|
-
this.subscriptionType = subscriptionType;
|
|
693
|
-
this.switchboards = switchboards;
|
|
694
|
-
this.agent = agent;
|
|
695
|
-
this.status = status;
|
|
696
|
-
this.callPickupTargetUsers = callPickupTargetUsers;
|
|
697
|
-
this.onlineCallRecordEnabled = onlineCallRecordEnabled;
|
|
610
|
+
static getQueryString(obj ) {
|
|
611
|
+
return Object.keys(obj)
|
|
612
|
+
.filter(key => obj[key])
|
|
613
|
+
.map(key => `${key}=${encodeURIComponent(obj[key])}`)
|
|
614
|
+
.join('&');
|
|
615
|
+
}
|
|
698
616
|
|
|
699
|
-
|
|
617
|
+
static base64Encode(str ) {
|
|
618
|
+
return typeof btoa !== 'undefined' ? btoa(str) : Base64.encode(str);
|
|
700
619
|
}
|
|
701
620
|
|
|
702
|
-
|
|
703
|
-
|
|
621
|
+
// @see https://github.com/facebook/flow/issues/183#issuecomment-358607052
|
|
622
|
+
constructor({ server, refreshTokenCallback, clientId, agent = null, token = null, fetchOptions } ) {
|
|
623
|
+
this.server = server;
|
|
624
|
+
this.agent = agent;
|
|
625
|
+
this.clientId = clientId;
|
|
626
|
+
this.refreshTokenCallback = refreshTokenCallback;
|
|
627
|
+
this.refreshTokenPromise = null;
|
|
628
|
+
this.fetchOptions = fetchOptions || {};
|
|
629
|
+
if (token) {
|
|
630
|
+
this.token = token;
|
|
631
|
+
}
|
|
704
632
|
|
|
705
|
-
|
|
706
|
-
for (const line of lines) {
|
|
707
|
-
if (line.state === LINE_STATE.RINGING) {
|
|
708
|
-
result = LINE_STATE.RINGING;
|
|
709
|
-
break;
|
|
710
|
-
}
|
|
633
|
+
this.shouldLogErrors = true;
|
|
711
634
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
635
|
+
methods.forEach(method => {
|
|
636
|
+
// $FlowFixMe
|
|
637
|
+
ApiRequester.prototype[method] = function sugar(...args) {
|
|
638
|
+
// Add method in arguments passed to `call`
|
|
639
|
+
args.splice(1, 0, method);
|
|
716
640
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
641
|
+
return this.call.call(this, ...args);
|
|
642
|
+
};
|
|
643
|
+
});
|
|
644
|
+
}
|
|
721
645
|
|
|
722
|
-
|
|
646
|
+
setTenant(tenant ) {
|
|
647
|
+
this.tenant = tenant;
|
|
723
648
|
}
|
|
724
649
|
|
|
725
|
-
|
|
726
|
-
|
|
650
|
+
setToken(token ) {
|
|
651
|
+
this.token = token;
|
|
727
652
|
}
|
|
728
653
|
|
|
729
|
-
|
|
730
|
-
this.
|
|
654
|
+
setFetchOptions(options ) {
|
|
655
|
+
this.fetchOptions = options;
|
|
656
|
+
}
|
|
731
657
|
|
|
732
|
-
|
|
658
|
+
disableErrorLogging() {
|
|
659
|
+
this.shouldLogErrors = false;
|
|
733
660
|
}
|
|
734
661
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
updatedForwardOptions.splice(index, 1, forwardOption);
|
|
662
|
+
enableErrorLogging() {
|
|
663
|
+
this.shouldLogErrors = true;
|
|
664
|
+
}
|
|
739
665
|
|
|
740
|
-
|
|
666
|
+
async call(
|
|
667
|
+
path ,
|
|
668
|
+
method = 'get',
|
|
669
|
+
body = null,
|
|
670
|
+
headers = null,
|
|
671
|
+
parse = ApiRequester.defaultParser,
|
|
672
|
+
firstCall = true,
|
|
673
|
+
) {
|
|
674
|
+
const url = this.computeUrl(method, path, body);
|
|
675
|
+
const newHeaders = this.getHeaders(headers);
|
|
676
|
+
let newBody = method === 'get' ? null : body;
|
|
677
|
+
if (newBody && newHeaders['Content-Type'] === 'application/json') {
|
|
678
|
+
newBody = JSON.stringify(newBody);
|
|
679
|
+
}
|
|
680
|
+
const isHead = method === 'head';
|
|
681
|
+
const hasEmptyResponse = method === 'delete' || isHead;
|
|
682
|
+
const newParse = hasEmptyResponse ? ApiRequester.successResponseParser : parse;
|
|
741
683
|
|
|
742
|
-
|
|
684
|
+
const fetchOptions = { ...this.fetchOptions || {} };
|
|
685
|
+
const extraHeaders = fetchOptions.headers || {};
|
|
686
|
+
delete fetchOptions.headers;
|
|
687
|
+
|
|
688
|
+
const options = {
|
|
689
|
+
method,
|
|
690
|
+
body: newBody,
|
|
691
|
+
headers: { ...this.getHeaders(headers), ...extraHeaders },
|
|
692
|
+
agent: this.agent,
|
|
693
|
+
...fetchOptions,
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
if (this.refreshTokenPromise) {
|
|
697
|
+
logger$1.info('A token is already refreshing, waiting ...', { url });
|
|
698
|
+
await this.refreshTokenPromise;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const start = new Date();
|
|
702
|
+
|
|
703
|
+
return realFetch()(url, options).then(response => {
|
|
704
|
+
const contentType = response.headers.get('content-type') || '';
|
|
705
|
+
const isJson = contentType.indexOf('application/json') !== -1;
|
|
706
|
+
|
|
707
|
+
IssueReporter$1.logRequest(url, options, response, start);
|
|
708
|
+
|
|
709
|
+
// Throw an error only if status >= 400
|
|
710
|
+
if ((isHead && response.status >= 500) || (!isHead && response.status >= 400)) {
|
|
711
|
+
const promise = isJson ? response.json() : response.text();
|
|
712
|
+
const exceptionClass = response.status >= 500 ? ServerError : BadResponse;
|
|
713
|
+
|
|
714
|
+
return promise.then(async (err ) => {
|
|
715
|
+
// Check if the token is still valid
|
|
716
|
+
if (firstCall && this._checkTokenExpired(response, err)) {
|
|
717
|
+
logger$1.warn('token expired', { error: err.reason });
|
|
718
|
+
// Replay the call after refreshing the token
|
|
719
|
+
return this._replayWithNewToken(err, path, method, body, headers, parse);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const error = typeof err === 'string'
|
|
723
|
+
? exceptionClass.fromText(err, response.status)
|
|
724
|
+
: exceptionClass.fromResponse(err, response.status);
|
|
725
|
+
|
|
726
|
+
if (this.shouldLogErrors) {
|
|
727
|
+
logger$1.error('API error', error);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
throw error;
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
return newParse(response, isJson);
|
|
735
|
+
}).catch(error => {
|
|
736
|
+
if (this.shouldLogErrors) {
|
|
737
|
+
logger$1.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
throw error;
|
|
741
|
+
});
|
|
743
742
|
}
|
|
744
743
|
|
|
745
|
-
|
|
746
|
-
|
|
744
|
+
_checkTokenExpired(response , err ) {
|
|
745
|
+
// Special case when authenticating form a token: we got a 404
|
|
746
|
+
const isTokenNotFound = response.status === 404 && this._isTokenNotFound(err);
|
|
747
747
|
|
|
748
|
-
return
|
|
748
|
+
return response.status === 401 || isTokenNotFound;
|
|
749
749
|
}
|
|
750
750
|
|
|
751
|
-
|
|
752
|
-
|
|
751
|
+
_isTokenNotFound(err ) {
|
|
752
|
+
return err && err.reason && err.reason[0] === 'No such token';
|
|
753
|
+
}
|
|
753
754
|
|
|
754
|
-
|
|
755
|
+
_replayWithNewToken(
|
|
756
|
+
err ,
|
|
757
|
+
path ,
|
|
758
|
+
method ,
|
|
759
|
+
body = null,
|
|
760
|
+
headers = null,
|
|
761
|
+
parse ,
|
|
762
|
+
) {
|
|
763
|
+
const isTokenNotFound = this._isTokenNotFound(err);
|
|
764
|
+
let newPath = path;
|
|
765
|
+
logger$1.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
|
|
766
|
+
|
|
767
|
+
this.refreshTokenPromise = this.refreshTokenPromise || this.refreshTokenCallback();
|
|
768
|
+
|
|
769
|
+
return this.refreshTokenPromise.then(() => {
|
|
770
|
+
this.refreshTokenPromise = null;
|
|
771
|
+
logger$1.info('token refreshed', { isTokenNotFound });
|
|
772
|
+
if (isTokenNotFound) {
|
|
773
|
+
const pathParts = path.split('/');
|
|
774
|
+
pathParts.pop();
|
|
775
|
+
pathParts.push(this.token);
|
|
776
|
+
newPath = pathParts.join('/');
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
return this.call(newPath, method, body, headers, parse, false);
|
|
780
|
+
}).catch((e) => {
|
|
781
|
+
this.refreshTokenPromise = null;
|
|
782
|
+
throw e;
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
getHeaders(header ) {
|
|
787
|
+
if (header instanceof Object) {
|
|
788
|
+
return header;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
return {
|
|
792
|
+
'X-Auth-Token': this.token,
|
|
793
|
+
...(this.tenant ? { 'Wazo-Tenant': this.tenant } : null),
|
|
794
|
+
Accept: 'application/json',
|
|
795
|
+
'Content-Type': 'application/json',
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
computeUrl(method , path , body ) {
|
|
800
|
+
const url = `${this.baseUrl}/${path}`;
|
|
801
|
+
|
|
802
|
+
return method === 'get' && body && Object.keys(body).length ? `${url}?${ApiRequester.getQueryString(body)}` : url;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
get baseUrl() {
|
|
806
|
+
return `https://${this.server}/api`;
|
|
755
807
|
}
|
|
756
808
|
}
|
|
757
809
|
|
|
758
810
|
//
|
|
759
|
-
|
|
760
811
|
|
|
761
|
-
const
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
812
|
+
const swarmPublicKey = `-----BEGIN PUBLIC KEY-----
|
|
813
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmkXOuNfY8u5xoTiIhkb8
|
|
814
|
+
djnbIwG/Wrz3vpo8BZir8L5e1a1nSy740qBjP7ZINBQoALDhFfmdOfJnCyEGiHuz
|
|
815
|
+
ZW6jbG6C3PryE3Bu6GKwqSmD6k3q4Zk27fpwYAnNl+rWhYYM563rJZBda/INyHNN
|
|
816
|
+
pK7M1mixWi7gNdjjXwoEXSSBx+VpYMkY6LiAB2mvHXTY9M1qI14dvgGoQISZQoKi
|
|
817
|
+
NMTRCg5UP2ic0Dd9nSz/XpcOxGfa+0fwIl1F7RC1tJXOqvkGGPTOV4LLfg/Yta3h
|
|
818
|
+
nUPX9EZZDIX6vO/0IBV1LzjSl2A1bYFYAjJfowv3i1CpvONBOClHjSY5t9Y8MH6p
|
|
819
|
+
BwIDAQAB
|
|
820
|
+
-----END PUBLIC KEY-----`;
|
|
767
821
|
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
822
|
+
//
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
|
|
776
826
|
|
|
777
|
-
|
|
778
|
-
|
|
827
|
+
|
|
828
|
+
|
|
779
829
|
|
|
780
830
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
831
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
|
|
793
835
|
|
|
794
836
|
|
|
795
|
-
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
|
|
796
841
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
842
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
843
|
|
|
819
844
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
845
|
|
|
825
|
-
|
|
846
|
+
|
|
826
847
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
848
|
+
|
|
830
849
|
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
850
|
+
|
|
839
851
|
|
|
840
852
|
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
+
class Line {
|
|
853
854
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
855
|
+
|
|
873
856
|
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
static parse(plain ) {
|
|
863
|
+
return new Line({
|
|
864
|
+
id: plain.id,
|
|
865
|
+
extensions: plain.extensions,
|
|
866
|
+
endpointCustom: plain.endpoint_custom || null,
|
|
867
|
+
endpointSccp: plain.endpoint_sccp || null,
|
|
868
|
+
endpointSip: plain.endpoint_sip || null,
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
static newFrom(profile ) {
|
|
873
|
+
return newFrom(profile, Line);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
is(line ) {
|
|
877
|
+
return this.id === line.id;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
hasExtension(extension ) {
|
|
881
|
+
if (!this.extensions) {
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
return this.extensions.some(ext => ext.exten === extension);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
constructor({ id, extensions, endpointCustom, endpointSccp, endpointSip } = {}) {
|
|
889
|
+
this.id = id;
|
|
890
|
+
this.extensions = extensions;
|
|
891
|
+
this.endpointCustom = endpointCustom || null;
|
|
892
|
+
this.endpointSccp = endpointSccp || null;
|
|
893
|
+
this.endpointSip = endpointSip || null;
|
|
894
|
+
|
|
895
|
+
// Useful to compare instead of instanceof with minified code
|
|
896
|
+
this.type = 'Line';
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
//
|
|
879
901
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
902
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
903
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
904
|
|
|
904
|
-
|
|
905
|
-
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
const FORWARD_KEYS = {
|
|
908
|
+
BUSY: 'busy',
|
|
909
|
+
NO_ANSWER: 'noanswer',
|
|
910
|
+
UNCONDITIONAL: 'unconditional',
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
|
|
906
914
|
|
|
907
|
-
|
|
908
|
-
|
|
909
915
|
|
|
916
|
+
|
|
910
917
|
|
|
911
918
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
919
|
+
class ForwardOption {
|
|
924
920
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
921
|
|
|
930
|
-
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
static parse(plain , key ) {
|
|
925
|
+
return new ForwardOption({
|
|
926
|
+
destination: plain.destination || '',
|
|
927
|
+
enabled: plain.enabled,
|
|
928
|
+
key,
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
static newFrom(profile ) {
|
|
933
|
+
return newFrom(profile, ForwardOption);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
constructor({ destination, enabled, key } = {}) {
|
|
937
|
+
this.destination = destination;
|
|
938
|
+
this.enabled = enabled;
|
|
939
|
+
this.key = key;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
setDestination(number ) {
|
|
943
|
+
this.destination = number;
|
|
944
|
+
|
|
945
|
+
return this;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
setEnabled(enabled ) {
|
|
949
|
+
this.enabled = enabled;
|
|
950
|
+
|
|
951
|
+
return this;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
is(other ) {
|
|
955
|
+
return this.key === other.key;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
//
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
const availableCodecs = ['vp8', 'vp9', 'h264'];
|
|
963
|
+
|
|
964
|
+
|
|
931
965
|
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
966
|
|
|
937
|
-
|
|
938
967
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
968
|
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
|
|
951
978
|
|
|
952
979
|
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
|
|
953
983
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
984
|
|
|
958
|
-
|
|
985
|
+
|
|
959
986
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
987
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
|
|
969
993
|
|
|
970
994
|
|
|
971
|
-
|
|
995
|
+
class SipLine {
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
|
|
972
999
|
|
|
973
|
-
|
|
1000
|
+
|
|
974
1001
|
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
const SOURCE_MOBILE = 'mobile';
|
|
980
|
-
|
|
981
|
-
class Contact {
|
|
982
1002
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
|
|
990
1006
|
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
1007
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
static merge(oldContacts , newContacts ) {
|
|
1015
|
-
return newContacts.map(current => {
|
|
1016
|
-
const old = oldContacts.find(contact => contact && contact.is(current));
|
|
1017
1008
|
|
|
1018
|
-
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1009
|
+
static parse(plain ) {
|
|
1010
|
+
let { username, secret, host } = plain;
|
|
1021
1011
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
const bLastName = bNames.lastName;
|
|
1027
|
-
|
|
1028
|
-
// last Name can be empty
|
|
1029
|
-
if (aLastName === bLastName) {
|
|
1030
|
-
return aNames.firstName.localeCompare(bNames.firstName);
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
return aLastName.localeCompare(bLastName);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
static parseMany(response ) {
|
|
1037
|
-
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
static manyGraphQlWithNumbersParser(numbers ) {
|
|
1041
|
-
return (response ) => {
|
|
1042
|
-
if (!response.data || !response.data.me || !response.data.me.contacts) {
|
|
1043
|
-
return [];
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
return response.data.me.contacts.edges.map((edge, i) => {
|
|
1047
|
-
if (!edge.node) {
|
|
1048
|
-
return null;
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
const { email } = edge.node;
|
|
1052
|
-
const name = edge.node.firstname && edge.node.lastname
|
|
1053
|
-
? `${edge.node.firstname || ''} ${edge.node.lastname || ''}` : edge.node.wazoReverse;
|
|
1054
|
-
|
|
1055
|
-
return new Contact({
|
|
1056
|
-
name,
|
|
1057
|
-
number: numbers[i],
|
|
1058
|
-
numbers: [{ label: 'primary', number: numbers[i] }],
|
|
1059
|
-
backend: edge.node.wazoBackend,
|
|
1060
|
-
source: edge.node.wazoSourceName,
|
|
1061
|
-
sourceId: edge.node.wazoSourceEntryId || '',
|
|
1062
|
-
email: email || '',
|
|
1063
|
-
emails: email ? [{ label: 'primary', email }] : [],
|
|
1064
|
-
uuid: edge.node.userUuid,
|
|
1065
|
-
});
|
|
1066
|
-
}).filter(contact => !!contact);
|
|
1067
|
-
};
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
static fetchNumbers(plain , columns ) {
|
|
1071
|
-
const numberColumns = columns
|
|
1072
|
-
.map((e, index) => ({ index, columnName: e }))
|
|
1073
|
-
.filter(e => e.columnName === 'number' || e.columnName === 'callable')
|
|
1074
|
-
.map(e => e.index);
|
|
1075
|
-
|
|
1076
|
-
return plain.column_values.filter((e, index) => numberColumns.some(i => i === index) && e !== null);
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
static parse(plain , columns ) {
|
|
1080
|
-
const numbers = Contact.fetchNumbers(plain, columns);
|
|
1081
|
-
const email = plain.column_values[columns.indexOf('email')];
|
|
1082
|
-
|
|
1083
|
-
return new Contact({
|
|
1084
|
-
name: plain.column_values[columns.indexOf('name')],
|
|
1085
|
-
number: numbers.length ? numbers[0] : '',
|
|
1086
|
-
numbers: numbers.map((number, i) => ({ label: i === 0 ? 'primary' : 'secondary', number })),
|
|
1087
|
-
favorited: plain.column_values[columns.indexOf('favorite')],
|
|
1088
|
-
email: email || '',
|
|
1089
|
-
emails: email ? [{ label: 'primary', email }] : [],
|
|
1090
|
-
entreprise: plain.column_values[columns.indexOf('entreprise')] || '',
|
|
1091
|
-
birthday: plain.column_values[columns.indexOf('birthday')] || '',
|
|
1092
|
-
address: plain.column_values[columns.indexOf('address')] || '',
|
|
1093
|
-
note: plain.column_values[columns.indexOf('note')] || '',
|
|
1094
|
-
endpointId: plain.relations.endpoint_id,
|
|
1095
|
-
personal: plain.column_values[columns.indexOf('personal')],
|
|
1096
|
-
source: plain.source,
|
|
1097
|
-
sourceId: plain.relations.source_entry_id || '',
|
|
1098
|
-
uuid: plain.relations.user_uuid,
|
|
1099
|
-
backend: plain.backend || '',
|
|
1100
|
-
});
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
static parseManyPersonal(results ) {
|
|
1104
|
-
return results.map(r => Contact.parsePersonal(r));
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
static parsePersonal(plain ) {
|
|
1108
|
-
return new Contact({
|
|
1109
|
-
name: `${plain.firstName || plain.firstname || ''} ${plain.lastName || plain.lastname || ''}`,
|
|
1110
|
-
number: plain.number || '',
|
|
1111
|
-
numbers: plain.number ? [{ label: 'primary', number: plain.number }] : [],
|
|
1112
|
-
email: plain.email || '',
|
|
1113
|
-
emails: plain.email ? [{ label: 'primary', email: plain.email }] : [],
|
|
1114
|
-
source: 'personal',
|
|
1115
|
-
sourceId: plain.id || '',
|
|
1116
|
-
entreprise: plain.entreprise || '',
|
|
1117
|
-
birthday: plain.birthday || '',
|
|
1118
|
-
address: plain.address || '',
|
|
1119
|
-
note: plain.note || '',
|
|
1120
|
-
favorited: plain.favorited,
|
|
1121
|
-
personal: true,
|
|
1122
|
-
backend: plain.backend || BACKEND.PERSONAL,
|
|
1123
|
-
});
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
static parseMobile(plain ) {
|
|
1127
|
-
let address = '';
|
|
1128
|
-
if (plain.postalAddresses.length) {
|
|
1129
|
-
const postalAddress = plain.postalAddresses[0];
|
|
1130
|
-
|
|
1131
|
-
address = `${postalAddress.street} ${postalAddress.city} ${postalAddress.postCode} ${postalAddress.country}`;
|
|
1132
|
-
}
|
|
1133
|
-
|
|
1134
|
-
return new Contact({
|
|
1135
|
-
name: `${plain.givenName || ''} ${plain.familyName || ''}`,
|
|
1136
|
-
number: plain.phoneNumbers.length ? plain.phoneNumbers[0].number : '',
|
|
1137
|
-
numbers: plain.phoneNumbers.length ? [{ label: 'primary', number: plain.phoneNumbers[0].number }] : [],
|
|
1138
|
-
email: plain.emailAddresses.length ? plain.emailAddresses[0].email : '',
|
|
1139
|
-
emails: plain.emailAddresses.length ? [{ label: 'primary', email: plain.emailAddresses[0].email }] : [],
|
|
1140
|
-
source: SOURCE_MOBILE,
|
|
1141
|
-
sourceId: plain.recordID || '',
|
|
1142
|
-
birthday: plain.birthday ? `${plain.birthday.year}-${plain.birthday.month}-${plain.birthday.day}` : '',
|
|
1143
|
-
address,
|
|
1144
|
-
note: plain.note || '',
|
|
1145
|
-
favorited: false,
|
|
1146
|
-
personal: true,
|
|
1147
|
-
});
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
|
-
static parseManyOffice365(response , source ) {
|
|
1151
|
-
return response.map(r => Contact.parseOffice365(r, source));
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
static parseOffice365(single , source ) {
|
|
1155
|
-
const emails = [];
|
|
1156
|
-
const numbers = [];
|
|
1157
|
-
|
|
1158
|
-
if (single.emailAddresses) {
|
|
1159
|
-
single.emailAddresses.map(email => emails.push({ email: email.address }));
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
if (single.businessPhones) {
|
|
1163
|
-
single.businessPhones.map(phone => numbers.push({ label: 'business', number: phone }));
|
|
1164
|
-
}
|
|
1012
|
+
// Since 20.13 engine so options are now in section
|
|
1013
|
+
if (plain.auth_section_options) {
|
|
1014
|
+
// $FlowFixMe
|
|
1015
|
+
const findOption = (options , name ) => options.find(option => option[0] === name);
|
|
1165
1016
|
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1017
|
+
const usernameOption = findOption(plain.auth_section_options, 'username');
|
|
1018
|
+
const secretOption = findOption(plain.auth_section_options, 'password');
|
|
1019
|
+
const hostOption = findOption(plain.endpoint_section_options, 'media_address');
|
|
1169
1020
|
|
|
1170
|
-
|
|
1171
|
-
|
|
1021
|
+
username = usernameOption ? usernameOption[1] : '';
|
|
1022
|
+
secret = secretOption ? secretOption[1] : '';
|
|
1023
|
+
host = hostOption ? hostOption[1] : '';
|
|
1172
1024
|
}
|
|
1173
1025
|
|
|
1174
|
-
return new
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1026
|
+
return new SipLine({
|
|
1027
|
+
id: plain.id,
|
|
1028
|
+
uuid: plain.uuid,
|
|
1029
|
+
tenantUuid: plain.tenant_uuid,
|
|
1030
|
+
username,
|
|
1031
|
+
secret,
|
|
1032
|
+
type: plain.type,
|
|
1033
|
+
host,
|
|
1034
|
+
options: plain.options,
|
|
1035
|
+
endpointSectionOptions: plain.endpoint_section_options,
|
|
1036
|
+
links: plain.links,
|
|
1037
|
+
trunk: plain.trunk,
|
|
1038
|
+
line: plain.line,
|
|
1182
1039
|
});
|
|
1183
1040
|
}
|
|
1184
1041
|
|
|
1185
|
-
static
|
|
1186
|
-
return
|
|
1042
|
+
static newFrom(sipLine ) {
|
|
1043
|
+
return newFrom(sipLine, SipLine);
|
|
1187
1044
|
}
|
|
1188
1045
|
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
if (single.emails) {
|
|
1194
|
-
single.emails.forEach(email =>
|
|
1195
|
-
(typeof email === 'object' ? { email: email.address, label: email.label } : { email }));
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
|
-
if (single.numbers_by_label) {
|
|
1199
|
-
Object.keys(single.numbers_by_label).forEach(label =>
|
|
1200
|
-
numbers.push({ label, number: single.numbers_by_label[label] }));
|
|
1201
|
-
} else if (single.numbers) {
|
|
1202
|
-
single.numbers.forEach(phone => numbers.push({ number: phone }));
|
|
1046
|
+
is(line ) {
|
|
1047
|
+
if (line.uuid) {
|
|
1048
|
+
return this.uuid === line.uuid;
|
|
1203
1049
|
}
|
|
1204
|
-
|
|
1205
|
-
return new Contact({
|
|
1206
|
-
sourceId: single.id || '',
|
|
1207
|
-
name: single.name,
|
|
1208
|
-
number: numbers.length ? numbers[0].number : '',
|
|
1209
|
-
numbers,
|
|
1210
|
-
emails,
|
|
1211
|
-
source: source.name,
|
|
1212
|
-
backend: BACKEND.GOOGLE,
|
|
1213
|
-
});
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
static parseManyWazo(response , source ) {
|
|
1217
|
-
return response.map(r => Contact.parseWazo(r, source));
|
|
1050
|
+
return this.id === line.id;
|
|
1218
1051
|
}
|
|
1219
1052
|
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
if (single.email) {
|
|
1225
|
-
emails.push({ label: 'email', email: single.email });
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
if (single.exten) {
|
|
1229
|
-
numbers.push({ label: 'exten', number: single.exten });
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1232
|
-
if (single.mobile_phone_number) {
|
|
1233
|
-
numbers.push({ label: 'mobile', number: single.mobile_phone_number });
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
return new Contact({
|
|
1237
|
-
uuid: single.uuid,
|
|
1238
|
-
sourceId: String(single.id) || '',
|
|
1239
|
-
name: `${single.firstname}${single.lastname ? ` ${single.lastname}` : ''}`,
|
|
1240
|
-
number: numbers.length ? numbers[0].number : '',
|
|
1241
|
-
numbers,
|
|
1242
|
-
emails,
|
|
1243
|
-
source: source.name,
|
|
1244
|
-
backend: BACKEND.WAZO,
|
|
1245
|
-
});
|
|
1053
|
+
getOptions() {
|
|
1054
|
+
// `options` params have beend remove since 20.13... we should now use endpointSectionOptions
|
|
1055
|
+
return this.endpointSectionOptions || this.options || [];
|
|
1246
1056
|
}
|
|
1247
1057
|
|
|
1248
|
-
|
|
1249
|
-
return
|
|
1058
|
+
isWebRtc() {
|
|
1059
|
+
return this.getOptions().some(option => option[0] === 'webrtc' && option[1] === 'yes');
|
|
1250
1060
|
}
|
|
1251
1061
|
|
|
1252
|
-
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
if (single && single.extensions && single.extensions.length > 0 && single.extensions[0].exten) {
|
|
1257
|
-
firstNumber = single.extensions[0].exten;
|
|
1258
|
-
numbers.push({ label: 'exten', number: firstNumber });
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
return new Contact({
|
|
1262
|
-
sourceId: String(single.id),
|
|
1263
|
-
name: single.name,
|
|
1264
|
-
number: firstNumber,
|
|
1265
|
-
numbers,
|
|
1266
|
-
source: source.name,
|
|
1267
|
-
backend: 'conference',
|
|
1268
|
-
});
|
|
1062
|
+
hasVideo() {
|
|
1063
|
+
const allow = this.getOptions().find(option => option[0] === 'allow');
|
|
1064
|
+
return Array.isArray(allow) && allow[1].split(',').some(codec => availableCodecs.some(c => c === codec));
|
|
1269
1065
|
}
|
|
1270
1066
|
|
|
1271
|
-
|
|
1272
|
-
return
|
|
1067
|
+
hasVideoConference() {
|
|
1068
|
+
return (
|
|
1069
|
+
this.getOptions().some(option => option[0] === 'max_audio_streams' && parseInt(option[1], 10) > 0)
|
|
1070
|
+
&& this.getOptions().some(option => option[0] === 'max_video_streams' && parseInt(option[1], 10) > 1)
|
|
1071
|
+
);
|
|
1273
1072
|
}
|
|
1274
1073
|
|
|
1275
1074
|
constructor({
|
|
1276
1075
|
id,
|
|
1277
1076
|
uuid,
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
note,
|
|
1289
|
-
state,
|
|
1290
|
-
lineState,
|
|
1291
|
-
lastActivity,
|
|
1292
|
-
mobile,
|
|
1293
|
-
status,
|
|
1294
|
-
endpointId,
|
|
1295
|
-
personal,
|
|
1296
|
-
favorited,
|
|
1297
|
-
backend,
|
|
1298
|
-
personalStatus,
|
|
1299
|
-
sessions,
|
|
1300
|
-
connected,
|
|
1301
|
-
doNotDisturb,
|
|
1302
|
-
ringing,
|
|
1303
|
-
previousPresential,
|
|
1304
|
-
lines,
|
|
1077
|
+
tenantUuid,
|
|
1078
|
+
username,
|
|
1079
|
+
secret,
|
|
1080
|
+
type,
|
|
1081
|
+
host,
|
|
1082
|
+
options,
|
|
1083
|
+
endpointSectionOptions,
|
|
1084
|
+
links,
|
|
1085
|
+
trunk,
|
|
1086
|
+
line,
|
|
1305
1087
|
} = {}) {
|
|
1306
1088
|
this.id = id;
|
|
1307
1089
|
this.uuid = uuid;
|
|
1308
|
-
this.
|
|
1309
|
-
this.
|
|
1310
|
-
this.
|
|
1311
|
-
this.
|
|
1312
|
-
this.
|
|
1313
|
-
this.
|
|
1314
|
-
this.
|
|
1315
|
-
this.
|
|
1316
|
-
this.
|
|
1317
|
-
this.
|
|
1318
|
-
this.note = note;
|
|
1319
|
-
this.state = state;
|
|
1320
|
-
this.lineState = lineState;
|
|
1321
|
-
this.lastActivity = lastActivity;
|
|
1322
|
-
this.mobile = mobile;
|
|
1323
|
-
this.status = status;
|
|
1324
|
-
this.endpointId = endpointId;
|
|
1325
|
-
this.personal = personal;
|
|
1326
|
-
this.favorited = favorited;
|
|
1327
|
-
this.backend = backend;
|
|
1328
|
-
this.personalStatus = personalStatus || '';
|
|
1329
|
-
this.sessions = sessions || [];
|
|
1330
|
-
this.connected = connected;
|
|
1331
|
-
this.doNotDisturb = doNotDisturb;
|
|
1332
|
-
this.ringing = ringing;
|
|
1333
|
-
this.previousPresential = previousPresential;
|
|
1334
|
-
this.lines = lines || [];
|
|
1090
|
+
this.tenantUuid = tenantUuid;
|
|
1091
|
+
this.username = username;
|
|
1092
|
+
this.secret = secret;
|
|
1093
|
+
this.type = type;
|
|
1094
|
+
this.host = host;
|
|
1095
|
+
this.options = options;
|
|
1096
|
+
this.endpointSectionOptions = endpointSectionOptions;
|
|
1097
|
+
this.links = links;
|
|
1098
|
+
this.trunk = trunk;
|
|
1099
|
+
this.line = line;
|
|
1335
1100
|
|
|
1336
1101
|
// Useful to compare instead of instanceof with minified code
|
|
1337
|
-
this.type = '
|
|
1102
|
+
this.type = 'SipLine';
|
|
1338
1103
|
}
|
|
1104
|
+
}
|
|
1339
1105
|
|
|
1340
|
-
|
|
1341
|
-
this.favorited = value;
|
|
1106
|
+
//
|
|
1342
1107
|
|
|
1343
|
-
|
|
1344
|
-
|
|
1108
|
+
const STATE = {
|
|
1109
|
+
AVAILABLE: 'available',
|
|
1110
|
+
UNAVAILABLE: 'unavailable',
|
|
1111
|
+
INVISIBLE: 'invisible',
|
|
1112
|
+
DISCONNECTED: 'disconnected',
|
|
1113
|
+
AWAY: 'away',
|
|
1114
|
+
};
|
|
1345
1115
|
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1116
|
+
const LINE_STATE = {
|
|
1117
|
+
AVAILABLE: 'available',
|
|
1118
|
+
HOLDING: 'holding',
|
|
1119
|
+
RINGING: 'ringing',
|
|
1120
|
+
TALKING: 'talking',
|
|
1121
|
+
UNAVAILABLE: 'unavailable',
|
|
1122
|
+
PROGRESSING: 'progressing',
|
|
1123
|
+
};
|
|
1349
1124
|
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
|
|
1353
1183
|
|
|
1354
|
-
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
class Profile {
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
static parse(plain ) {
|
|
1234
|
+
return new Profile({
|
|
1235
|
+
id: plain.uuid,
|
|
1236
|
+
firstName: plain.firstName || plain.firstname || '',
|
|
1237
|
+
lastName: plain.lastName || plain.lastname || '',
|
|
1238
|
+
email: plain.email,
|
|
1239
|
+
lines: plain.lines.map(line => Line.parse(line)),
|
|
1240
|
+
username: plain.username,
|
|
1241
|
+
mobileNumber: plain.mobile_phone_number || '',
|
|
1242
|
+
forwards: [
|
|
1243
|
+
ForwardOption.parse(plain.forwards.unconditional, FORWARD_KEYS.UNCONDITIONAL),
|
|
1244
|
+
ForwardOption.parse(plain.forwards.noanswer, FORWARD_KEYS.NO_ANSWER),
|
|
1245
|
+
ForwardOption.parse(plain.forwards.busy, FORWARD_KEYS.BUSY),
|
|
1246
|
+
],
|
|
1247
|
+
doNotDisturb: plain.services.dnd.enabled,
|
|
1248
|
+
subscriptionType: plain.subscription_type,
|
|
1249
|
+
voicemail: plain.voicemail,
|
|
1250
|
+
switchboards: plain.switchboards || [],
|
|
1251
|
+
agent: plain.agent,
|
|
1252
|
+
status: '',
|
|
1253
|
+
callPickupTargetUsers: plain.call_pickup_target_users || [],
|
|
1254
|
+
onlineCallRecordEnabled: plain.online_call_record_enabled,
|
|
1255
|
+
});
|
|
1355
1256
|
}
|
|
1356
1257
|
|
|
1357
|
-
|
|
1358
|
-
return
|
|
1258
|
+
static newFrom(profile ) {
|
|
1259
|
+
return newFrom(profile, Profile);
|
|
1359
1260
|
}
|
|
1360
1261
|
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1262
|
+
constructor({
|
|
1263
|
+
id,
|
|
1264
|
+
firstName,
|
|
1265
|
+
lastName,
|
|
1266
|
+
email,
|
|
1267
|
+
lines,
|
|
1268
|
+
username,
|
|
1269
|
+
mobileNumber,
|
|
1270
|
+
forwards,
|
|
1271
|
+
doNotDisturb,
|
|
1272
|
+
state,
|
|
1273
|
+
subscriptionType,
|
|
1274
|
+
voicemail,
|
|
1275
|
+
switchboards,
|
|
1276
|
+
agent,
|
|
1277
|
+
status,
|
|
1278
|
+
sipLines,
|
|
1279
|
+
callPickupTargetUsers,
|
|
1280
|
+
onlineCallRecordEnabled,
|
|
1281
|
+
} = {}) {
|
|
1282
|
+
this.id = id;
|
|
1283
|
+
this.firstName = firstName;
|
|
1284
|
+
this.lastName = lastName;
|
|
1285
|
+
this.email = email;
|
|
1286
|
+
this.lines = lines;
|
|
1287
|
+
this.username = username;
|
|
1288
|
+
this.mobileNumber = mobileNumber;
|
|
1289
|
+
this.forwards = forwards;
|
|
1290
|
+
this.doNotDisturb = doNotDisturb;
|
|
1291
|
+
this.state = state;
|
|
1292
|
+
this.voicemail = voicemail;
|
|
1293
|
+
this.subscriptionType = subscriptionType;
|
|
1294
|
+
this.switchboards = switchboards;
|
|
1295
|
+
this.agent = agent;
|
|
1296
|
+
this.status = status;
|
|
1297
|
+
this.callPickupTargetUsers = callPickupTargetUsers;
|
|
1298
|
+
this.onlineCallRecordEnabled = onlineCallRecordEnabled;
|
|
1364
1299
|
|
|
1365
|
-
|
|
1366
|
-
return this.endpointId === endpointId;
|
|
1300
|
+
this.sipLines = sipLines || [];
|
|
1367
1301
|
}
|
|
1368
1302
|
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
}
|
|
1303
|
+
static getLinesState(lines ) {
|
|
1304
|
+
let result = LINE_STATE.UNAVAILABLE;
|
|
1372
1305
|
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1306
|
+
// eslint-disable-next-line
|
|
1307
|
+
for (const line of lines) {
|
|
1308
|
+
if (line.state === LINE_STATE.RINGING) {
|
|
1309
|
+
result = LINE_STATE.RINGING;
|
|
1310
|
+
break;
|
|
1311
|
+
}
|
|
1376
1312
|
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1313
|
+
if (line.state === LINE_STATE.TALKING) {
|
|
1314
|
+
result = LINE_STATE.TALKING;
|
|
1315
|
+
break;
|
|
1316
|
+
}
|
|
1380
1317
|
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1318
|
+
if (line.state === LINE_STATE.AVAILABLE) {
|
|
1319
|
+
result = LINE_STATE.AVAILABLE;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1384
1322
|
|
|
1385
|
-
|
|
1386
|
-
return this.lineState === LINE_STATE.TALKING || this.lineState === LINE_STATE.HOLDING;
|
|
1323
|
+
return result;
|
|
1387
1324
|
}
|
|
1388
1325
|
|
|
1389
|
-
|
|
1390
|
-
return this.
|
|
1326
|
+
hasId(id ) {
|
|
1327
|
+
return id === this.id;
|
|
1391
1328
|
}
|
|
1392
1329
|
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
}
|
|
1330
|
+
setMobileNumber(number ) {
|
|
1331
|
+
this.mobileNumber = number;
|
|
1396
1332
|
|
|
1397
|
-
|
|
1398
|
-
return this.lineState === LINE_STATE.PROGRESSING;
|
|
1333
|
+
return this;
|
|
1399
1334
|
}
|
|
1400
1335
|
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
});
|
|
1336
|
+
setForwardOption(forwardOption ) {
|
|
1337
|
+
const updatedForwardOptions = this.forwards.slice();
|
|
1338
|
+
const index = updatedForwardOptions.findIndex(forward => forward.is(forwardOption));
|
|
1339
|
+
updatedForwardOptions.splice(index, 1, forwardOption);
|
|
1406
1340
|
|
|
1407
|
-
|
|
1408
|
-
this.lineState = old.lineState;
|
|
1409
|
-
}
|
|
1341
|
+
this.forwards = updatedForwardOptions;
|
|
1410
1342
|
|
|
1411
1343
|
return this;
|
|
1412
1344
|
}
|
|
1413
1345
|
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
isCallable(session ) {
|
|
1419
|
-
return !!this.number && !!session && !session.is(this);
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
isFromMobile() {
|
|
1423
|
-
return this.source === SOURCE_MOBILE;
|
|
1424
|
-
}
|
|
1346
|
+
setDoNotDisturb(enabled ) {
|
|
1347
|
+
this.doNotDisturb = enabled;
|
|
1425
1348
|
|
|
1426
|
-
|
|
1427
|
-
return this.favorited;
|
|
1349
|
+
return this;
|
|
1428
1350
|
}
|
|
1429
1351
|
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
return {
|
|
1433
|
-
firstName: '',
|
|
1434
|
-
lastName: '',
|
|
1435
|
-
};
|
|
1436
|
-
}
|
|
1437
|
-
const names = this.name.split(/\s+/);
|
|
1438
|
-
const firstName = names[0];
|
|
1439
|
-
const lastName = names.slice(1).join(' ');
|
|
1352
|
+
setState(state ) {
|
|
1353
|
+
this.state = state;
|
|
1440
1354
|
|
|
1441
|
-
return
|
|
1442
|
-
firstName,
|
|
1443
|
-
lastName,
|
|
1444
|
-
};
|
|
1355
|
+
return this;
|
|
1445
1356
|
}
|
|
1446
1357
|
}
|
|
1447
1358
|
|
|
1448
|
-
//
|
|
1449
|
-
|
|
1450
|
-
const compareVersions = (a, b) => {
|
|
1451
|
-
let i;
|
|
1452
|
-
let diff;
|
|
1453
|
-
const regExStrip0 = /(\.0+)+$/;
|
|
1454
|
-
const segmentsA = a.replace(regExStrip0, '').split('.');
|
|
1455
|
-
const segmentsB = b.replace(regExStrip0, '').split('.');
|
|
1456
|
-
const l = Math.min(segmentsA.length, segmentsB.length);
|
|
1359
|
+
//
|
|
1360
|
+
|
|
1457
1361
|
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
}
|
|
1464
|
-
return segmentsA.length - segmentsB.length;
|
|
1362
|
+
const BACKEND = {
|
|
1363
|
+
OFFICE365: 'office365',
|
|
1364
|
+
PERSONAL: 'personal',
|
|
1365
|
+
GOOGLE: 'google',
|
|
1366
|
+
WAZO: 'wazo',
|
|
1465
1367
|
};
|
|
1466
1368
|
|
|
1467
|
-
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
|
|
1378
|
+
|
|
1379
|
+
|
|
1380
|
+
|
|
1468
1381
|
|
|
1469
|
-
|
|
1470
|
-
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
|
|
1397
|
+
|
|
1398
|
+
|
|
1399
|
+
|
|
1400
|
+
|
|
1401
|
+
|
|
1471
1402
|
|
|
1403
|
+
|
|
1404
|
+
|
|
1405
|
+
|
|
1406
|
+
|
|
1407
|
+
|
|
1408
|
+
|
|
1472
1409
|
|
|
1410
|
+
|
|
1411
|
+
|
|
1412
|
+
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
|
|
1418
|
+
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
|
|
1422
|
+
|
|
1473
1423
|
|
|
1474
1424
|
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
1425
|
|
|
1426
|
+
|
|
1427
|
+
|
|
1428
|
+
|
|
1429
|
+
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
|
|
1433
|
+
|
|
1434
|
+
|
|
1435
|
+
|
|
1436
|
+
|
|
1437
|
+
|
|
1438
|
+
|
|
1439
|
+
|
|
1440
|
+
|
|
1441
|
+
|
|
1442
|
+
// @see: https://github.com/rt2zz/react-native-contacts#example-contact-record
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
|
|
1446
|
+
|
|
1447
|
+
|
|
1448
|
+
|
|
1449
|
+
|
|
1482
1450
|
|
|
1451
|
+
|
|
1452
|
+
|
|
1453
|
+
|
|
1454
|
+
|
|
1483
1455
|
|
|
1484
|
-
|
|
1456
|
+
|
|
1485
1457
|
|
|
1458
|
+
|
|
1459
|
+
|
|
1460
|
+
|
|
1486
1461
|
|
|
1462
|
+
|
|
1463
|
+
|
|
1487
1464
|
|
|
1465
|
+
|
|
1466
|
+
|
|
1488
1467
|
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1468
|
+
|
|
1469
|
+
|
|
1494
1470
|
|
|
1495
|
-
|
|
1471
|
+
|
|
1472
|
+
|
|
1473
|
+
|
|
1474
|
+
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+
|
|
1496
1478
|
|
|
1497
1479
|
|
|
1498
1480
|
|
|
1481
|
+
|
|
1482
|
+
|
|
1483
|
+
|
|
1484
|
+
|
|
1485
|
+
|
|
1486
|
+
|
|
1499
1487
|
|
|
1500
|
-
|
|
1501
|
-
|
|
1488
|
+
|
|
1489
|
+
|
|
1490
|
+
|
|
1491
|
+
|
|
1492
|
+
|
|
1493
|
+
|
|
1494
|
+
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
|
|
1498
|
+
|
|
1499
|
+
|
|
1500
|
+
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
|
|
1504
|
+
|
|
1505
|
+
|
|
1506
|
+
|
|
1507
|
+
|
|
1508
|
+
|
|
1509
|
+
|
|
1502
1510
|
|
|
1503
1511
|
|
|
1504
1512
|
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
|
+
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
|
|
1505
1519
|
|
|
1506
|
-
|
|
1520
|
+
|
|
1521
|
+
|
|
1522
|
+
|
|
1523
|
+
|
|
1524
|
+
|
|
1525
|
+
|
|
1526
|
+
|
|
1527
|
+
|
|
1528
|
+
|
|
1507
1529
|
|
|
1530
|
+
|
|
1531
|
+
|
|
1532
|
+
|
|
1533
|
+
|
|
1534
|
+
|
|
1535
|
+
|
|
1536
|
+
|
|
1537
|
+
|
|
1538
|
+
|
|
1539
|
+
|
|
1508
1540
|
|
|
1541
|
+
|
|
1542
|
+
|
|
1509
1543
|
|
|
1510
1544
|
|
|
1511
|
-
|
|
1545
|
+
|
|
1546
|
+
|
|
1547
|
+
|
|
1548
|
+
|
|
1512
1549
|
|
|
1513
1550
|
|
|
1551
|
+
|
|
1552
|
+
|
|
1553
|
+
|
|
1554
|
+
|
|
1555
|
+
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
|
|
1561
|
+
|
|
1562
|
+
|
|
1563
|
+
|
|
1564
|
+
|
|
1514
1565
|
|
|
1515
|
-
|
|
1516
|
-
|
|
1566
|
+
|
|
1567
|
+
|
|
1568
|
+
|
|
1569
|
+
|
|
1570
|
+
|
|
1571
|
+
|
|
1517
1572
|
|
|
1573
|
+
|
|
1574
|
+
|
|
1575
|
+
|
|
1576
|
+
|
|
1577
|
+
|
|
1518
1578
|
|
|
1519
1579
|
|
|
1520
|
-
|
|
1580
|
+
const SOURCE_MOBILE = 'mobile';
|
|
1581
|
+
|
|
1582
|
+
class Contact {
|
|
1583
|
+
|
|
1584
|
+
|
|
1585
|
+
|
|
1521
1586
|
|
|
1522
1587
|
|
|
1523
|
-
|
|
1588
|
+
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
|
|
1594
|
+
|
|
1595
|
+
|
|
1524
1596
|
|
|
1525
1597
|
|
|
1598
|
+
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
|
|
1605
|
+
|
|
1606
|
+
|
|
1607
|
+
|
|
1608
|
+
|
|
1609
|
+
|
|
1526
1610
|
|
|
1527
|
-
|
|
1528
1611
|
|
|
1529
1612
|
|
|
1530
1613
|
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
static parse(plain ) {
|
|
1534
|
-
const token = plain.data.metadata ? plain.data.metadata.jwt : null;
|
|
1535
|
-
let authorizations = [];
|
|
1536
|
-
|
|
1537
|
-
// Add authorizations from JWT
|
|
1538
|
-
if (token) {
|
|
1539
|
-
const isValid = jws.JWS.verifyJWT(token, swarmKey, { alg: ['RS256'], verifyAt: new Date() });
|
|
1540
|
-
if (isValid) {
|
|
1541
|
-
const decodedToken = jws.JWS.readSafeJSONString(b64utoutf8(token.split('.')[1]));
|
|
1542
|
-
authorizations = decodedToken ? decodedToken.authorizations : [];
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
|
|
1546
|
-
return new Session({
|
|
1547
|
-
token: plain.data.token,
|
|
1548
|
-
refreshToken: plain.data.refresh_token || null,
|
|
1549
|
-
uuid: plain.data.metadata ? plain.data.metadata.uuid : null,
|
|
1550
|
-
sessionUuid: plain.data.session_uuid,
|
|
1551
|
-
authorizations,
|
|
1552
|
-
acl: plain.data.acls ? plain.data.acls : plain.data.acl ? plain.data.acl : [],
|
|
1553
|
-
tenantUuid: plain.data.metadata ? plain.data.metadata.tenant_uuid : undefined,
|
|
1554
|
-
expiresAt: new Date(`${plain.data.utc_expires_at}z`),
|
|
1555
|
-
engineUuid: plain.data.xivo_uuid,
|
|
1556
|
-
});
|
|
1557
|
-
}
|
|
1558
|
-
|
|
1559
|
-
static newFrom(profile ) {
|
|
1560
|
-
return newFrom(profile, Session);
|
|
1561
|
-
}
|
|
1562
|
-
|
|
1563
|
-
constructor({
|
|
1564
|
-
token,
|
|
1565
|
-
uuid,
|
|
1566
|
-
tenantUuid,
|
|
1567
|
-
profile,
|
|
1568
|
-
expiresAt,
|
|
1569
|
-
authorizations,
|
|
1570
|
-
acl,
|
|
1571
|
-
engineVersion,
|
|
1572
|
-
refreshToken,
|
|
1573
|
-
sessionUuid,
|
|
1574
|
-
engineUuid,
|
|
1575
|
-
} = {}) {
|
|
1576
|
-
this.token = token;
|
|
1577
|
-
this.uuid = uuid;
|
|
1578
|
-
this.tenantUuid = tenantUuid || null;
|
|
1579
|
-
this.profile = profile;
|
|
1580
|
-
this.expiresAt = expiresAt;
|
|
1581
|
-
this.authorizations = authorizations || [];
|
|
1582
|
-
this.acl = acl || [];
|
|
1583
|
-
this.engineVersion = engineVersion;
|
|
1584
|
-
this.refreshToken = refreshToken;
|
|
1585
|
-
this.sessionUuid = sessionUuid;
|
|
1586
|
-
this.engineUuid = engineUuid;
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
|
-
hasExpired(date = new Date()) {
|
|
1590
|
-
return date >= this.expiresAt;
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
is(contact ) {
|
|
1594
|
-
return Boolean(contact) && this.uuid === contact.uuid;
|
|
1595
|
-
}
|
|
1596
|
-
|
|
1597
|
-
using(profile ) {
|
|
1598
|
-
this.profile = profile;
|
|
1599
|
-
|
|
1600
|
-
return this;
|
|
1601
|
-
}
|
|
1602
|
-
|
|
1603
|
-
hasAuthorizations() {
|
|
1604
|
-
return this.authorizations && !!this.authorizations.length;
|
|
1605
|
-
}
|
|
1606
|
-
|
|
1607
|
-
displayName() {
|
|
1608
|
-
return this.profile ? `${this.profile.firstName} ${this.profile.lastName}` : '';
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
hasAccessToVoicemail() {
|
|
1612
|
-
if (!this.profile) {
|
|
1613
|
-
return false;
|
|
1614
|
-
}
|
|
1615
|
-
return !!this.profile.voicemail;
|
|
1616
|
-
}
|
|
1617
|
-
|
|
1618
|
-
primaryLine() {
|
|
1619
|
-
return this.profile && this.profile.lines.length > 0 ? this.profile.lines[0] : null;
|
|
1620
|
-
}
|
|
1621
|
-
|
|
1622
|
-
primarySipLine() {
|
|
1623
|
-
return this.profile && this.profile.sipLines.length > 0 ? this.profile.sipLines[0] : null;
|
|
1624
|
-
}
|
|
1625
|
-
|
|
1626
|
-
primaryWebRtcLine() {
|
|
1627
|
-
return this.profile && (this.profile.sipLines || []).find(sipLine => sipLine && sipLine.isWebRtc());
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
|
-
primaryCtiLine() {
|
|
1631
|
-
return this.profile && (this.profile.sipLines || []).find(sipLine => sipLine && !sipLine.isWebRtc());
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
|
-
primaryContext() {
|
|
1635
|
-
if (this.engineVersion) {
|
|
1636
|
-
if (this.hasEngineVersionGte(MINIMUM_WAZO_ENGINE_VERSION_FOR_DEFAULT_CONTEXT)) {
|
|
1637
|
-
return 'default';
|
|
1638
|
-
}
|
|
1639
|
-
}
|
|
1640
1614
|
|
|
1641
|
-
|
|
1615
|
+
static merge(oldContacts , newContacts ) {
|
|
1616
|
+
return newContacts.map(current => {
|
|
1617
|
+
const old = oldContacts.find(contact => contact && contact.is(current));
|
|
1642
1618
|
|
|
1643
|
-
|
|
1619
|
+
return old ? current.merge(old) : current;
|
|
1620
|
+
});
|
|
1644
1621
|
}
|
|
1645
1622
|
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1623
|
+
static sortContacts(a , b ) {
|
|
1624
|
+
const aNames = a.separateName();
|
|
1625
|
+
const bNames = b.separateName();
|
|
1626
|
+
const aLastName = aNames.lastName;
|
|
1627
|
+
const bLastName = bNames.lastName;
|
|
1649
1628
|
|
|
1650
|
-
|
|
1651
|
-
|
|
1629
|
+
// last Name can be empty
|
|
1630
|
+
if (aLastName === bLastName) {
|
|
1631
|
+
return aNames.firstName.localeCompare(bNames.firstName);
|
|
1632
|
+
}
|
|
1652
1633
|
|
|
1653
|
-
return
|
|
1634
|
+
return aLastName.localeCompare(bLastName);
|
|
1654
1635
|
}
|
|
1655
1636
|
|
|
1656
|
-
|
|
1657
|
-
return
|
|
1637
|
+
static parseMany(response ) {
|
|
1638
|
+
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
1658
1639
|
}
|
|
1659
1640
|
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1641
|
+
static manyGraphQlWithNumbersParser(numbers ) {
|
|
1642
|
+
return (response ) => {
|
|
1643
|
+
if (!response.data || !response.data.me || !response.data.me.contacts) {
|
|
1644
|
+
return [];
|
|
1645
|
+
}
|
|
1665
1646
|
|
|
1666
|
-
|
|
1667
|
-
|
|
1647
|
+
return response.data.me.contacts.edges.map((edge, i) => {
|
|
1648
|
+
if (!edge.node) {
|
|
1649
|
+
return null;
|
|
1650
|
+
}
|
|
1668
1651
|
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1652
|
+
const { email } = edge.node;
|
|
1653
|
+
const name = edge.node.firstname && edge.node.lastname
|
|
1654
|
+
? `${edge.node.firstname || ''} ${edge.node.lastname || ''}` : edge.node.wazoReverse;
|
|
1672
1655
|
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1656
|
+
return new Contact({
|
|
1657
|
+
name,
|
|
1658
|
+
number: numbers[i],
|
|
1659
|
+
numbers: [{ label: 'primary', number: numbers[i] }],
|
|
1660
|
+
backend: edge.node.wazoBackend,
|
|
1661
|
+
source: edge.node.wazoSourceName,
|
|
1662
|
+
sourceId: edge.node.wazoSourceEntryId || '',
|
|
1663
|
+
email: email || '',
|
|
1664
|
+
emails: email ? [{ label: 'primary', email }] : [],
|
|
1665
|
+
uuid: edge.node.userUuid,
|
|
1666
|
+
});
|
|
1667
|
+
}).filter(contact => !!contact);
|
|
1668
|
+
};
|
|
1676
1669
|
}
|
|
1677
|
-
}
|
|
1678
1670
|
|
|
1679
|
-
|
|
1680
|
-
|
|
1671
|
+
static fetchNumbers(plain , columns ) {
|
|
1672
|
+
const numberColumns = columns
|
|
1673
|
+
.map((e, index) => ({ index, columnName: e }))
|
|
1674
|
+
.filter(e => e.columnName === 'number' || e.columnName === 'callable')
|
|
1675
|
+
.map(e => e.index);
|
|
1681
1676
|
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
// $FlowFixMe
|
|
1685
|
-
if (
|
|
1686
|
-
(!instance[key] && from[key])
|
|
1687
|
-
|| (typeof instance[key] !== 'undefined' && typeof from[key] !== 'undefined' && instance[key] !== from[key])
|
|
1688
|
-
) {
|
|
1689
|
-
// $FlowFixMe
|
|
1690
|
-
instance[key] = from[key];
|
|
1691
|
-
}
|
|
1692
|
-
});
|
|
1693
|
-
};
|
|
1677
|
+
return plain.column_values.filter((e, index) => numberColumns.some(i => i === index) && e !== null);
|
|
1678
|
+
}
|
|
1694
1679
|
|
|
1695
|
-
|
|
1680
|
+
static parse(plain , columns ) {
|
|
1681
|
+
const numbers = Contact.fetchNumbers(plain, columns);
|
|
1682
|
+
const email = plain.column_values[columns.indexOf('email')];
|
|
1696
1683
|
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1684
|
+
return new Contact({
|
|
1685
|
+
name: plain.column_values[columns.indexOf('name')],
|
|
1686
|
+
number: numbers.length ? numbers[0] : '',
|
|
1687
|
+
numbers: numbers.map((number, i) => ({ label: i === 0 ? 'primary' : 'secondary', number })),
|
|
1688
|
+
favorited: plain.column_values[columns.indexOf('favorite')],
|
|
1689
|
+
email: email || '',
|
|
1690
|
+
emails: email ? [{ label: 'primary', email }] : [],
|
|
1691
|
+
entreprise: plain.column_values[columns.indexOf('entreprise')] || '',
|
|
1692
|
+
birthday: plain.column_values[columns.indexOf('birthday')] || '',
|
|
1693
|
+
address: plain.column_values[columns.indexOf('address')] || '',
|
|
1694
|
+
note: plain.column_values[columns.indexOf('note')] || '',
|
|
1695
|
+
endpointId: plain.relations.endpoint_id,
|
|
1696
|
+
personal: plain.column_values[columns.indexOf('personal')],
|
|
1697
|
+
source: plain.source,
|
|
1698
|
+
sourceId: plain.relations.source_entry_id || '',
|
|
1699
|
+
uuid: plain.relations.user_uuid,
|
|
1700
|
+
backend: plain.backend || '',
|
|
1701
|
+
});
|
|
1707
1702
|
}
|
|
1708
1703
|
|
|
1709
|
-
static
|
|
1710
|
-
return
|
|
1704
|
+
static parseManyPersonal(results ) {
|
|
1705
|
+
return results.map(r => Contact.parsePersonal(r));
|
|
1711
1706
|
}
|
|
1712
1707
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
this.timestamp = timestamp;
|
|
1731
|
-
this.status = status;
|
|
1732
|
-
this.errorId = errorId;
|
|
1733
|
-
this.details = details;
|
|
1734
|
-
this.error = error;
|
|
1708
|
+
static parsePersonal(plain ) {
|
|
1709
|
+
return new Contact({
|
|
1710
|
+
name: `${plain.firstName || plain.firstname || ''} ${plain.lastName || plain.lastname || ''}`,
|
|
1711
|
+
number: plain.number || '',
|
|
1712
|
+
numbers: plain.number ? [{ label: 'primary', number: plain.number }] : [],
|
|
1713
|
+
email: plain.email || '',
|
|
1714
|
+
emails: plain.email ? [{ label: 'primary', email: plain.email }] : [],
|
|
1715
|
+
source: 'personal',
|
|
1716
|
+
sourceId: plain.id || '',
|
|
1717
|
+
entreprise: plain.entreprise || '',
|
|
1718
|
+
birthday: plain.birthday || '',
|
|
1719
|
+
address: plain.address || '',
|
|
1720
|
+
note: plain.note || '',
|
|
1721
|
+
favorited: plain.favorited,
|
|
1722
|
+
personal: true,
|
|
1723
|
+
backend: plain.backend || BACKEND.PERSONAL,
|
|
1724
|
+
});
|
|
1735
1725
|
}
|
|
1736
|
-
}
|
|
1737
1726
|
|
|
1738
|
-
|
|
1727
|
+
static parseMobile(plain ) {
|
|
1728
|
+
let address = '';
|
|
1729
|
+
if (plain.postalAddresses.length) {
|
|
1730
|
+
const postalAddress = plain.postalAddresses[0];
|
|
1739
1731
|
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
return new ServerError(
|
|
1743
|
-
error.message || JSON.stringify(error),
|
|
1744
|
-
status,
|
|
1745
|
-
error.timestamp,
|
|
1746
|
-
error.error_id,
|
|
1747
|
-
error.details,
|
|
1748
|
-
);
|
|
1749
|
-
}
|
|
1732
|
+
address = `${postalAddress.street} ${postalAddress.city} ${postalAddress.postCode} ${postalAddress.country}`;
|
|
1733
|
+
}
|
|
1750
1734
|
|
|
1751
|
-
|
|
1752
|
-
|
|
1735
|
+
return new Contact({
|
|
1736
|
+
name: `${plain.givenName || ''} ${plain.familyName || ''}`,
|
|
1737
|
+
number: plain.phoneNumbers.length ? plain.phoneNumbers[0].number : '',
|
|
1738
|
+
numbers: plain.phoneNumbers.length ? [{ label: 'primary', number: plain.phoneNumbers[0].number }] : [],
|
|
1739
|
+
email: plain.emailAddresses.length ? plain.emailAddresses[0].email : '',
|
|
1740
|
+
emails: plain.emailAddresses.length ? [{ label: 'primary', email: plain.emailAddresses[0].email }] : [],
|
|
1741
|
+
source: SOURCE_MOBILE,
|
|
1742
|
+
sourceId: plain.recordID || '',
|
|
1743
|
+
birthday: plain.birthday ? `${plain.birthday.year}-${plain.birthday.month}-${plain.birthday.day}` : '',
|
|
1744
|
+
address,
|
|
1745
|
+
note: plain.note || '',
|
|
1746
|
+
favorited: false,
|
|
1747
|
+
personal: true,
|
|
1748
|
+
});
|
|
1753
1749
|
}
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
/* */
|
|
1757
|
-
/* global navigator */
|
|
1758
|
-
const isMobile = () => typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
|
|
1759
1750
|
|
|
1760
|
-
|
|
1751
|
+
static parseManyOffice365(response , source ) {
|
|
1752
|
+
return response.map(r => Contact.parseOffice365(r, source));
|
|
1753
|
+
}
|
|
1761
1754
|
|
|
1762
|
-
|
|
1763
|
-
const
|
|
1764
|
-
const
|
|
1765
|
-
const LOG = 'log';
|
|
1766
|
-
const WARN = 'warn';
|
|
1767
|
-
const ERROR = 'error';
|
|
1768
|
-
const CONSOLE_METHODS = [INFO, LOG, WARN, ERROR];
|
|
1769
|
-
const LOG_LEVELS = [TRACE, DEBUG, INFO, LOG, WARN, ERROR];
|
|
1770
|
-
const CATEGORY_PREFIX = 'logger-category=';
|
|
1755
|
+
static parseOffice365(single , source ) {
|
|
1756
|
+
const emails = [];
|
|
1757
|
+
const numbers = [];
|
|
1771
1758
|
|
|
1772
|
-
|
|
1759
|
+
if (single.emailAddresses) {
|
|
1760
|
+
single.emailAddresses.map(email => emails.push({ email: email.address }));
|
|
1761
|
+
}
|
|
1773
1762
|
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
instance.INFO = INFO;
|
|
1778
|
-
instance.LOG = LOG;
|
|
1779
|
-
instance.WARN = WARN;
|
|
1780
|
-
instance.ERROR = ERROR;
|
|
1763
|
+
if (single.businessPhones) {
|
|
1764
|
+
single.businessPhones.map(phone => numbers.push({ label: 'business', number: phone }));
|
|
1765
|
+
}
|
|
1781
1766
|
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
instance.info = (...args) => instance.apply(null, [INFO, ...args]);
|
|
1786
|
-
instance.log = (...args) => instance.apply(null, [LOG, ...args]);
|
|
1787
|
-
instance.warn = (...args) => instance.apply(null, [WARN, ...args]);
|
|
1788
|
-
instance.error = (...args) => instance.apply(null, [ERROR, ...args]);
|
|
1789
|
-
}
|
|
1767
|
+
if (single.mobilePhone) {
|
|
1768
|
+
numbers.push({ label: 'mobile', number: single.mobilePhone });
|
|
1769
|
+
}
|
|
1790
1770
|
|
|
1791
|
-
|
|
1792
|
-
};
|
|
1771
|
+
if (single.homePhones) {
|
|
1772
|
+
single.homePhones.map(phone => numbers.push({ label: 'home', number: phone }));
|
|
1773
|
+
}
|
|
1793
1774
|
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1775
|
+
return new Contact({
|
|
1776
|
+
sourceId: single.id || '',
|
|
1777
|
+
name: single.displayName || '',
|
|
1778
|
+
number: numbers.length ? numbers[0].number : '',
|
|
1779
|
+
numbers,
|
|
1780
|
+
emails,
|
|
1781
|
+
source: source.name,
|
|
1782
|
+
backend: BACKEND.OFFICE365,
|
|
1783
|
+
});
|
|
1800
1784
|
}
|
|
1801
1785
|
|
|
1802
|
-
|
|
1803
|
-
|
|
1786
|
+
static parseManyGoogle(response , source ) {
|
|
1787
|
+
return response.map(r => Contact.parseGoogle(r, source));
|
|
1788
|
+
}
|
|
1804
1789
|
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1790
|
+
static parseGoogle(single , source ) {
|
|
1791
|
+
const emails = [];
|
|
1792
|
+
const numbers = [];
|
|
1811
1793
|
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1794
|
+
if (single.emails) {
|
|
1795
|
+
single.emails.forEach(email =>
|
|
1796
|
+
(typeof email === 'object' ? { email: email.address, label: email.label } : { email }));
|
|
1797
|
+
}
|
|
1815
1798
|
|
|
1816
|
-
|
|
1817
|
-
|
|
1799
|
+
if (single.numbers_by_label) {
|
|
1800
|
+
Object.keys(single.numbers_by_label).forEach(label =>
|
|
1801
|
+
numbers.push({ label, number: single.numbers_by_label[label] }));
|
|
1802
|
+
} else if (single.numbers) {
|
|
1803
|
+
single.numbers.forEach(phone => numbers.push({ number: phone }));
|
|
1804
|
+
}
|
|
1818
1805
|
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1806
|
+
return new Contact({
|
|
1807
|
+
sourceId: single.id || '',
|
|
1808
|
+
name: single.name || '',
|
|
1809
|
+
number: numbers.length ? numbers[0].number : '',
|
|
1810
|
+
numbers,
|
|
1811
|
+
emails,
|
|
1812
|
+
source: source.name,
|
|
1813
|
+
backend: BACKEND.GOOGLE,
|
|
1814
|
+
});
|
|
1822
1815
|
}
|
|
1823
1816
|
|
|
1824
|
-
|
|
1825
|
-
|
|
1817
|
+
static parseManyWazo(response , source ) {
|
|
1818
|
+
return response.map(r => Contact.parseWazo(r, source));
|
|
1826
1819
|
}
|
|
1827
1820
|
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1821
|
+
static parseWazo(single , source ) {
|
|
1822
|
+
const emails = [];
|
|
1823
|
+
const numbers = [];
|
|
1831
1824
|
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
this.init();
|
|
1825
|
+
if (single.email) {
|
|
1826
|
+
emails.push({ label: 'email', email: single.email });
|
|
1835
1827
|
}
|
|
1836
1828
|
|
|
1837
|
-
|
|
1829
|
+
if (single.exten) {
|
|
1830
|
+
numbers.push({ label: 'exten', number: single.exten });
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
if (single.mobile_phone_number) {
|
|
1834
|
+
numbers.push({ label: 'mobile', number: single.mobile_phone_number });
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
return new Contact({
|
|
1838
|
+
uuid: single.uuid,
|
|
1839
|
+
sourceId: String(single.id) || '',
|
|
1840
|
+
name: `${single.firstname}${single.lastname ? ` ${single.lastname}` : ''}`,
|
|
1841
|
+
number: numbers.length ? numbers[0].number : '',
|
|
1842
|
+
numbers,
|
|
1843
|
+
emails,
|
|
1844
|
+
source: source.name,
|
|
1845
|
+
backend: BACKEND.WAZO,
|
|
1846
|
+
});
|
|
1838
1847
|
}
|
|
1839
1848
|
|
|
1840
|
-
|
|
1841
|
-
|
|
1849
|
+
static parseManyConference(response , source ) {
|
|
1850
|
+
return response.map(r => Contact.parseConference(r, source));
|
|
1842
1851
|
}
|
|
1843
1852
|
|
|
1844
|
-
|
|
1845
|
-
const
|
|
1846
|
-
|
|
1847
|
-
};
|
|
1853
|
+
static parseConference(single , source ) {
|
|
1854
|
+
const numbers = [];
|
|
1855
|
+
let firstNumber = '';
|
|
1848
1856
|
|
|
1849
|
-
|
|
1857
|
+
if (single && single.extensions && single.extensions.length > 0 && single.extensions[0].exten) {
|
|
1858
|
+
firstNumber = single.extensions[0].exten;
|
|
1859
|
+
numbers.push({ label: 'exten', number: firstNumber });
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
return new Contact({
|
|
1863
|
+
sourceId: String(single.id),
|
|
1864
|
+
name: single.name,
|
|
1865
|
+
number: firstNumber,
|
|
1866
|
+
numbers,
|
|
1867
|
+
source: source.name,
|
|
1868
|
+
backend: 'conference',
|
|
1869
|
+
});
|
|
1850
1870
|
}
|
|
1851
1871
|
|
|
1852
|
-
|
|
1853
|
-
return
|
|
1872
|
+
static newFrom(contact ) {
|
|
1873
|
+
return newFrom(contact, Contact);
|
|
1854
1874
|
}
|
|
1855
1875
|
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1876
|
+
constructor({
|
|
1877
|
+
id,
|
|
1878
|
+
uuid,
|
|
1879
|
+
name,
|
|
1880
|
+
number,
|
|
1881
|
+
numbers,
|
|
1882
|
+
email,
|
|
1883
|
+
emails,
|
|
1884
|
+
source,
|
|
1885
|
+
sourceId,
|
|
1886
|
+
entreprise,
|
|
1887
|
+
birthday,
|
|
1888
|
+
address,
|
|
1889
|
+
note,
|
|
1890
|
+
state,
|
|
1891
|
+
lineState,
|
|
1892
|
+
lastActivity,
|
|
1893
|
+
mobile,
|
|
1894
|
+
status,
|
|
1895
|
+
endpointId,
|
|
1896
|
+
personal,
|
|
1897
|
+
favorited,
|
|
1898
|
+
backend,
|
|
1899
|
+
personalStatus,
|
|
1900
|
+
sessions,
|
|
1901
|
+
connected,
|
|
1902
|
+
doNotDisturb,
|
|
1903
|
+
ringing,
|
|
1904
|
+
previousPresential,
|
|
1905
|
+
lines,
|
|
1906
|
+
} = {}) {
|
|
1907
|
+
this.id = id;
|
|
1908
|
+
this.uuid = uuid;
|
|
1909
|
+
this.name = name || '';
|
|
1910
|
+
this.number = number;
|
|
1911
|
+
this.numbers = numbers;
|
|
1912
|
+
this.email = email;
|
|
1913
|
+
this.emails = emails;
|
|
1914
|
+
this.source = source;
|
|
1915
|
+
this.sourceId = sourceId;
|
|
1916
|
+
this.entreprise = entreprise;
|
|
1917
|
+
this.birthday = birthday;
|
|
1918
|
+
this.address = address;
|
|
1919
|
+
this.note = note;
|
|
1920
|
+
this.state = state;
|
|
1921
|
+
this.lineState = lineState;
|
|
1922
|
+
this.lastActivity = lastActivity;
|
|
1923
|
+
this.mobile = mobile;
|
|
1924
|
+
this.status = status;
|
|
1925
|
+
this.endpointId = endpointId;
|
|
1926
|
+
this.personal = personal;
|
|
1927
|
+
this.favorited = favorited;
|
|
1928
|
+
this.backend = backend;
|
|
1929
|
+
this.personalStatus = personalStatus || '';
|
|
1930
|
+
this.sessions = sessions || [];
|
|
1931
|
+
this.connected = connected;
|
|
1932
|
+
this.doNotDisturb = doNotDisturb;
|
|
1933
|
+
this.ringing = ringing;
|
|
1934
|
+
this.previousPresential = previousPresential;
|
|
1935
|
+
this.lines = lines || [];
|
|
1860
1936
|
|
|
1861
|
-
//
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
if (args[0].indexOf(CATEGORY_PREFIX) === 0) {
|
|
1865
|
-
category = args[0].split('=')[1];
|
|
1866
|
-
// eslint-disable-next-line no-param-reassign
|
|
1867
|
-
args.splice(0, 1);
|
|
1868
|
-
}
|
|
1937
|
+
// Useful to compare instead of instanceof with minified code
|
|
1938
|
+
this.type = 'Contact';
|
|
1939
|
+
}
|
|
1869
1940
|
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
if (lastArg && ((typeof lastArg === 'object' && Object.keys(lastArg).length) || lastArg instanceof Error)) {
|
|
1873
|
-
if (lastArg instanceof Error) {
|
|
1874
|
-
extra = {
|
|
1875
|
-
errorMessage: lastArg.message,
|
|
1876
|
-
errorStack: lastArg.stack,
|
|
1877
|
-
errorType: lastArg.constructor.name,
|
|
1878
|
-
};
|
|
1879
|
-
} else {
|
|
1880
|
-
extra = lastArg;
|
|
1881
|
-
}
|
|
1882
|
-
// eslint-disable-next-line no-param-reassign
|
|
1883
|
-
args.splice(1, 1);
|
|
1884
|
-
}
|
|
1941
|
+
setFavorite(value ) {
|
|
1942
|
+
this.favorited = value;
|
|
1885
1943
|
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
let consoleMessage = message;
|
|
1944
|
+
return this;
|
|
1945
|
+
}
|
|
1889
1946
|
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
}
|
|
1947
|
+
is(other ) {
|
|
1948
|
+
const sameSourceId = this.sourceId !== null && other.sourceId !== null && this.sourceId === other.sourceId;
|
|
1949
|
+
const sameUuid = !!this.uuid && !!other.uuid && this.uuid === other.uuid;
|
|
1894
1950
|
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1951
|
+
const hasSameId = sameSourceId || sameUuid;
|
|
1952
|
+
const hasSameBackend = !!this.backend && !!other.backend && this.backend === other.backend;
|
|
1953
|
+
const hasSameSource = !!this.source && !!other.source && this.source === other.source;
|
|
1898
1954
|
|
|
1899
|
-
|
|
1900
|
-
|
|
1955
|
+
return !!other && hasSameId && hasSameBackend && hasSameSource;
|
|
1956
|
+
}
|
|
1901
1957
|
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1958
|
+
hasId(id ) {
|
|
1959
|
+
return this.uuid === id;
|
|
1960
|
+
}
|
|
1905
1961
|
|
|
1906
|
-
|
|
1962
|
+
hasNumber(number ) {
|
|
1963
|
+
return this.number === number;
|
|
1907
1964
|
}
|
|
1908
1965
|
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
}
|
|
1913
|
-
const { status } = response;
|
|
1914
|
-
const duration = new Date() - start;
|
|
1966
|
+
hasEndpointId(endpointId ) {
|
|
1967
|
+
return this.endpointId === endpointId;
|
|
1968
|
+
}
|
|
1915
1969
|
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
} else if (status >= 500) {
|
|
1920
|
-
level = ERROR;
|
|
1921
|
-
}
|
|
1970
|
+
isAvailable() {
|
|
1971
|
+
return this.state === STATE.AVAILABLE;
|
|
1972
|
+
}
|
|
1922
1973
|
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
});
|
|
1974
|
+
isAway() {
|
|
1975
|
+
return this.state === STATE.AWAY;
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
isUnavailable() {
|
|
1979
|
+
return this.state === STATE.UNAVAILABLE;
|
|
1930
1980
|
}
|
|
1931
1981
|
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
console.warn('IssueReporter\'s logs aren\'t stored anymore. Please use fluentd to store them');
|
|
1935
|
-
return [];
|
|
1982
|
+
isInvisible() {
|
|
1983
|
+
return this.state === STATE.INVISIBLE;
|
|
1936
1984
|
}
|
|
1937
1985
|
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
return [];
|
|
1986
|
+
isInCall() {
|
|
1987
|
+
return this.lineState === LINE_STATE.TALKING || this.lineState === LINE_STATE.HOLDING;
|
|
1941
1988
|
}
|
|
1942
1989
|
|
|
1943
|
-
|
|
1944
|
-
return this.
|
|
1990
|
+
isRinging() {
|
|
1991
|
+
return this.ringing;
|
|
1945
1992
|
}
|
|
1946
1993
|
|
|
1947
|
-
|
|
1948
|
-
this.
|
|
1949
|
-
CONSOLE_METHODS.forEach((methodName ) => {
|
|
1950
|
-
// eslint-disable-next-line
|
|
1951
|
-
this.oldConsoleMethods[methodName] = console[methodName];
|
|
1952
|
-
window.console[methodName] = (...args) => {
|
|
1953
|
-
// Store message
|
|
1954
|
-
try {
|
|
1955
|
-
this.log(methodName, args.join(' '));
|
|
1956
|
-
// Use old console method to log it normally
|
|
1957
|
-
this.oldConsoleMethods[methodName].apply(null, args);
|
|
1958
|
-
} catch (e) {
|
|
1959
|
-
// Avoid circular structure issues
|
|
1960
|
-
}
|
|
1961
|
-
};
|
|
1962
|
-
});
|
|
1994
|
+
isInUseOrRinging() {
|
|
1995
|
+
return this.lineState === LINE_STATE.TALKING || this.lineState === LINE_STATE.RINGING;
|
|
1963
1996
|
}
|
|
1964
1997
|
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
}
|
|
1998
|
+
isProgressing() {
|
|
1999
|
+
return this.lineState === LINE_STATE.PROGRESSING;
|
|
2000
|
+
}
|
|
1969
2001
|
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
2002
|
+
merge(old ) {
|
|
2003
|
+
Object.keys(old).filter(key => key !== 'lineState').forEach(key => {
|
|
2004
|
+
// $FlowFixMe
|
|
2005
|
+
this[key] = old[key] || this[key];
|
|
2006
|
+
});
|
|
2007
|
+
|
|
2008
|
+
if (old.lineState && !this.lineState) {
|
|
2009
|
+
this.lineState = old.lineState;
|
|
1973
2010
|
}
|
|
1974
2011
|
|
|
1975
|
-
|
|
1976
|
-
|
|
2012
|
+
return this;
|
|
2013
|
+
}
|
|
1977
2014
|
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
headers: {
|
|
1981
|
-
Accept: 'application/json',
|
|
1982
|
-
'Content-Type': 'application/json',
|
|
1983
|
-
},
|
|
1984
|
-
body: safeStringify({
|
|
1985
|
-
level,
|
|
1986
|
-
...payload,
|
|
1987
|
-
...extra,
|
|
1988
|
-
}),
|
|
1989
|
-
}).catch(() => {
|
|
1990
|
-
setTimeout(() => {
|
|
1991
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
1992
|
-
payload._retry = retry + 1;
|
|
1993
|
-
this._sendToRemoteLogger(level, payload, retry + 1);
|
|
1994
|
-
}, 5000 + retry * 1000);
|
|
1995
|
-
});
|
|
2015
|
+
isIntern() {
|
|
2016
|
+
return !!this.uuid;
|
|
1996
2017
|
}
|
|
1997
2018
|
|
|
1998
|
-
|
|
1999
|
-
return
|
|
2019
|
+
isCallable(session ) {
|
|
2020
|
+
return !!this.number && !!session && !session.is(this);
|
|
2000
2021
|
}
|
|
2001
2022
|
|
|
2002
|
-
|
|
2003
|
-
return
|
|
2023
|
+
isFromMobile() {
|
|
2024
|
+
return this.source === SOURCE_MOBILE;
|
|
2004
2025
|
}
|
|
2005
|
-
}
|
|
2006
2026
|
|
|
2007
|
-
|
|
2027
|
+
isFavorite() {
|
|
2028
|
+
return this.favorited;
|
|
2029
|
+
}
|
|
2008
2030
|
|
|
2009
|
-
|
|
2031
|
+
separateName() {
|
|
2032
|
+
if (!this.name) {
|
|
2033
|
+
return {
|
|
2034
|
+
firstName: '',
|
|
2035
|
+
lastName: '',
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
const names = this.name.split(/\s+/);
|
|
2039
|
+
const firstName = names[0];
|
|
2040
|
+
const lastName = names.slice(1).join(' ');
|
|
2010
2041
|
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2042
|
+
return {
|
|
2043
|
+
firstName,
|
|
2044
|
+
lastName,
|
|
2045
|
+
};
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2019
2048
|
|
|
2020
|
-
|
|
2049
|
+
// Can't use `semver` package as Wazo version aren't in semver format
|
|
2021
2050
|
|
|
2022
|
-
const
|
|
2051
|
+
const compareVersions = (a, b) => {
|
|
2052
|
+
let i;
|
|
2053
|
+
let diff;
|
|
2054
|
+
const regExStrip0 = /(\.0+)+$/;
|
|
2055
|
+
const segmentsA = a.replace(regExStrip0, '').split('.');
|
|
2056
|
+
const segmentsB = b.replace(regExStrip0, '').split('.');
|
|
2057
|
+
const l = Math.min(segmentsA.length, segmentsB.length);
|
|
2023
2058
|
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2059
|
+
for (i = 0; i < l; i++) {
|
|
2060
|
+
diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
|
|
2061
|
+
if (diff) {
|
|
2062
|
+
return diff;
|
|
2063
|
+
}
|
|
2029
2064
|
}
|
|
2065
|
+
return segmentsA.length - segmentsB.length;
|
|
2066
|
+
};
|
|
2030
2067
|
|
|
2031
|
-
|
|
2032
|
-
// React native
|
|
2033
|
-
return fetch;
|
|
2034
|
-
}
|
|
2068
|
+
//
|
|
2035
2069
|
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
// Used to trick the optimizer to avoid requiring `node-fetch/lib/index` directly
|
|
2039
|
-
// It causes to require it on browsers when delivered by a nodejs engine (cf: vitejs).
|
|
2040
|
-
try {
|
|
2041
|
-
// $FlowFixMe
|
|
2042
|
-
return require(Math.random() >= 0 ? 'node-fetch/lib/index' : '');
|
|
2043
|
-
} catch (e) {
|
|
2044
|
-
return fetch;
|
|
2045
|
-
}
|
|
2046
|
-
};
|
|
2070
|
+
const swarmKey = KEYUTIL.getKey(swarmPublicKey);
|
|
2071
|
+
const MINIMUM_WAZO_ENGINE_VERSION_FOR_DEFAULT_CONTEXT = '19.08';
|
|
2047
2072
|
|
|
2048
|
-
class ApiRequester {
|
|
2049
2073
|
|
|
2074
|
+
|
|
2050
2075
|
|
|
2076
|
+
|
|
2077
|
+
|
|
2078
|
+
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
|
|
2051
2083
|
|
|
2084
|
+
|
|
2085
|
+
|
|
2052
2086
|
|
|
2053
|
-
|
|
2087
|
+
|
|
2088
|
+
|
|
2089
|
+
|
|
2090
|
+
|
|
2091
|
+
|
|
2092
|
+
|
|
2054
2093
|
|
|
2055
|
-
|
|
2056
|
-
|
|
2094
|
+
|
|
2095
|
+
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
|
|
2099
|
+
|
|
2100
|
+
|
|
2101
|
+
|
|
2102
|
+
|
|
2103
|
+
|
|
2104
|
+
|
|
2057
2105
|
|
|
2106
|
+
|
|
2107
|
+
|
|
2058
2108
|
|
|
2059
2109
|
|
|
2110
|
+
|
|
2111
|
+
|
|
2060
2112
|
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
static defaultParser(response ) {
|
|
2070
|
-
return response.json().then((data ) => data);
|
|
2071
|
-
}
|
|
2113
|
+
|
|
2114
|
+
|
|
2115
|
+
|
|
2116
|
+
|
|
2117
|
+
|
|
2118
|
+
|
|
2119
|
+
|
|
2072
2120
|
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2121
|
+
class Session {
|
|
2122
|
+
|
|
2123
|
+
|
|
2124
|
+
|
|
2125
|
+
|
|
2126
|
+
|
|
2127
|
+
|
|
2128
|
+
|
|
2129
|
+
|
|
2130
|
+
|
|
2131
|
+
|
|
2132
|
+
|
|
2079
2133
|
|
|
2080
|
-
static
|
|
2081
|
-
|
|
2082
|
-
|
|
2134
|
+
static parse(plain ) {
|
|
2135
|
+
const token = plain.data.metadata ? plain.data.metadata.jwt : null;
|
|
2136
|
+
let authorizations = [];
|
|
2083
2137
|
|
|
2084
|
-
|
|
2085
|
-
constructor({ server, refreshTokenCallback, clientId, agent = null, token = null, fetchOptions } ) {
|
|
2086
|
-
this.server = server;
|
|
2087
|
-
this.agent = agent;
|
|
2088
|
-
this.clientId = clientId;
|
|
2089
|
-
this.refreshTokenCallback = refreshTokenCallback;
|
|
2090
|
-
this.refreshTokenPromise = null;
|
|
2091
|
-
this.fetchOptions = fetchOptions || {};
|
|
2138
|
+
// Add authorizations from JWT
|
|
2092
2139
|
if (token) {
|
|
2093
|
-
|
|
2140
|
+
const isValid = jws.JWS.verifyJWT(token, swarmKey, { alg: ['RS256'], verifyAt: new Date() });
|
|
2141
|
+
if (isValid) {
|
|
2142
|
+
const decodedToken = jws.JWS.readSafeJSONString(b64utoutf8(token.split('.')[1]));
|
|
2143
|
+
authorizations = decodedToken ? decodedToken.authorizations : [];
|
|
2144
|
+
}
|
|
2094
2145
|
}
|
|
2095
2146
|
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2147
|
+
return new Session({
|
|
2148
|
+
token: plain.data.token,
|
|
2149
|
+
refreshToken: plain.data.refresh_token || null,
|
|
2150
|
+
uuid: plain.data.metadata ? plain.data.metadata.uuid : null,
|
|
2151
|
+
sessionUuid: plain.data.session_uuid,
|
|
2152
|
+
authorizations,
|
|
2153
|
+
acl: plain.data.acls ? plain.data.acls : plain.data.acl ? plain.data.acl : [],
|
|
2154
|
+
tenantUuid: plain.data.metadata ? plain.data.metadata.tenant_uuid : undefined,
|
|
2155
|
+
expiresAt: new Date(`${plain.data.utc_expires_at}z`),
|
|
2156
|
+
engineUuid: plain.data.xivo_uuid,
|
|
2104
2157
|
});
|
|
2105
2158
|
}
|
|
2106
2159
|
|
|
2107
|
-
|
|
2108
|
-
|
|
2160
|
+
static newFrom(profile ) {
|
|
2161
|
+
return newFrom(profile, Session);
|
|
2109
2162
|
}
|
|
2110
2163
|
|
|
2111
|
-
|
|
2164
|
+
constructor({
|
|
2165
|
+
token,
|
|
2166
|
+
uuid,
|
|
2167
|
+
tenantUuid,
|
|
2168
|
+
profile,
|
|
2169
|
+
expiresAt,
|
|
2170
|
+
authorizations,
|
|
2171
|
+
acl,
|
|
2172
|
+
engineVersion,
|
|
2173
|
+
refreshToken,
|
|
2174
|
+
sessionUuid,
|
|
2175
|
+
engineUuid,
|
|
2176
|
+
} = {}) {
|
|
2112
2177
|
this.token = token;
|
|
2178
|
+
this.uuid = uuid;
|
|
2179
|
+
this.tenantUuid = tenantUuid || null;
|
|
2180
|
+
this.profile = profile;
|
|
2181
|
+
this.expiresAt = expiresAt;
|
|
2182
|
+
this.authorizations = authorizations || [];
|
|
2183
|
+
this.acl = acl || [];
|
|
2184
|
+
this.engineVersion = engineVersion;
|
|
2185
|
+
this.refreshToken = refreshToken;
|
|
2186
|
+
this.sessionUuid = sessionUuid;
|
|
2187
|
+
this.engineUuid = engineUuid;
|
|
2113
2188
|
}
|
|
2114
2189
|
|
|
2115
|
-
|
|
2116
|
-
this.
|
|
2190
|
+
hasExpired(date = new Date()) {
|
|
2191
|
+
return date >= this.expiresAt;
|
|
2117
2192
|
}
|
|
2118
2193
|
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
body = null,
|
|
2123
|
-
headers = null,
|
|
2124
|
-
parse = ApiRequester.defaultParser,
|
|
2125
|
-
firstCall = true,
|
|
2126
|
-
) {
|
|
2127
|
-
const url = this.computeUrl(method, path, body);
|
|
2128
|
-
const newHeaders = this.getHeaders(headers);
|
|
2129
|
-
let newBody = method === 'get' ? null : body;
|
|
2130
|
-
if (newBody && newHeaders['Content-Type'] === 'application/json') {
|
|
2131
|
-
newBody = JSON.stringify(newBody);
|
|
2132
|
-
}
|
|
2133
|
-
const isHead = method === 'head';
|
|
2134
|
-
const hasEmptyResponse = method === 'delete' || isHead;
|
|
2135
|
-
const newParse = hasEmptyResponse ? ApiRequester.successResponseParser : parse;
|
|
2136
|
-
|
|
2137
|
-
const fetchOptions = { ...this.fetchOptions || {} };
|
|
2138
|
-
const extraHeaders = fetchOptions.headers || {};
|
|
2139
|
-
delete fetchOptions.headers;
|
|
2194
|
+
is(contact ) {
|
|
2195
|
+
return Boolean(contact) && this.uuid === contact.uuid;
|
|
2196
|
+
}
|
|
2140
2197
|
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
body: newBody,
|
|
2144
|
-
headers: { ...this.getHeaders(headers), ...extraHeaders },
|
|
2145
|
-
agent: this.agent,
|
|
2146
|
-
...fetchOptions,
|
|
2147
|
-
};
|
|
2198
|
+
using(profile ) {
|
|
2199
|
+
this.profile = profile;
|
|
2148
2200
|
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
await this.refreshTokenPromise;
|
|
2152
|
-
}
|
|
2201
|
+
return this;
|
|
2202
|
+
}
|
|
2153
2203
|
|
|
2154
|
-
|
|
2204
|
+
hasAuthorizations() {
|
|
2205
|
+
return this.authorizations && !!this.authorizations.length;
|
|
2206
|
+
}
|
|
2155
2207
|
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2208
|
+
displayName() {
|
|
2209
|
+
return this.profile ? `${this.profile.firstName} ${this.profile.lastName}` : '';
|
|
2210
|
+
}
|
|
2159
2211
|
|
|
2160
|
-
|
|
2212
|
+
hasAccessToVoicemail() {
|
|
2213
|
+
if (!this.profile) {
|
|
2214
|
+
return false;
|
|
2215
|
+
}
|
|
2216
|
+
return !!this.profile.voicemail;
|
|
2217
|
+
}
|
|
2161
2218
|
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
const exceptionClass = response.status >= 500 ? ServerError : BadResponse;
|
|
2219
|
+
primaryLine() {
|
|
2220
|
+
return this.profile && this.profile.lines.length > 0 ? this.profile.lines[0] : null;
|
|
2221
|
+
}
|
|
2166
2222
|
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
logger$1.warn('token expired', { error: err.reason });
|
|
2171
|
-
// Replay the call after refreshing the token
|
|
2172
|
-
return this._replayWithNewToken(err, path, method, body, headers, parse);
|
|
2173
|
-
}
|
|
2223
|
+
primarySipLine() {
|
|
2224
|
+
return this.profile && this.profile.sipLines.length > 0 ? this.profile.sipLines[0] : null;
|
|
2225
|
+
}
|
|
2174
2226
|
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2227
|
+
primaryWebRtcLine() {
|
|
2228
|
+
return this.profile && (this.profile.sipLines || []).find(sipLine => sipLine && sipLine.isWebRtc());
|
|
2229
|
+
}
|
|
2178
2230
|
|
|
2179
|
-
|
|
2231
|
+
primaryCtiLine() {
|
|
2232
|
+
return this.profile && (this.profile.sipLines || []).find(sipLine => sipLine && !sipLine.isWebRtc());
|
|
2233
|
+
}
|
|
2180
2234
|
|
|
2181
|
-
|
|
2182
|
-
|
|
2235
|
+
primaryContext() {
|
|
2236
|
+
if (this.engineVersion) {
|
|
2237
|
+
if (this.hasEngineVersionGte(MINIMUM_WAZO_ENGINE_VERSION_FOR_DEFAULT_CONTEXT)) {
|
|
2238
|
+
return 'default';
|
|
2183
2239
|
}
|
|
2240
|
+
}
|
|
2184
2241
|
|
|
2185
|
-
|
|
2186
|
-
}).catch(error => {
|
|
2187
|
-
logger$1.error('Fetch failed', { url, options, message: error.message, stack: error.stack });
|
|
2188
|
-
|
|
2189
|
-
throw error;
|
|
2190
|
-
});
|
|
2191
|
-
}
|
|
2192
|
-
|
|
2193
|
-
_checkTokenExpired(response , err ) {
|
|
2194
|
-
// Special case when authenticating form a token: we got a 404
|
|
2195
|
-
const isTokenNotFound = response.status === 404 && this._isTokenNotFound(err);
|
|
2242
|
+
const line = this.primaryLine();
|
|
2196
2243
|
|
|
2197
|
-
return
|
|
2244
|
+
return line && line.extensions.length > 0 ? line.extensions[0].context : 'default';
|
|
2198
2245
|
}
|
|
2199
2246
|
|
|
2200
|
-
|
|
2201
|
-
return
|
|
2247
|
+
hasEngineVersionGte(version ) {
|
|
2248
|
+
return this.engineVersion && compareVersions(String(this.engineVersion), String(version)) >= 0;
|
|
2202
2249
|
}
|
|
2203
2250
|
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
path ,
|
|
2207
|
-
method ,
|
|
2208
|
-
body = null,
|
|
2209
|
-
headers = null,
|
|
2210
|
-
parse ,
|
|
2211
|
-
) {
|
|
2212
|
-
const isTokenNotFound = this._isTokenNotFound(err);
|
|
2213
|
-
let newPath = path;
|
|
2214
|
-
logger$1.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
|
|
2215
|
-
|
|
2216
|
-
this.refreshTokenPromise = this.refreshTokenPromise || this.refreshTokenCallback();
|
|
2251
|
+
primaryNumber() {
|
|
2252
|
+
const line = this.primaryLine();
|
|
2217
2253
|
|
|
2218
|
-
return
|
|
2219
|
-
|
|
2220
|
-
logger$1.info('token refreshed', { isTokenNotFound });
|
|
2221
|
-
if (isTokenNotFound) {
|
|
2222
|
-
const pathParts = path.split('/');
|
|
2223
|
-
pathParts.pop();
|
|
2224
|
-
pathParts.push(this.token);
|
|
2225
|
-
newPath = pathParts.join('/');
|
|
2226
|
-
}
|
|
2254
|
+
return line && line.extensions.length ? line.extensions[0].exten : null;
|
|
2255
|
+
}
|
|
2227
2256
|
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
this.refreshTokenPromise = null;
|
|
2231
|
-
throw e;
|
|
2232
|
-
});
|
|
2257
|
+
allLines() {
|
|
2258
|
+
return this.profile ? this.profile.lines || [] : [];
|
|
2233
2259
|
}
|
|
2234
2260
|
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2261
|
+
allNumbers() {
|
|
2262
|
+
const extensions = this.allLines().map(line => line.extensions.map(extension => extension.exten));
|
|
2263
|
+
if (!extensions.length) {
|
|
2264
|
+
return [];
|
|
2238
2265
|
}
|
|
2239
2266
|
|
|
2240
|
-
return
|
|
2241
|
-
'X-Auth-Token': this.token,
|
|
2242
|
-
...(this.tenant ? { 'Wazo-Tenant': this.tenant } : null),
|
|
2243
|
-
Accept: 'application/json',
|
|
2244
|
-
'Content-Type': 'application/json',
|
|
2245
|
-
};
|
|
2267
|
+
return extensions.reduce((a, b) => a.concat(b));
|
|
2246
2268
|
}
|
|
2247
2269
|
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
return method === 'get' && body && Object.keys(body).length ? `${url}?${ApiRequester.getQueryString(body)}` : url;
|
|
2270
|
+
hasExtension(extension ) {
|
|
2271
|
+
return this.allNumbers().some(number => number === extension);
|
|
2252
2272
|
}
|
|
2253
2273
|
|
|
2254
|
-
get
|
|
2255
|
-
|
|
2274
|
+
get acls() {
|
|
2275
|
+
console.warn('`acls` property of Session has been removed in Wazo\'s SDK, please use `acl` instead.');
|
|
2276
|
+
return this.acl;
|
|
2256
2277
|
}
|
|
2257
2278
|
}
|
|
2258
2279
|
|
|
@@ -2988,17 +3009,66 @@ class Voicemail {
|
|
|
2988
3009
|
|
|
2989
3010
|
//
|
|
2990
3011
|
|
|
3012
|
+
|
|
3013
|
+
|
|
3014
|
+
|
|
3015
|
+
|
|
3016
|
+
|
|
3017
|
+
|
|
3018
|
+
|
|
3019
|
+
|
|
3020
|
+
|
|
3021
|
+
|
|
3022
|
+
|
|
3023
|
+
|
|
3024
|
+
|
|
3025
|
+
|
|
3026
|
+
|
|
3027
|
+
|
|
3028
|
+
class Recording {
|
|
3029
|
+
|
|
3030
|
+
|
|
3031
|
+
|
|
3032
|
+
|
|
3033
|
+
|
|
3034
|
+
|
|
3035
|
+
static parseMany(recordings ) {
|
|
3036
|
+
return recordings.map(item => Recording.parse(item));
|
|
3037
|
+
}
|
|
3038
|
+
|
|
3039
|
+
static parse(plain ) {
|
|
3040
|
+
return new Recording({
|
|
3041
|
+
deleted: plain.deleted,
|
|
3042
|
+
fileName: plain.filename,
|
|
3043
|
+
end: plain.end_time ? moment(plain.end_time).toDate() : null,
|
|
3044
|
+
start: moment(plain.start_time).toDate(),
|
|
3045
|
+
uuid: plain.uuid,
|
|
3046
|
+
});
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3049
|
+
constructor({ deleted, end, fileName, start, uuid } ) {
|
|
3050
|
+
this.deleted = deleted;
|
|
3051
|
+
this.end = end;
|
|
3052
|
+
this.fileName = fileName;
|
|
3053
|
+
this.start = start;
|
|
3054
|
+
this.uuid = uuid;
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
//
|
|
3059
|
+
|
|
2991
3060
|
|
|
2992
|
-
|
|
3061
|
+
|
|
2993
3062
|
|
|
2994
3063
|
|
|
2995
3064
|
|
|
2996
3065
|
|
|
2997
3066
|
|
|
2998
|
-
|
|
3067
|
+
|
|
2999
3068
|
|
|
3000
3069
|
|
|
3001
3070
|
|
|
3071
|
+
|
|
3002
3072
|
|
|
3003
3073
|
|
|
3004
3074
|
|
|
@@ -3011,7 +3081,7 @@ class Voicemail {
|
|
|
3011
3081
|
|
|
3012
3082
|
|
|
3013
3083
|
|
|
3014
|
-
|
|
3084
|
+
|
|
3015
3085
|
|
|
3016
3086
|
|
|
3017
3087
|
|
|
@@ -3026,13 +3096,14 @@ class Voicemail {
|
|
|
3026
3096
|
|
|
3027
3097
|
|
|
3028
3098
|
|
|
3029
|
-
|
|
3099
|
+
|
|
3100
|
+
|
|
3030
3101
|
|
|
3031
3102
|
|
|
3032
3103
|
class CallLog {
|
|
3033
3104
|
|
|
3034
3105
|
|
|
3035
|
-
|
|
3106
|
+
|
|
3036
3107
|
|
|
3037
3108
|
|
|
3038
3109
|
|
|
@@ -3049,7 +3120,7 @@ class CallLog {
|
|
|
3049
3120
|
|
|
3050
3121
|
|
|
3051
3122
|
|
|
3052
|
-
|
|
3123
|
+
|
|
3053
3124
|
|
|
3054
3125
|
static merge(current , toMerge ) {
|
|
3055
3126
|
const onlyUnique = (value, index, self) => self.indexOf(value) === index;
|
|
@@ -3066,7 +3137,7 @@ class CallLog {
|
|
|
3066
3137
|
|
|
3067
3138
|
static parse(plain ) {
|
|
3068
3139
|
return new CallLog({
|
|
3069
|
-
answer: moment(plain.answer).toDate(),
|
|
3140
|
+
answer: plain.answer ? moment(plain.answer).toDate() : null,
|
|
3070
3141
|
answered: plain.answered,
|
|
3071
3142
|
callDirection: plain.call_direction,
|
|
3072
3143
|
destination: {
|
|
@@ -3080,13 +3151,14 @@ class CallLog {
|
|
|
3080
3151
|
id: plain.id,
|
|
3081
3152
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3082
3153
|
start: moment(plain.start).toDate(),
|
|
3083
|
-
end: moment(plain.end).toDate(),
|
|
3154
|
+
end: plain.end ? moment(plain.end).toDate() : null,
|
|
3155
|
+
recordings: Recording.parseMany(plain.recordings),
|
|
3084
3156
|
});
|
|
3085
3157
|
}
|
|
3086
3158
|
|
|
3087
3159
|
static parseNew(plain , session ) {
|
|
3088
3160
|
return new CallLog({
|
|
3089
|
-
answer: moment(plain.answer).toDate(),
|
|
3161
|
+
answer: plain.answer ? moment(plain.answer).toDate() : null,
|
|
3090
3162
|
answered: plain.answered,
|
|
3091
3163
|
callDirection: plain.call_direction,
|
|
3092
3164
|
destination: {
|
|
@@ -3100,7 +3172,8 @@ class CallLog {
|
|
|
3100
3172
|
id: plain.id,
|
|
3101
3173
|
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3102
3174
|
start: moment(plain.start).toDate(),
|
|
3103
|
-
end: moment(plain.end).toDate(),
|
|
3175
|
+
end: plain.end ? moment(plain.end).toDate() : null,
|
|
3176
|
+
recordings: Recording.parseMany(plain.recordings),
|
|
3104
3177
|
// @TODO: FIXME add verification declined vs missed call
|
|
3105
3178
|
newMissedCall: session
|
|
3106
3179
|
&& session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
|
|
@@ -4321,6 +4394,10 @@ class ApiClient {
|
|
|
4321
4394
|
this.fetchOptions = fetchOptions;
|
|
4322
4395
|
this.client.setFetchOptions(fetchOptions);
|
|
4323
4396
|
}
|
|
4397
|
+
|
|
4398
|
+
disableErrorLogging() {
|
|
4399
|
+
this.client.disableErrorLogging();
|
|
4400
|
+
}
|
|
4324
4401
|
}
|
|
4325
4402
|
|
|
4326
4403
|
/* eslint-disable dot-notation */
|