@wazo/sdk 0.37.0 → 0.37.4
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 +91 -23
- package/esm/__tests__/web-rtc-client.test.js +165 -56
- package/esm/api/agentd.js +7 -1
- package/esm/api/amid.js +7 -1
- package/esm/api/application.js +7 -1
- package/esm/api/auth.js +7 -1
- package/esm/api/call-logd.js +17 -23
- package/esm/api/calld.js +10 -18
- package/esm/api/chatd.js +7 -1
- package/esm/api/confd.js +78 -1
- package/esm/api/ctid-ng.js +7 -1
- package/esm/api/dird.js +7 -1
- package/esm/api/webhookd.js +7 -1
- package/esm/api-client.js +91 -23
- package/esm/checker/Checker.js +169 -56
- package/esm/checker/checks/aor.js +91 -23
- package/esm/checker/checks/api.js +91 -23
- package/esm/checker/checks/index.js +169 -56
- package/esm/checker/checks/wazo-websocket.js +11 -1
- package/esm/checker/checks/webrtc-transport.js +165 -56
- package/esm/checker/checks/webrtc.js +165 -56
- package/esm/domain/AdHocAPIConference.js +1722 -1654
- package/esm/domain/CallLog.js +10 -22
- package/esm/domain/CallSession.js +1 -18
- package/esm/domain/Features.js +91 -23
- package/esm/domain/IndirectTransfer.js +0 -17
- package/esm/domain/Meeting.js +71 -0
- package/esm/domain/Phone/CTIPhone.js +98 -26
- package/esm/domain/Phone/Phone.js +0 -17
- package/esm/domain/Phone/WebRTCPhone.js +47 -27
- package/esm/domain/Room.js +0 -17
- package/esm/domain/SwitchboardCall.js +0 -17
- package/esm/domain/__tests__/CallLog.test.js +10 -22
- package/esm/domain/__tests__/CallSession.test.js +1 -18
- package/esm/domain/__tests__/IndirectTransfer.test.js +1 -18
- package/esm/domain/__tests__/Room.test.js +1 -18
- package/esm/index.js +3880 -3111
- package/esm/lib/WazoSessionDescriptionHandler.js +24 -10
- package/esm/service/CallApi.js +91 -23
- package/esm/service/IssueReporter.js +7 -1
- package/esm/service/__tests__/IssueReporter.test.js +9 -1
- package/esm/service/getApiClient.js +91 -23
- package/esm/simple/Auth.js +1126 -360
- package/esm/simple/Configuration.js +1126 -360
- package/esm/simple/Directory.js +91 -23
- package/esm/simple/Phone.js +3724 -2958
- package/esm/simple/Websocket.js +13 -1
- package/esm/simple/index.js +1128 -362
- package/esm/simple/room/LocalParticipant.js +1097 -331
- package/esm/simple/room/Participant.js +1097 -331
- package/esm/simple/room/RemoteParticipant.js +1097 -331
- package/esm/simple/room/Room.js +1097 -331
- package/esm/simple/room/SipRoom.js +12996 -0
- package/esm/simple/room/Stream.js +1128 -362
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +5157 -4389
- package/esm/simple/utils.js +1128 -362
- package/esm/utils/__tests__/api-requester.test.js +7 -1
- package/esm/utils/api-requester.js +7 -1
- package/esm/web-rtc-client.js +165 -56
- package/esm/websocket-client.js +12 -2
- package/lib/__tests__/api-client.test.js +91 -23
- package/lib/__tests__/web-rtc-client.test.js +165 -56
- package/lib/api/agentd.js +7 -1
- package/lib/api/amid.js +7 -1
- package/lib/api/application.js +7 -1
- package/lib/api/auth.js +7 -1
- package/lib/api/call-logd.js +17 -23
- package/lib/api/calld.js +10 -18
- package/lib/api/chatd.js +7 -1
- package/lib/api/confd.js +78 -1
- package/lib/api/ctid-ng.js +7 -1
- package/lib/api/dird.js +7 -1
- package/lib/api/webhookd.js +7 -1
- package/lib/api-client.js +91 -23
- package/lib/checker/Checker.js +169 -56
- package/lib/checker/checks/aor.js +91 -23
- package/lib/checker/checks/api.js +91 -23
- package/lib/checker/checks/index.js +169 -56
- package/lib/checker/checks/wazo-websocket.js +11 -1
- package/lib/checker/checks/webrtc-transport.js +165 -56
- package/lib/checker/checks/webrtc.js +165 -56
- package/lib/domain/AdHocAPIConference.js +1722 -1654
- package/lib/domain/CallLog.js +10 -22
- package/lib/domain/CallSession.js +1 -18
- package/lib/domain/Features.js +91 -23
- package/lib/domain/IndirectTransfer.js +0 -17
- package/lib/domain/Meeting.js +73 -0
- package/lib/domain/Phone/CTIPhone.js +98 -26
- package/lib/domain/Phone/Phone.js +0 -16
- package/lib/domain/Phone/WebRTCPhone.js +47 -27
- package/lib/domain/Room.js +0 -17
- package/lib/domain/SwitchboardCall.js +0 -17
- package/lib/domain/__tests__/CallLog.test.js +10 -22
- package/lib/domain/__tests__/CallSession.test.js +1 -18
- package/lib/domain/__tests__/IndirectTransfer.test.js +1 -18
- package/lib/domain/__tests__/Room.test.js +1 -18
- package/lib/index.js +3880 -3111
- package/lib/lib/WazoSessionDescriptionHandler.js +24 -10
- package/lib/service/CallApi.js +91 -23
- package/lib/service/IssueReporter.js +7 -1
- package/lib/service/__tests__/IssueReporter.test.js +9 -1
- package/lib/service/getApiClient.js +91 -23
- package/lib/simple/Auth.js +1126 -360
- package/lib/simple/Configuration.js +1126 -360
- package/lib/simple/Directory.js +91 -23
- package/lib/simple/Phone.js +3724 -2958
- package/lib/simple/Websocket.js +13 -1
- package/lib/simple/index.js +1128 -362
- package/lib/simple/room/LocalParticipant.js +1097 -331
- package/lib/simple/room/Participant.js +1097 -331
- package/lib/simple/room/RemoteParticipant.js +1097 -331
- package/lib/simple/room/Room.js +1097 -331
- package/lib/simple/room/SipRoom.js +13006 -0
- package/lib/simple/room/Stream.js +1128 -362
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +5157 -4389
- package/lib/simple/utils.js +1128 -362
- package/lib/utils/__tests__/api-requester.test.js +7 -1
- package/lib/utils/api-requester.js +7 -1
- package/lib/web-rtc-client.js +165 -56
- package/lib/websocket-client.js +13 -1
- package/package.json +1 -1
- package/src/api/calld.js +3 -0
- package/src/api/confd.js +13 -0
- package/src/domain/CallLog.js +10 -22
- package/src/domain/CallSession.js +1 -2
- package/src/domain/Meeting.js +59 -0
- package/src/domain/Phone/CTIPhone.js +6 -2
- package/src/domain/Phone/Phone.js +2 -0
- package/src/domain/Phone/WebRTCPhone.js +22 -8
- package/src/index.js +6 -0
- package/src/lib/WazoSessionDescriptionHandler.js +17 -9
- package/src/service/IssueReporter.js +7 -1
- package/src/service/__tests__/IssueReporter.test.js +2 -0
- package/src/simple/Phone.js +13 -4
- package/src/simple/index.js +8 -0
- package/src/simple/room/Participant.js +7 -0
- package/src/simple/room/Room.js +157 -79
- package/src/simple/room/SipRoom.js +147 -0
- package/src/simple/room/Stream.js +1 -3
- package/src/simple/room/__tests__/RemoteParticipant.test.js +3 -2
- package/src/types/WebSocketMessage.js +21 -0
- package/src/web-rtc-client.js +57 -24
- package/src/websocket-client.js +4 -0
|
@@ -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,2067 +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
|
-
lines,
|
|
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;
|
|
704
|
-
|
|
705
|
-
this.sipLines = sipLines || [];
|
|
616
|
+
static getQueryString(obj ) {
|
|
617
|
+
return Object.keys(obj)
|
|
618
|
+
.filter(key => obj[key])
|
|
619
|
+
.map(key => `${key}=${encodeURIComponent(obj[key])}`)
|
|
620
|
+
.join('&');
|
|
706
621
|
}
|
|
707
622
|
|
|
708
|
-
static
|
|
709
|
-
|
|
623
|
+
static base64Encode(str ) {
|
|
624
|
+
return typeof btoa !== 'undefined' ? btoa(str) : jsBase64.Base64.encode(str);
|
|
625
|
+
}
|
|
710
626
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
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
|
+
}
|
|
717
638
|
|
|
718
|
-
|
|
719
|
-
result = LINE_STATE.TALKING;
|
|
720
|
-
break;
|
|
721
|
-
}
|
|
639
|
+
this.shouldLogErrors = true;
|
|
722
640
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
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);
|
|
727
646
|
|
|
728
|
-
|
|
647
|
+
return this.call.call(this, ...args);
|
|
648
|
+
};
|
|
649
|
+
});
|
|
729
650
|
}
|
|
730
651
|
|
|
731
|
-
|
|
732
|
-
|
|
652
|
+
setTenant(tenant ) {
|
|
653
|
+
this.tenant = tenant;
|
|
733
654
|
}
|
|
734
655
|
|
|
735
|
-
|
|
736
|
-
this.
|
|
737
|
-
|
|
738
|
-
return this;
|
|
656
|
+
setToken(token ) {
|
|
657
|
+
this.token = token;
|
|
739
658
|
}
|
|
740
659
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
updatedForwardOptions.splice(index, 1, forwardOption);
|
|
660
|
+
setFetchOptions(options ) {
|
|
661
|
+
this.fetchOptions = options;
|
|
662
|
+
}
|
|
745
663
|
|
|
746
|
-
|
|
664
|
+
disableErrorLogging() {
|
|
665
|
+
this.shouldLogErrors = false;
|
|
666
|
+
}
|
|
747
667
|
|
|
748
|
-
|
|
668
|
+
enableErrorLogging() {
|
|
669
|
+
this.shouldLogErrors = true;
|
|
749
670
|
}
|
|
750
671
|
|
|
751
|
-
|
|
752
|
-
|
|
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;
|
|
753
689
|
|
|
754
|
-
|
|
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
|
+
});
|
|
755
748
|
}
|
|
756
749
|
|
|
757
|
-
|
|
758
|
-
|
|
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);
|
|
759
753
|
|
|
760
|
-
return
|
|
754
|
+
return response.status === 401 || isTokenNotFound;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
_isTokenNotFound(err ) {
|
|
758
|
+
return err && err.reason && err.reason[0] === 'No such token';
|
|
759
|
+
}
|
|
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
909
|
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
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
|
-
|
|
945
|
-
|
|
946
973
|
|
|
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
|
-
|
|
1024
|
-
return old ? current.merge(old) : current;
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
static sortContacts(a , b ) {
|
|
1029
|
-
const aNames = a.separateName();
|
|
1030
|
-
const bNames = b.separateName();
|
|
1031
|
-
const aLastName = aNames.lastName;
|
|
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
1014
|
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
}
|
|
1015
|
+
static parse(plain ) {
|
|
1016
|
+
let { username, secret, host } = plain;
|
|
1167
1017
|
|
|
1168
|
-
|
|
1169
|
-
|
|
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
1620
|
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
const
|
|
1546
|
-
if (isValid) {
|
|
1547
|
-
const decodedToken = jsrsasign.jws.JWS.readSafeJSONString(jsrsasign.b64utoutf8(token.split('.')[1]));
|
|
1548
|
-
authorizations = decodedToken ? decodedToken.authorizations : [];
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1621
|
+
static merge(oldContacts , newContacts ) {
|
|
1622
|
+
return newContacts.map(current => {
|
|
1623
|
+
const old = oldContacts.find(contact => contact && contact.is(current));
|
|
1551
1624
|
|
|
1552
|
-
|
|
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,
|
|
1625
|
+
return old ? current.merge(old) : current;
|
|
1562
1626
|
});
|
|
1563
1627
|
}
|
|
1564
1628
|
|
|
1565
|
-
static
|
|
1566
|
-
|
|
1567
|
-
|
|
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;
|
|
1568
1634
|
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
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
|
-
}
|
|
1635
|
+
// last Name can be empty
|
|
1636
|
+
if (aLastName === bLastName) {
|
|
1637
|
+
return aNames.firstName.localeCompare(bNames.firstName);
|
|
1638
|
+
}
|
|
1594
1639
|
|
|
1595
|
-
|
|
1596
|
-
return date >= this.expiresAt;
|
|
1640
|
+
return aLastName.localeCompare(bLastName);
|
|
1597
1641
|
}
|
|
1598
1642
|
|
|
1599
|
-
|
|
1600
|
-
return
|
|
1643
|
+
static parseMany(response ) {
|
|
1644
|
+
return response.results.map(r => Contact.parse(r, response.column_types));
|
|
1601
1645
|
}
|
|
1602
1646
|
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1647
|
+
static manyGraphQlWithNumbersParser(numbers ) {
|
|
1648
|
+
return (response ) => {
|
|
1649
|
+
if (!response.data || !response.data.me || !response.data.me.contacts) {
|
|
1650
|
+
return [];
|
|
1651
|
+
}
|
|
1608
1652
|
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1653
|
+
return response.data.me.contacts.edges.map((edge, i) => {
|
|
1654
|
+
if (!edge.node) {
|
|
1655
|
+
return null;
|
|
1656
|
+
}
|
|
1612
1657
|
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1658
|
+
const { email } = edge.node;
|
|
1659
|
+
const name = edge.node.firstname && edge.node.lastname
|
|
1660
|
+
? `${edge.node.firstname || ''} ${edge.node.lastname || ''}` : edge.node.wazoReverse;
|
|
1616
1661
|
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
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
|
+
};
|
|
1622
1675
|
}
|
|
1623
1676
|
|
|
1624
|
-
|
|
1625
|
-
|
|
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);
|
|
1682
|
+
|
|
1683
|
+
return plain.column_values.filter((e, index) => numberColumns.some(i => i === index) && e !== null);
|
|
1626
1684
|
}
|
|
1627
1685
|
|
|
1628
|
-
|
|
1629
|
-
|
|
1686
|
+
static parse(plain , columns ) {
|
|
1687
|
+
const numbers = Contact.fetchNumbers(plain, columns);
|
|
1688
|
+
const email = plain.column_values[columns.indexOf('email')];
|
|
1689
|
+
|
|
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
|
+
});
|
|
1630
1708
|
}
|
|
1631
1709
|
|
|
1632
|
-
|
|
1633
|
-
return
|
|
1710
|
+
static parseManyPersonal(results ) {
|
|
1711
|
+
return results.map(r => Contact.parsePersonal(r));
|
|
1634
1712
|
}
|
|
1635
1713
|
|
|
1636
|
-
|
|
1637
|
-
return
|
|
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
|
+
});
|
|
1638
1731
|
}
|
|
1639
1732
|
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1733
|
+
static parseMobile(plain ) {
|
|
1734
|
+
let address = '';
|
|
1735
|
+
if (plain.postalAddresses.length) {
|
|
1736
|
+
const postalAddress = plain.postalAddresses[0];
|
|
1646
1737
|
|
|
1647
|
-
|
|
1738
|
+
address = `${postalAddress.street} ${postalAddress.city} ${postalAddress.postCode} ${postalAddress.country}`;
|
|
1739
|
+
}
|
|
1648
1740
|
|
|
1649
|
-
return
|
|
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
|
+
});
|
|
1650
1755
|
}
|
|
1651
1756
|
|
|
1652
|
-
|
|
1653
|
-
return
|
|
1757
|
+
static parseManyOffice365(response , source ) {
|
|
1758
|
+
return response.map(r => Contact.parseOffice365(r, source));
|
|
1654
1759
|
}
|
|
1655
1760
|
|
|
1656
|
-
|
|
1657
|
-
const
|
|
1761
|
+
static parseOffice365(single , source ) {
|
|
1762
|
+
const emails = [];
|
|
1763
|
+
const numbers = [];
|
|
1658
1764
|
|
|
1659
|
-
|
|
1660
|
-
|
|
1765
|
+
if (single.emailAddresses) {
|
|
1766
|
+
single.emailAddresses.map(email => emails.push({ email: email.address }));
|
|
1767
|
+
}
|
|
1661
1768
|
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1769
|
+
if (single.businessPhones) {
|
|
1770
|
+
single.businessPhones.map(phone => numbers.push({ label: 'business', number: phone }));
|
|
1771
|
+
}
|
|
1665
1772
|
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
if (!extensions.length) {
|
|
1669
|
-
return [];
|
|
1773
|
+
if (single.mobilePhone) {
|
|
1774
|
+
numbers.push({ label: 'mobile', number: single.mobilePhone });
|
|
1670
1775
|
}
|
|
1671
1776
|
|
|
1672
|
-
|
|
1673
|
-
|
|
1777
|
+
if (single.homePhones) {
|
|
1778
|
+
single.homePhones.map(phone => numbers.push({ label: 'home', number: phone }));
|
|
1779
|
+
}
|
|
1674
1780
|
|
|
1675
|
-
|
|
1676
|
-
|
|
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
|
+
});
|
|
1677
1790
|
}
|
|
1678
1791
|
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
return this.acl;
|
|
1792
|
+
static parseManyGoogle(response , source ) {
|
|
1793
|
+
return response.map(r => Contact.parseGoogle(r, source));
|
|
1682
1794
|
}
|
|
1683
|
-
}
|
|
1684
1795
|
|
|
1685
|
-
|
|
1686
|
-
|
|
1796
|
+
static parseGoogle(single , source ) {
|
|
1797
|
+
const emails = [];
|
|
1798
|
+
const numbers = [];
|
|
1687
1799
|
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
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];
|
|
1800
|
+
if (single.emails) {
|
|
1801
|
+
single.emails.forEach(email =>
|
|
1802
|
+
(typeof email === 'object' ? { email: email.address, label: email.label } : { email }));
|
|
1697
1803
|
}
|
|
1698
|
-
});
|
|
1699
|
-
};
|
|
1700
1804
|
|
|
1701
|
-
|
|
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
|
+
}
|
|
1702
1811
|
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
);
|
|
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
|
+
});
|
|
1713
1821
|
}
|
|
1714
1822
|
|
|
1715
|
-
static
|
|
1716
|
-
return
|
|
1823
|
+
static parseManyWazo(response , source ) {
|
|
1824
|
+
return response.map(r => Contact.parseWazo(r, source));
|
|
1717
1825
|
}
|
|
1718
1826
|
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1827
|
+
static parseWazo(single , source ) {
|
|
1828
|
+
const emails = [];
|
|
1829
|
+
const numbers = [];
|
|
1725
1830
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
timestamp = null,
|
|
1730
|
-
errorId = null,
|
|
1731
|
-
details = null,
|
|
1732
|
-
error = null,
|
|
1733
|
-
) {
|
|
1734
|
-
super(message);
|
|
1831
|
+
if (single.email) {
|
|
1832
|
+
emails.push({ label: 'email', email: single.email });
|
|
1833
|
+
}
|
|
1735
1834
|
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
this.details = details;
|
|
1740
|
-
this.error = error;
|
|
1741
|
-
}
|
|
1742
|
-
}
|
|
1835
|
+
if (single.exten) {
|
|
1836
|
+
numbers.push({ label: 'exten', number: single.exten });
|
|
1837
|
+
}
|
|
1743
1838
|
|
|
1744
|
-
|
|
1839
|
+
if (single.mobile_phone_number) {
|
|
1840
|
+
numbers.push({ label: 'mobile', number: single.mobile_phone_number });
|
|
1841
|
+
}
|
|
1745
1842
|
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
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
|
+
});
|
|
1755
1853
|
}
|
|
1756
1854
|
|
|
1757
|
-
static
|
|
1758
|
-
return
|
|
1855
|
+
static parseManyConference(response , source ) {
|
|
1856
|
+
return response.map(r => Contact.parseConference(r, source));
|
|
1759
1857
|
}
|
|
1760
|
-
}
|
|
1761
|
-
|
|
1762
|
-
/* */
|
|
1763
|
-
/* global navigator */
|
|
1764
|
-
const isMobile = () => typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
|
|
1765
|
-
|
|
1766
|
-
/* global window */
|
|
1767
|
-
|
|
1768
|
-
const TRACE = 'trace';
|
|
1769
|
-
const DEBUG = 'debug';
|
|
1770
|
-
const INFO = 'info';
|
|
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=';
|
|
1777
1858
|
|
|
1778
|
-
|
|
1859
|
+
static parseConference(single , source ) {
|
|
1860
|
+
const numbers = [];
|
|
1861
|
+
let firstNumber = '';
|
|
1779
1862
|
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
instance.LOG = LOG;
|
|
1785
|
-
instance.WARN = WARN;
|
|
1786
|
-
instance.ERROR = ERROR;
|
|
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
|
+
}
|
|
1787
1867
|
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
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
|
+
});
|
|
1795
1876
|
}
|
|
1796
1877
|
|
|
1797
|
-
|
|
1798
|
-
|
|
1878
|
+
static newFrom(contact ) {
|
|
1879
|
+
return newFrom(contact, Contact);
|
|
1880
|
+
}
|
|
1799
1881
|
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
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 || [];
|
|
1942
|
+
|
|
1943
|
+
// Useful to compare instead of instanceof with minified code
|
|
1944
|
+
this.type = 'Contact';
|
|
1806
1945
|
}
|
|
1807
1946
|
|
|
1808
|
-
|
|
1809
|
-
|
|
1947
|
+
setFavorite(value ) {
|
|
1948
|
+
this.favorited = value;
|
|
1810
1949
|
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1950
|
+
return this;
|
|
1951
|
+
}
|
|
1817
1952
|
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
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;
|
|
1821
1956
|
|
|
1822
|
-
|
|
1823
|
-
|
|
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;
|
|
1824
1960
|
|
|
1825
|
-
|
|
1826
|
-
this.enabled = false;
|
|
1827
|
-
this.remoteClientConfiguration = null;
|
|
1961
|
+
return !!other && hasSameId && hasSameBackend && hasSameSource;
|
|
1828
1962
|
}
|
|
1829
1963
|
|
|
1830
|
-
|
|
1831
|
-
this.
|
|
1964
|
+
hasId(id ) {
|
|
1965
|
+
return this.uuid === id;
|
|
1832
1966
|
}
|
|
1833
1967
|
|
|
1834
|
-
|
|
1835
|
-
this.
|
|
1968
|
+
hasNumber(number ) {
|
|
1969
|
+
return this.number === number;
|
|
1836
1970
|
}
|
|
1837
1971
|
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
this.init();
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
|
-
this.enabled = true;
|
|
1972
|
+
hasEndpointId(endpointId ) {
|
|
1973
|
+
return this.endpointId === endpointId;
|
|
1844
1974
|
}
|
|
1845
1975
|
|
|
1846
|
-
|
|
1847
|
-
this.
|
|
1976
|
+
isAvailable() {
|
|
1977
|
+
return this.state === STATE.AVAILABLE;
|
|
1848
1978
|
}
|
|
1849
1979
|
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
this.log.apply(this, [level, this._makeCategory(category), ...args]);
|
|
1853
|
-
};
|
|
1854
|
-
|
|
1855
|
-
return addLevelsTo(logger, true);
|
|
1980
|
+
isAway() {
|
|
1981
|
+
return this.state === STATE.AWAY;
|
|
1856
1982
|
}
|
|
1857
1983
|
|
|
1858
|
-
|
|
1859
|
-
return
|
|
1984
|
+
isUnavailable() {
|
|
1985
|
+
return this.state === STATE.UNAVAILABLE;
|
|
1860
1986
|
}
|
|
1861
1987
|
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
}
|
|
1866
|
-
|
|
1867
|
-
// Handle category label
|
|
1868
|
-
let category = null;
|
|
1869
|
-
let extra = {};
|
|
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
|
-
}
|
|
1875
|
-
|
|
1876
|
-
// Handle extra data as object for the last argument
|
|
1877
|
-
const lastArg = args[args.length - 1];
|
|
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
|
-
}
|
|
1891
|
-
|
|
1892
|
-
const date = moment__default['default']().format('YYYY-MM-DD HH:mm:ss.SSS');
|
|
1893
|
-
const message = args.join(', ');
|
|
1894
|
-
let consoleMessage = message;
|
|
1895
|
-
|
|
1896
|
-
if (Object.keys(extra).length) {
|
|
1897
|
-
const parsedExtra = safeStringify(extra);
|
|
1898
|
-
consoleMessage = `${consoleMessage} (${parsedExtra})`;
|
|
1899
|
-
}
|
|
1988
|
+
isInvisible() {
|
|
1989
|
+
return this.state === STATE.INVISIBLE;
|
|
1990
|
+
}
|
|
1900
1991
|
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1992
|
+
isInCall() {
|
|
1993
|
+
return this.lineState === LINE_STATE.TALKING || this.lineState === LINE_STATE.HOLDING;
|
|
1994
|
+
}
|
|
1904
1995
|
|
|
1905
|
-
|
|
1906
|
-
|
|
1996
|
+
isRinging() {
|
|
1997
|
+
return this.ringing;
|
|
1998
|
+
}
|
|
1907
1999
|
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
2000
|
+
isInUseOrRinging() {
|
|
2001
|
+
return this.lineState === LINE_STATE.TALKING || this.lineState === LINE_STATE.RINGING;
|
|
2002
|
+
}
|
|
1911
2003
|
|
|
1912
|
-
|
|
2004
|
+
isProgressing() {
|
|
2005
|
+
return this.lineState === LINE_STATE.PROGRESSING;
|
|
1913
2006
|
}
|
|
1914
2007
|
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
const duration = new Date() - start;
|
|
2008
|
+
merge(old ) {
|
|
2009
|
+
Object.keys(old).filter(key => key !== 'lineState').forEach(key => {
|
|
2010
|
+
// $FlowFixMe
|
|
2011
|
+
this[key] = old[key] || this[key];
|
|
2012
|
+
});
|
|
1921
2013
|
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
level = WARN;
|
|
1925
|
-
} else if (status >= 500) {
|
|
1926
|
-
level = ERROR;
|
|
2014
|
+
if (old.lineState && !this.lineState) {
|
|
2015
|
+
this.lineState = old.lineState;
|
|
1927
2016
|
}
|
|
1928
2017
|
|
|
1929
|
-
|
|
1930
|
-
status,
|
|
1931
|
-
body: this.removeSlashes(JSON.stringify(options.body)),
|
|
1932
|
-
method: options.method,
|
|
1933
|
-
headers: options.headers,
|
|
1934
|
-
duration,
|
|
1935
|
-
});
|
|
1936
|
-
}
|
|
1937
|
-
|
|
1938
|
-
// Logs aren't stored anymore
|
|
1939
|
-
getLogs() {
|
|
1940
|
-
console.warn('IssueReporter\'s logs aren\'t stored anymore. Please use fluentd to store them');
|
|
1941
|
-
return [];
|
|
2018
|
+
return this;
|
|
1942
2019
|
}
|
|
1943
2020
|
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
return [];
|
|
2021
|
+
isIntern() {
|
|
2022
|
+
return !!this.uuid;
|
|
1947
2023
|
}
|
|
1948
2024
|
|
|
1949
|
-
|
|
1950
|
-
return this.
|
|
2025
|
+
isCallable(session ) {
|
|
2026
|
+
return !!this.number && !!session && !session.is(this);
|
|
1951
2027
|
}
|
|
1952
2028
|
|
|
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
|
-
});
|
|
2029
|
+
isFromMobile() {
|
|
2030
|
+
return this.source === SOURCE_MOBILE;
|
|
1969
2031
|
}
|
|
1970
2032
|
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
}
|
|
2033
|
+
isFavorite() {
|
|
2034
|
+
return this.favorited;
|
|
2035
|
+
}
|
|
1975
2036
|
|
|
1976
|
-
|
|
1977
|
-
if (!
|
|
1978
|
-
return
|
|
2037
|
+
separateName() {
|
|
2038
|
+
if (!this.name) {
|
|
2039
|
+
return {
|
|
2040
|
+
firstName: '',
|
|
2041
|
+
lastName: '',
|
|
2042
|
+
};
|
|
1979
2043
|
}
|
|
2044
|
+
const names = this.name.split(/\s+/);
|
|
2045
|
+
const firstName = names[0];
|
|
2046
|
+
const lastName = names.slice(1).join(' ');
|
|
1980
2047
|
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
method: 'POST',
|
|
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
|
-
});
|
|
2048
|
+
return {
|
|
2049
|
+
firstName,
|
|
2050
|
+
lastName,
|
|
2051
|
+
};
|
|
2002
2052
|
}
|
|
2053
|
+
}
|
|
2003
2054
|
|
|
2004
|
-
|
|
2005
|
-
return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
|
|
2006
|
-
}
|
|
2055
|
+
// Can't use `semver` package as Wazo version aren't in semver format
|
|
2007
2056
|
|
|
2008
|
-
|
|
2009
|
-
|
|
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);
|
|
2064
|
+
|
|
2065
|
+
for (i = 0; i < l; i++) {
|
|
2066
|
+
diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
|
|
2067
|
+
if (diff) {
|
|
2068
|
+
return diff;
|
|
2069
|
+
}
|
|
2010
2070
|
}
|
|
2011
|
-
|
|
2071
|
+
return segmentsA.length - segmentsB.length;
|
|
2072
|
+
};
|
|
2012
2073
|
|
|
2013
|
-
|
|
2074
|
+
//
|
|
2014
2075
|
|
|
2015
|
-
|
|
2076
|
+
const swarmKey = jsrsasign.KEYUTIL.getKey(swarmPublicKey);
|
|
2077
|
+
const MINIMUM_WAZO_ENGINE_VERSION_FOR_DEFAULT_CONTEXT = '19.08';
|
|
2016
2078
|
|
|
2017
|
-
|
|
2018
2079
|
|
|
2080
|
+
|
|
2019
2081
|
|
|
2082
|
+
|
|
2083
|
+
|
|
2084
|
+
|
|
2085
|
+
|
|
2086
|
+
|
|
2087
|
+
|
|
2088
|
+
|
|
2020
2089
|
|
|
2021
|
-
|
|
2022
|
-
|
|
2090
|
+
|
|
2091
|
+
|
|
2092
|
+
|
|
2093
|
+
|
|
2023
2094
|
|
|
2095
|
+
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
|
|
2099
|
+
|
|
2100
|
+
|
|
2101
|
+
|
|
2102
|
+
|
|
2103
|
+
|
|
2024
2104
|
|
|
2025
2105
|
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
const realFetch = () => {
|
|
2032
|
-
if (typeof document !== 'undefined') {
|
|
2033
|
-
// Browser
|
|
2034
|
-
return window.fetch;
|
|
2035
|
-
}
|
|
2036
|
-
|
|
2037
|
-
if (isMobile()) {
|
|
2038
|
-
// React native
|
|
2039
|
-
return fetch;
|
|
2040
|
-
}
|
|
2041
|
-
|
|
2042
|
-
// nodejs
|
|
2043
|
-
// this package is disable for react-native in package.json because it requires nodejs modules
|
|
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
|
-
};
|
|
2106
|
+
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
|
|
2110
|
+
|
|
2053
2111
|
|
|
2054
|
-
|
|
2055
|
-
|
|
2112
|
+
|
|
2113
|
+
|
|
2056
2114
|
|
|
2057
|
-
|
|
2058
2115
|
|
|
2116
|
+
|
|
2117
|
+
|
|
2118
|
+
|
|
2119
|
+
|
|
2120
|
+
|
|
2059
2121
|
|
|
2122
|
+
|
|
2123
|
+
|
|
2060
2124
|
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2125
|
+
|
|
2064
2126
|
|
|
2065
|
-
|
|
2127
|
+
class Session {
|
|
2066
2128
|
|
|
2067
|
-
|
|
2068
2129
|
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
}
|
|
2079
|
-
|
|
2080
|
-
static getQueryString(obj ) {
|
|
2081
|
-
return Object.keys(obj)
|
|
2082
|
-
.filter(key => obj[key])
|
|
2083
|
-
.map(key => `${key}=${encodeURIComponent(obj[key])}`)
|
|
2084
|
-
.join('&');
|
|
2085
|
-
}
|
|
2130
|
+
|
|
2131
|
+
|
|
2132
|
+
|
|
2133
|
+
|
|
2134
|
+
|
|
2135
|
+
|
|
2136
|
+
|
|
2137
|
+
|
|
2138
|
+
|
|
2086
2139
|
|
|
2087
|
-
static
|
|
2088
|
-
|
|
2089
|
-
|
|
2140
|
+
static parse(plain ) {
|
|
2141
|
+
const token = plain.data.metadata ? plain.data.metadata.jwt : null;
|
|
2142
|
+
let authorizations = [];
|
|
2090
2143
|
|
|
2091
|
-
|
|
2092
|
-
constructor({ server, refreshTokenCallback, clientId, agent = null, token = null, fetchOptions } ) {
|
|
2093
|
-
this.server = server;
|
|
2094
|
-
this.agent = agent;
|
|
2095
|
-
this.clientId = clientId;
|
|
2096
|
-
this.refreshTokenCallback = refreshTokenCallback;
|
|
2097
|
-
this.refreshTokenPromise = null;
|
|
2098
|
-
this.fetchOptions = fetchOptions || {};
|
|
2144
|
+
// Add authorizations from JWT
|
|
2099
2145
|
if (token) {
|
|
2100
|
-
|
|
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
|
+
}
|
|
2101
2151
|
}
|
|
2102
2152
|
|
|
2103
|
-
|
|
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,
|
|
2163
|
+
});
|
|
2164
|
+
}
|
|
2104
2165
|
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
// Add method in arguments passed to `call`
|
|
2109
|
-
args.splice(1, 0, method);
|
|
2166
|
+
static newFrom(profile ) {
|
|
2167
|
+
return newFrom(profile, Session);
|
|
2168
|
+
}
|
|
2110
2169
|
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
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
|
+
} = {}) {
|
|
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;
|
|
2114
2194
|
}
|
|
2115
2195
|
|
|
2116
|
-
|
|
2117
|
-
this.
|
|
2196
|
+
hasExpired(date = new Date()) {
|
|
2197
|
+
return date >= this.expiresAt;
|
|
2118
2198
|
}
|
|
2119
2199
|
|
|
2120
|
-
|
|
2121
|
-
this.
|
|
2200
|
+
is(contact ) {
|
|
2201
|
+
return Boolean(contact) && this.uuid === contact.uuid;
|
|
2122
2202
|
}
|
|
2123
2203
|
|
|
2124
|
-
|
|
2125
|
-
this.
|
|
2126
|
-
}
|
|
2204
|
+
using(profile ) {
|
|
2205
|
+
this.profile = profile;
|
|
2127
2206
|
|
|
2128
|
-
|
|
2129
|
-
this.shouldLogErrors = false;
|
|
2207
|
+
return this;
|
|
2130
2208
|
}
|
|
2131
2209
|
|
|
2132
|
-
|
|
2133
|
-
this.
|
|
2210
|
+
hasAuthorizations() {
|
|
2211
|
+
return this.authorizations && !!this.authorizations.length;
|
|
2134
2212
|
}
|
|
2135
2213
|
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
body = null,
|
|
2140
|
-
headers = null,
|
|
2141
|
-
parse = ApiRequester.defaultParser,
|
|
2142
|
-
firstCall = true,
|
|
2143
|
-
) {
|
|
2144
|
-
const url = this.computeUrl(method, path, body);
|
|
2145
|
-
const newHeaders = this.getHeaders(headers);
|
|
2146
|
-
let newBody = method === 'get' ? null : body;
|
|
2147
|
-
if (newBody && newHeaders['Content-Type'] === 'application/json') {
|
|
2148
|
-
newBody = JSON.stringify(newBody);
|
|
2149
|
-
}
|
|
2150
|
-
const isHead = method === 'head';
|
|
2151
|
-
const hasEmptyResponse = method === 'delete' || isHead;
|
|
2152
|
-
const newParse = hasEmptyResponse ? ApiRequester.successResponseParser : parse;
|
|
2153
|
-
|
|
2154
|
-
const fetchOptions = { ...this.fetchOptions || {} };
|
|
2155
|
-
const extraHeaders = fetchOptions.headers || {};
|
|
2156
|
-
delete fetchOptions.headers;
|
|
2157
|
-
|
|
2158
|
-
const options = {
|
|
2159
|
-
method,
|
|
2160
|
-
body: newBody,
|
|
2161
|
-
headers: { ...this.getHeaders(headers), ...extraHeaders },
|
|
2162
|
-
agent: this.agent,
|
|
2163
|
-
...fetchOptions,
|
|
2164
|
-
};
|
|
2214
|
+
displayName() {
|
|
2215
|
+
return this.profile ? `${this.profile.firstName} ${this.profile.lastName}` : '';
|
|
2216
|
+
}
|
|
2165
2217
|
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2218
|
+
hasAccessToVoicemail() {
|
|
2219
|
+
if (!this.profile) {
|
|
2220
|
+
return false;
|
|
2169
2221
|
}
|
|
2222
|
+
return !!this.profile.voicemail;
|
|
2223
|
+
}
|
|
2170
2224
|
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
const contentType = response.headers.get('content-type') || '';
|
|
2175
|
-
const isJson = contentType.indexOf('application/json') !== -1;
|
|
2176
|
-
|
|
2177
|
-
IssueReporter$1.logRequest(url, options, response, start);
|
|
2178
|
-
|
|
2179
|
-
// Throw an error only if status >= 400
|
|
2180
|
-
if ((isHead && response.status >= 500) || (!isHead && response.status >= 400)) {
|
|
2181
|
-
const promise = isJson ? response.json() : response.text();
|
|
2182
|
-
const exceptionClass = response.status >= 500 ? ServerError : BadResponse;
|
|
2183
|
-
|
|
2184
|
-
return promise.then(async (err ) => {
|
|
2185
|
-
// Check if the token is still valid
|
|
2186
|
-
if (firstCall && this._checkTokenExpired(response, err)) {
|
|
2187
|
-
logger$1.warn('token expired', { error: err.reason });
|
|
2188
|
-
// Replay the call after refreshing the token
|
|
2189
|
-
return this._replayWithNewToken(err, path, method, body, headers, parse);
|
|
2190
|
-
}
|
|
2225
|
+
primaryLine() {
|
|
2226
|
+
return this.profile && this.profile.lines.length > 0 ? this.profile.lines[0] : null;
|
|
2227
|
+
}
|
|
2191
2228
|
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2229
|
+
primarySipLine() {
|
|
2230
|
+
return this.profile && this.profile.sipLines.length > 0 ? this.profile.sipLines[0] : null;
|
|
2231
|
+
}
|
|
2195
2232
|
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2233
|
+
primaryWebRtcLine() {
|
|
2234
|
+
return this.profile && (this.profile.sipLines || []).find(sipLine => sipLine && sipLine.isWebRtc());
|
|
2235
|
+
}
|
|
2199
2236
|
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2237
|
+
primaryCtiLine() {
|
|
2238
|
+
return this.profile && (this.profile.sipLines || []).find(sipLine => sipLine && !sipLine.isWebRtc());
|
|
2239
|
+
}
|
|
2203
2240
|
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
if (this.
|
|
2207
|
-
|
|
2241
|
+
primaryContext() {
|
|
2242
|
+
if (this.engineVersion) {
|
|
2243
|
+
if (this.hasEngineVersionGte(MINIMUM_WAZO_ENGINE_VERSION_FOR_DEFAULT_CONTEXT)) {
|
|
2244
|
+
return 'default';
|
|
2208
2245
|
}
|
|
2246
|
+
}
|
|
2209
2247
|
|
|
2210
|
-
|
|
2211
|
-
});
|
|
2212
|
-
}
|
|
2213
|
-
|
|
2214
|
-
_checkTokenExpired(response , err ) {
|
|
2215
|
-
// Special case when authenticating form a token: we got a 404
|
|
2216
|
-
const isTokenNotFound = response.status === 404 && this._isTokenNotFound(err);
|
|
2248
|
+
const line = this.primaryLine();
|
|
2217
2249
|
|
|
2218
|
-
return
|
|
2250
|
+
return line && line.extensions.length > 0 ? line.extensions[0].context : 'default';
|
|
2219
2251
|
}
|
|
2220
2252
|
|
|
2221
|
-
|
|
2222
|
-
return
|
|
2253
|
+
hasEngineVersionGte(version ) {
|
|
2254
|
+
return this.engineVersion && compareVersions(String(this.engineVersion), String(version)) >= 0;
|
|
2223
2255
|
}
|
|
2224
2256
|
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
path ,
|
|
2228
|
-
method ,
|
|
2229
|
-
body = null,
|
|
2230
|
-
headers = null,
|
|
2231
|
-
parse ,
|
|
2232
|
-
) {
|
|
2233
|
-
const isTokenNotFound = this._isTokenNotFound(err);
|
|
2234
|
-
let newPath = path;
|
|
2235
|
-
logger$1.info('refreshing token', { inProgress: !!this.refreshTokenPromise });
|
|
2236
|
-
|
|
2237
|
-
this.refreshTokenPromise = this.refreshTokenPromise || this.refreshTokenCallback();
|
|
2257
|
+
primaryNumber() {
|
|
2258
|
+
const line = this.primaryLine();
|
|
2238
2259
|
|
|
2239
|
-
return
|
|
2240
|
-
|
|
2241
|
-
logger$1.info('token refreshed', { isTokenNotFound });
|
|
2242
|
-
if (isTokenNotFound) {
|
|
2243
|
-
const pathParts = path.split('/');
|
|
2244
|
-
pathParts.pop();
|
|
2245
|
-
pathParts.push(this.token);
|
|
2246
|
-
newPath = pathParts.join('/');
|
|
2247
|
-
}
|
|
2260
|
+
return line && line.extensions.length ? line.extensions[0].exten : null;
|
|
2261
|
+
}
|
|
2248
2262
|
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
this.refreshTokenPromise = null;
|
|
2252
|
-
throw e;
|
|
2253
|
-
});
|
|
2263
|
+
allLines() {
|
|
2264
|
+
return this.profile ? this.profile.lines || [] : [];
|
|
2254
2265
|
}
|
|
2255
2266
|
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2267
|
+
allNumbers() {
|
|
2268
|
+
const extensions = this.allLines().map(line => line.extensions.map(extension => extension.exten));
|
|
2269
|
+
if (!extensions.length) {
|
|
2270
|
+
return [];
|
|
2259
2271
|
}
|
|
2260
2272
|
|
|
2261
|
-
return
|
|
2262
|
-
'X-Auth-Token': this.token,
|
|
2263
|
-
...(this.tenant ? { 'Wazo-Tenant': this.tenant } : null),
|
|
2264
|
-
Accept: 'application/json',
|
|
2265
|
-
'Content-Type': 'application/json',
|
|
2266
|
-
};
|
|
2273
|
+
return extensions.reduce((a, b) => a.concat(b));
|
|
2267
2274
|
}
|
|
2268
2275
|
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
return method === 'get' && body && Object.keys(body).length ? `${url}?${ApiRequester.getQueryString(body)}` : url;
|
|
2276
|
+
hasExtension(extension ) {
|
|
2277
|
+
return this.allNumbers().some(number => number === extension);
|
|
2273
2278
|
}
|
|
2274
2279
|
|
|
2275
|
-
get
|
|
2276
|
-
|
|
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;
|
|
2277
2283
|
}
|
|
2278
2284
|
}
|
|
2279
2285
|
|
|
@@ -2699,6 +2705,65 @@ class ExternalApp {
|
|
|
2699
2705
|
}
|
|
2700
2706
|
}
|
|
2701
2707
|
|
|
2708
|
+
//
|
|
2709
|
+
|
|
2710
|
+
|
|
2711
|
+
|
|
2712
|
+
|
|
2713
|
+
|
|
2714
|
+
|
|
2715
|
+
|
|
2716
|
+
|
|
2717
|
+
|
|
2718
|
+
|
|
2719
|
+
|
|
2720
|
+
class Meeting {
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
|
|
2724
|
+
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
|
|
2728
|
+
|
|
2729
|
+
|
|
2730
|
+
|
|
2731
|
+
static parse(plain ) {
|
|
2732
|
+
return new Meeting({
|
|
2733
|
+
guestSipAuthorization: plain.guest_sip_authorization,
|
|
2734
|
+
hostname: plain.hostname,
|
|
2735
|
+
name: plain.name,
|
|
2736
|
+
ownerUuids: plain.owner_uuids,
|
|
2737
|
+
port: plain.port,
|
|
2738
|
+
uuid: plain.uuid,
|
|
2739
|
+
number: plain.number,
|
|
2740
|
+
});
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
static newFrom(meeting ) {
|
|
2744
|
+
return newFrom(meeting, Meeting);
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
|
|
2748
|
+
this.guestSipAuthorization = guestSipAuthorization;
|
|
2749
|
+
this.hostname = hostname;
|
|
2750
|
+
this.name = name;
|
|
2751
|
+
this.ownerUuids = ownerUuids;
|
|
2752
|
+
this.port = port;
|
|
2753
|
+
this.uuid = uuid;
|
|
2754
|
+
this.number = number;
|
|
2755
|
+
|
|
2756
|
+
// Useful to compare instead of instanceof with minified code
|
|
2757
|
+
this.type = 'Meeting';
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2760
|
+
getGuestSipCredentials() {
|
|
2761
|
+
// eslint-disable-next-line no-undef
|
|
2762
|
+
const [username, secret] = atob(this.guestSipAuthorization).split(':');
|
|
2763
|
+
return { username, secret };
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
|
|
2702
2767
|
/* */
|
|
2703
2768
|
|
|
2704
2769
|
var confdMethods = (client , baseUrl ) => ({
|
|
@@ -2763,6 +2828,18 @@ var confdMethods = (client , baseUrl ) => ({
|
|
|
2763
2828
|
return null;
|
|
2764
2829
|
}
|
|
2765
2830
|
},
|
|
2831
|
+
|
|
2832
|
+
createMyMeeting: (name ) =>
|
|
2833
|
+
client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
|
|
2834
|
+
|
|
2835
|
+
deleteMyMeeting: (meetingUuid ) =>
|
|
2836
|
+
client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
|
|
2837
|
+
|
|
2838
|
+
getMeeting: (meetingUuid ) =>
|
|
2839
|
+
client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
2840
|
+
|
|
2841
|
+
guestGetMeeting: (meetingUuid ) =>
|
|
2842
|
+
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
2766
2843
|
});
|
|
2767
2844
|
|
|
2768
2845
|
//
|
|
@@ -3141,7 +3218,11 @@ class CallLog {
|
|
|
3141
3218
|
answered: plain.answered,
|
|
3142
3219
|
callDirection: plain.call_direction,
|
|
3143
3220
|
destination: {
|
|
3144
|
-
|
|
3221
|
+
// @TEMP: Temporarily assuming empty numbers are meetings
|
|
3222
|
+
// which is admittedly a very dangerous assumption. Did i mention it was temporary?
|
|
3223
|
+
extension: plain.requested_extension
|
|
3224
|
+
|| plain.destination_extension
|
|
3225
|
+
|| `meeting-${plain.requested_name || plain.destination_name || ''}`,
|
|
3145
3226
|
name: plain.requested_name || plain.destination_name || '',
|
|
3146
3227
|
},
|
|
3147
3228
|
source: {
|
|
@@ -3157,27 +3238,11 @@ class CallLog {
|
|
|
3157
3238
|
}
|
|
3158
3239
|
|
|
3159
3240
|
static parseNew(plain , session ) {
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
extension: plain.requested_extension || plain.destination_extension,
|
|
3166
|
-
name: plain.requested_name || plain.destination_name || '',
|
|
3167
|
-
},
|
|
3168
|
-
source: {
|
|
3169
|
-
extension: plain.source_extension,
|
|
3170
|
-
name: plain.source_name,
|
|
3171
|
-
},
|
|
3172
|
-
id: plain.id,
|
|
3173
|
-
duration: (plain.duration || 0) * 1000, // duration is in seconds
|
|
3174
|
-
start: moment__default['default'](plain.start).toDate(),
|
|
3175
|
-
end: plain.end ? moment__default['default'](plain.end).toDate() : null,
|
|
3176
|
-
recordings: Recording.parseMany(plain.recordings),
|
|
3177
|
-
// @TODO: FIXME add verification declined vs missed call
|
|
3178
|
-
newMissedCall: session
|
|
3179
|
-
&& session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
|
|
3180
|
-
});
|
|
3241
|
+
const callLog = CallLog.parse(plain);
|
|
3242
|
+
// @TODO: FIXME add verification declined vs missed call
|
|
3243
|
+
callLog.newMissedCall = session
|
|
3244
|
+
&& session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
|
|
3245
|
+
return callLog;
|
|
3181
3246
|
}
|
|
3182
3247
|
|
|
3183
3248
|
static newFrom(profile ) {
|
|
@@ -3919,6 +3984,9 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
3919
3984
|
getConferenceParticipantsAsUser: async (conferenceId ) =>
|
|
3920
3985
|
client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
|
|
3921
3986
|
|
|
3987
|
+
getMeetingParticipantsAsUser: async (meetingUuid ) =>
|
|
3988
|
+
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
|
|
3989
|
+
|
|
3922
3990
|
listTrunks: () => client.get(`${baseUrl}/trunks`),
|
|
3923
3991
|
|
|
3924
3992
|
mute: (callId ) =>
|