@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
@@ -769,7 +769,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
769
769
  .then(() => {
770
770
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
771
771
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
772
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
772
+ if (this.peerConnection.addTransceiver) {
773
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
774
+ }
773
775
  }
774
776
  })
775
777
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -796,12 +798,6 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
796
798
  };
797
799
  })
798
800
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
799
- .then((sessionDescription) => {
800
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
801
- this.localMediaStreamConstraints = options.constraints;
802
-
803
- return sessionDescription;
804
- })
805
801
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
806
802
  .catch((error) => {
807
803
  wazoLogger.error('error when creating media', error);
@@ -996,6 +992,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
996
992
 
997
993
  // set the transceiver direction to the answer direction
998
994
  this._peerConnection.getTransceivers().forEach((transceiver) => {
995
+ if (transceiver.stopped) {
996
+ return;
997
+ }
999
998
  if (transceiver.direction /* guarding, but should always be true */) {
1000
999
  const { receiver } = transceiver;
1001
1000
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -1040,10 +1039,15 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
1040
1039
  if (kind !== 'audio' && kind !== 'video') {
1041
1040
  throw new Error(`Unknown new track kind ${kind}.`);
1042
1041
  }
1043
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
1042
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
1043
+ otherSender.track && otherSender.track.kind === kind);
1044
1044
 
1045
1045
  // Do not reuse sender video tracks in SFU
1046
1046
  if (sender && (!sfu || newTrack.kind === 'audio')) {
1047
+ if (sender.track) {
1048
+ // eslint-disable-next-line no-param-reassign
1049
+ newTrack.enabled = sender.track.enabled;
1050
+ }
1047
1051
  trackUpdates.push(
1048
1052
  new Promise((resolve) => {
1049
1053
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -1077,7 +1081,11 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
1077
1081
  // Review: could make streamless tracks a configurable option?
1078
1082
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
1079
1083
  try {
1080
- pc.addTrack(newTrack, localStream);
1084
+ if (pc.addTrack) {
1085
+ pc.addTrack(newTrack, localStream);
1086
+ } else {
1087
+ pc.addStream(localStream);
1088
+ }
1081
1089
  } catch (error) {
1082
1090
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
1083
1091
  throw error;
@@ -3034,6 +3042,65 @@ class ExternalApp {
3034
3042
  }
3035
3043
  }
3036
3044
 
3045
+ //
3046
+
3047
+
3048
+
3049
+
3050
+
3051
+
3052
+
3053
+
3054
+
3055
+
3056
+
3057
+ class Meeting {
3058
+
3059
+
3060
+
3061
+
3062
+
3063
+
3064
+
3065
+
3066
+
3067
+
3068
+ static parse(plain ) {
3069
+ return new Meeting({
3070
+ guestSipAuthorization: plain.guest_sip_authorization,
3071
+ hostname: plain.hostname,
3072
+ name: plain.name,
3073
+ ownerUuids: plain.owner_uuids,
3074
+ port: plain.port,
3075
+ uuid: plain.uuid,
3076
+ number: plain.number,
3077
+ });
3078
+ }
3079
+
3080
+ static newFrom(meeting ) {
3081
+ return newFrom(meeting, Meeting);
3082
+ }
3083
+
3084
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
3085
+ this.guestSipAuthorization = guestSipAuthorization;
3086
+ this.hostname = hostname;
3087
+ this.name = name;
3088
+ this.ownerUuids = ownerUuids;
3089
+ this.port = port;
3090
+ this.uuid = uuid;
3091
+ this.number = number;
3092
+
3093
+ // Useful to compare instead of instanceof with minified code
3094
+ this.type = 'Meeting';
3095
+ }
3096
+
3097
+ getGuestSipCredentials() {
3098
+ // eslint-disable-next-line no-undef
3099
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
3100
+ return { username, secret };
3101
+ }
3102
+ }
3103
+
3037
3104
  /* */
3038
3105
 
3039
3106
  var confdMethods = (client , baseUrl ) => ({
@@ -3098,6 +3165,18 @@ var confdMethods = (client , baseUrl ) => ({
3098
3165
  return null;
3099
3166
  }
3100
3167
  },
3168
+
3169
+ createMyMeeting: (name ) =>
3170
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
3171
+
3172
+ deleteMyMeeting: (meetingUuid ) =>
3173
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
3174
+
3175
+ getMeeting: (meetingUuid ) =>
3176
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
3177
+
3178
+ guestGetMeeting: (meetingUuid ) =>
3179
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
3101
3180
  });
3102
3181
 
3103
3182
  //
@@ -3682,7 +3761,11 @@ class CallLog {
3682
3761
  answered: plain.answered,
3683
3762
  callDirection: plain.call_direction,
3684
3763
  destination: {
3685
- extension: plain.requested_extension || plain.destination_extension,
3764
+ // @TEMP: Temporarily assuming empty numbers are meetings
3765
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3766
+ extension: plain.requested_extension
3767
+ || plain.destination_extension
3768
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3686
3769
  name: plain.requested_name || plain.destination_name || '',
3687
3770
  },
3688
3771
  source: {
@@ -3698,27 +3781,11 @@ class CallLog {
3698
3781
  }
3699
3782
 
3700
3783
  static parseNew(plain , session ) {
3701
- return new CallLog({
3702
- answer: plain.answer ? moment(plain.answer).toDate() : null,
3703
- answered: plain.answered,
3704
- callDirection: plain.call_direction,
3705
- destination: {
3706
- extension: plain.requested_extension || plain.destination_extension,
3707
- name: plain.requested_name || plain.destination_name || '',
3708
- },
3709
- source: {
3710
- extension: plain.source_extension,
3711
- name: plain.source_name,
3712
- },
3713
- id: plain.id,
3714
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3715
- start: moment(plain.start).toDate(),
3716
- end: plain.end ? moment(plain.end).toDate() : null,
3717
- recordings: Recording.parseMany(plain.recordings),
3718
- // @TODO: FIXME add verification declined vs missed call
3719
- newMissedCall: session
3720
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3721
- });
3784
+ const callLog = CallLog.parse(plain);
3785
+ // @TODO: FIXME add verification declined vs missed call
3786
+ callLog.newMissedCall = session
3787
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3788
+ return callLog;
3722
3789
  }
3723
3790
 
3724
3791
  static newFrom(profile ) {
@@ -4475,6 +4542,9 @@ var calldMethods = (client , baseUrl ) => ({
4475
4542
  getConferenceParticipantsAsUser: async (conferenceId ) =>
4476
4543
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
4477
4544
 
4545
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4546
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4547
+
4478
4548
  listTrunks: () => client.get(`${baseUrl}/trunks`),
4479
4549
 
4480
4550
  mute: (callId ) =>
@@ -5107,6 +5177,7 @@ const MAX_REGISTER_TRIES = 10;
5107
5177
 
5108
5178
 
5109
5179
 
5180
+
5110
5181
 
5111
5182
 
5112
5183
 
@@ -5133,6 +5204,7 @@ class WebRTCClient extends Emitter {
5133
5204
 
5134
5205
 
5135
5206
 
5207
+
5136
5208
 
5137
5209
  // sugar
5138
5210
 
@@ -5171,6 +5243,8 @@ class WebRTCClient extends Emitter {
5171
5243
  super();
5172
5244
  this.uaConfigOverrides = uaConfigOverrides;
5173
5245
  this.config = config;
5246
+ this.skipRegister = config.skipRegister;
5247
+
5174
5248
  this._buildConfig(config, session).then((newConfig ) => {
5175
5249
  this.config = newConfig;
5176
5250
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -5298,14 +5372,22 @@ class WebRTCClient extends Emitter {
5298
5372
  }
5299
5373
 
5300
5374
  register(tries = 0) {
5301
- logger.info('sdk webrtc registering...', {
5375
+ const logInfo = {
5302
5376
  userAgent: !!this.userAgent,
5303
5377
  registered: this.isRegistered(),
5304
5378
  connectionPromise: !!this.connectionPromise,
5305
5379
  registerer: !!this.registerer,
5306
5380
  waiting: this.registerer && this.registerer.waiting,
5307
5381
  tries,
5308
- });
5382
+ skipRegister: this.skipRegister,
5383
+ };
5384
+
5385
+ if (this.skipRegister) {
5386
+ logger.info('sdk webrtc skip register...', logInfo);
5387
+ return Promise.resolve();
5388
+ }
5389
+
5390
+ logger.info('sdk webrtc registering...', logInfo);
5309
5391
 
5310
5392
  if (!this.userAgent) {
5311
5393
  logger.info('sdk webrtc recreating User Agent');
@@ -5636,12 +5718,18 @@ class WebRTCClient extends Emitter {
5636
5718
  }
5637
5719
 
5638
5720
  if (pc.getSenders) {
5721
+ if (!pc.getSenders().length) {
5722
+ return false;
5723
+ }
5639
5724
  pc.getSenders().forEach(sender => {
5640
5725
  if (sender && sender.track && sender.track.kind === 'audio') {
5641
5726
  muted = muted && !sender.track.enabled;
5642
5727
  }
5643
5728
  });
5644
5729
  } else {
5730
+ if (!pc.getLocalStreams().length) {
5731
+ return false;
5732
+ }
5645
5733
  pc.getLocalStreams().forEach(stream => {
5646
5734
  stream.getAudioTracks().forEach(track => {
5647
5735
  muted = muted && !track.enabled;
@@ -5700,6 +5788,8 @@ class WebRTCClient extends Emitter {
5700
5788
  }
5701
5789
  options.sessionDescriptionHandlerOptions = {
5702
5790
  constraints: options.constraints,
5791
+ hold: true,
5792
+ conference: isConference,
5703
5793
  };
5704
5794
 
5705
5795
  // Send re-INVITE
@@ -5742,6 +5832,8 @@ class WebRTCClient extends Emitter {
5742
5832
  }
5743
5833
  options.sessionDescriptionHandlerOptions = {
5744
5834
  constraints: options.constraints,
5835
+ hold: false,
5836
+ conference: isConference,
5745
5837
  };
5746
5838
 
5747
5839
  // Send re-INVITE
@@ -5925,7 +6017,8 @@ class WebRTCClient extends Emitter {
5925
6017
  }
5926
6018
  const sdh = session.sessionDescriptionHandler;
5927
6019
  const pc = sdh.peerConnection;
5928
- const localStream = this.getLocalStream(this.getSipSessionId(session));
6020
+ const sessionId = this.getSipSessionId(session);
6021
+ const localStream = this.getLocalStream(sessionId);
5929
6022
 
5930
6023
  // Release old video stream
5931
6024
  if (localStream) {
@@ -5951,11 +6044,8 @@ class WebRTCClient extends Emitter {
5951
6044
 
5952
6045
  // let's update the local stream
5953
6046
  this.eventEmitter.emit('onVideoInputChange', stream);
5954
- try {
5955
- await sdh.setLocalMediaStream(stream);
5956
- } catch (_) {
5957
- // Nothing to do
5958
- }
6047
+ this.setLocalMediaStream(sessionId, stream);
6048
+
5959
6049
  return stream;
5960
6050
  });
5961
6051
  }
@@ -6257,9 +6347,11 @@ class WebRTCClient extends Emitter {
6257
6347
  remoteStream.removeTrack(track);
6258
6348
  });
6259
6349
 
6260
- pc.getReceivers().forEach(receiver => {
6261
- remoteStream.addTrack(receiver.track);
6262
- });
6350
+ if (pc.getReceivers) {
6351
+ pc.getReceivers().forEach(receiver => {
6352
+ remoteStream.addTrack(receiver.track);
6353
+ });
6354
+ }
6263
6355
  }
6264
6356
 
6265
6357
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -6294,6 +6386,25 @@ class WebRTCClient extends Emitter {
6294
6386
  return sessionId in this.conferences;
6295
6387
  }
6296
6388
 
6389
+ createAudioElementFor(sessionId ) {
6390
+ const audio = document.createElement('audio');
6391
+ audio.setAttribute('id', `audio-${sessionId}`);
6392
+
6393
+ if (audio.setSinkId && this.audioOutputDeviceId) {
6394
+ audio.setSinkId(this.audioOutputDeviceId);
6395
+ }
6396
+
6397
+ if (document.body) {
6398
+ document.body.appendChild(audio);
6399
+ }
6400
+ this.audioElements[sessionId] = audio;
6401
+
6402
+ audio.volume = this.audioOutputVolume;
6403
+ audio.autoplay = true;
6404
+
6405
+ return audio;
6406
+ }
6407
+
6297
6408
  _onTransportError() {
6298
6409
  this.eventEmitter.emit(TRANSPORT_ERROR);
6299
6410
  this.attemptReconnection();
@@ -6523,7 +6634,7 @@ class WebRTCClient extends Emitter {
6523
6634
  let hadRemoteVideo = false;
6524
6635
 
6525
6636
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
6526
- // Becase when `onInvite` is called we already got the video track
6637
+ // Because when `onInvite` is called we already got the video track
6527
6638
  session.onInviteRequest = (request) => {
6528
6639
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
6529
6640
 
@@ -6598,20 +6709,10 @@ class WebRTCClient extends Emitter {
6598
6709
  const isConference = this.isConference(sessionId);
6599
6710
 
6600
6711
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
6601
- const audio = document.createElement('audio');
6602
- audio.setAttribute('id', `audio-${sessionId}`);
6603
-
6604
- if (audio.setSinkId && this.audioOutputDeviceId) {
6605
- audio.setSinkId(this.audioOutputDeviceId);
6606
- }
6607
-
6608
- if (document.body) {
6609
- document.body.appendChild(audio);
6610
- }
6611
- this.audioElements[sessionId] = audio;
6712
+ this.createAudioElementFor(sessionId);
6612
6713
  }
6613
6714
 
6614
- const audioElement = this.audioElements[this.getSipSessionId(session)];
6715
+ const audioElement = this.audioElements[sessionId];
6615
6716
  const stream = newStream || this.getRemoteStream(sessionId);
6616
6717
 
6617
6718
  if (!this._isWeb() || !stream) {
@@ -2699,6 +2699,65 @@ class ExternalApp {
2699
2699
  }
2700
2700
  }
2701
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
+
2702
2761
  /* */
2703
2762
 
2704
2763
  var confdMethods = (client , baseUrl ) => ({
@@ -2763,6 +2822,18 @@ var confdMethods = (client , baseUrl ) => ({
2763
2822
  return null;
2764
2823
  }
2765
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),
2766
2837
  });
2767
2838
 
2768
2839
  //
@@ -3141,7 +3212,11 @@ class CallLog {
3141
3212
  answered: plain.answered,
3142
3213
  callDirection: plain.call_direction,
3143
3214
  destination: {
3144
- extension: plain.requested_extension || plain.destination_extension,
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 || ''}`,
3145
3220
  name: plain.requested_name || plain.destination_name || '',
3146
3221
  },
3147
3222
  source: {
@@ -3157,27 +3232,11 @@ class CallLog {
3157
3232
  }
3158
3233
 
3159
3234
  static parseNew(plain , session ) {
3160
- return new CallLog({
3161
- answer: plain.answer ? moment(plain.answer).toDate() : null,
3162
- answered: plain.answered,
3163
- callDirection: plain.call_direction,
3164
- destination: {
3165
- extension: plain.requested_extension || plain.destination_extension,
3166
- name: plain.requested_name || plain.destination_name || '',
3167
- },
3168
- source: {
3169
- extension: plain.source_extension,
3170
- name: plain.source_name,
3171
- },
3172
- id: plain.id,
3173
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3174
- start: moment(plain.start).toDate(),
3175
- end: plain.end ? moment(plain.end).toDate() : null,
3176
- recordings: Recording.parseMany(plain.recordings),
3177
- // @TODO: FIXME add verification declined vs missed call
3178
- newMissedCall: session
3179
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3180
- });
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;
3181
3240
  }
3182
3241
 
3183
3242
  static newFrom(profile ) {
@@ -3919,6 +3978,9 @@ var calldMethods = (client , baseUrl ) => ({
3919
3978
  getConferenceParticipantsAsUser: async (conferenceId ) =>
3920
3979
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
3921
3980
 
3981
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
3982
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
3983
+
3922
3984
  listTrunks: () => client.get(`${baseUrl}/trunks`),
3923
3985
 
3924
3986
  mute: (callId ) =>
@@ -162,7 +162,11 @@ class CallLog {
162
162
  answered: plain.answered,
163
163
  callDirection: plain.call_direction,
164
164
  destination: {
165
- extension: plain.requested_extension || plain.destination_extension,
165
+ // @TEMP: Temporarily assuming empty numbers are meetings
166
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
167
+ extension: plain.requested_extension
168
+ || plain.destination_extension
169
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
166
170
  name: plain.requested_name || plain.destination_name || '',
167
171
  },
168
172
  source: {
@@ -178,27 +182,11 @@ class CallLog {
178
182
  }
179
183
 
180
184
  static parseNew(plain , session ) {
181
- return new CallLog({
182
- answer: plain.answer ? moment(plain.answer).toDate() : null,
183
- answered: plain.answered,
184
- callDirection: plain.call_direction,
185
- destination: {
186
- extension: plain.requested_extension || plain.destination_extension,
187
- name: plain.requested_name || plain.destination_name || '',
188
- },
189
- source: {
190
- extension: plain.source_extension,
191
- name: plain.source_name,
192
- },
193
- id: plain.id,
194
- duration: (plain.duration || 0) * 1000, // duration is in seconds
195
- start: moment(plain.start).toDate(),
196
- end: plain.end ? moment(plain.end).toDate() : null,
197
- recordings: Recording.parseMany(plain.recordings),
198
- // @TODO: FIXME add verification declined vs missed call
199
- newMissedCall: session
200
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
201
- });
185
+ const callLog = CallLog.parse(plain);
186
+ // @TODO: FIXME add verification declined vs missed call
187
+ callLog.newMissedCall = session
188
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
189
+ return callLog;
202
190
  }
203
191
 
204
192
  static newFrom(profile ) {