@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
@@ -311,7 +311,13 @@ class IssueReporter {
311
311
  }
312
312
 
313
313
  _isLevelAbove(level1 , level2 ) {
314
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
314
+ const index1 = LOG_LEVELS.indexOf(level1);
315
+ const index2 = LOG_LEVELS.indexOf(level2);
316
+ if (index1 === -1 || index2 === -1) {
317
+ return false;
318
+ }
319
+
320
+ return index1 > index2;
315
321
  }
316
322
 
317
323
  _makeCategory(category ) {
@@ -313,7 +313,13 @@ class IssueReporter {
313
313
  }
314
314
 
315
315
  _isLevelAbove(level1 , level2 ) {
316
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
316
+ const index1 = LOG_LEVELS.indexOf(level1);
317
+ const index2 = LOG_LEVELS.indexOf(level2);
318
+ if (index1 === -1 || index2 === -1) {
319
+ return false;
320
+ }
321
+
322
+ return index1 > index2;
317
323
  }
318
324
 
319
325
  _makeCategory(category ) {
@@ -602,7 +602,13 @@ class IssueReporter {
602
602
  }
603
603
 
604
604
  _isLevelAbove(level1 , level2 ) {
605
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
605
+ const index1 = LOG_LEVELS.indexOf(level1);
606
+ const index2 = LOG_LEVELS.indexOf(level2);
607
+ if (index1 === -1 || index2 === -1) {
608
+ return false;
609
+ }
610
+
611
+ return index1 > index2;
606
612
  }
607
613
 
608
614
  _makeCategory(category ) {
@@ -774,7 +780,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
774
780
  .then(() => {
775
781
  if (isConference && (options.constraints && !options.constraints.video) && !('hold' in options) && !audioOnly) {
776
782
  // Add a video an empty bundle to be able to replaceTrack when joining a conference without video
777
- this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
783
+ if (this.peerConnection.addTransceiver) {
784
+ this.peerConnection.addTransceiver('video', { streams: [this._localMediaStream], direction: 'sendrecv' });
785
+ }
778
786
  }
779
787
  })
780
788
  .then(() => this.createLocalOfferOrAnswer(options))
@@ -801,12 +809,6 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
801
809
  };
802
810
  })
803
811
  .then((sessionDescription) => this.applyModifiers(sessionDescription, modifiers))
804
- .then((sessionDescription) => {
805
- // Set new constraints to avoid the constraints check issue in `sdh.getLocalMediaStream` later.
806
- this.localMediaStreamConstraints = options.constraints;
807
-
808
- return sessionDescription;
809
- })
810
812
  .then((sessionDescription) => ({ body: sessionDescription.sdp, contentType: 'application/sdp' }))
811
813
  .catch((error) => {
812
814
  wazoLogger.error('error when creating media', error);
@@ -1001,6 +1003,9 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
1001
1003
 
1002
1004
  // set the transceiver direction to the answer direction
1003
1005
  this._peerConnection.getTransceivers().forEach((transceiver) => {
1006
+ if (transceiver.stopped) {
1007
+ return;
1008
+ }
1004
1009
  if (transceiver.direction /* guarding, but should always be true */) {
1005
1010
  const { receiver } = transceiver;
1006
1011
  if (isConference && audioOnly && receiver.track && receiver.track.kind === 'video') {
@@ -1045,10 +1050,15 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
1045
1050
  if (kind !== 'audio' && kind !== 'video') {
1046
1051
  throw new Error(`Unknown new track kind ${kind}.`);
1047
1052
  }
1048
- const sender = pc.getSenders().find((otherSender) => otherSender.track && otherSender.track.kind === kind);
1053
+ const sender = pc.getSenders && pc.getSenders().find((otherSender) =>
1054
+ otherSender.track && otherSender.track.kind === kind);
1049
1055
 
1050
1056
  // Do not reuse sender video tracks in SFU
1051
1057
  if (sender && (!sfu || newTrack.kind === 'audio')) {
1058
+ if (sender.track) {
1059
+ // eslint-disable-next-line no-param-reassign
1060
+ newTrack.enabled = sender.track.enabled;
1061
+ }
1052
1062
  trackUpdates.push(
1053
1063
  new Promise((resolve) => {
1054
1064
  this.logger.debug(`SessionDescriptionHandler.setLocalMediaStream - replacing sender ${kind} track`);
@@ -1082,7 +1092,11 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
1082
1092
  // Review: could make streamless tracks a configurable option?
1083
1093
  // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack#Usage_notes
1084
1094
  try {
1085
- pc.addTrack(newTrack, localStream);
1095
+ if (pc.addTrack) {
1096
+ pc.addTrack(newTrack, localStream);
1097
+ } else {
1098
+ pc.addStream(localStream);
1099
+ }
1086
1100
  } catch (error) {
1087
1101
  this.logger.error(`SessionDescriptionHandler.setLocalMediaStream - failed to add sender ${kind} track`);
1088
1102
  throw error;
@@ -3039,6 +3053,65 @@ class ExternalApp {
3039
3053
  }
3040
3054
  }
3041
3055
 
3056
+ //
3057
+
3058
+
3059
+
3060
+
3061
+
3062
+
3063
+
3064
+
3065
+
3066
+
3067
+
3068
+ class Meeting {
3069
+
3070
+
3071
+
3072
+
3073
+
3074
+
3075
+
3076
+
3077
+
3078
+
3079
+ static parse(plain ) {
3080
+ return new Meeting({
3081
+ guestSipAuthorization: plain.guest_sip_authorization,
3082
+ hostname: plain.hostname,
3083
+ name: plain.name,
3084
+ ownerUuids: plain.owner_uuids,
3085
+ port: plain.port,
3086
+ uuid: plain.uuid,
3087
+ number: plain.number,
3088
+ });
3089
+ }
3090
+
3091
+ static newFrom(meeting ) {
3092
+ return newFrom(meeting, Meeting);
3093
+ }
3094
+
3095
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number } = {}) {
3096
+ this.guestSipAuthorization = guestSipAuthorization;
3097
+ this.hostname = hostname;
3098
+ this.name = name;
3099
+ this.ownerUuids = ownerUuids;
3100
+ this.port = port;
3101
+ this.uuid = uuid;
3102
+ this.number = number;
3103
+
3104
+ // Useful to compare instead of instanceof with minified code
3105
+ this.type = 'Meeting';
3106
+ }
3107
+
3108
+ getGuestSipCredentials() {
3109
+ // eslint-disable-next-line no-undef
3110
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
3111
+ return { username, secret };
3112
+ }
3113
+ }
3114
+
3042
3115
  /* */
3043
3116
 
3044
3117
  var confdMethods = (client , baseUrl ) => ({
@@ -3103,6 +3176,18 @@ var confdMethods = (client , baseUrl ) => ({
3103
3176
  return null;
3104
3177
  }
3105
3178
  },
3179
+
3180
+ createMyMeeting: (name ) =>
3181
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
3182
+
3183
+ deleteMyMeeting: (meetingUuid ) =>
3184
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
3185
+
3186
+ getMeeting: (meetingUuid ) =>
3187
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
3188
+
3189
+ guestGetMeeting: (meetingUuid ) =>
3190
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
3106
3191
  });
3107
3192
 
3108
3193
  //
@@ -3687,7 +3772,11 @@ class CallLog {
3687
3772
  answered: plain.answered,
3688
3773
  callDirection: plain.call_direction,
3689
3774
  destination: {
3690
- extension: plain.requested_extension || plain.destination_extension,
3775
+ // @TEMP: Temporarily assuming empty numbers are meetings
3776
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
3777
+ extension: plain.requested_extension
3778
+ || plain.destination_extension
3779
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
3691
3780
  name: plain.requested_name || plain.destination_name || '',
3692
3781
  },
3693
3782
  source: {
@@ -3703,27 +3792,11 @@ class CallLog {
3703
3792
  }
3704
3793
 
3705
3794
  static parseNew(plain , session ) {
3706
- return new CallLog({
3707
- answer: plain.answer ? moment__default['default'](plain.answer).toDate() : null,
3708
- answered: plain.answered,
3709
- callDirection: plain.call_direction,
3710
- destination: {
3711
- extension: plain.requested_extension || plain.destination_extension,
3712
- name: plain.requested_name || plain.destination_name || '',
3713
- },
3714
- source: {
3715
- extension: plain.source_extension,
3716
- name: plain.source_name,
3717
- },
3718
- id: plain.id,
3719
- duration: (plain.duration || 0) * 1000, // duration is in seconds
3720
- start: moment__default['default'](plain.start).toDate(),
3721
- end: plain.end ? moment__default['default'](plain.end).toDate() : null,
3722
- recordings: Recording.parseMany(plain.recordings),
3723
- // @TODO: FIXME add verification declined vs missed call
3724
- newMissedCall: session
3725
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
3726
- });
3795
+ const callLog = CallLog.parse(plain);
3796
+ // @TODO: FIXME add verification declined vs missed call
3797
+ callLog.newMissedCall = session
3798
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
3799
+ return callLog;
3727
3800
  }
3728
3801
 
3729
3802
  static newFrom(profile ) {
@@ -4480,6 +4553,9 @@ var calldMethods = (client , baseUrl ) => ({
4480
4553
  getConferenceParticipantsAsUser: async (conferenceId ) =>
4481
4554
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
4482
4555
 
4556
+ getMeetingParticipantsAsUser: async (meetingUuid ) =>
4557
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4558
+
4483
4559
  listTrunks: () => client.get(`${baseUrl}/trunks`),
4484
4560
 
4485
4561
  mute: (callId ) =>
@@ -5115,6 +5191,7 @@ const MAX_REGISTER_TRIES = 10;
5115
5191
 
5116
5192
 
5117
5193
 
5194
+
5118
5195
 
5119
5196
 
5120
5197
 
@@ -5141,6 +5218,7 @@ class WebRTCClient extends Emitter {
5141
5218
 
5142
5219
 
5143
5220
 
5221
+
5144
5222
 
5145
5223
  // sugar
5146
5224
 
@@ -5179,6 +5257,8 @@ class WebRTCClient extends Emitter {
5179
5257
  super();
5180
5258
  this.uaConfigOverrides = uaConfigOverrides;
5181
5259
  this.config = config;
5260
+ this.skipRegister = config.skipRegister;
5261
+
5182
5262
  this._buildConfig(config, session).then((newConfig ) => {
5183
5263
  this.config = newConfig;
5184
5264
  this.userAgent = this.createUserAgent(uaConfigOverrides);
@@ -5306,14 +5386,22 @@ class WebRTCClient extends Emitter {
5306
5386
  }
5307
5387
 
5308
5388
  register(tries = 0) {
5309
- logger.info('sdk webrtc registering...', {
5389
+ const logInfo = {
5310
5390
  userAgent: !!this.userAgent,
5311
5391
  registered: this.isRegistered(),
5312
5392
  connectionPromise: !!this.connectionPromise,
5313
5393
  registerer: !!this.registerer,
5314
5394
  waiting: this.registerer && this.registerer.waiting,
5315
5395
  tries,
5316
- });
5396
+ skipRegister: this.skipRegister,
5397
+ };
5398
+
5399
+ if (this.skipRegister) {
5400
+ logger.info('sdk webrtc skip register...', logInfo);
5401
+ return Promise.resolve();
5402
+ }
5403
+
5404
+ logger.info('sdk webrtc registering...', logInfo);
5317
5405
 
5318
5406
  if (!this.userAgent) {
5319
5407
  logger.info('sdk webrtc recreating User Agent');
@@ -5644,12 +5732,18 @@ class WebRTCClient extends Emitter {
5644
5732
  }
5645
5733
 
5646
5734
  if (pc.getSenders) {
5735
+ if (!pc.getSenders().length) {
5736
+ return false;
5737
+ }
5647
5738
  pc.getSenders().forEach(sender => {
5648
5739
  if (sender && sender.track && sender.track.kind === 'audio') {
5649
5740
  muted = muted && !sender.track.enabled;
5650
5741
  }
5651
5742
  });
5652
5743
  } else {
5744
+ if (!pc.getLocalStreams().length) {
5745
+ return false;
5746
+ }
5653
5747
  pc.getLocalStreams().forEach(stream => {
5654
5748
  stream.getAudioTracks().forEach(track => {
5655
5749
  muted = muted && !track.enabled;
@@ -5706,6 +5800,9 @@ class WebRTCClient extends Emitter {
5706
5800
  if (!this._isWeb()) {
5707
5801
  options.sessionDescriptionHandlerModifiers = [modifiers.holdModifier];
5708
5802
  }
5803
+ options.sessionDescriptionHandlerOptions = {
5804
+ constraints: options.constraints,
5805
+ };
5709
5806
 
5710
5807
  // Send re-INVITE
5711
5808
  return session.invite(options);
@@ -5745,6 +5842,9 @@ class WebRTCClient extends Emitter {
5745
5842
  // (eg: holdModifier)
5746
5843
  options.sessionDescriptionHandlerModifiers = [];
5747
5844
  }
5845
+ options.sessionDescriptionHandlerOptions = {
5846
+ constraints: options.constraints,
5847
+ };
5748
5848
 
5749
5849
  // Send re-INVITE
5750
5850
  return session.invite(options);
@@ -5927,7 +6027,8 @@ class WebRTCClient extends Emitter {
5927
6027
  }
5928
6028
  const sdh = session.sessionDescriptionHandler;
5929
6029
  const pc = sdh.peerConnection;
5930
- const localStream = this.getLocalStream(this.getSipSessionId(session));
6030
+ const sessionId = this.getSipSessionId(session);
6031
+ const localStream = this.getLocalStream(sessionId);
5931
6032
 
5932
6033
  // Release old video stream
5933
6034
  if (localStream) {
@@ -5953,11 +6054,8 @@ class WebRTCClient extends Emitter {
5953
6054
 
5954
6055
  // let's update the local stream
5955
6056
  this.eventEmitter.emit('onVideoInputChange', stream);
5956
- try {
5957
- await sdh.setLocalMediaStream(stream);
5958
- } catch (_) {
5959
- // Nothing to do
5960
- }
6057
+ this.setLocalMediaStream(sessionId, stream);
6058
+
5961
6059
  return stream;
5962
6060
  });
5963
6061
  }
@@ -6259,9 +6357,11 @@ class WebRTCClient extends Emitter {
6259
6357
  remoteStream.removeTrack(track);
6260
6358
  });
6261
6359
 
6262
- pc.getReceivers().forEach(receiver => {
6263
- remoteStream.addTrack(receiver.track);
6264
- });
6360
+ if (pc.getReceivers) {
6361
+ pc.getReceivers().forEach(receiver => {
6362
+ remoteStream.addTrack(receiver.track);
6363
+ });
6364
+ }
6265
6365
  }
6266
6366
 
6267
6367
  getMediaConfiguration(enableVideo , conference = false, constraints = null) {
@@ -6296,6 +6396,25 @@ class WebRTCClient extends Emitter {
6296
6396
  return sessionId in this.conferences;
6297
6397
  }
6298
6398
 
6399
+ createAudioElementFor(sessionId ) {
6400
+ const audio = document.createElement('audio');
6401
+ audio.setAttribute('id', `audio-${sessionId}`);
6402
+
6403
+ if (audio.setSinkId && this.audioOutputDeviceId) {
6404
+ audio.setSinkId(this.audioOutputDeviceId);
6405
+ }
6406
+
6407
+ if (document.body) {
6408
+ document.body.appendChild(audio);
6409
+ }
6410
+ this.audioElements[sessionId] = audio;
6411
+
6412
+ audio.volume = this.audioOutputVolume;
6413
+ audio.autoplay = true;
6414
+
6415
+ return audio;
6416
+ }
6417
+
6299
6418
  _onTransportError() {
6300
6419
  this.eventEmitter.emit(TRANSPORT_ERROR);
6301
6420
  this.attemptReconnection();
@@ -6525,7 +6644,7 @@ class WebRTCClient extends Emitter {
6525
6644
  let hadRemoteVideo = false;
6526
6645
 
6527
6646
  // Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
6528
- // Becase when `onInvite` is called we already got the video track
6647
+ // Because when `onInvite` is called we already got the video track
6529
6648
  session.onInviteRequest = (request) => {
6530
6649
  hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
6531
6650
 
@@ -6600,20 +6719,10 @@ class WebRTCClient extends Emitter {
6600
6719
  const isConference = this.isConference(sessionId);
6601
6720
 
6602
6721
  if (this._hasAudio() && this._isWeb() && !(sessionId in this.audioElements)) {
6603
- const audio = document.createElement('audio');
6604
- audio.setAttribute('id', `audio-${sessionId}`);
6605
-
6606
- if (audio.setSinkId && this.audioOutputDeviceId) {
6607
- audio.setSinkId(this.audioOutputDeviceId);
6608
- }
6609
-
6610
- if (document.body) {
6611
- document.body.appendChild(audio);
6612
- }
6613
- this.audioElements[sessionId] = audio;
6722
+ this.createAudioElementFor(sessionId);
6614
6723
  }
6615
6724
 
6616
- const audioElement = this.audioElements[this.getSipSessionId(session)];
6725
+ const audioElement = this.audioElements[sessionId];
6617
6726
  const stream = newStream || this.getRemoteStream(sessionId);
6618
6727
 
6619
6728
  if (!this._isWeb() || !stream) {
@@ -310,7 +310,13 @@ class IssueReporter {
310
310
  }
311
311
 
312
312
  _isLevelAbove(level1 , level2 ) {
313
- return LOG_LEVELS.indexOf(level1) > LOG_LEVELS.indexOf(level2);
313
+ const index1 = LOG_LEVELS.indexOf(level1);
314
+ const index2 = LOG_LEVELS.indexOf(level2);
315
+ if (index1 === -1 || index2 === -1) {
316
+ return false;
317
+ }
318
+
319
+ return index1 > index2;
314
320
  }
315
321
 
316
322
  _makeCategory(category ) {
@@ -469,6 +475,8 @@ const CONFERENCE_USER_PARTICIPANT_JOINED = 'conference_user_participant_joined';
469
475
  const CONFERENCE_USER_PARTICIPANT_LEFT = 'conference_user_participant_left';
470
476
  const CONFERENCE_USER_PARTICIPANT_TALK_STARTED = 'conference_user_participant_talk_started';
471
477
  const CONFERENCE_USER_PARTICIPANT_TALK_STOPPED = 'conference_user_participant_talk_stopped';
478
+ const MEETING_USER_PARTICIPANT_JOINED = 'meeting_user_participant_joined';
479
+ const MEETING_USER_PARTICIPANT_LEFT = 'meeting_user_participant_left';
472
480
  const SWITCHBOARD_QUEUED_CALLS_UPDATED = 'switchboard_queued_calls_updated';
473
481
  const SWITCHBOARD_QUEUED_CALL_ANSWERED = 'switchboard_queued_call_answered';
474
482
  const SWITCHBOARD_HELD_CALLS_UPDATED = 'switchboard_held_calls_updated';
@@ -815,6 +823,8 @@ WebSocketClient.eventLists = [
815
823
  CHATD_USER_ROOM_CREATED,
816
824
  CONFERENCE_USER_PARTICIPANT_JOINED,
817
825
  CONFERENCE_USER_PARTICIPANT_LEFT,
826
+ MEETING_USER_PARTICIPANT_JOINED,
827
+ MEETING_USER_PARTICIPANT_LEFT,
818
828
  CONFERENCE_USER_PARTICIPANT_TALK_STARTED,
819
829
  CONFERENCE_USER_PARTICIPANT_TALK_STOPPED,
820
830
  SWITCHBOARD_QUEUED_CALLS_UPDATED,
@@ -902,6 +912,8 @@ exports.FAX_OUTBOUND_USER_FAILED = FAX_OUTBOUND_USER_FAILED;
902
912
  exports.FAX_OUTBOUND_USER_SUCCEEDED = FAX_OUTBOUND_USER_SUCCEEDED;
903
913
  exports.HEARTBEAT_ENGINE_VERSION = HEARTBEAT_ENGINE_VERSION;
904
914
  exports.LINE_STATUS_UPDATED = LINE_STATUS_UPDATED;
915
+ exports.MEETING_USER_PARTICIPANT_JOINED = MEETING_USER_PARTICIPANT_JOINED;
916
+ exports.MEETING_USER_PARTICIPANT_LEFT = MEETING_USER_PARTICIPANT_LEFT;
905
917
  exports.SOCKET_EVENTS = SOCKET_EVENTS;
906
918
  exports.SWITCHBOARD_HELD_CALLS_UPDATED = SWITCHBOARD_HELD_CALLS_UPDATED;
907
919
  exports.SWITCHBOARD_HELD_CALL_ANSWERED = SWITCHBOARD_HELD_CALL_ANSWERED;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wazo/sdk",
3
- "version": "0.37.0",
3
+ "version": "0.37.4",
4
4
  "description": "Wazo's JavaScript Software Development Kit.",
5
5
  "main": "dist/wazo-sdk.js",
6
6
  "author": "Wazo (http://wazo.io)",
package/src/api/calld.js CHANGED
@@ -133,6 +133,9 @@ export default (client: ApiRequester, baseUrl: string) => ({
133
133
  getConferenceParticipantsAsUser: async (conferenceId: string): Promise<Object> =>
134
134
  client.get(`${baseUrl}/users/me/conferences/${conferenceId}/participants`),
135
135
 
136
+ getMeetingParticipantsAsUser: async (meetingUuid: string): Promise<Object> =>
137
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
138
+
136
139
  listTrunks: () => client.get(`${baseUrl}/trunks`),
137
140
 
138
141
  mute: (callId: string) =>
package/src/api/confd.js CHANGED
@@ -4,6 +4,7 @@ import type { UUID, ListConfdUsersResponse, ListApplicationsResponse } from '../
4
4
  import Profile from '../domain/Profile';
5
5
  import SipLine from '../domain/SipLine';
6
6
  import ExternalApp from '../domain/ExternalApp';
7
+ import Meeting from '../domain/Meeting';
7
8
 
8
9
  export default (client: ApiRequester, baseUrl: string) => ({
9
10
  listUsers: (): Promise<ListConfdUsersResponse> => client.get(`${baseUrl}/users`, null),
@@ -67,4 +68,16 @@ export default (client: ApiRequester, baseUrl: string) => ({
67
68
  return null;
68
69
  }
69
70
  },
71
+
72
+ createMyMeeting: (name: string): Promise<Meeting> =>
73
+ client.post(`${baseUrl}/users/me/meetings`, { name }).then(Meeting.parse),
74
+
75
+ deleteMyMeeting: (meetingUuid: string): Promise<Meeting> =>
76
+ client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
77
+
78
+ getMeeting: (meetingUuid: string): Promise<Meeting> =>
79
+ client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
80
+
81
+ guestGetMeeting: (meetingUuid: string): Promise<Meeting> =>
82
+ client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
70
83
  });
@@ -91,7 +91,11 @@ export default class CallLog {
91
91
  answered: plain.answered,
92
92
  callDirection: plain.call_direction,
93
93
  destination: {
94
- extension: plain.requested_extension || plain.destination_extension,
94
+ // @TEMP: Temporarily assuming empty numbers are meetings
95
+ // which is admittedly a very dangerous assumption. Did i mention it was temporary?
96
+ extension: plain.requested_extension
97
+ || plain.destination_extension
98
+ || `meeting-${plain.requested_name || plain.destination_name || ''}`,
95
99
  name: plain.requested_name || plain.destination_name || '',
96
100
  },
97
101
  source: {
@@ -107,27 +111,11 @@ export default class CallLog {
107
111
  }
108
112
 
109
113
  static parseNew(plain: CallLogResponse, session: Session): CallLog {
110
- return new CallLog({
111
- answer: plain.answer ? moment(plain.answer).toDate() : null,
112
- answered: plain.answered,
113
- callDirection: plain.call_direction,
114
- destination: {
115
- extension: plain.requested_extension || plain.destination_extension,
116
- name: plain.requested_name || plain.destination_name || '',
117
- },
118
- source: {
119
- extension: plain.source_extension,
120
- name: plain.source_name,
121
- },
122
- id: plain.id,
123
- duration: (plain.duration || 0) * 1000, // duration is in seconds
124
- start: moment(plain.start).toDate(),
125
- end: plain.end ? moment(plain.end).toDate() : null,
126
- recordings: Recording.parseMany(plain.recordings),
127
- // @TODO: FIXME add verification declined vs missed call
128
- newMissedCall: session
129
- && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered,
130
- });
114
+ const callLog: CallLog = CallLog.parse(plain);
115
+ // @TODO: FIXME add verification declined vs missed call
116
+ callLog.newMissedCall = session
117
+ && session.hasExtension(plain.requested_extension || plain.destination_extension) && !plain.answered;
118
+ return callLog;
131
119
  }
132
120
 
133
121
  static newFrom(profile: CallLog) {
@@ -2,7 +2,6 @@
2
2
  import { SessionState } from 'sip.js/lib/api/session-state';
3
3
 
4
4
  import Call from './Call';
5
- import Session from './Session';
6
5
  import newFrom from '../utils/new-from';
7
6
  import updateFrom from '../utils/update-from';
8
7
 
@@ -311,7 +310,7 @@ export default class CallSession {
311
310
  return newFrom(callSession, CallSession);
312
311
  }
313
312
 
314
- static parseCall(session: Session, call: Call): CallSession {
313
+ static parseCall(call: Call): CallSession {
315
314
  return new CallSession({
316
315
  callId: call.id,
317
316
  sipCallId: call.sipCallId,
@@ -0,0 +1,59 @@
1
+ // @flow
2
+ import newFrom from '../utils/new-from';
3
+
4
+ export type MeetingCreationResponse = {
5
+ guest_sip_authorization: string,
6
+ hostname: string,
7
+ name: string,
8
+ owner_uuids: Array<string>,
9
+ port: string,
10
+ uuid: string,
11
+ number: string
12
+ }
13
+
14
+ export default class Meeting {
15
+ type: string;
16
+
17
+ guestSipAuthorization: string;
18
+ hostname: string;
19
+ uuid: string;
20
+ name: string;
21
+ port: string;
22
+ number: string;
23
+ ownerUuids: Array<string>;
24
+
25
+ static parse(plain: MeetingCreationResponse): Meeting {
26
+ return new Meeting({
27
+ guestSipAuthorization: plain.guest_sip_authorization,
28
+ hostname: plain.hostname,
29
+ name: plain.name,
30
+ ownerUuids: plain.owner_uuids,
31
+ port: plain.port,
32
+ uuid: plain.uuid,
33
+ number: plain.number,
34
+ });
35
+ }
36
+
37
+ static newFrom(meeting: Meeting) {
38
+ return newFrom(meeting, Meeting);
39
+ }
40
+
41
+ constructor({ uuid, name, guestSipAuthorization, ownerUuids, port, hostname, number }: Object = {}) {
42
+ this.guestSipAuthorization = guestSipAuthorization;
43
+ this.hostname = hostname;
44
+ this.name = name;
45
+ this.ownerUuids = ownerUuids;
46
+ this.port = port;
47
+ this.uuid = uuid;
48
+ this.number = number;
49
+
50
+ // Useful to compare instead of instanceof with minified code
51
+ this.type = 'Meeting';
52
+ }
53
+
54
+ getGuestSipCredentials() {
55
+ // eslint-disable-next-line no-undef
56
+ const [username, secret] = atob(this.guestSipAuthorization).split(':');
57
+ return { username, secret };
58
+ }
59
+ }
@@ -102,7 +102,7 @@ export default class CTIPhone extends Emitter implements Phone {
102
102
  if (!this.currentCall) {
103
103
  return null;
104
104
  }
105
- const callSession = CallSession.parseCall(this.session, this.currentCall);
105
+ const callSession = CallSession.parseCall(this.currentCall);
106
106
  this.eventEmitter.emit('onCallOutgoing', callSession);
107
107
 
108
108
  return callSession;
@@ -286,6 +286,10 @@ export default class CTIPhone extends Emitter implements Phone {
286
286
  return null;
287
287
  }
288
288
 
289
+ getLocalVideoStream(): ?MediaStream {
290
+ return null;
291
+ }
292
+
289
293
  setActiveSipSession() {}
290
294
 
291
295
  isRegistered(): boolean {
@@ -301,7 +305,7 @@ export default class CTIPhone extends Emitter implements Phone {
301
305
  }
302
306
 
303
307
  getCurrentCallSession(): ?CallSession {
304
- return this.currentCall ? CallSession.parseCall(this.session, this.currentCall) : null;
308
+ return this.currentCall ? CallSession.parseCall(this.currentCall) : null;
305
309
  }
306
310
 
307
311
  enableRinging() {}
@@ -56,6 +56,8 @@ export interface Phone {
56
56
 
57
57
  getLocalStreamForCall(callSession: CallSession): ?MediaStream;
58
58
 
59
+ getLocalVideoStream(callSession: CallSession): ?MediaStream;
60
+
59
61
  getOptions(): AvailablePhoneOptions;
60
62
 
61
63
  getRemoteStreamForCall(callSession: CallSession): ?MediaStream;