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