@wazo/sdk 0.37.2 → 0.37.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/wazo-sdk.js +5 -5
  2. package/esm/__tests__/api-client.test.js +84 -22
  3. package/esm/__tests__/web-rtc-client.test.js +156 -55
  4. package/esm/api/call-logd.js +10 -22
  5. package/esm/api/calld.js +3 -0
  6. package/esm/api/confd.js +71 -0
  7. package/esm/api-client.js +84 -22
  8. package/esm/checker/Checker.js +160 -55
  9. package/esm/checker/checks/aor.js +84 -22
  10. package/esm/checker/checks/api.js +84 -22
  11. package/esm/checker/checks/index.js +160 -55
  12. package/esm/checker/checks/wazo-websocket.js +4 -0
  13. package/esm/checker/checks/webrtc-transport.js +156 -55
  14. package/esm/checker/checks/webrtc.js +156 -55
  15. package/esm/domain/AdHocAPIConference.js +84 -22
  16. package/esm/domain/CallLog.js +10 -22
  17. package/esm/domain/Features.js +84 -22
  18. package/esm/domain/Meeting.js +71 -0
  19. package/esm/domain/Phone/CTIPhone.js +84 -22
  20. package/esm/domain/Phone/WebRTCPhone.js +22 -8
  21. package/esm/domain/__tests__/CallLog.test.js +10 -22
  22. package/esm/index.js +726 -371
  23. package/esm/lib/WazoSessionDescriptionHandler.js +17 -9
  24. package/esm/service/CallApi.js +84 -22
  25. package/esm/service/getApiClient.js +84 -22
  26. package/esm/simple/Auth.js +717 -363
  27. package/esm/simple/Configuration.js +717 -363
  28. package/esm/simple/Directory.js +84 -22
  29. package/esm/simple/Phone.js +709 -355
  30. package/esm/simple/Websocket.js +6 -0
  31. package/esm/simple/index.js +719 -365
  32. package/esm/simple/room/LocalParticipant.js +689 -335
  33. package/esm/simple/room/Participant.js +689 -335
  34. package/esm/simple/room/RemoteParticipant.js +689 -335
  35. package/esm/simple/room/Room.js +689 -335
  36. package/esm/simple/room/SipRoom.js +13001 -0
  37. package/esm/simple/room/Stream.js +719 -365
  38. package/esm/simple/room/__tests__/RemoteParticipant.test.js +4130 -3774
  39. package/esm/simple/utils.js +719 -365
  40. package/esm/web-rtc-client.js +156 -55
  41. package/esm/websocket-client.js +5 -1
  42. package/lib/__tests__/api-client.test.js +84 -22
  43. package/lib/__tests__/web-rtc-client.test.js +156 -55
  44. package/lib/api/call-logd.js +10 -22
  45. package/lib/api/calld.js +3 -0
  46. package/lib/api/confd.js +71 -0
  47. package/lib/api-client.js +84 -22
  48. package/lib/checker/Checker.js +160 -55
  49. package/lib/checker/checks/aor.js +84 -22
  50. package/lib/checker/checks/api.js +84 -22
  51. package/lib/checker/checks/index.js +160 -55
  52. package/lib/checker/checks/wazo-websocket.js +4 -0
  53. package/lib/checker/checks/webrtc-transport.js +156 -55
  54. package/lib/checker/checks/webrtc.js +156 -55
  55. package/lib/domain/AdHocAPIConference.js +84 -22
  56. package/lib/domain/CallLog.js +10 -22
  57. package/lib/domain/Features.js +84 -22
  58. package/lib/domain/Meeting.js +73 -0
  59. package/lib/domain/Phone/CTIPhone.js +84 -22
  60. package/lib/domain/Phone/WebRTCPhone.js +22 -8
  61. package/lib/domain/__tests__/CallLog.test.js +10 -22
  62. package/lib/index.js +726 -371
  63. package/lib/lib/WazoSessionDescriptionHandler.js +17 -9
  64. package/lib/service/CallApi.js +84 -22
  65. package/lib/service/getApiClient.js +84 -22
  66. package/lib/simple/Auth.js +717 -363
  67. package/lib/simple/Configuration.js +717 -363
  68. package/lib/simple/Directory.js +84 -22
  69. package/lib/simple/Phone.js +709 -355
  70. package/lib/simple/Websocket.js +6 -0
  71. package/lib/simple/index.js +719 -365
  72. package/lib/simple/room/LocalParticipant.js +689 -335
  73. package/lib/simple/room/Participant.js +689 -335
  74. package/lib/simple/room/RemoteParticipant.js +689 -335
  75. package/lib/simple/room/Room.js +689 -335
  76. package/lib/simple/room/SipRoom.js +13011 -0
  77. package/lib/simple/room/Stream.js +719 -365
  78. package/lib/simple/room/__tests__/RemoteParticipant.test.js +4131 -3775
  79. package/lib/simple/utils.js +719 -365
  80. package/lib/web-rtc-client.js +156 -55
  81. package/lib/websocket-client.js +6 -0
  82. package/package.json +1 -1
  83. package/src/api/calld.js +3 -0
  84. package/src/api/confd.js +13 -0
  85. package/src/domain/CallLog.js +10 -22
  86. package/src/domain/Meeting.js +59 -0
  87. package/src/domain/Phone/WebRTCPhone.js +22 -8
  88. package/src/index.js +2 -0
  89. package/src/lib/WazoSessionDescriptionHandler.js +17 -9
  90. package/src/simple/Phone.js +13 -4
  91. package/src/simple/index.js +4 -0
  92. package/src/simple/room/Participant.js +7 -0
  93. package/src/simple/room/Room.js +158 -79
  94. package/src/simple/room/SipRoom.js +147 -0
  95. package/src/simple/room/Stream.js +1 -3
  96. package/src/simple/room/__tests__/RemoteParticipant.test.js +3 -2
  97. package/src/types/WebSocketMessage.js +21 -0
  98. package/src/web-rtc-client.js +55 -24
  99. package/src/websocket-client.js +4 -0
@@ -2501,6 +2501,65 @@ class ExternalApp {
2501
2501
  }
2502
2502
  }
2503
2503
 
2504
+ //
2505
+
2506
+
2507
+
2508
+
2509
+
2510
+
2511
+
2512
+
2513
+
2514
+
2515
+
2516
+ class Meeting {
2517
+
2518
+
2519
+
2520
+
2521
+
2522
+
2523
+
2524
+
2525
+
2526
+
2527
+ static parse(plain ) {
2528
+ return new Meeting({
2529
+ guestSipAuthorization: plain.guest_sip_authorization,
2530
+ hostname: plain.hostname,
2531
+ name: plain.name,
2532
+ ownerUuids: plain.owner_uuids,
2533
+ port: plain.port,
2534
+ uuid: plain.uuid,
2535
+ number: plain.number,
2536
+ });
2537
+ }
2538
+
2539
+ static newFrom(meeting ) {
2540
+ return newFrom(meeting, Meeting);
2541
+ }
2542
+
2543
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2544
+ this.guestSipAuthorization = guestSipAuthorization;
2545
+ this.hostname = hostname;
2546
+ this.name = name;
2547
+ this.ownerUuids = ownerUuids;
2548
+ this.port = port;
2549
+ this.uuid = uuid;
2550
+ this.number = number;
2551
+
2552
+ // Useful to compare instead of instanceof with minified code
2553
+ this.type = 'Meeting';
2554
+ }
2555
+
2556
+ getGuestSipCredentials() {
2557
+ // eslint-disable-next-line no-undef
2558
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2559
+ return { username, secret };
2560
+ }
2561
+ }
2562
+
2504
2563
  /* */
2505
2564
 
2506
2565
  var confdMethods = (client , baseUrl ) => ({
@@ -2565,6 +2624,18 @@ var confdMethods = (client , baseUrl ) => ({
2565
2624
  return null;
2566
2625
  }
2567
2626
  },
2627
+
2628
+ createMyMeeting: (name ) =>
2629
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2630
+
2631
+ deleteMyMeeting: (meetingUuid ) =>
2632
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2633
+
2634
+ getMeeting: (meetingUuid ) =>
2635
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2636
+
2637
+ guestGetMeeting: (meetingUuid ) =>
2638
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2568
2639
  });
2569
2640
 
2570
2641
  //
@@ -3149,7 +3220,11 @@ class CallLog {
3149
3220
  answered: plain.answered,
3150
3221
  callDirection: plain.call_direction,
3151
3222
  destination: {
3152
- extension: plain.requested_extension || plain.destination_extension,
3223
+ // @TEMP: Temporarily assuming empty numbers are meetings
3224
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3225
+ extension: plain.requested_extension
3226
+ || plain.destination_extension
3227
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3153
3228
  name: plain.requested_name || plain.destination_name || '',
3154
3229
  },
3155
3230
  source: {
@@ -3165,27 +3240,11 @@ class CallLog {
3165
3240
  }
3166
3241
 
3167
3242
  static parseNew(plain , session ) {
3168
- return new CallLog({
3169
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
3170
- answered: plain.answered,
3171
- callDirection: plain.call_direction,
3172
- destination: {
3173
- extension: plain.requested_extension || plain.destination_extension,
3174
- name: plain.requested_name || plain.destination_name || '',
3175
- },
3176
- source: {
3177
- extension: plain.source_extension,
3178
- name: plain.source_name,
3179
- },
3180
- id: plain.id,
3181
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3182
- start: moment__default['default'](plain.start).toDate(),
3183
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3184
- recordings: Recording.parseMany(plain.recordings),
3185
- // @TODO: FIXME add verification declined vs missed call
3186
- newMissedCall: session
3187
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3188
- });
3243
+ const callLog = CallLog.parse(plain);
3244
+ // @TODO: FIXME add verification declined vs missed call
3245
+ callLog.newMissedCall = session
3246
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3247
+ return callLog;
3189
3248
  }
3190
3249
 
3191
3250
  static newFrom(profile ) {
@@ -3927,6 +3986,9 @@ var calldMethods = (client , baseUrl ) => ({
3927
3986
  getConferenceParticipantsAsUser: async (conferenceId ) =>
3928
3987
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
3929
3988
 
3989
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
3990
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
3991
+
3930
3992
  listTrunks: () => client.get(`${baseUrl}/trunks`),
3931
3993
 
3932
3994
  mute: (callId ) =>
@@ -0,0 +1,73 @@
1
+ 'use strict';
2
+
3
+ //
4
+
5
+ var newFrom = (instance , ToClass ) => {
6
+ const args = {};
7
+ Object.getOwnPropertyNames(instance).forEach(prop => {
8
+ args[prop] = instance[prop];
9
+ });
10
+
11
+ return new ToClass(args);
12
+ };
13
+
14
+ //
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+ class Meeting {
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+ static parse(plain ) {
38
+ return new Meeting({
39
+ guestSipAuthorization: plain.guest_sip_authorization,
40
+ hostname: plain.hostname,
41
+ name: plain.name,
42
+ ownerUuids: plain.owner_uuids,
43
+ port: plain.port,
44
+ uuid: plain.uuid,
45
+ number: plain.number,
46
+ });
47
+ }
48
+
49
+ static newFrom(meeting ) {
50
+ return newFrom(meeting, Meeting);
51
+ }
52
+
53
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
54
+ this.guestSipAuthorization = guestSipAuthorization;
55
+ this.hostname = hostname;
56
+ this.name = name;
57
+ this.ownerUuids = ownerUuids;
58
+ this.port = port;
59
+ this.uuid = uuid;
60
+ this.number = number;
61
+
62
+ // Useful to compare instead of instanceof with minified code
63
+ this.type = 'Meeting';
64
+ }
65
+
66
+ getGuestSipCredentials() {
67
+ // eslint-disable-next-line no-undef
68
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
69
+ return { username, secret };
70
+ }
71
+ }
72
+
73
+ module.exports = Meeting;
@@ -2193,7 +2193,11 @@ class CallLog {
2193
2193
  answered: plain.answered,
2194
2194
  callDirection: plain.call_direction,
2195
2195
  destination: {
2196
- extension: plain.requested_extension || plain.destination_extension,
2196
+ // @TEMP: Temporarily assuming empty numbers are meetings
2197
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
2198
+ extension: plain.requested_extension
2199
+ || plain.destination_extension
2200
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
2197
2201
  name: plain.requested_name || plain.destination_name || '',
2198
2202
  },
2199
2203
  source: {
@@ -2209,27 +2213,11 @@ class CallLog {
2209
2213
  }
2210
2214
 
2211
2215
  static parseNew(plain , session ) {
2212
- return new CallLog({
2213
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
2214
- answered: plain.answered,
2215
- callDirection: plain.call_direction,
2216
- destination: {
2217
- extension: plain.requested_extension || plain.destination_extension,
2218
- name: plain.requested_name || plain.destination_name || '',
2219
- },
2220
- source: {
2221
- extension: plain.source_extension,
2222
- name: plain.source_name,
2223
- },
2224
- id: plain.id,
2225
- duration: (plain.duration || 0) * 1000, // duration is in seconds
2226
- start: moment__default['default'](plain.start).toDate(),
2227
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
2228
- recordings: Recording.parseMany(plain.recordings),
2229
- // @TODO: FIXME add verification declined vs missed call
2230
- newMissedCall: session
2231
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
2232
- });
2216
+ const callLog = CallLog.parse(plain);
2217
+ // @TODO: FIXME add verification declined vs missed call
2218
+ callLog.newMissedCall = session
2219
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
2220
+ return callLog;
2233
2221
  }
2234
2222
 
2235
2223
  static newFrom(profile ) {
@@ -3388,6 +3376,65 @@ class ExternalApp {
3388
3376
  }
3389
3377
  }
3390
3378
 
3379
+ //
3380
+
3381
+
3382
+
3383
+
3384
+
3385
+
3386
+
3387
+
3388
+
3389
+
3390
+
3391
+ class Meeting {
3392
+
3393
+
3394
+
3395
+
3396
+
3397
+
3398
+
3399
+
3400
+
3401
+
3402
+ static parse(plain ) {
3403
+ return new Meeting({
3404
+ guestSipAuthorization: plain.guest_sip_authorization,
3405
+ hostname: plain.hostname,
3406
+ name: plain.name,
3407
+ ownerUuids: plain.owner_uuids,
3408
+ port: plain.port,
3409
+ uuid: plain.uuid,
3410
+ number: plain.number,
3411
+ });
3412
+ }
3413
+
3414
+ static newFrom(meeting ) {
3415
+ return newFrom(meeting, Meeting);
3416
+ }
3417
+
3418
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
3419
+ this.guestSipAuthorization = guestSipAuthorization;
3420
+ this.hostname = hostname;
3421
+ this.name = name;
3422
+ this.ownerUuids = ownerUuids;
3423
+ this.port = port;
3424
+ this.uuid = uuid;
3425
+ this.number = number;
3426
+
3427
+ // Useful to compare instead of instanceof with minified code
3428
+ this.type = 'Meeting';
3429
+ }
3430
+
3431
+ getGuestSipCredentials() {
3432
+ // eslint-disable-next-line no-undef
3433
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
3434
+ return { username, secret };
3435
+ }
3436
+ }
3437
+
3391
3438
  /* */
3392
3439
 
3393
3440
  var confdMethods = (client , baseUrl ) => ({
@@ -3452,6 +3499,18 @@ var confdMethods = (client , baseUrl ) => ({
3452
3499
  return null;
3453
3500
  }
3454
3501
  },
3502
+
3503
+ createMyMeeting: (name ) =>
3504
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
3505
+
3506
+ deleteMyMeeting: (meetingUuid ) =>
3507
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
3508
+
3509
+ getMeeting: (meetingUuid ) =>
3510
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
3511
+
3512
+ guestGetMeeting: (meetingUuid ) =>
3513
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
3455
3514
  });
3456
3515
 
3457
3516
  //
@@ -4279,6 +4338,9 @@ var calldMethods = (client , baseUrl ) => ({
4279
4338
  getConferenceParticipantsAsUser: async (conferenceId ) =>
4280
4339
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
4281
4340
 
4341
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4342
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4343
+
4282
4344
  listTrunks: () => client.get(`${baseUrl}/trunks`),
4283
4345
 
4284
4346
  mute: (callId ) =>
@@ -960,7 +960,7 @@ class WebRTCPhone extends Emitter {
960
960
  });
961
961
 
962
962
  if (!sipSession) {
963
- return null;
963
+ return false;
964
964
  }
965
965
 
966
966
  // $FlowFixMe
@@ -970,19 +970,17 @@ class WebRTCPhone extends Emitter {
970
970
  // Downgrade
971
971
  if (constraints && !isUpgrade) {
972
972
  // No reinvite needed
973
- return this._downgradeToAudio(callSession);
973
+ this._downgradeToAudio(callSession);
974
+ return false;
974
975
  }
975
976
 
976
977
  if (isUpgrade) {
977
978
  const shouldReinvite = await this._upgradeToVideo(callSession, constraints, conference);
978
979
  if (!shouldReinvite) {
979
- return;
980
+ return false;
980
981
  }
981
982
  }
982
983
 
983
- // Force reinvite in SDH
984
- sipSession.sessionDescriptionHandler.localMediaStreamConstraints = null;
985
-
986
984
  return this.client.reinvite(sipSession, constraints, conference, audioOnly);
987
985
  }
988
986
 
@@ -1055,7 +1053,7 @@ class WebRTCPhone extends Emitter {
1055
1053
  _downgradeToAudio(callSession ) {
1056
1054
  const sipSession = this.findSipSession(callSession);
1057
1055
  if (!sipSession) {
1058
- return;
1056
+ return false;
1059
1057
  }
1060
1058
 
1061
1059
  // Release local video stream when downgrading to audio
@@ -1257,6 +1255,10 @@ class WebRTCPhone extends Emitter {
1257
1255
  localStream.removeTrack(videoTrack);
1258
1256
  }
1259
1257
 
1258
+ if (localStream) {
1259
+ localStream.addTrack(screenTrack);
1260
+ }
1261
+
1260
1262
  if (sender) {
1261
1263
  sender.replaceTrack(screenTrack);
1262
1264
  }
@@ -1272,6 +1274,7 @@ class WebRTCPhone extends Emitter {
1272
1274
  }
1273
1275
 
1274
1276
  logger.info('WebRTC phone - stop screen sharing');
1277
+ let reinvited = false;
1275
1278
 
1276
1279
  try {
1277
1280
  if (this.currentScreenShare.stream) {
@@ -1286,7 +1289,8 @@ class WebRTCPhone extends Emitter {
1286
1289
  // When upgrading directly to screenshare (eg: we don't have a videoLocalStream to replace)
1287
1290
  // We have to downgrade to audio.
1288
1291
  const screenshareStopped = this.currentScreenShare.sender && this.currentScreenShare.hadVideo;
1289
- await this.sendReinvite(targetCallSession, { audio: false, video: screenshareStopped }, conference);
1292
+ const constraints = { audio: false, video: screenshareStopped };
1293
+ reinvited = await this.sendReinvite(targetCallSession, constraints, conference);
1290
1294
  }
1291
1295
  } catch (e) {
1292
1296
  console.warn(e);
@@ -1300,6 +1304,8 @@ class WebRTCPhone extends Emitter {
1300
1304
  );
1301
1305
 
1302
1306
  this.currentScreenShare = null;
1307
+
1308
+ return reinvited;
1303
1309
  }
1304
1310
 
1305
1311
  async _getStreamFromConstraints(constraints , conference = false) {
@@ -1360,6 +1366,10 @@ class WebRTCPhone extends Emitter {
1360
1366
  this.client.changeAudioOutputDevice(id);
1361
1367
  }
1362
1368
 
1369
+ createAudioElementFor(sessionId ) {
1370
+ return this.client.createAudioElementFor(sessionId);
1371
+ }
1372
+
1363
1373
  changeRingDevice(id ) {
1364
1374
  this.audioRingDeviceId = id;
1365
1375
  }
@@ -2007,6 +2017,10 @@ class WebRTCPhone extends Emitter {
2007
2017
  return callSession ? this.client.hasLocalVideo(callSession.sipCallId) : null;
2008
2018
  }
2009
2019
 
2020
+ hasALocalVideoTrack(callSession ) {
2021
+ return callSession ? this.client.hasALocalVideoTrack(callSession.sipCallId) : null;
2022
+ }
2023
+
2010
2024
  getRemoteStream(callSession ) {
2011
2025
  return callSession ? this.client.getRemoteStream(callSession.sipCallId) : null;
2012
2026
  }
@@ -168,7 +168,11 @@ class CallLog {
168
168
  answered: plain.answered,
169
169
  callDirection: plain.call_direction,
170
170
  destination: {
171
- extension: plain.requested_extension || plain.destination_extension,
171
+ // @TEMP: Temporarily assuming empty numbers are meetings
172
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
173
+ extension: plain.requested_extension
174
+ || plain.destination_extension
175
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
172
176
  name: plain.requested_name || plain.destination_name || '',
173
177
  },
174
178
  source: {
@@ -184,27 +188,11 @@ class CallLog {
184
188
  }
185
189
 
186
190
  static parseNew(plain , session ) {
187
- return new CallLog({
188
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
189
- answered: plain.answered,
190
- callDirection: plain.call_direction,
191
- destination: {
192
- extension: plain.requested_extension || plain.destination_extension,
193
- name: plain.requested_name || plain.destination_name || '',
194
- },
195
- source: {
196
- extension: plain.source_extension,
197
- name: plain.source_name,
198
- },
199
- id: plain.id,
200
- duration: (plain.duration || 0) * 1000, // duration is in seconds
201
- start: moment__default['default'](plain.start).toDate(),
202
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
203
- recordings: Recording.parseMany(plain.recordings),
204
- // @TODO: FIXME add verification declined vs missed call
205
- newMissedCall: session
206
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
207
- });
191
+ const callLog = CallLog.parse(plain);
192
+ // @TODO: FIXME add verification declined vs missed call
193
+ callLog.newMissedCall = session
194
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
195
+ return callLog;
208
196
  }
209
197
 
210
198
  static newFrom(profile ) {