@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.
Files changed (144) hide show
  1. package/dist/wazo-sdk.js +5 -5
  2. package/esm/__tests__/api-client.test.js +91 -23
  3. package/esm/__tests__/web-rtc-client.test.js +165 -56
  4. package/esm/api/agentd.js +7 -1
  5. package/esm/api/amid.js +7 -1
  6. package/esm/api/application.js +7 -1
  7. package/esm/api/auth.js +7 -1
  8. package/esm/api/call-logd.js +17 -23
  9. package/esm/api/calld.js +10 -18
  10. package/esm/api/chatd.js +7 -1
  11. package/esm/api/confd.js +78 -1
  12. package/esm/api/ctid-ng.js +7 -1
  13. package/esm/api/dird.js +7 -1
  14. package/esm/api/webhookd.js +7 -1
  15. package/esm/api-client.js +91 -23
  16. package/esm/checker/Checker.js +169 -56
  17. package/esm/checker/checks/aor.js +91 -23
  18. package/esm/checker/checks/api.js +91 -23
  19. package/esm/checker/checks/index.js +169 -56
  20. package/esm/checker/checks/wazo-websocket.js +11 -1
  21. package/esm/checker/checks/webrtc-transport.js +165 -56
  22. package/esm/checker/checks/webrtc.js +165 -56
  23. package/esm/domain/AdHocAPIConference.js +1722 -1654
  24. package/esm/domain/CallLog.js +10 -22
  25. package/esm/domain/CallSession.js +1 -18
  26. package/esm/domain/Features.js +91 -23
  27. package/esm/domain/IndirectTransfer.js +0 -17
  28. package/esm/domain/Meeting.js +71 -0
  29. package/esm/domain/Phone/CTIPhone.js +98 -26
  30. package/esm/domain/Phone/Phone.js +0 -17
  31. package/esm/domain/Phone/WebRTCPhone.js +47 -27
  32. package/esm/domain/Room.js +0 -17
  33. package/esm/domain/SwitchboardCall.js +0 -17
  34. package/esm/domain/__tests__/CallLog.test.js +10 -22
  35. package/esm/domain/__tests__/CallSession.test.js +1 -18
  36. package/esm/domain/__tests__/IndirectTransfer.test.js +1 -18
  37. package/esm/domain/__tests__/Room.test.js +1 -18
  38. package/esm/index.js +3880 -3111
  39. package/esm/lib/WazoSessionDescriptionHandler.js +24 -10
  40. package/esm/service/CallApi.js +91 -23
  41. package/esm/service/IssueReporter.js +7 -1
  42. package/esm/service/__tests__/IssueReporter.test.js +9 -1
  43. package/esm/service/getApiClient.js +91 -23
  44. package/esm/simple/Auth.js +1126 -360
  45. package/esm/simple/Configuration.js +1126 -360
  46. package/esm/simple/Directory.js +91 -23
  47. package/esm/simple/Phone.js +3724 -2958
  48. package/esm/simple/Websocket.js +13 -1
  49. package/esm/simple/index.js +1128 -362
  50. package/esm/simple/room/LocalParticipant.js +1097 -331
  51. package/esm/simple/room/Participant.js +1097 -331
  52. package/esm/simple/room/RemoteParticipant.js +1097 -331
  53. package/esm/simple/room/Room.js +1097 -331
  54. package/esm/simple/room/SipRoom.js +12996 -0
  55. package/esm/simple/room/Stream.js +1128 -362
  56. package/esm/simple/room/__tests__/RemoteParticipant.test.js +5157 -4389
  57. package/esm/simple/utils.js +1128 -362
  58. package/esm/utils/__tests__/api-requester.test.js +7 -1
  59. package/esm/utils/api-requester.js +7 -1
  60. package/esm/web-rtc-client.js +165 -56
  61. package/esm/websocket-client.js +12 -2
  62. package/lib/__tests__/api-client.test.js +91 -23
  63. package/lib/__tests__/web-rtc-client.test.js +165 -56
  64. package/lib/api/agentd.js +7 -1
  65. package/lib/api/amid.js +7 -1
  66. package/lib/api/application.js +7 -1
  67. package/lib/api/auth.js +7 -1
  68. package/lib/api/call-logd.js +17 -23
  69. package/lib/api/calld.js +10 -18
  70. package/lib/api/chatd.js +7 -1
  71. package/lib/api/confd.js +78 -1
  72. package/lib/api/ctid-ng.js +7 -1
  73. package/lib/api/dird.js +7 -1
  74. package/lib/api/webhookd.js +7 -1
  75. package/lib/api-client.js +91 -23
  76. package/lib/checker/Checker.js +169 -56
  77. package/lib/checker/checks/aor.js +91 -23
  78. package/lib/checker/checks/api.js +91 -23
  79. package/lib/checker/checks/index.js +169 -56
  80. package/lib/checker/checks/wazo-websocket.js +11 -1
  81. package/lib/checker/checks/webrtc-transport.js +165 -56
  82. package/lib/checker/checks/webrtc.js +165 -56
  83. package/lib/domain/AdHocAPIConference.js +1722 -1654
  84. package/lib/domain/CallLog.js +10 -22
  85. package/lib/domain/CallSession.js +1 -18
  86. package/lib/domain/Features.js +91 -23
  87. package/lib/domain/IndirectTransfer.js +0 -17
  88. package/lib/domain/Meeting.js +73 -0
  89. package/lib/domain/Phone/CTIPhone.js +98 -26
  90. package/lib/domain/Phone/Phone.js +0 -16
  91. package/lib/domain/Phone/WebRTCPhone.js +47 -27
  92. package/lib/domain/Room.js +0 -17
  93. package/lib/domain/SwitchboardCall.js +0 -17
  94. package/lib/domain/__tests__/CallLog.test.js +10 -22
  95. package/lib/domain/__tests__/CallSession.test.js +1 -18
  96. package/lib/domain/__tests__/IndirectTransfer.test.js +1 -18
  97. package/lib/domain/__tests__/Room.test.js +1 -18
  98. package/lib/index.js +3880 -3111
  99. package/lib/lib/WazoSessionDescriptionHandler.js +24 -10
  100. package/lib/service/CallApi.js +91 -23
  101. package/lib/service/IssueReporter.js +7 -1
  102. package/lib/service/__tests__/IssueReporter.test.js +9 -1
  103. package/lib/service/getApiClient.js +91 -23
  104. package/lib/simple/Auth.js +1126 -360
  105. package/lib/simple/Configuration.js +1126 -360
  106. package/lib/simple/Directory.js +91 -23
  107. package/lib/simple/Phone.js +3724 -2958
  108. package/lib/simple/Websocket.js +13 -1
  109. package/lib/simple/index.js +1128 -362
  110. package/lib/simple/room/LocalParticipant.js +1097 -331
  111. package/lib/simple/room/Participant.js +1097 -331
  112. package/lib/simple/room/RemoteParticipant.js +1097 -331
  113. package/lib/simple/room/Room.js +1097 -331
  114. package/lib/simple/room/SipRoom.js +13006 -0
  115. package/lib/simple/room/Stream.js +1128 -362
  116. package/lib/simple/room/__tests__/RemoteParticipant.test.js +5157 -4389
  117. package/lib/simple/utils.js +1128 -362
  118. package/lib/utils/__tests__/api-requester.test.js +7 -1
  119. package/lib/utils/api-requester.js +7 -1
  120. package/lib/web-rtc-client.js +165 -56
  121. package/lib/websocket-client.js +13 -1
  122. package/package.json +1 -1
  123. package/src/api/calld.js +3 -0
  124. package/src/api/confd.js +13 -0
  125. package/src/domain/CallLog.js +10 -22
  126. package/src/domain/CallSession.js +1 -2
  127. package/src/domain/Meeting.js +59 -0
  128. package/src/domain/Phone/CTIPhone.js +6 -2
  129. package/src/domain/Phone/Phone.js +2 -0
  130. package/src/domain/Phone/WebRTCPhone.js +22 -8
  131. package/src/index.js +6 -0
  132. package/src/lib/WazoSessionDescriptionHandler.js +17 -9
  133. package/src/service/IssueReporter.js +7 -1
  134. package/src/service/__tests__/IssueReporter.test.js +2 -0
  135. package/src/simple/Phone.js +13 -4
  136. package/src/simple/index.js +8 -0
  137. package/src/simple/room/Participant.js +7 -0
  138. package/src/simple/room/Room.js +157 -79
  139. package/src/simple/room/SipRoom.js +147 -0
  140. package/src/simple/room/Stream.js +1 -3
  141. package/src/simple/room/__tests__/RemoteParticipant.test.js +3 -2
  142. package/src/types/WebSocketMessage.js +21 -0
  143. package/src/web-rtc-client.js +57 -24
  144. package/src/websocket-client.js +4 -0
@@ -337,7 +337,13 @@ class IssueReporter {
337
337
  }
338
338
 
339
339
  _isLevelAbove(level1 , level2 ) {
340
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
340
+ const index1 = LOG_LEVELS.indexOf(level1);
341
+ const index2 = LOG_LEVELS.indexOf(level2);
342
+ if (index1 === -1 || index2 === -1) {
343
+ return false;
344
+ }
345
+
346
+ return index1 > index2;
341
347
  }
342
348
 
343
349
  _makeCategory(category ) {
@@ -2515,6 +2521,65 @@ class ExternalApp {
2515
2521
  }
2516
2522
  }
2517
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
+
2518
2583
  /* */
2519
2584
 
2520
2585
  var confdMethods = (client , baseUrl ) => ({
@@ -2579,6 +2644,18 @@ var confdMethods = (client , baseUrl ) => ({
2579
2644
  return null;
2580
2645
  }
2581
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),
2582
2659
  });
2583
2660
 
2584
2661
  //
@@ -3189,7 +3266,11 @@ class CallLog {
3189
3266
  answered: plain.answered,
3190
3267
  callDirection: plain.call_direction,
3191
3268
  destination: {
3192
- 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 || ''}`,
3193
3274
  name: plain.requested_name || plain.destination_name || '',
3194
3275
  },
3195
3276
  source: {
@@ -3205,27 +3286,11 @@ class CallLog {
3205
3286
  }
3206
3287
 
3207
3288
  static parseNew(plain , session ) {
3208
- return new CallLog({
3209
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
3210
- answered: plain.answered,
3211
- callDirection: plain.call_direction,
3212
- destination: {
3213
- extension: plain.requested_extension || plain.destination_extension,
3214
- name: plain.requested_name || plain.destination_name || '',
3215
- },
3216
- source: {
3217
- extension: plain.source_extension,
3218
- name: plain.source_name,
3219
- },
3220
- id: plain.id,
3221
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3222
- start: moment__default['default'](plain.start).toDate(),
3223
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3224
- recordings: Recording.parseMany(plain.recordings),
3225
- // @TODO: FIXME add verification declined vs missed call
3226
- newMissedCall: session
3227
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3228
- });
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;
3229
3294
  }
3230
3295
 
3231
3296
  static newFrom(profile ) {
@@ -3982,6 +4047,9 @@ var calldMethods = (client , baseUrl ) => ({
3982
4047
  getConferenceParticipantsAsUser: async (conferenceId ) =>
3983
4048
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
3984
4049
 
4050
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4051
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4052
+
3985
4053
  listTrunks: () => client.get(`${baseUrl}/trunks`),
3986
4054
 
3987
4055
  mute: (callId ) =>
@@ -4716,6 +4784,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
4716
4784
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
4717
4785
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
4718
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';
4719
4789
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
4720
4790
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
4721
4791
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -5062,6 +5132,8 @@ WebSocketClient.eventLists = [
5062
5132
  CHATD_USER_ROOM_CREATED,
5063
5133
  CONFERENCE_USER_PARTICIPANT_JOINED,
5064
5134
  CONFERENCE_USER_PARTICIPANT_LEFT,
5135
+ MEETING_USER_PARTICIPANT_JOINED,
5136
+ MEETING_USER_PARTICIPANT_LEFT,
5065
5137
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
5066
5138
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
5067
5139
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -5298,7 +5370,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5298
5370
  .then(() => {
5299
5371
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
5300
5372
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
5301
- 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
+ }
5302
5376
  }
5303
5377
  })
5304
5378
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -5325,12 +5399,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5325
5399
  };
5326
5400
  })
5327
5401
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
5328
- .then((sessionDescription) => {
5329
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
5330
- this.localMediaStreamConstraints = options.constraints;
5331
-
5332
- return sessionDescription;
5333
- })
5334
5402
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
5335
5403
  .catch((error) => {
5336
5404
  wazoLogger.error('error when creating media', error);
@@ -5525,6 +5593,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5525
5593
 
5526
5594
  // set the transceiver direction to the answer direction
5527
5595
  this._peerConnection.getTransceivers().forEach((transceiver) => {
5596
+ if (transceiver.stopped) {
5597
+ return;
5598
+ }
5528
5599
  if (transceiver.direction /* guarding, but should always be true */) {
5529
5600
  const { receiver } = transceiver;
5530
5601
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -5569,10 +5640,15 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5569
5640
  if (kind !== 'audio' && kind !== 'video') {
5570
5641
  throw new Error(`Unknown new track kind ${kind}.`);
5571
5642
  }
5572
- 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);
5573
5645
 
5574
5646
  // Do not reuse sender video tracks in SFU
5575
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
+ }
5576
5652
  trackUpdates.push(
5577
5653
  new Promise((resolve) => {
5578
5654
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -5606,7 +5682,11 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
5606
5682
  // Review: could make streamless tracks a configurable option?
5607
5683
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
5608
5684
  try {
5609
- pc.addTrack(newTrack, localStream);
5685
+ if (pc.addTrack) {
5686
+ pc.addTrack(newTrack, localStream);
5687
+ } else {
5688
+ pc.addStream(localStream);
5689
+ }
5610
5690
  } catch (error) {
5611
5691
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
5612
5692
  throw error;
@@ -5690,6 +5770,7 @@ const MAX_REGISTER_TRIES = 10;
5690
5770
 
5691
5771
 
5692
5772
 
5773
+
5693
5774
 
5694
5775
 
5695
5776
 
@@ -5716,6 +5797,7 @@ class WebRTCClient extends Emitter {
5716
5797
 
5717
5798
 
5718
5799
 
5800
+
5719
5801
 
5720
5802
  // sugar
5721
5803
 
@@ -5754,6 +5836,8 @@ class WebRTCClient extends Emitter {
5754
5836
  super();
5755
5837
  this.uaConfigOverrides = uaConfigOverrides;
5756
5838
  this.config = config;
5839
+ this.skipRegister = config.skipRegister;
5840
+
5757
5841
  this._buildConfig(config, session).then((newConfig ) => {
5758
5842
  this.config = newConfig;
5759
5843
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -5881,14 +5965,22 @@ class WebRTCClient extends Emitter {
5881
5965
  }
5882
5966
 
5883
5967
  register(tries = 0) {
5884
- logger$1.info('sdk webrtc registering...', {
5968
+ const logInfo = {
5885
5969
  userAgent: !!this.userAgent,
5886
5970
  registered: this.isRegistered(),
5887
5971
  connectionPromise: !!this.connectionPromise,
5888
5972
  registerer: !!this.registerer,
5889
5973
  waiting: this.registerer && this.registerer.waiting,
5890
5974
  tries,
5891
- });
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);
5892
5984
 
5893
5985
  if (!this.userAgent) {
5894
5986
  logger$1.info('sdk webrtc recreating User Agent');
@@ -6219,12 +6311,18 @@ class WebRTCClient extends Emitter {
6219
6311
  }
6220
6312
 
6221
6313
  if (pc.getSenders) {
6314
+ if (!pc.getSenders().length) {
6315
+ return false;
6316
+ }
6222
6317
  pc.getSenders().forEach(sender => {
6223
6318
  if (sender && sender.track && sender.track.kind === 'audio') {
6224
6319
  muted = muted && !sender.track.enabled;
6225
6320
  }
6226
6321
  });
6227
6322
  } else {
6323
+ if (!pc.getLocalStreams().length) {
6324
+ return false;
6325
+ }
6228
6326
  pc.getLocalStreams().forEach(stream => {
6229
6327
  stream.getAudioTracks().forEach(track => {
6230
6328
  muted = muted && !track.enabled;
@@ -6281,6 +6379,9 @@ class WebRTCClient extends Emitter {
6281
6379
  if (!this._isWeb()) {
6282
6380
  options.sessionDescriptionHandlerModifiers = [modifiers.holdModifier];
6283
6381
  }
6382
+ options.sessionDescriptionHandlerOptions = {
6383
+ constraints: options.constraints,
6384
+ };
6284
6385
 
6285
6386
  // Send re-INVITE
6286
6387
  return session.invite(options);
@@ -6320,6 +6421,9 @@ class WebRTCClient extends Emitter {
6320
6421
  // (eg: holdModifier)
6321
6422
  options.sessionDescriptionHandlerModifiers = [];
6322
6423
  }
6424
+ options.sessionDescriptionHandlerOptions = {
6425
+ constraints: options.constraints,
6426
+ };
6323
6427
 
6324
6428
  // Send re-INVITE
6325
6429
  return session.invite(options);
@@ -6502,7 +6606,8 @@ class WebRTCClient extends Emitter {
6502
6606
  }
6503
6607
  const sdh = session.sessionDescriptionHandler;
6504
6608
  const pc = sdh.peerConnection;
6505
- const localStream = this.getLocalStream(this.getSipSessionId(session));
6609
+ const sessionId = this.getSipSessionId(session);
6610
+ const localStream = this.getLocalStream(sessionId);
6506
6611
 
6507
6612
  // Release old video stream
6508
6613
  if (localStream) {
@@ -6528,11 +6633,8 @@ class WebRTCClient extends Emitter {
6528
6633
 
6529
6634
  // let's update the local stream
6530
6635
  this.eventEmitter.emit('onVideoInputChange', stream);
6531
- try {
6532
- await sdh.setLocalMediaStream(stream);
6533
- } catch (_) {
6534
- // Nothing to do
6535
- }
6636
+ this.setLocalMediaStream(sessionId, stream);
6637
+
6536
6638
  return stream;
6537
6639
  });
6538
6640
  }
@@ -6834,9 +6936,11 @@ class WebRTCClient extends Emitter {
6834
6936
  remoteStream.removeTrack(track);
6835
6937
  });
6836
6938
 
6837
- pc.getReceivers().forEach(receiver => {
6838
- remoteStream.addTrack(receiver.track);
6839
- });
6939
+ if (pc.getReceivers) {
6940
+ pc.getReceivers().forEach(receiver => {
6941
+ remoteStream.addTrack(receiver.track);
6942
+ });
6943
+ }
6840
6944
  }
6841
6945
 
6842
6946
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -6871,6 +6975,25 @@ class WebRTCClient extends Emitter {
6871
6975
  return sessionId in this.conferences;
6872
6976
  }
6873
6977
 
6978
+ createAudioElementFor(sessionId ) {
6979
+ const audio = document.createElement('audio');
6980
+ audio.setAttribute('id', `audio-${sessionId}`);
6981
+
6982
+ if (audio.setSinkId && this.audioOutputDeviceId) {
6983
+ audio.setSinkId(this.audioOutputDeviceId);
6984
+ }
6985
+
6986
+ if (document.body) {
6987
+ document.body.appendChild(audio);
6988
+ }
6989
+ this.audioElements[sessionId] = audio;
6990
+
6991
+ audio.volume = this.audioOutputVolume;
6992
+ audio.autoplay = true;
6993
+
6994
+ return audio;
6995
+ }
6996
+
6874
6997
  _onTransportError() {
6875
6998
  this.eventEmitter.emit(TRANSPORT_ERROR);
6876
6999
  this.attemptReconnection();
@@ -7100,7 +7223,7 @@ class WebRTCClient extends Emitter {
7100
7223
  let hadRemoteVideo = false;
7101
7224
 
7102
7225
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
7103
- // Becase when `onInvite` is called we already got the video track
7226
+ // Because when `onInvite` is called we already got the video track
7104
7227
  session.onInviteRequest = (request) => {
7105
7228
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
7106
7229
 
@@ -7175,20 +7298,10 @@ class WebRTCClient extends Emitter {
7175
7298
  const isConference = this.isConference(sessionId);
7176
7299
 
7177
7300
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
7178
- const audio = document.createElement('audio');
7179
- audio.setAttribute('id', `audio-${sessionId}`);
7180
-
7181
- if (audio.setSinkId && this.audioOutputDeviceId) {
7182
- audio.setSinkId(this.audioOutputDeviceId);
7183
- }
7184
-
7185
- if (document.body) {
7186
- document.body.appendChild(audio);
7187
- }
7188
- this.audioElements[sessionId] = audio;
7301
+ this.createAudioElementFor(sessionId);
7189
7302
  }
7190
7303
 
7191
- const audioElement = this.audioElements[this.getSipSessionId(session)];
7304
+ const audioElement = this.audioElements[sessionId];
7192
7305
  const stream = newStream || this.getRemoteStream(sessionId);
7193
7306
 
7194
7307
  if (!this._isWeb() || !stream) {
@@ -315,7 +315,13 @@ class IssueReporter {
315
315
  }
316
316
 
317
317
  _isLevelAbove(level1 , level2 ) {
318
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
318
+ const index1 = LOG_LEVELS.indexOf(level1);
319
+ const index2 = LOG_LEVELS.indexOf(level2);
320
+ if (index1 === -1 || index2 === -1) {
321
+ return false;
322
+ }
323
+
324
+ return index1 > index2;
319
325
  }
320
326
 
321
327
  _makeCategory(category ) {
@@ -2493,6 +2499,65 @@ class ExternalApp {
2493
2499
  }
2494
2500
  }
2495
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
+
2496
2561
  /* */
2497
2562
 
2498
2563
  var confdMethods = (client , baseUrl ) => ({
@@ -2557,6 +2622,18 @@ var confdMethods = (client , baseUrl ) => ({
2557
2622
  return null;
2558
2623
  }
2559
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),
2560
2637
  });
2561
2638
 
2562
2639
  //
@@ -3141,7 +3218,11 @@ class CallLog {
3141
3218
  answered: plain.answered,
3142
3219
  callDirection: plain.call_direction,
3143
3220
  destination: {
3144
- 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 || ''}`,
3145
3226
  name: plain.requested_name || plain.destination_name || '',
3146
3227
  },
3147
3228
  source: {
@@ -3157,27 +3238,11 @@ class CallLog {
3157
3238
  }
3158
3239
 
3159
3240
  static parseNew(plain , session ) {
3160
- return new CallLog({
3161
- answer: plain.answer ? moment__default['default'](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__default['default'](plain.start).toDate(),
3175
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3176
- recordings: Recording.parseMany(plain.recordings),
3177
- // @TODO: FIXME add verification declined vs missed call
3178
- newMissedCall: session
3179
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3180
- });
3241
+ const callLog = CallLog.parse(plain);
3242
+ // @TODO: FIXME add verification declined vs missed call
3243
+ callLog.newMissedCall = session
3244
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3245
+ return callLog;
3181
3246
  }
3182
3247
 
3183
3248
  static newFrom(profile ) {
@@ -3934,6 +3999,9 @@ var calldMethods = (client , baseUrl ) => ({
3934
3999
  getConferenceParticipantsAsUser: async (conferenceId ) =>
3935
4000
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
3936
4001
 
4002
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4003
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4004
+
3937
4005
  listTrunks: () => client.get(`${baseUrl}/trunks`),
3938
4006
 
3939
4007
  mute: (callId ) =>