@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
@@ -2521,6 +2521,65 @@ class ExternalApp {
2521
2521
  }
2522
2522
  }
2523
2523
 
2524
+ //
2525
+
2526
+
2527
+
2528
+
2529
+
2530
+
2531
+
2532
+
2533
+
2534
+
2535
+
2536
+ class Meeting {
2537
+
2538
+
2539
+
2540
+
2541
+
2542
+
2543
+
2544
+
2545
+
2546
+
2547
+ static parse(plain ) {
2548
+ return new Meeting({
2549
+ guestSipAuthorization: plain.guest_sip_authorization,
2550
+ hostname: plain.hostname,
2551
+ name: plain.name,
2552
+ ownerUuids: plain.owner_uuids,
2553
+ port: plain.port,
2554
+ uuid: plain.uuid,
2555
+ number: plain.number,
2556
+ });
2557
+ }
2558
+
2559
+ static newFrom(meeting ) {
2560
+ return newFrom(meeting, Meeting);
2561
+ }
2562
+
2563
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2564
+ this.guestSipAuthorization = guestSipAuthorization;
2565
+ this.hostname = hostname;
2566
+ this.name = name;
2567
+ this.ownerUuids = ownerUuids;
2568
+ this.port = port;
2569
+ this.uuid = uuid;
2570
+ this.number = number;
2571
+
2572
+ // Useful to compare instead of instanceof with minified code
2573
+ this.type = 'Meeting';
2574
+ }
2575
+
2576
+ getGuestSipCredentials() {
2577
+ // eslint-disable-next-line no-undef
2578
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2579
+ return { username, secret };
2580
+ }
2581
+ }
2582
+
2524
2583
  /* */
2525
2584
 
2526
2585
  var confdMethods = (client , baseUrl ) => ({
@@ -2585,6 +2644,18 @@ var confdMethods = (client , baseUrl ) => ({
2585
2644
  return null;
2586
2645
  }
2587
2646
  },
2647
+
2648
+ createMyMeeting: (name ) =>
2649
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2650
+
2651
+ deleteMyMeeting: (meetingUuid ) =>
2652
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2653
+
2654
+ getMeeting: (meetingUuid ) =>
2655
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2656
+
2657
+ guestGetMeeting: (meetingUuid ) =>
2658
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2588
2659
  });
2589
2660
 
2590
2661
  //
@@ -3195,7 +3266,11 @@ class CallLog {
3195
3266
  answered: plain.answered,
3196
3267
  callDirection: plain.call_direction,
3197
3268
  destination: {
3198
- extension: plain.requested_extension || plain.destination_extension,
3269
+ // @TEMP: Temporarily assuming empty numbers are meetings
3270
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3271
+ extension: plain.requested_extension
3272
+ || plain.destination_extension
3273
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3199
3274
  name: plain.requested_name || plain.destination_name || '',
3200
3275
  },
3201
3276
  source: {
@@ -3211,27 +3286,11 @@ class CallLog {
3211
3286
  }
3212
3287
 
3213
3288
  static parseNew(plain , session ) {
3214
- return new CallLog({
3215
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
3216
- answered: plain.answered,
3217
- callDirection: plain.call_direction,
3218
- destination: {
3219
- extension: plain.requested_extension || plain.destination_extension,
3220
- name: plain.requested_name || plain.destination_name || '',
3221
- },
3222
- source: {
3223
- extension: plain.source_extension,
3224
- name: plain.source_name,
3225
- },
3226
- id: plain.id,
3227
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3228
- start: moment__default['default'](plain.start).toDate(),
3229
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3230
- recordings: Recording.parseMany(plain.recordings),
3231
- // @TODO: FIXME add verification declined vs missed call
3232
- newMissedCall: session
3233
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3234
- });
3289
+ const callLog = CallLog.parse(plain);
3290
+ // @TODO: FIXME add verification declined vs missed call
3291
+ callLog.newMissedCall = session
3292
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3293
+ return callLog;
3235
3294
  }
3236
3295
 
3237
3296
  static newFrom(profile ) {
@@ -3988,6 +4047,9 @@ var calldMethods = (client , baseUrl ) => ({
3988
4047
  getConferenceParticipantsAsUser: async (conferenceId ) =>
3989
4048
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
3990
4049
 
4050
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4051
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4052
+
3991
4053
  listTrunks: () => client.get(`${baseUrl}/trunks`),
3992
4054
 
3993
4055
  mute: (callId ) =>
@@ -4722,6 +4784,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
4722
4784
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
4723
4785
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
4724
4786
  const CONFERENCE_USER_PARTICIPANT_TALK_STOPPED = 'conference_user_participant_talk_stopped';
4787
+ const MEETING_USER_PARTICIPANT_JOINED = 'meeting_user_participant_joined';
4788
+ const MEETING_USER_PARTICIPANT_LEFT = 'meeting_user_participant_left';
4725
4789
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
4726
4790
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
4727
4791
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -5068,6 +5132,8 @@ WebSocketClient.eventLists = [
5068
5132
  CHATD_USER_ROOM_CREATED,
5069
5133
  CONFERENCE_USER_PARTICIPANT_JOINED,
5070
5134
  CONFERENCE_USER_PARTICIPANT_LEFT,
5135
+ MEETING_USER_PARTICIPANT_JOINED,
5136
+ MEETING_USER_PARTICIPANT_LEFT,
5071
5137
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
5072
5138
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
5073
5139
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -5304,7 +5370,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5304
5370
  .then(() => {
5305
5371
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
5306
5372
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
5307
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5373
+ if (this.peerConnection.addTransceiver) {
5374
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5375
+ }
5308
5376
  }
5309
5377
  })
5310
5378
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -5331,12 +5399,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5331
5399
  };
5332
5400
  })
5333
5401
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
5334
- .then((sessionDescription) => {
5335
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
5336
- this.localMediaStreamConstraints = options.constraints;
5337
-
5338
- return sessionDescription;
5339
- })
5340
5402
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
5341
5403
  .catch((error) => {
5342
5404
  wazoLogger.error('error when creating media', error);
@@ -5531,6 +5593,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5531
5593
 
5532
5594
  // set the transceiver direction to the answer direction
5533
5595
  this._peerConnection.getTransceivers().forEach((transceiver) => {
5596
+ if (transceiver.stopped) {
5597
+ return;
5598
+ }
5534
5599
  if (transceiver.direction /* guarding, but should always be true */) {
5535
5600
  const { receiver } = transceiver;
5536
5601
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -5575,10 +5640,15 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5575
5640
  if (kind !== 'audio' && kind !== 'video') {
5576
5641
  throw new Error(`Unknown new track kind ${kind}.`);
5577
5642
  }
5578
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
5643
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
5644
+ otherSender.track && otherSender.track.kind === kind);
5579
5645
 
5580
5646
  // Do not reuse sender video tracks in SFU
5581
5647
  if (sender && (!sfu || newTrack.kind === 'audio')) {
5648
+ if (sender.track) {
5649
+ // eslint-disable-next-line no-param-reassign
5650
+ newTrack.enabled = sender.track.enabled;
5651
+ }
5582
5652
  trackUpdates.push(
5583
5653
  new Promise((resolve) => {
5584
5654
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -5612,7 +5682,11 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5612
5682
  // Review: could make streamless tracks a configurable option?
5613
5683
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
5614
5684
  try {
5615
- pc.addTrack(newTrack, localStream);
5685
+ if (pc.addTrack) {
5686
+ pc.addTrack(newTrack, localStream);
5687
+ } else {
5688
+ pc.addStream(localStream);
5689
+ }
5616
5690
  } catch (error) {
5617
5691
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
5618
5692
  throw error;
@@ -5696,6 +5770,7 @@ const MAX_REGISTER_TRIES = 10;
5696
5770
 
5697
5771
 
5698
5772
 
5773
+
5699
5774
 
5700
5775
 
5701
5776
 
@@ -5722,6 +5797,7 @@ class WebRTCClient extends Emitter {
5722
5797
 
5723
5798
 
5724
5799
 
5800
+
5725
5801
 
5726
5802
  // sugar
5727
5803
 
@@ -5760,6 +5836,8 @@ class WebRTCClient extends Emitter {
5760
5836
  super();
5761
5837
  this.uaConfigOverrides = uaConfigOverrides;
5762
5838
  this.config = config;
5839
+ this.skipRegister = config.skipRegister;
5840
+
5763
5841
  this._buildConfig(config, session).then((newConfig ) => {
5764
5842
  this.config = newConfig;
5765
5843
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -5887,14 +5965,22 @@ class WebRTCClient extends Emitter {
5887
5965
  }
5888
5966
 
5889
5967
  register(tries = 0) {
5890
- logger$1.info('sdk webrtc registering...', {
5968
+ const logInfo = {
5891
5969
  userAgent: !!this.userAgent,
5892
5970
  registered: this.isRegistered(),
5893
5971
  connectionPromise: !!this.connectionPromise,
5894
5972
  registerer: !!this.registerer,
5895
5973
  waiting: this.registerer && this.registerer.waiting,
5896
5974
  tries,
5897
- });
5975
+ skipRegister: this.skipRegister,
5976
+ };
5977
+
5978
+ if (this.skipRegister) {
5979
+ logger$1.info('sdk webrtc skip register...', logInfo);
5980
+ return Promise.resolve();
5981
+ }
5982
+
5983
+ logger$1.info('sdk webrtc registering...', logInfo);
5898
5984
 
5899
5985
  if (!this.userAgent) {
5900
5986
  logger$1.info('sdk webrtc recreating User Agent');
@@ -6225,12 +6311,18 @@ class WebRTCClient extends Emitter {
6225
6311
  }
6226
6312
 
6227
6313
  if (pc.getSenders) {
6314
+ if (!pc.getSenders().length) {
6315
+ return false;
6316
+ }
6228
6317
  pc.getSenders().forEach(sender => {
6229
6318
  if (sender && sender.track && sender.track.kind === 'audio') {
6230
6319
  muted = muted && !sender.track.enabled;
6231
6320
  }
6232
6321
  });
6233
6322
  } else {
6323
+ if (!pc.getLocalStreams().length) {
6324
+ return false;
6325
+ }
6234
6326
  pc.getLocalStreams().forEach(stream => {
6235
6327
  stream.getAudioTracks().forEach(track => {
6236
6328
  muted = muted && !track.enabled;
@@ -6289,6 +6381,8 @@ class WebRTCClient extends Emitter {
6289
6381
  }
6290
6382
  options.sessionDescriptionHandlerOptions = {
6291
6383
  constraints: options.constraints,
6384
+ hold: true,
6385
+ conference: isConference,
6292
6386
  };
6293
6387
 
6294
6388
  // Send re-INVITE
@@ -6331,6 +6425,8 @@ class WebRTCClient extends Emitter {
6331
6425
  }
6332
6426
  options.sessionDescriptionHandlerOptions = {
6333
6427
  constraints: options.constraints,
6428
+ hold: false,
6429
+ conference: isConference,
6334
6430
  };
6335
6431
 
6336
6432
  // Send re-INVITE
@@ -6514,7 +6610,8 @@ class WebRTCClient extends Emitter {
6514
6610
  }
6515
6611
  const sdh = session.sessionDescriptionHandler;
6516
6612
  const pc = sdh.peerConnection;
6517
- const localStream = this.getLocalStream(this.getSipSessionId(session));
6613
+ const sessionId = this.getSipSessionId(session);
6614
+ const localStream = this.getLocalStream(sessionId);
6518
6615
 
6519
6616
  // Release old video stream
6520
6617
  if (localStream) {
@@ -6540,11 +6637,8 @@ class WebRTCClient extends Emitter {
6540
6637
 
6541
6638
  // let's update the local stream
6542
6639
  this.eventEmitter.emit('onVideoInputChange', stream);
6543
- try {
6544
- await sdh.setLocalMediaStream(stream);
6545
- } catch (_) {
6546
- // Nothing to do
6547
- }
6640
+ this.setLocalMediaStream(sessionId, stream);
6641
+
6548
6642
  return stream;
6549
6643
  });
6550
6644
  }
@@ -6846,9 +6940,11 @@ class WebRTCClient extends Emitter {
6846
6940
  remoteStream.removeTrack(track);
6847
6941
  });
6848
6942
 
6849
- pc.getReceivers().forEach(receiver => {
6850
- remoteStream.addTrack(receiver.track);
6851
- });
6943
+ if (pc.getReceivers) {
6944
+ pc.getReceivers().forEach(receiver => {
6945
+ remoteStream.addTrack(receiver.track);
6946
+ });
6947
+ }
6852
6948
  }
6853
6949
 
6854
6950
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -6883,6 +6979,25 @@ class WebRTCClient extends Emitter {
6883
6979
  return sessionId in this.conferences;
6884
6980
  }
6885
6981
 
6982
+ createAudioElementFor(sessionId ) {
6983
+ const audio = document.createElement('audio');
6984
+ audio.setAttribute('id', `audio-${sessionId}`);
6985
+
6986
+ if (audio.setSinkId && this.audioOutputDeviceId) {
6987
+ audio.setSinkId(this.audioOutputDeviceId);
6988
+ }
6989
+
6990
+ if (document.body) {
6991
+ document.body.appendChild(audio);
6992
+ }
6993
+ this.audioElements[sessionId] = audio;
6994
+
6995
+ audio.volume = this.audioOutputVolume;
6996
+ audio.autoplay = true;
6997
+
6998
+ return audio;
6999
+ }
7000
+
6886
7001
  _onTransportError() {
6887
7002
  this.eventEmitter.emit(TRANSPORT_ERROR);
6888
7003
  this.attemptReconnection();
@@ -7112,7 +7227,7 @@ class WebRTCClient extends Emitter {
7112
7227
  let hadRemoteVideo = false;
7113
7228
 
7114
7229
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
7115
- // Becase when `onInvite` is called we already got the video track
7230
+ // Because when `onInvite` is called we already got the video track
7116
7231
  session.onInviteRequest = (request) => {
7117
7232
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
7118
7233
 
@@ -7187,20 +7302,10 @@ class WebRTCClient extends Emitter {
7187
7302
  const isConference = this.isConference(sessionId);
7188
7303
 
7189
7304
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
7190
- const audio = document.createElement('audio');
7191
- audio.setAttribute('id', `audio-${sessionId}`);
7192
-
7193
- if (audio.setSinkId && this.audioOutputDeviceId) {
7194
- audio.setSinkId(this.audioOutputDeviceId);
7195
- }
7196
-
7197
- if (document.body) {
7198
- document.body.appendChild(audio);
7199
- }
7200
- this.audioElements[sessionId] = audio;
7305
+ this.createAudioElementFor(sessionId);
7201
7306
  }
7202
7307
 
7203
- const audioElement = this.audioElements[this.getSipSessionId(session)];
7308
+ const audioElement = this.audioElements[sessionId];
7204
7309
  const stream = newStream || this.getRemoteStream(sessionId);
7205
7310
 
7206
7311
  if (!this._isWeb() || !stream) {
@@ -2499,6 +2499,65 @@ class ExternalApp {
2499
2499
  }
2500
2500
  }
2501
2501
 
2502
+ //
2503
+
2504
+
2505
+
2506
+
2507
+
2508
+
2509
+
2510
+
2511
+
2512
+
2513
+
2514
+ class Meeting {
2515
+
2516
+
2517
+
2518
+
2519
+
2520
+
2521
+
2522
+
2523
+
2524
+
2525
+ static parse(plain ) {
2526
+ return new Meeting({
2527
+ guestSipAuthorization: plain.guest_sip_authorization,
2528
+ hostname: plain.hostname,
2529
+ name: plain.name,
2530
+ ownerUuids: plain.owner_uuids,
2531
+ port: plain.port,
2532
+ uuid: plain.uuid,
2533
+ number: plain.number,
2534
+ });
2535
+ }
2536
+
2537
+ static newFrom(meeting ) {
2538
+ return newFrom(meeting, Meeting);
2539
+ }
2540
+
2541
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2542
+ this.guestSipAuthorization = guestSipAuthorization;
2543
+ this.hostname = hostname;
2544
+ this.name = name;
2545
+ this.ownerUuids = ownerUuids;
2546
+ this.port = port;
2547
+ this.uuid = uuid;
2548
+ this.number = number;
2549
+
2550
+ // Useful to compare instead of instanceof with minified code
2551
+ this.type = 'Meeting';
2552
+ }
2553
+
2554
+ getGuestSipCredentials() {
2555
+ // eslint-disable-next-line no-undef
2556
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2557
+ return { username, secret };
2558
+ }
2559
+ }
2560
+
2502
2561
  /* */
2503
2562
 
2504
2563
  var confdMethods = (client , baseUrl ) => ({
@@ -2563,6 +2622,18 @@ var confdMethods = (client , baseUrl ) => ({
2563
2622
  return null;
2564
2623
  }
2565
2624
  },
2625
+
2626
+ createMyMeeting: (name ) =>
2627
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2628
+
2629
+ deleteMyMeeting: (meetingUuid ) =>
2630
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2631
+
2632
+ getMeeting: (meetingUuid ) =>
2633
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2634
+
2635
+ guestGetMeeting: (meetingUuid ) =>
2636
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2566
2637
  });
2567
2638
 
2568
2639
  //
@@ -3147,7 +3218,11 @@ class CallLog {
3147
3218
  answered: plain.answered,
3148
3219
  callDirection: plain.call_direction,
3149
3220
  destination: {
3150
- extension: plain.requested_extension || plain.destination_extension,
3221
+ // @TEMP: Temporarily assuming empty numbers are meetings
3222
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3223
+ extension: plain.requested_extension
3224
+ || plain.destination_extension
3225
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3151
3226
  name: plain.requested_name || plain.destination_name || '',
3152
3227
  },
3153
3228
  source: {
@@ -3163,27 +3238,11 @@ class CallLog {
3163
3238
  }
3164
3239
 
3165
3240
  static parseNew(plain , session ) {
3166
- return new CallLog({
3167
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
3168
- answered: plain.answered,
3169
- callDirection: plain.call_direction,
3170
- destination: {
3171
- extension: plain.requested_extension || plain.destination_extension,
3172
- name: plain.requested_name || plain.destination_name || '',
3173
- },
3174
- source: {
3175
- extension: plain.source_extension,
3176
- name: plain.source_name,
3177
- },
3178
- id: plain.id,
3179
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3180
- start: moment__default['default'](plain.start).toDate(),
3181
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3182
- recordings: Recording.parseMany(plain.recordings),
3183
- // @TODO: FIXME add verification declined vs missed call
3184
- newMissedCall: session
3185
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3186
- });
3241
+ const callLog = CallLog.parse(plain);
3242
+ // @TODO: FIXME add verification declined vs missed call
3243
+ callLog.newMissedCall = session
3244
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3245
+ return callLog;
3187
3246
  }
3188
3247
 
3189
3248
  static newFrom(profile ) {
@@ -3940,6 +3999,9 @@ var calldMethods = (client , baseUrl ) => ({
3940
3999
  getConferenceParticipantsAsUser: async (conferenceId ) =>
3941
4000
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
3942
4001
 
4002
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4003
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4004
+
3943
4005
  listTrunks: () => client.get(`${baseUrl}/trunks`),
3944
4006
 
3945
4007
  mute: (callId ) =>
@@ -2499,6 +2499,65 @@ class ExternalApp {
2499
2499
  }
2500
2500
  }
2501
2501
 
2502
+ //
2503
+
2504
+
2505
+
2506
+
2507
+
2508
+
2509
+
2510
+
2511
+
2512
+
2513
+
2514
+ class Meeting {
2515
+
2516
+
2517
+
2518
+
2519
+
2520
+
2521
+
2522
+
2523
+
2524
+
2525
+ static parse(plain ) {
2526
+ return new Meeting({
2527
+ guestSipAuthorization: plain.guest_sip_authorization,
2528
+ hostname: plain.hostname,
2529
+ name: plain.name,
2530
+ ownerUuids: plain.owner_uuids,
2531
+ port: plain.port,
2532
+ uuid: plain.uuid,
2533
+ number: plain.number,
2534
+ });
2535
+ }
2536
+
2537
+ static newFrom(meeting ) {
2538
+ return newFrom(meeting, Meeting);
2539
+ }
2540
+
2541
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2542
+ this.guestSipAuthorization = guestSipAuthorization;
2543
+ this.hostname = hostname;
2544
+ this.name = name;
2545
+ this.ownerUuids = ownerUuids;
2546
+ this.port = port;
2547
+ this.uuid = uuid;
2548
+ this.number = number;
2549
+
2550
+ // Useful to compare instead of instanceof with minified code
2551
+ this.type = 'Meeting';
2552
+ }
2553
+
2554
+ getGuestSipCredentials() {
2555
+ // eslint-disable-next-line no-undef
2556
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2557
+ return { username, secret };
2558
+ }
2559
+ }
2560
+
2502
2561
  /* */
2503
2562
 
2504
2563
  var confdMethods = (client , baseUrl ) => ({
@@ -2563,6 +2622,18 @@ var confdMethods = (client , baseUrl ) => ({
2563
2622
  return null;
2564
2623
  }
2565
2624
  },
2625
+
2626
+ createMyMeeting: (name ) =>
2627
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2628
+
2629
+ deleteMyMeeting: (meetingUuid ) =>
2630
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2631
+
2632
+ getMeeting: (meetingUuid ) =>
2633
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2634
+
2635
+ guestGetMeeting: (meetingUuid ) =>
2636
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2566
2637
  });
2567
2638
 
2568
2639
  //
@@ -3147,7 +3218,11 @@ class CallLog {
3147
3218
  answered: plain.answered,
3148
3219
  callDirection: plain.call_direction,
3149
3220
  destination: {
3150
- extension: plain.requested_extension || plain.destination_extension,
3221
+ // @TEMP: Temporarily assuming empty numbers are meetings
3222
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3223
+ extension: plain.requested_extension
3224
+ || plain.destination_extension
3225
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3151
3226
  name: plain.requested_name || plain.destination_name || '',
3152
3227
  },
3153
3228
  source: {
@@ -3163,27 +3238,11 @@ class CallLog {
3163
3238
  }
3164
3239
 
3165
3240
  static parseNew(plain , session ) {
3166
- return new CallLog({
3167
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
3168
- answered: plain.answered,
3169
- callDirection: plain.call_direction,
3170
- destination: {
3171
- extension: plain.requested_extension || plain.destination_extension,
3172
- name: plain.requested_name || plain.destination_name || '',
3173
- },
3174
- source: {
3175
- extension: plain.source_extension,
3176
- name: plain.source_name,
3177
- },
3178
- id: plain.id,
3179
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3180
- start: moment__default['default'](plain.start).toDate(),
3181
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3182
- recordings: Recording.parseMany(plain.recordings),
3183
- // @TODO: FIXME add verification declined vs missed call
3184
- newMissedCall: session
3185
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3186
- });
3241
+ const callLog = CallLog.parse(plain);
3242
+ // @TODO: FIXME add verification declined vs missed call
3243
+ callLog.newMissedCall = session
3244
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3245
+ return callLog;
3187
3246
  }
3188
3247
 
3189
3248
  static newFrom(profile ) {
@@ -3940,6 +3999,9 @@ var calldMethods = (client , baseUrl ) => ({
3940
3999
  getConferenceParticipantsAsUser: async (conferenceId ) =>
3941
4000
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
3942
4001
 
4002
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4003
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4004
+
3943
4005
  listTrunks: () => client.get(`${baseUrl}/trunks`),
3944
4006
 
3945
4007
  mute: (callId ) =>