@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
@@ -327,7 +327,13 @@ class IssueReporter {
327
327
  }
328
328
 
329
329
  _isLevelAbove(level1 , level2 ) {
330
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
330
+ const index1 = LOG_LEVELS.indexOf(level1);
331
+ const index2 = LOG_LEVELS.indexOf(level2);
332
+ if (index1 === -1 || index2 === -1) {
333
+ return false;
334
+ }
335
+
336
+ return index1 > index2;
331
337
  }
332
338
 
333
339
  _makeCategory(category ) {
@@ -2505,6 +2511,65 @@ class ExternalApp {
2505
2511
  }
2506
2512
  }
2507
2513
 
2514
+ //
2515
+
2516
+
2517
+
2518
+
2519
+
2520
+
2521
+
2522
+
2523
+
2524
+
2525
+
2526
+ class Meeting {
2527
+
2528
+
2529
+
2530
+
2531
+
2532
+
2533
+
2534
+
2535
+
2536
+
2537
+ static parse(plain ) {
2538
+ return new Meeting({
2539
+ guestSipAuthorization: plain.guest_sip_authorization,
2540
+ hostname: plain.hostname,
2541
+ name: plain.name,
2542
+ ownerUuids: plain.owner_uuids,
2543
+ port: plain.port,
2544
+ uuid: plain.uuid,
2545
+ number: plain.number,
2546
+ });
2547
+ }
2548
+
2549
+ static newFrom(meeting ) {
2550
+ return newFrom(meeting, Meeting);
2551
+ }
2552
+
2553
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2554
+ this.guestSipAuthorization = guestSipAuthorization;
2555
+ this.hostname = hostname;
2556
+ this.name = name;
2557
+ this.ownerUuids = ownerUuids;
2558
+ this.port = port;
2559
+ this.uuid = uuid;
2560
+ this.number = number;
2561
+
2562
+ // Useful to compare instead of instanceof with minified code
2563
+ this.type = 'Meeting';
2564
+ }
2565
+
2566
+ getGuestSipCredentials() {
2567
+ // eslint-disable-next-line no-undef
2568
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2569
+ return { username, secret };
2570
+ }
2571
+ }
2572
+
2508
2573
  /* */
2509
2574
 
2510
2575
  var confdMethods = (client , baseUrl ) => ({
@@ -2569,6 +2634,18 @@ var confdMethods = (client , baseUrl ) => ({
2569
2634
  return null;
2570
2635
  }
2571
2636
  },
2637
+
2638
+ createMyMeeting: (name ) =>
2639
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2640
+
2641
+ deleteMyMeeting: (meetingUuid ) =>
2642
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2643
+
2644
+ getMeeting: (meetingUuid ) =>
2645
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2646
+
2647
+ guestGetMeeting: (meetingUuid ) =>
2648
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2572
2649
  });
2573
2650
 
2574
2651
  //
@@ -3179,7 +3256,11 @@ class CallLog {
3179
3256
  answered: plain.answered,
3180
3257
  callDirection: plain.call_direction,
3181
3258
  destination: {
3182
- extension: plain.requested_extension || plain.destination_extension,
3259
+ // @TEMP: Temporarily assuming empty numbers are meetings
3260
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3261
+ extension: plain.requested_extension
3262
+ || plain.destination_extension
3263
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3183
3264
  name: plain.requested_name || plain.destination_name || '',
3184
3265
  },
3185
3266
  source: {
@@ -3195,27 +3276,11 @@ class CallLog {
3195
3276
  }
3196
3277
 
3197
3278
  static parseNew(plain , session ) {
3198
- return new CallLog({
3199
- answer: plain.answer ? moment(plain.answer).toDate() : null,
3200
- answered: plain.answered,
3201
- callDirection: plain.call_direction,
3202
- destination: {
3203
- extension: plain.requested_extension || plain.destination_extension,
3204
- name: plain.requested_name || plain.destination_name || '',
3205
- },
3206
- source: {
3207
- extension: plain.source_extension,
3208
- name: plain.source_name,
3209
- },
3210
- id: plain.id,
3211
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3212
- start: moment(plain.start).toDate(),
3213
- end: plain.end ? moment(plain.end).toDate() : null,
3214
- recordings: Recording.parseMany(plain.recordings),
3215
- // @TODO: FIXME add verification declined vs missed call
3216
- newMissedCall: session
3217
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3218
- });
3279
+ const callLog = CallLog.parse(plain);
3280
+ // @TODO: FIXME add verification declined vs missed call
3281
+ callLog.newMissedCall = session
3282
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3283
+ return callLog;
3219
3284
  }
3220
3285
 
3221
3286
  static newFrom(profile ) {
@@ -3972,6 +4037,9 @@ var calldMethods = (client , baseUrl ) => ({
3972
4037
  getConferenceParticipantsAsUser: async (conferenceId ) =>
3973
4038
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
3974
4039
 
4040
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4041
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4042
+
3975
4043
  listTrunks: () => client.get(`${baseUrl}/trunks`),
3976
4044
 
3977
4045
  mute: (callId ) =>
@@ -4706,6 +4774,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
4706
4774
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
4707
4775
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
4708
4776
  const CONFERENCE_USER_PARTICIPANT_TALK_STOPPED = 'conference_user_participant_talk_stopped';
4777
+ const MEETING_USER_PARTICIPANT_JOINED = 'meeting_user_participant_joined';
4778
+ const MEETING_USER_PARTICIPANT_LEFT = 'meeting_user_participant_left';
4709
4779
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
4710
4780
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
4711
4781
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -5052,6 +5122,8 @@ WebSocketClient.eventLists = [
5052
5122
  CHATD_USER_ROOM_CREATED,
5053
5123
  CONFERENCE_USER_PARTICIPANT_JOINED,
5054
5124
  CONFERENCE_USER_PARTICIPANT_LEFT,
5125
+ MEETING_USER_PARTICIPANT_JOINED,
5126
+ MEETING_USER_PARTICIPANT_LEFT,
5055
5127
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
5056
5128
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
5057
5129
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -5288,7 +5360,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5288
5360
  .then(() => {
5289
5361
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
5290
5362
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
5291
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5363
+ if (this.peerConnection.addTransceiver) {
5364
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
5365
+ }
5292
5366
  }
5293
5367
  })
5294
5368
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -5315,12 +5389,6 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5315
5389
  };
5316
5390
  })
5317
5391
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
5318
- .then((sessionDescription) => {
5319
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
5320
- this.localMediaStreamConstraints = options.constraints;
5321
-
5322
- return sessionDescription;
5323
- })
5324
5392
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
5325
5393
  .catch((error) => {
5326
5394
  wazoLogger.error('error when creating media', error);
@@ -5515,6 +5583,9 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5515
5583
 
5516
5584
  // set the transceiver direction to the answer direction
5517
5585
  this._peerConnection.getTransceivers().forEach((transceiver) => {
5586
+ if (transceiver.stopped) {
5587
+ return;
5588
+ }
5518
5589
  if (transceiver.direction /* guarding, but should always be true */) {
5519
5590
  const { receiver } = transceiver;
5520
5591
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -5559,10 +5630,15 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5559
5630
  if (kind !== 'audio' && kind !== 'video') {
5560
5631
  throw new Error(`Unknown new track kind ${kind}.`);
5561
5632
  }
5562
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
5633
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
5634
+ otherSender.track && otherSender.track.kind === kind);
5563
5635
 
5564
5636
  // Do not reuse sender video tracks in SFU
5565
5637
  if (sender && (!sfu || newTrack.kind === 'audio')) {
5638
+ if (sender.track) {
5639
+ // eslint-disable-next-line no-param-reassign
5640
+ newTrack.enabled = sender.track.enabled;
5641
+ }
5566
5642
  trackUpdates.push(
5567
5643
  new Promise((resolve) => {
5568
5644
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -5596,7 +5672,11 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
5596
5672
  // Review: could make streamless tracks a configurable option?
5597
5673
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
5598
5674
  try {
5599
- pc.addTrack(newTrack, localStream);
5675
+ if (pc.addTrack) {
5676
+ pc.addTrack(newTrack, localStream);
5677
+ } else {
5678
+ pc.addStream(localStream);
5679
+ }
5600
5680
  } catch (error) {
5601
5681
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
5602
5682
  throw error;
@@ -5680,6 +5760,7 @@ const MAX_REGISTER_TRIES = 10;
5680
5760
 
5681
5761
 
5682
5762
 
5763
+
5683
5764
 
5684
5765
 
5685
5766
 
@@ -5706,6 +5787,7 @@ class WebRTCClient extends Emitter {
5706
5787
 
5707
5788
 
5708
5789
 
5790
+
5709
5791
 
5710
5792
  // sugar
5711
5793
 
@@ -5744,6 +5826,8 @@ class WebRTCClient extends Emitter {
5744
5826
  super();
5745
5827
  this.uaConfigOverrides = uaConfigOverrides;
5746
5828
  this.config = config;
5829
+ this.skipRegister = config.skipRegister;
5830
+
5747
5831
  this._buildConfig(config, session).then((newConfig ) => {
5748
5832
  this.config = newConfig;
5749
5833
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -5871,14 +5955,22 @@ class WebRTCClient extends Emitter {
5871
5955
  }
5872
5956
 
5873
5957
  register(tries = 0) {
5874
- logger$1.info('sdk webrtc registering...', {
5958
+ const logInfo = {
5875
5959
  userAgent: !!this.userAgent,
5876
5960
  registered: this.isRegistered(),
5877
5961
  connectionPromise: !!this.connectionPromise,
5878
5962
  registerer: !!this.registerer,
5879
5963
  waiting: this.registerer && this.registerer.waiting,
5880
5964
  tries,
5881
- });
5965
+ skipRegister: this.skipRegister,
5966
+ };
5967
+
5968
+ if (this.skipRegister) {
5969
+ logger$1.info('sdk webrtc skip register...', logInfo);
5970
+ return Promise.resolve();
5971
+ }
5972
+
5973
+ logger$1.info('sdk webrtc registering...', logInfo);
5882
5974
 
5883
5975
  if (!this.userAgent) {
5884
5976
  logger$1.info('sdk webrtc recreating User Agent');
@@ -6209,12 +6301,18 @@ class WebRTCClient extends Emitter {
6209
6301
  }
6210
6302
 
6211
6303
  if (pc.getSenders) {
6304
+ if (!pc.getSenders().length) {
6305
+ return false;
6306
+ }
6212
6307
  pc.getSenders().forEach(sender => {
6213
6308
  if (sender && sender.track && sender.track.kind === 'audio') {
6214
6309
  muted = muted && !sender.track.enabled;
6215
6310
  }
6216
6311
  });
6217
6312
  } else {
6313
+ if (!pc.getLocalStreams().length) {
6314
+ return false;
6315
+ }
6218
6316
  pc.getLocalStreams().forEach(stream => {
6219
6317
  stream.getAudioTracks().forEach(track => {
6220
6318
  muted = muted && !track.enabled;
@@ -6271,6 +6369,9 @@ class WebRTCClient extends Emitter {
6271
6369
  if (!this._isWeb()) {
6272
6370
  options.sessionDescriptionHandlerModifiers = [holdModifier];
6273
6371
  }
6372
+ options.sessionDescriptionHandlerOptions = {
6373
+ constraints: options.constraints,
6374
+ };
6274
6375
 
6275
6376
  // Send re-INVITE
6276
6377
  return session.invite(options);
@@ -6310,6 +6411,9 @@ class WebRTCClient extends Emitter {
6310
6411
  // (eg: holdModifier)
6311
6412
  options.sessionDescriptionHandlerModifiers = [];
6312
6413
  }
6414
+ options.sessionDescriptionHandlerOptions = {
6415
+ constraints: options.constraints,
6416
+ };
6313
6417
 
6314
6418
  // Send re-INVITE
6315
6419
  return session.invite(options);
@@ -6492,7 +6596,8 @@ class WebRTCClient extends Emitter {
6492
6596
  }
6493
6597
  const sdh = session.sessionDescriptionHandler;
6494
6598
  const pc = sdh.peerConnection;
6495
- const localStream = this.getLocalStream(this.getSipSessionId(session));
6599
+ const sessionId = this.getSipSessionId(session);
6600
+ const localStream = this.getLocalStream(sessionId);
6496
6601
 
6497
6602
  // Release old video stream
6498
6603
  if (localStream) {
@@ -6518,11 +6623,8 @@ class WebRTCClient extends Emitter {
6518
6623
 
6519
6624
  // let's update the local stream
6520
6625
  this.eventEmitter.emit('onVideoInputChange', stream);
6521
- try {
6522
- await sdh.setLocalMediaStream(stream);
6523
- } catch (_) {
6524
- // Nothing to do
6525
- }
6626
+ this.setLocalMediaStream(sessionId, stream);
6627
+
6526
6628
  return stream;
6527
6629
  });
6528
6630
  }
@@ -6824,9 +6926,11 @@ class WebRTCClient extends Emitter {
6824
6926
  remoteStream.removeTrack(track);
6825
6927
  });
6826
6928
 
6827
- pc.getReceivers().forEach(receiver => {
6828
- remoteStream.addTrack(receiver.track);
6829
- });
6929
+ if (pc.getReceivers) {
6930
+ pc.getReceivers().forEach(receiver => {
6931
+ remoteStream.addTrack(receiver.track);
6932
+ });
6933
+ }
6830
6934
  }
6831
6935
 
6832
6936
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -6861,6 +6965,25 @@ class WebRTCClient extends Emitter {
6861
6965
  return sessionId in this.conferences;
6862
6966
  }
6863
6967
 
6968
+ createAudioElementFor(sessionId ) {
6969
+ const audio = document.createElement('audio');
6970
+ audio.setAttribute('id', `audio-${sessionId}`);
6971
+
6972
+ if (audio.setSinkId && this.audioOutputDeviceId) {
6973
+ audio.setSinkId(this.audioOutputDeviceId);
6974
+ }
6975
+
6976
+ if (document.body) {
6977
+ document.body.appendChild(audio);
6978
+ }
6979
+ this.audioElements[sessionId] = audio;
6980
+
6981
+ audio.volume = this.audioOutputVolume;
6982
+ audio.autoplay = true;
6983
+
6984
+ return audio;
6985
+ }
6986
+
6864
6987
  _onTransportError() {
6865
6988
  this.eventEmitter.emit(TRANSPORT_ERROR);
6866
6989
  this.attemptReconnection();
@@ -7090,7 +7213,7 @@ class WebRTCClient extends Emitter {
7090
7213
  let hadRemoteVideo = false;
7091
7214
 
7092
7215
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
7093
- // Becase when `onInvite` is called we already got the video track
7216
+ // Because when `onInvite` is called we already got the video track
7094
7217
  session.onInviteRequest = (request) => {
7095
7218
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
7096
7219
 
@@ -7165,20 +7288,10 @@ class WebRTCClient extends Emitter {
7165
7288
  const isConference = this.isConference(sessionId);
7166
7289
 
7167
7290
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
7168
- const audio = document.createElement('audio');
7169
- audio.setAttribute('id', `audio-${sessionId}`);
7170
-
7171
- if (audio.setSinkId && this.audioOutputDeviceId) {
7172
- audio.setSinkId(this.audioOutputDeviceId);
7173
- }
7174
-
7175
- if (document.body) {
7176
- document.body.appendChild(audio);
7177
- }
7178
- this.audioElements[sessionId] = audio;
7291
+ this.createAudioElementFor(sessionId);
7179
7292
  }
7180
7293
 
7181
- const audioElement = this.audioElements[this.getSipSessionId(session)];
7294
+ const audioElement = this.audioElements[sessionId];
7182
7295
  const stream = newStream || this.getRemoteStream(sessionId);
7183
7296
 
7184
7297
  if (!this._isWeb() || !stream) {
@@ -309,7 +309,13 @@ class IssueReporter {
309
309
  }
310
310
 
311
311
  _isLevelAbove(level1 , level2 ) {
312
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
312
+ const index1 = LOG_LEVELS.indexOf(level1);
313
+ const index2 = LOG_LEVELS.indexOf(level2);
314
+ if (index1 === -1 || index2 === -1) {
315
+ return false;
316
+ }
317
+
318
+ return index1 > index2;
313
319
  }
314
320
 
315
321
  _makeCategory(category ) {
@@ -2487,6 +2493,65 @@ class ExternalApp {
2487
2493
  }
2488
2494
  }
2489
2495
 
2496
+ //
2497
+
2498
+
2499
+
2500
+
2501
+
2502
+
2503
+
2504
+
2505
+
2506
+
2507
+
2508
+ class Meeting {
2509
+
2510
+
2511
+
2512
+
2513
+
2514
+
2515
+
2516
+
2517
+
2518
+
2519
+ static parse(plain ) {
2520
+ return new Meeting({
2521
+ guestSipAuthorization: plain.guest_sip_authorization,
2522
+ hostname: plain.hostname,
2523
+ name: plain.name,
2524
+ ownerUuids: plain.owner_uuids,
2525
+ port: plain.port,
2526
+ uuid: plain.uuid,
2527
+ number: plain.number,
2528
+ });
2529
+ }
2530
+
2531
+ static newFrom(meeting ) {
2532
+ return newFrom(meeting, Meeting);
2533
+ }
2534
+
2535
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
2536
+ this.guestSipAuthorization = guestSipAuthorization;
2537
+ this.hostname = hostname;
2538
+ this.name = name;
2539
+ this.ownerUuids = ownerUuids;
2540
+ this.port = port;
2541
+ this.uuid = uuid;
2542
+ this.number = number;
2543
+
2544
+ // Useful to compare instead of instanceof with minified code
2545
+ this.type = 'Meeting';
2546
+ }
2547
+
2548
+ getGuestSipCredentials() {
2549
+ // eslint-disable-next-line no-undef
2550
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
2551
+ return { username, secret };
2552
+ }
2553
+ }
2554
+
2490
2555
  /* */
2491
2556
 
2492
2557
  var confdMethods = (client , baseUrl ) => ({
@@ -2551,6 +2616,18 @@ var confdMethods = (client , baseUrl ) => ({
2551
2616
  return null;
2552
2617
  }
2553
2618
  },
2619
+
2620
+ createMyMeeting: (name ) =>
2621
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
2622
+
2623
+ deleteMyMeeting: (meetingUuid ) =>
2624
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
2625
+
2626
+ getMeeting: (meetingUuid ) =>
2627
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
2628
+
2629
+ guestGetMeeting: (meetingUuid ) =>
2630
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
2554
2631
  });
2555
2632
 
2556
2633
  //
@@ -3135,7 +3212,11 @@ class CallLog {
3135
3212
  answered: plain.answered,
3136
3213
  callDirection: plain.call_direction,
3137
3214
  destination: {
3138
- 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 || ''}`,
3139
3220
  name: plain.requested_name || plain.destination_name || '',
3140
3221
  },
3141
3222
  source: {
@@ -3151,27 +3232,11 @@ class CallLog {
3151
3232
  }
3152
3233
 
3153
3234
  static parseNew(plain , session ) {
3154
- return new CallLog({
3155
- answer: plain.answer ? moment(plain.answer).toDate() : null,
3156
- answered: plain.answered,
3157
- callDirection: plain.call_direction,
3158
- destination: {
3159
- extension: plain.requested_extension || plain.destination_extension,
3160
- name: plain.requested_name || plain.destination_name || '',
3161
- },
3162
- source: {
3163
- extension: plain.source_extension,
3164
- name: plain.source_name,
3165
- },
3166
- id: plain.id,
3167
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3168
- start: moment(plain.start).toDate(),
3169
- end: plain.end ? moment(plain.end).toDate() : null,
3170
- recordings: Recording.parseMany(plain.recordings),
3171
- // @TODO: FIXME add verification declined vs missed call
3172
- newMissedCall: session
3173
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3174
- });
3235
+ const callLog = CallLog.parse(plain);
3236
+ // @TODO: FIXME add verification declined vs missed call
3237
+ callLog.newMissedCall = session
3238
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3239
+ return callLog;
3175
3240
  }
3176
3241
 
3177
3242
  static newFrom(profile ) {
@@ -3928,6 +3993,9 @@ var calldMethods = (client , baseUrl ) => ({
3928
3993
  getConferenceParticipantsAsUser: async (conferenceId ) =>
3929
3994
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
3930
3995
 
3996
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
3997
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
3998
+
3931
3999
  listTrunks: () => client.get(`${baseUrl}/trunks`),
3932
4000
 
3933
4001
  mute: (callId ) =>