@wazo/sdk 0.38.5 → 0.38.8

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 (135) hide show
  1. package/README.md +1 -1
  2. package/dist/wazo-sdk.js +2 -2
  3. package/esm/__tests__/api-client.test.js +148 -2
  4. package/esm/__tests__/web-rtc-client.test.js +303 -26
  5. package/esm/api/calld.js +14 -0
  6. package/esm/api/confd.js +134 -2
  7. package/esm/api/ctid-ng.js +6 -0
  8. package/esm/api-client.js +148 -2
  9. package/esm/checker/Checker.js +212 -26
  10. package/esm/checker/checks/aor.js +148 -2
  11. package/esm/checker/checks/api.js +148 -2
  12. package/esm/checker/checks/index.js +212 -26
  13. package/esm/checker/checks/wazo-websocket.js +2 -0
  14. package/esm/checker/checks/webrtc-transport.js +210 -26
  15. package/esm/checker/checks/webrtc.js +210 -26
  16. package/esm/domain/AdHocAPIConference.js +148 -2
  17. package/esm/domain/Call.js +6 -0
  18. package/esm/domain/CallSession.js +1 -1
  19. package/esm/domain/Features.js +148 -2
  20. package/esm/domain/Meeting.js +18 -0
  21. package/esm/domain/MeetingAuthorization.js +70 -0
  22. package/esm/domain/Phone/CTIPhone.js +149 -3
  23. package/esm/domain/Phone/WebRTCPhone.js +3 -3
  24. package/esm/domain/__tests__/Call.test.js +6 -0
  25. package/esm/domain/__tests__/CallSession.test.js +1 -1
  26. package/esm/domain/__tests__/IndirectTransfer.test.js +1 -1
  27. package/esm/domain/__tests__/Meeting.test.js +87 -1
  28. package/esm/domain/__tests__/MeetingAuthorization.test.js +109 -0
  29. package/esm/domain/__tests__/Room.test.js +1 -1
  30. package/esm/index.js +258 -32
  31. package/esm/lib/WazoSessionDescriptionHandler.js +22 -1
  32. package/esm/service/CallApi.js +148 -2
  33. package/esm/service/getApiClient.js +148 -2
  34. package/esm/simple/Auth.js +258 -32
  35. package/esm/simple/Configuration.js +258 -32
  36. package/esm/simple/Directory.js +148 -2
  37. package/esm/simple/Phone.js +258 -32
  38. package/esm/simple/Websocket.js +3 -0
  39. package/esm/simple/index.js +258 -32
  40. package/esm/simple/room/LocalParticipant.js +258 -32
  41. package/esm/simple/room/Participant.js +258 -32
  42. package/esm/simple/room/RemoteParticipant.js +258 -32
  43. package/esm/simple/room/Room.js +258 -32
  44. package/esm/simple/room/SipRoom.js +258 -32
  45. package/esm/simple/room/Stream.js +258 -32
  46. package/esm/simple/room/__tests__/Participant.test.js +14747 -0
  47. package/esm/simple/room/__tests__/RemoteParticipant.test.js +258 -32
  48. package/esm/simple/utils.js +258 -32
  49. package/esm/utils/__tests__/object.test.js +57 -0
  50. package/esm/utils/__tests__/sdp.test.js +50 -0
  51. package/esm/utils/__tests__/string.test.js +30 -0
  52. package/esm/utils/object.js +24 -0
  53. package/esm/utils/sdp.js +19 -1
  54. package/esm/utils/string.js +10 -0
  55. package/esm/web-rtc-client.js +210 -26
  56. package/esm/websocket-client.js +3 -1
  57. package/lib/__tests__/api-client.test.js +148 -2
  58. package/lib/__tests__/web-rtc-client.test.js +303 -26
  59. package/lib/api/calld.js +14 -0
  60. package/lib/api/confd.js +134 -2
  61. package/lib/api/ctid-ng.js +6 -0
  62. package/lib/api-client.js +148 -2
  63. package/lib/checker/Checker.js +212 -26
  64. package/lib/checker/checks/aor.js +148 -2
  65. package/lib/checker/checks/api.js +148 -2
  66. package/lib/checker/checks/index.js +212 -26
  67. package/lib/checker/checks/wazo-websocket.js +2 -0
  68. package/lib/checker/checks/webrtc-transport.js +210 -26
  69. package/lib/checker/checks/webrtc.js +210 -26
  70. package/lib/domain/AdHocAPIConference.js +148 -2
  71. package/lib/domain/Call.js +6 -0
  72. package/lib/domain/CallSession.js +1 -1
  73. package/lib/domain/Features.js +148 -2
  74. package/lib/domain/Meeting.js +18 -0
  75. package/lib/domain/MeetingAuthorization.js +79 -0
  76. package/lib/domain/Phone/CTIPhone.js +149 -3
  77. package/lib/domain/Phone/WebRTCPhone.js +3 -3
  78. package/lib/domain/__tests__/Call.test.js +6 -0
  79. package/lib/domain/__tests__/CallSession.test.js +1 -1
  80. package/lib/domain/__tests__/IndirectTransfer.test.js +1 -1
  81. package/lib/domain/__tests__/Meeting.test.js +87 -1
  82. package/lib/domain/__tests__/MeetingAuthorization.test.js +111 -0
  83. package/lib/domain/__tests__/Room.test.js +1 -1
  84. package/lib/index.js +258 -32
  85. package/lib/lib/WazoSessionDescriptionHandler.js +22 -1
  86. package/lib/service/CallApi.js +148 -2
  87. package/lib/service/getApiClient.js +148 -2
  88. package/lib/simple/Auth.js +258 -32
  89. package/lib/simple/Configuration.js +258 -32
  90. package/lib/simple/Directory.js +148 -2
  91. package/lib/simple/Phone.js +258 -32
  92. package/lib/simple/Websocket.js +3 -0
  93. package/lib/simple/index.js +258 -32
  94. package/lib/simple/room/LocalParticipant.js +258 -32
  95. package/lib/simple/room/Participant.js +258 -32
  96. package/lib/simple/room/RemoteParticipant.js +258 -32
  97. package/lib/simple/room/Room.js +258 -32
  98. package/lib/simple/room/SipRoom.js +258 -32
  99. package/lib/simple/room/Stream.js +258 -32
  100. package/lib/simple/room/__tests__/Participant.test.js +14757 -0
  101. package/lib/simple/room/__tests__/RemoteParticipant.test.js +258 -32
  102. package/lib/simple/utils.js +258 -32
  103. package/lib/utils/__tests__/object.test.js +59 -0
  104. package/lib/utils/__tests__/sdp.test.js +50 -0
  105. package/lib/utils/__tests__/string.test.js +32 -0
  106. package/lib/utils/object.js +28 -0
  107. package/lib/utils/sdp.js +19 -0
  108. package/lib/utils/string.js +14 -0
  109. package/lib/web-rtc-client.js +210 -26
  110. package/lib/websocket-client.js +3 -0
  111. package/package.json +2 -2
  112. package/src/__tests__/web-rtc-client.test.js +93 -0
  113. package/src/api/calld.js +8 -0
  114. package/src/api/confd.js +43 -2
  115. package/src/domain/Call.js +6 -0
  116. package/src/domain/CallSession.js +1 -1
  117. package/src/domain/Meeting.js +20 -0
  118. package/src/domain/MeetingAuthorization.js +67 -0
  119. package/src/domain/Phone/WebRTCPhone.js +2 -2
  120. package/src/domain/__tests__/Meeting.test.js +70 -1
  121. package/src/domain/__tests__/MeetingAuthorization.test.js +58 -0
  122. package/src/lib/WazoSessionDescriptionHandler.js +5 -2
  123. package/src/simple/room/Participant.js +40 -0
  124. package/src/simple/room/Room.js +2 -2
  125. package/src/simple/room/SipRoom.js +1 -1
  126. package/src/simple/room/__tests__/Participant.test.js +81 -0
  127. package/src/types/WebSocketMessage.js +7 -1
  128. package/src/utils/__tests__/object.test.js +35 -0
  129. package/src/utils/__tests__/sdp.test.js +33 -1
  130. package/src/utils/__tests__/string.test.js +23 -0
  131. package/src/utils/object.js +15 -0
  132. package/src/utils/sdp.js +18 -0
  133. package/src/utils/string.js +8 -0
  134. package/src/web-rtc-client.js +40 -23
  135. package/src/websocket-client.js +2 -0
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ //
4
+
5
+ const camelToUnderscore = (key ) => {
6
+ if (typeof key !== 'string') {
7
+ throw new Error('Input is not a string');
8
+ }
9
+ return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
10
+ };
11
+
12
+ describe('string utils', () => {
13
+ describe('camelToUnderscore', () => {
14
+ it('', () => {
15
+ expect(() => camelToUnderscore(null)).toThrow('Input is not a string');
16
+ expect(() => camelToUnderscore(undefined)).toThrow('Input is not a string');
17
+ expect(() => camelToUnderscore({})).toThrow('Input is not a string');
18
+ expect(() => camelToUnderscore([])).toThrow('Input is not a string');
19
+ });
20
+
21
+ it('should convert camel-cased string to underscore', () => {
22
+ expect(camelToUnderscore('loremIpsum')).toEqual('lorem_ipsum');
23
+ expect(camelToUnderscore('lorem-ipsum')).toEqual('lorem-ipsum');
24
+ expect(camelToUnderscore('')).toEqual('');
25
+ });
26
+
27
+ it('should not prefix string with an underscore', () => {
28
+ expect(camelToUnderscore('LoremIpsum')).toEqual('lorem_ipsum');
29
+ expect(camelToUnderscore('L123')).toEqual('l123');
30
+ });
31
+ });
32
+ });
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ //
6
+
7
+ const camelToUnderscore = (key ) => {
8
+ if (typeof key !== 'string') {
9
+ throw new Error('Input is not a string');
10
+ }
11
+ return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
12
+ };
13
+
14
+ //
15
+
16
+ const convertKeysFromCamelToUnderscore = (args ) => {
17
+ if (!args || typeof args !== 'object' || Array.isArray(args)) {
18
+ throw new Error('Input is not an object');
19
+ }
20
+
21
+ return Object.keys(args).reduce((acc, key) => {
22
+ acc[camelToUnderscore(key)] = typeof args[key] === 'object' && !Array.isArray(args[key])
23
+ ? convertKeysFromCamelToUnderscore(args[key]) : args[key];
24
+ return acc;
25
+ }, {});
26
+ };
27
+
28
+ exports.convertKeysFromCamelToUnderscore = convertKeysFromCamelToUnderscore;
package/lib/utils/sdp.js CHANGED
@@ -130,7 +130,26 @@ const fixSdp = (sdp , candidates , forcePort = true)
130
130
  return fixed;
131
131
  };
132
132
 
133
+ const addIcesInAllBundles = (sdp ) => {
134
+ const parsedSdp = sdpParser__default['default'].parse(sdp);
135
+
136
+ const mediaWithCandidate = parsedSdp.media.find(media => !!media.candidates);
137
+ if (!mediaWithCandidate) {
138
+ return sdp;
139
+ }
140
+
141
+ const { candidates } = mediaWithCandidate;
142
+
143
+ parsedSdp.media = parsedSdp.media.map(media => ({
144
+ ...media,
145
+ candidates: media.candidates || candidates,
146
+ }));
147
+
148
+ return sdpParser__default['default'].write(parsedSdp);
149
+ };
150
+
133
151
  exports.activateVideoModifier = activateVideoModifier;
152
+ exports.addIcesInAllBundles = addIcesInAllBundles;
134
153
  exports.areCandidateValid = areCandidateValid;
135
154
  exports.deactivateVideoModifier = deactivateVideoModifier;
136
155
  exports.fixBundle = fixBundle;
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ //
6
+
7
+ const camelToUnderscore = (key ) => {
8
+ if (typeof key !== 'string') {
9
+ throw new Error('Input is not a string');
10
+ }
11
+ return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
12
+ };
13
+
14
+ exports.camelToUnderscore = camelToUnderscore;
@@ -789,6 +789,24 @@ const fixSdp = (sdp , candidates , forcePort = true)
789
789
  return fixed;
790
790
  };
791
791
 
792
+ const addIcesInAllBundles = (sdp ) => {
793
+ const parsedSdp = sdpParser__default['default'].parse(sdp);
794
+
795
+ const mediaWithCandidate = parsedSdp.media.find(media => !!media.candidates);
796
+ if (!mediaWithCandidate) {
797
+ return sdp;
798
+ }
799
+
800
+ const { candidates } = mediaWithCandidate;
801
+
802
+ parsedSdp.media = parsedSdp.media.map(media => ({
803
+ ...media,
804
+ candidates: media.candidates || candidates,
805
+ }));
806
+
807
+ return sdpParser__default['default'].write(parsedSdp);
808
+ };
809
+
792
810
  /* global RTCSessionDescriptionInit, navigator */
793
811
 
794
812
  const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
@@ -918,7 +936,10 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
918
936
 
919
937
  // Check if we got ICEs
920
938
  if (sdp.indexOf('a=candidate') !== -1) {
921
- return description;
939
+ return {
940
+ type: description.type,
941
+ sdp: addIcesInAllBundles(sdp),
942
+ };
922
943
  }
923
944
 
924
945
  wazoLogger.info('No ICE candidates found in SDP, fixing it with gathered ices', this.gatheredCandidates);
@@ -3192,6 +3213,70 @@ class ExternalApp {
3192
3213
 
3193
3214
  //
3194
3215
 
3216
+ class MeetingAuthorization {
3217
+
3218
+
3219
+
3220
+
3221
+
3222
+
3223
+ constructor({
3224
+ meetingUuid,
3225
+ uuid,
3226
+ userUuid,
3227
+ userName,
3228
+ } = {}) {
3229
+ this.meetingUuid = meetingUuid;
3230
+ this.uuid = uuid;
3231
+ this.userUuid = userUuid;
3232
+ this.userName = userName;
3233
+ }
3234
+
3235
+ setStatus(status ) {
3236
+ this.status = status;
3237
+ }
3238
+
3239
+ getStatus() {
3240
+ return this.status;
3241
+ }
3242
+
3243
+ static parse(plain ) {
3244
+ const {
3245
+ meeting_uuid: meetingUuid,
3246
+ uuid,
3247
+ guest_uuid: userUuid,
3248
+ guest_name: userName,
3249
+ } = plain;
3250
+
3251
+ return new MeetingAuthorization({
3252
+ meetingUuid,
3253
+ uuid,
3254
+ userUuid,
3255
+ userName,
3256
+ });
3257
+ }
3258
+
3259
+ static parseMany(items ) {
3260
+ if (!items) {
3261
+ return [];
3262
+ }
3263
+ return items.map(MeetingAuthorization.parse);
3264
+ }
3265
+ }
3266
+
3267
+ //
3268
+
3269
+
3270
+
3271
+
3272
+
3273
+
3274
+
3275
+
3276
+
3277
+
3278
+
3279
+
3195
3280
 
3196
3281
 
3197
3282
 
@@ -3202,6 +3287,7 @@ class ExternalApp {
3202
3287
 
3203
3288
 
3204
3289
 
3290
+
3205
3291
 
3206
3292
 
3207
3293
  class Meeting {
@@ -3216,6 +3302,8 @@ class Meeting {
3216
3302
 
3217
3303
 
3218
3304
 
3305
+
3306
+
3219
3307
 
3220
3308
  static parse(plain ) {
3221
3309
  return new Meeting({
@@ -3228,6 +3316,7 @@ class Meeting {
3228
3316
  extension: plain.exten,
3229
3317
  persistent: plain.persistent,
3230
3318
  creationTime: moment__default['default'](plain.creation_time).toDate(),
3319
+ requireAuthorization: plain.require_authorization,
3231
3320
  });
3232
3321
  }
3233
3322
 
@@ -3252,6 +3341,7 @@ class Meeting {
3252
3341
  extension,
3253
3342
  persistent,
3254
3343
  creationTime,
3344
+ requireAuthorization,
3255
3345
  } = {}) {
3256
3346
  this.guestSipAuthorization = guestSipAuthorization;
3257
3347
  this.uri = uri;
@@ -3262,6 +3352,7 @@ class Meeting {
3262
3352
  this.extension = extension;
3263
3353
  this.persistent = persistent;
3264
3354
  this.creationTime = creationTime;
3355
+ this.requireAuthorization = requireAuthorization;
3265
3356
 
3266
3357
  // Useful to compare instead of instanceof with minified code
3267
3358
  this.type = 'Meeting';
@@ -3272,8 +3363,32 @@ class Meeting {
3272
3363
  const [username, secret] = atob(this.guestSipAuthorization).split(':');
3273
3364
  return { username, secret };
3274
3365
  }
3366
+
3275
3367
  }
3276
3368
 
3369
+ //
3370
+
3371
+ const camelToUnderscore = (key ) => {
3372
+ if (typeof key !== 'string') {
3373
+ throw new Error('Input is not a string');
3374
+ }
3375
+ return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
3376
+ };
3377
+
3378
+ //
3379
+
3380
+ const convertKeysFromCamelToUnderscore = (args ) => {
3381
+ if (!args || typeof args !== 'object' || Array.isArray(args)) {
3382
+ throw new Error('Input is not an object');
3383
+ }
3384
+
3385
+ return Object.keys(args).reduce((acc, key) => {
3386
+ acc[camelToUnderscore(key)] = typeof args[key] === 'object' && !Array.isArray(args[key])
3387
+ ? convertKeysFromCamelToUnderscore(args[key]) : args[key];
3388
+ return acc;
3389
+ }, {});
3390
+ };
3391
+
3277
3392
  /* */
3278
3393
 
3279
3394
  var confdMethods = (client , baseUrl ) => ({
@@ -3342,8 +3457,18 @@ var confdMethods = (client , baseUrl ) => ({
3342
3457
  getMyMeetings: () =>
3343
3458
  client.get(`${baseUrl}/users/me/meetings`).then(response => Meeting.parseMany(response.items)),
3344
3459
 
3345
- createMyMeeting: (name , persistent ) =>
3346
- client.post(`${baseUrl}/users/me/meetings`, { name, persistent }).then(Meeting.parse),
3460
+ createMyMeeting: (args ) =>
3461
+ client
3462
+ .post(`${baseUrl}/users/me/meetings`, convertKeysFromCamelToUnderscore(args))
3463
+ .then(Meeting.parse),
3464
+
3465
+ updateMyMeeting: (meetingUuid , data ) =>
3466
+ client.put(
3467
+ `${baseUrl}/users/me/meetings/${meetingUuid}`,
3468
+ convertKeysFromCamelToUnderscore(data),
3469
+ null,
3470
+ ApiRequester.successResponseParser,
3471
+ ),
3347
3472
 
3348
3473
  deleteMyMeeting: (meetingUuid ) =>
3349
3474
  client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
@@ -3351,8 +3476,36 @@ var confdMethods = (client , baseUrl ) => ({
3351
3476
  getMeeting: (meetingUuid ) =>
3352
3477
  client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
3353
3478
 
3479
+ meetingAuthorizations: (meetingUuid ) =>
3480
+ client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations`, null).then(MeetingAuthorization.parseMany),
3481
+
3482
+ meetingAuthorizationReject: (meetingUuid , authorizationUuid ) =>
3483
+ client.put(
3484
+ `${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/reject`,
3485
+ {},
3486
+ null,
3487
+ ApiRequester.successResponseParser,
3488
+ ),
3489
+
3490
+ meetingAuthorizationAccept: (meetingUuid , authorizationUuid ) =>
3491
+ client.put(
3492
+ `${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/accept`,
3493
+ {},
3494
+ null,
3495
+ ApiRequester.successResponseParser,
3496
+ ),
3497
+
3354
3498
  guestGetMeeting: (meetingUuid ) =>
3355
3499
  client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
3500
+
3501
+ guestAuthorizationRequest: (userUuid , meetingUuid , username ) =>
3502
+ client
3503
+ .post(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations`, { guest_name: username })
3504
+ .then(MeetingAuthorization.parse),
3505
+
3506
+ guestAuthorizationCheck: (userUuid , meetingUuid , authorizationUuid ) =>
3507
+ client.get(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations/${authorizationUuid}`, null),
3508
+
3356
3509
  });
3357
3510
 
3358
3511
  //
@@ -3618,6 +3771,7 @@ const RECORD_STATE_ACTIVE = 'active';
3618
3771
 
3619
3772
 
3620
3773
 
3774
+
3621
3775
 
3622
3776
 
3623
3777
 
@@ -3628,6 +3782,7 @@ const RECORD_STATE_ACTIVE = 'active';
3628
3782
 
3629
3783
 
3630
3784
 
3785
+
3631
3786
 
3632
3787
 
3633
3788
 
@@ -3656,6 +3811,7 @@ class Call {
3656
3811
 
3657
3812
 
3658
3813
 
3814
+
3659
3815
 
3660
3816
 
3661
3817
 
@@ -3680,6 +3836,7 @@ class Call {
3680
3836
  calleeNumber: plain.peer_caller_id_number,
3681
3837
  dialedExtension: plain.dialed_extension,
3682
3838
  isCaller: plain.is_caller,
3839
+ isVideo: plain.is_video,
3683
3840
  muted: plain.muted,
3684
3841
  onHold: plain.on_hold,
3685
3842
  status: plain.status,
@@ -3703,6 +3860,7 @@ class Call {
3703
3860
  calleeNumber,
3704
3861
  dialedExtension,
3705
3862
  isCaller,
3863
+ isVideo,
3706
3864
  lineId,
3707
3865
  muted,
3708
3866
  onHold,
@@ -3726,6 +3884,7 @@ class Call {
3726
3884
  this.startingTime = startingTime;
3727
3885
  this.talkingToIds = talkingToIds || [];
3728
3886
  this.recording = recording;
3887
+ this.isVideo = !!isVideo;
3729
3888
 
3730
3889
  // Useful to compare instead of instanceof with minified code
3731
3890
  this.type = 'Call';
@@ -4785,6 +4944,14 @@ var calldMethods = (client , baseUrl ) => ({
4785
4944
  getMeetingParticipantsAsUser: async (meetingUuid ) =>
4786
4945
  client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
4787
4946
 
4947
+ banMeetingParticipant: (meetingUuid , participantUuid ) =>
4948
+ client.delete(
4949
+ `${baseUrl}/users/me/meetings/${meetingUuid}/participants/${participantUuid}`,
4950
+ null,
4951
+ null,
4952
+ ApiRequester.successResponseParser,
4953
+ ),
4954
+
4788
4955
  listTrunks: () => client.get(`${baseUrl}/trunks`),
4789
4956
 
4790
4957
  mute: (callId ) =>
@@ -6428,41 +6595,58 @@ class WebRTCClient extends Emitter {
6428
6595
  });
6429
6596
  }
6430
6597
 
6431
- changeAudioInputDevice(id , session ) {
6598
+ async changeAudioInputDevice(id , session , force ) {
6432
6599
  const currentId = this.getAudioDeviceId();
6433
6600
  logger.info('setting audio input device', { id, currentId, session: !!session });
6434
6601
 
6435
- if (id === currentId) {
6602
+ if (!force && id === currentId) {
6436
6603
  return null;
6437
6604
  }
6438
6605
 
6606
+ // in order to handle an audio track change for default devices
6607
+ // we need the actual id of the device (not 'default')
6608
+ let deviceId = id;
6609
+ if (id === 'default' && navigator.mediaDevices) {
6610
+ const devices = await navigator.mediaDevices.enumerateDevices();
6611
+ const defaultDevice = devices.find(device => device.deviceId === 'default');
6612
+ if (defaultDevice) {
6613
+ const deviceLabel = defaultDevice.label.replace('Default - ', '');
6614
+ const targetDevice = devices.find(device => device.label === deviceLabel);
6615
+ if (targetDevice) {
6616
+ deviceId = targetDevice.deviceId;
6617
+ if (!force && deviceId === currentId) {
6618
+ return null;
6619
+ }
6620
+ }
6621
+ }
6622
+ }
6623
+
6439
6624
  // let's update the local audio value
6440
6625
  if (this.audio) {
6441
6626
  this.audio = {
6442
6627
  deviceId: {
6443
- exact: id,
6628
+ exact: deviceId,
6444
6629
  },
6445
6630
  };
6446
6631
  }
6447
6632
 
6448
- if (session) {
6633
+ if (session && navigator.mediaDevices) {
6449
6634
  const sdh = session.sessionDescriptionHandler;
6450
6635
  const pc = sdh.peerConnection;
6451
6636
 
6452
- // $FlowFixMe
6453
- return navigator.mediaDevices.getUserMedia({ audio: { deviceId: { exact: id } } }).then(async stream => {
6454
- const audioTrack = stream.getAudioTracks()[0];
6455
- const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
6637
+ const constraints = { audio: { deviceId: { exact: deviceId } } };
6638
+ const stream = await navigator.mediaDevices.getUserMedia(constraints);
6639
+ const audioTrack = stream.getAudioTracks()[0];
6640
+ const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
6456
6641
 
6457
- if (sender) {
6458
- if (sender.track) {
6459
- audioTrack.enabled = sender.track.enabled;
6460
- }
6461
- sender.replaceTrack(audioTrack);
6642
+ if (sender) {
6643
+ if (sender.track) {
6644
+ audioTrack.enabled = sender.track.enabled;
6462
6645
  }
6646
+ sender.replaceTrack(audioTrack);
6647
+ }
6463
6648
 
6464
- return stream;
6465
- });
6649
+ return stream;
6466
6650
  }
6467
6651
  }
6468
6652
 
@@ -6482,14 +6666,14 @@ class WebRTCClient extends Emitter {
6482
6666
  return null;
6483
6667
  }
6484
6668
 
6485
- // let's update the local video value
6486
- if (this.video) {
6487
- this.video = {
6488
- deviceId: {
6489
- exact: id,
6490
- },
6491
- };
6492
- }
6669
+ // let's make sure we don't lose other video constraints settings -- width, height, frameRate...
6670
+ const videoObject = typeof this.video === 'object' ? this.video : {};
6671
+ this.video = {
6672
+ ...videoObject,
6673
+ deviceId: {
6674
+ exact: id,
6675
+ },
6676
+ };
6493
6677
  }
6494
6678
 
6495
6679
  changeSessionVideoInputDevice(id , session ) {
@@ -617,6 +617,7 @@ const AGENT_UNPAUSED = 'agent_unpaused';
617
617
  const CONFERENCE_ADHOC_PARTICIPANT_LEFT = 'conference_adhoc_participant_left';
618
618
  const CONFERENCE_ADHOC_DELETED = 'conference_adhoc_deleted';
619
619
  const MEETING_USER_PROGRESS = 'meeting_user_progress';
620
+ const MEETING_USER_GUEST_AUTHORIZATION_CREATED = 'meeting_user_guest_authorization_created';
620
621
 
621
622
  const BLACKLIST_EVENTS = [
622
623
  CHAT_MESSAGE_SENT,
@@ -968,6 +969,7 @@ WebSocketClient.eventLists = [
968
969
  CONFERENCE_ADHOC_PARTICIPANT_LEFT,
969
970
  CONFERENCE_ADHOC_DELETED,
970
971
  MEETING_USER_PROGRESS,
972
+ MEETING_USER_GUEST_AUTHORIZATION_CREATED,
971
973
  ];
972
974
 
973
975
  exports.AGENT_PAUSED = AGENT_PAUSED;
@@ -1021,6 +1023,7 @@ exports.FAX_OUTBOUND_USER_FAILED = FAX_OUTBOUND_USER_FAILED;
1021
1023
  exports.FAX_OUTBOUND_USER_SUCCEEDED = FAX_OUTBOUND_USER_SUCCEEDED;
1022
1024
  exports.HEARTBEAT_ENGINE_VERSION = HEARTBEAT_ENGINE_VERSION;
1023
1025
  exports.LINE_STATUS_UPDATED = LINE_STATUS_UPDATED;
1026
+ exports.MEETING_USER_GUEST_AUTHORIZATION_CREATED = MEETING_USER_GUEST_AUTHORIZATION_CREATED;
1024
1027
  exports.MEETING_USER_PARTICIPANT_JOINED = MEETING_USER_PARTICIPANT_JOINED;
1025
1028
  exports.MEETING_USER_PARTICIPANT_LEFT = MEETING_USER_PARTICIPANT_LEFT;
1026
1029
  exports.MEETING_USER_PROGRESS = MEETING_USER_PROGRESS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wazo/sdk",
3
- "version": "0.38.5",
3
+ "version": "0.38.8",
4
4
  "description": "Wazo's JavaScript Software Development Kit.",
5
5
  "main": "dist/wazo-sdk.js",
6
6
  "author": "Wazo (http://wazo.io)",
@@ -100,4 +100,4 @@
100
100
  "react-native": {
101
101
  "node-fetch/lib/index": false
102
102
  }
103
- }
103
+ }
@@ -43,3 +43,96 @@ describe('WebRTC client', () => {
43
43
  expect(client.isAudioMuted(oldKindUnmuted)).toBeFalsy();
44
44
  });
45
45
  });
46
+
47
+ describe('changeAudioInputDevice', () => {
48
+ const defaultId = 'default';
49
+ const deviceId = 'device1';
50
+ const constraints = { audio: { deviceId: { exact: defaultId } }, video: null };
51
+
52
+ const session = {
53
+ sessionDescriptionHandler: {
54
+ peerConnection: {
55
+ getSenders: () => [{ track: { kind: 'audio', enabled: true } }],
56
+ },
57
+ },
58
+ };
59
+
60
+ const stream = {};
61
+ const getAudioTracksMock = jest.fn(() => []);
62
+ Object.defineProperty(stream, 'getAudioTracks', {
63
+ value: getAudioTracksMock,
64
+ });
65
+
66
+ const getUserMediaMock = jest.fn(async () => {
67
+ return new Promise(resolve => {
68
+ resolve(stream);
69
+ });
70
+ });
71
+
72
+ const devices = [
73
+ { deviceId: 'default', kind: 'audioinput', label: 'Default - Fake Microphone', groupId: 'fak3Gr0up3' },
74
+ { deviceId: 'fak3d3v1c3', kind: 'audioinput', label: 'Fake Microphone', groupId: 'fak3Gr0up3' },
75
+ ];
76
+ const enumerateDevicesMock = jest.fn(async () => {
77
+ return new Promise(resolve => {
78
+ resolve(devices);
79
+ });
80
+ });
81
+
82
+ Object.defineProperty(global.navigator, 'mediaDevices', {
83
+ value: {
84
+ getUserMedia: getUserMediaMock,
85
+ enumerateDevices: enumerateDevicesMock,
86
+ },
87
+ });
88
+
89
+ it('should change the audio input track if the provided id is different', async () => {
90
+ client.setMediaConstraints(constraints);
91
+ expect(client.getAudioDeviceId()).toBe(defaultId);
92
+ const result = await client.changeAudioInputDevice(deviceId, session);
93
+ expect(result).toBeTruthy();
94
+ });
95
+
96
+ it('should NOT change the audio input track if the provided id is the same', async () => {
97
+ client.setMediaConstraints(constraints);
98
+ expect(client.getAudioDeviceId()).toBe(defaultId);
99
+ const result = await client.changeAudioInputDevice(defaultId, session);
100
+ expect(result).toBeFalsy();
101
+ });
102
+
103
+ it('should change the audio input track if the provided id is the same and force param is TRUE', async () => {
104
+ client.setMediaConstraints(constraints);
105
+ expect(client.getAudioDeviceId()).toBe(defaultId);
106
+ const result = await client.changeAudioInputDevice(defaultId, session, true);
107
+ expect(result).toBeTruthy();
108
+ });
109
+
110
+ describe('setVideoInputDevice', () => {
111
+ it('should retain its original video values', () => {
112
+ const video = { height: { min: 480, max: 720 }, width: { min: 640, max: 1280 } };
113
+
114
+ client.video = video;
115
+ client.setVideoInputDevice(deviceId);
116
+ expect(client.video).toEqual({ ...video, deviceId: { exact: deviceId } });
117
+ });
118
+
119
+ it('should set deviceId when video\'s original value is true', () => {
120
+ client.video = true;
121
+ client.setVideoInputDevice(deviceId);
122
+ expect(client.video).toEqual({ deviceId: { exact: deviceId } });
123
+ });
124
+
125
+ it('should set deviceId when video\'s original value is not set', () => {
126
+ client.video = undefined;
127
+ client.setVideoInputDevice(deviceId);
128
+ expect(client.video).toEqual({ deviceId: { exact: deviceId } });
129
+ });
130
+
131
+ it('should NOT set deviceId when its value does not change', () => {
132
+ client.video = { deviceId: { exact: deviceId } };
133
+ const result = client.setVideoInputDevice(deviceId);
134
+ expect(result).toEqual(null);
135
+ expect(client.video).toEqual({ deviceId: { exact: deviceId } });
136
+ });
137
+ });
138
+ });
package/src/api/calld.js CHANGED
@@ -137,6 +137,14 @@ export default (client: ApiRequester, baseUrl: string) => ({
137
137
  getMeetingParticipantsAsUser: async (meetingUuid: string): Promise<Object> =>
138
138
  client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
139
139
 
140
+ banMeetingParticipant: (meetingUuid: string, participantUuid: string) =>
141
+ client.delete(
142
+ `${baseUrl}/users/me/meetings/${meetingUuid}/participants/${participantUuid}`,
143
+ null,
144
+ null,
145
+ ApiRequester.successResponseParser,
146
+ ),
147
+
140
148
  listTrunks: () => client.get(`${baseUrl}/trunks`),
141
149
 
142
150
  mute: (callId: string) =>