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