@wazo/sdk 0.38.6 → 0.38.9
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.
- package/dist/wazo-sdk.js +2 -2
- package/esm/__tests__/api-client.test.js +142 -2
- package/esm/__tests__/web-rtc-client.test.js +249 -28
- package/esm/api/calld.js +8 -0
- package/esm/api/confd.js +134 -2
- package/esm/api-client.js +142 -2
- package/esm/checker/Checker.js +205 -25
- package/esm/checker/checks/aor.js +142 -2
- package/esm/checker/checks/api.js +142 -2
- package/esm/checker/checks/index.js +205 -25
- package/esm/checker/checks/wazo-websocket.js +2 -0
- package/esm/checker/checks/webrtc-transport.js +203 -25
- package/esm/checker/checks/webrtc.js +203 -25
- package/esm/domain/AdHocAPIConference.js +142 -2
- package/esm/domain/Features.js +142 -2
- package/esm/domain/Meeting.js +18 -0
- package/esm/domain/MeetingAuthorization.js +70 -0
- package/esm/domain/Phone/CTIPhone.js +142 -2
- package/esm/domain/Phone/WebRTCPhone.js +1 -3
- package/esm/domain/__tests__/Meeting.test.js +87 -1
- package/esm/domain/__tests__/MeetingAuthorization.test.js +109 -0
- package/esm/index.js +249 -31
- package/esm/lib/WazoSessionDescriptionHandler.js +22 -1
- package/esm/service/CallApi.js +142 -2
- package/esm/service/getApiClient.js +142 -2
- package/esm/simple/Auth.js +249 -31
- package/esm/simple/Configuration.js +249 -31
- package/esm/simple/Directory.js +142 -2
- package/esm/simple/Phone.js +249 -31
- package/esm/simple/Websocket.js +3 -0
- package/esm/simple/index.js +249 -31
- package/esm/simple/room/LocalParticipant.js +249 -31
- package/esm/simple/room/Participant.js +249 -31
- package/esm/simple/room/RemoteParticipant.js +249 -31
- package/esm/simple/room/Room.js +249 -31
- package/esm/simple/room/SipRoom.js +249 -31
- package/esm/simple/room/Stream.js +249 -31
- package/esm/simple/room/__tests__/Participant.test.js +14745 -0
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +249 -31
- package/esm/simple/utils.js +249 -31
- package/esm/utils/__tests__/object.test.js +57 -0
- package/esm/utils/__tests__/sdp.test.js +50 -0
- package/esm/utils/__tests__/string.test.js +30 -0
- package/esm/utils/object.js +24 -0
- package/esm/utils/sdp.js +19 -1
- package/esm/utils/string.js +10 -0
- package/esm/web-rtc-client.js +203 -25
- package/esm/websocket-client.js +3 -1
- package/lib/__tests__/api-client.test.js +142 -2
- package/lib/__tests__/web-rtc-client.test.js +249 -28
- package/lib/api/calld.js +8 -0
- package/lib/api/confd.js +134 -2
- package/lib/api-client.js +142 -2
- package/lib/checker/Checker.js +205 -25
- package/lib/checker/checks/aor.js +142 -2
- package/lib/checker/checks/api.js +142 -2
- package/lib/checker/checks/index.js +205 -25
- package/lib/checker/checks/wazo-websocket.js +2 -0
- package/lib/checker/checks/webrtc-transport.js +203 -25
- package/lib/checker/checks/webrtc.js +203 -25
- package/lib/domain/AdHocAPIConference.js +142 -2
- package/lib/domain/Features.js +142 -2
- package/lib/domain/Meeting.js +18 -0
- package/lib/domain/MeetingAuthorization.js +79 -0
- package/lib/domain/Phone/CTIPhone.js +142 -2
- package/lib/domain/Phone/WebRTCPhone.js +1 -3
- package/lib/domain/__tests__/Meeting.test.js +87 -1
- package/lib/domain/__tests__/MeetingAuthorization.test.js +111 -0
- package/lib/index.js +249 -31
- package/lib/lib/WazoSessionDescriptionHandler.js +22 -1
- package/lib/service/CallApi.js +142 -2
- package/lib/service/getApiClient.js +142 -2
- package/lib/simple/Auth.js +249 -31
- package/lib/simple/Configuration.js +249 -31
- package/lib/simple/Directory.js +142 -2
- package/lib/simple/Phone.js +249 -31
- package/lib/simple/Websocket.js +3 -0
- package/lib/simple/index.js +249 -31
- package/lib/simple/room/LocalParticipant.js +249 -31
- package/lib/simple/room/Participant.js +249 -31
- package/lib/simple/room/RemoteParticipant.js +249 -31
- package/lib/simple/room/Room.js +249 -31
- package/lib/simple/room/SipRoom.js +249 -31
- package/lib/simple/room/Stream.js +249 -31
- package/lib/simple/room/__tests__/Participant.test.js +14755 -0
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +249 -31
- package/lib/simple/utils.js +249 -31
- package/lib/utils/__tests__/object.test.js +59 -0
- package/lib/utils/__tests__/sdp.test.js +50 -0
- package/lib/utils/__tests__/string.test.js +32 -0
- package/lib/utils/object.js +28 -0
- package/lib/utils/sdp.js +19 -0
- package/lib/utils/string.js +14 -0
- package/lib/web-rtc-client.js +203 -25
- package/lib/websocket-client.js +3 -0
- package/package.json +2 -2
- package/src/__tests__/web-rtc-client.test.js +46 -3
- package/src/api/calld.js +8 -0
- package/src/api/confd.js +43 -2
- package/src/domain/Meeting.js +20 -0
- package/src/domain/MeetingAuthorization.js +67 -0
- package/src/domain/Phone/WebRTCPhone.js +1 -3
- package/src/domain/__tests__/Meeting.test.js +70 -1
- package/src/domain/__tests__/MeetingAuthorization.test.js +58 -0
- package/src/lib/WazoSessionDescriptionHandler.js +5 -2
- package/src/simple/room/Participant.js +40 -0
- package/src/simple/room/Room.js +2 -2
- package/src/simple/room/SipRoom.js +1 -1
- package/src/simple/room/__tests__/Participant.test.js +81 -0
- package/src/types/WebSocketMessage.js +7 -1
- package/src/utils/__tests__/object.test.js +35 -0
- package/src/utils/__tests__/sdp.test.js +33 -1
- package/src/utils/__tests__/string.test.js +23 -0
- package/src/utils/object.js +15 -0
- package/src/utils/sdp.js +18 -0
- package/src/utils/string.js +8 -0
- package/src/web-rtc-client.js +39 -22
- package/src/websocket-client.js +2 -0
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;
|
package/lib/web-rtc-client.js
CHANGED
|
@@ -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
|
|
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: (
|
|
3346
|
-
client
|
|
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
|
//
|
|
@@ -4791,6 +4944,14 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
4791
4944
|
getMeetingParticipantsAsUser: async (meetingUuid ) =>
|
|
4792
4945
|
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
|
|
4793
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
|
+
|
|
4794
4955
|
listTrunks: () => client.get(`${baseUrl}/trunks`),
|
|
4795
4956
|
|
|
4796
4957
|
mute: (callId ) =>
|
|
@@ -6434,7 +6595,7 @@ class WebRTCClient extends Emitter {
|
|
|
6434
6595
|
});
|
|
6435
6596
|
}
|
|
6436
6597
|
|
|
6437
|
-
changeAudioInputDevice(id , session , force ) {
|
|
6598
|
+
async changeAudioInputDevice(id , session , force ) {
|
|
6438
6599
|
const currentId = this.getAudioDeviceId();
|
|
6439
6600
|
logger.info('setting audio input device', { id, currentId, session: !!session });
|
|
6440
6601
|
|
|
@@ -6442,33 +6603,50 @@ class WebRTCClient extends Emitter {
|
|
|
6442
6603
|
return null;
|
|
6443
6604
|
}
|
|
6444
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
|
+
|
|
6445
6624
|
// let's update the local audio value
|
|
6446
6625
|
if (this.audio) {
|
|
6447
6626
|
this.audio = {
|
|
6448
6627
|
deviceId: {
|
|
6449
|
-
exact:
|
|
6628
|
+
exact: deviceId,
|
|
6450
6629
|
},
|
|
6451
6630
|
};
|
|
6452
6631
|
}
|
|
6453
6632
|
|
|
6454
|
-
if (session) {
|
|
6633
|
+
if (session && navigator.mediaDevices) {
|
|
6455
6634
|
const sdh = session.sessionDescriptionHandler;
|
|
6456
6635
|
const pc = sdh.peerConnection;
|
|
6457
6636
|
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
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);
|
|
6462
6641
|
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
}
|
|
6467
|
-
sender.replaceTrack(audioTrack);
|
|
6642
|
+
if (sender) {
|
|
6643
|
+
if (sender.track) {
|
|
6644
|
+
audioTrack.enabled = sender.track.enabled;
|
|
6468
6645
|
}
|
|
6646
|
+
sender.replaceTrack(audioTrack);
|
|
6647
|
+
}
|
|
6469
6648
|
|
|
6470
|
-
|
|
6471
|
-
});
|
|
6649
|
+
return stream;
|
|
6472
6650
|
}
|
|
6473
6651
|
}
|
|
6474
6652
|
|
|
@@ -6488,14 +6666,14 @@ class WebRTCClient extends Emitter {
|
|
|
6488
6666
|
return null;
|
|
6489
6667
|
}
|
|
6490
6668
|
|
|
6491
|
-
// let's
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
}
|
|
6498
|
-
}
|
|
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
|
+
};
|
|
6499
6677
|
}
|
|
6500
6678
|
|
|
6501
6679
|
changeSessionVideoInputDevice(id , session ) {
|
package/lib/websocket-client.js
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "0.38.9",
|
|
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
|
+
}
|
|
@@ -69,27 +69,70 @@ describe('changeAudioInputDevice', () => {
|
|
|
69
69
|
});
|
|
70
70
|
});
|
|
71
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
|
+
|
|
72
82
|
Object.defineProperty(global.navigator, 'mediaDevices', {
|
|
73
83
|
value: {
|
|
74
84
|
getUserMedia: getUserMediaMock,
|
|
85
|
+
enumerateDevices: enumerateDevicesMock,
|
|
75
86
|
},
|
|
76
87
|
});
|
|
77
88
|
|
|
78
89
|
it('should change the audio input track if the provided id is different', async () => {
|
|
79
90
|
client.setMediaConstraints(constraints);
|
|
80
91
|
expect(client.getAudioDeviceId()).toBe(defaultId);
|
|
81
|
-
|
|
92
|
+
const result = await client.changeAudioInputDevice(deviceId, session);
|
|
93
|
+
expect(result).toBeTruthy();
|
|
82
94
|
});
|
|
83
95
|
|
|
84
96
|
it('should NOT change the audio input track if the provided id is the same', async () => {
|
|
85
97
|
client.setMediaConstraints(constraints);
|
|
86
98
|
expect(client.getAudioDeviceId()).toBe(defaultId);
|
|
87
|
-
|
|
99
|
+
const result = await client.changeAudioInputDevice(defaultId, session);
|
|
100
|
+
expect(result).toBeFalsy();
|
|
88
101
|
});
|
|
89
102
|
|
|
90
103
|
it('should change the audio input track if the provided id is the same and force param is TRUE', async () => {
|
|
91
104
|
client.setMediaConstraints(constraints);
|
|
92
105
|
expect(client.getAudioDeviceId()).toBe(defaultId);
|
|
93
|
-
|
|
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
|
+
});
|
|
94
137
|
});
|
|
95
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) =>
|
package/src/api/confd.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/* @flow */
|
|
2
2
|
import ApiRequester from '../utils/api-requester';
|
|
3
3
|
import type { UUID, ListConfdUsersResponse, ListApplicationsResponse } from '../domain/types';
|
|
4
|
+
import type { MeetingCreateArguments, MeetingUpdateArguments } from '../domain/Meeting';
|
|
4
5
|
import Profile from '../domain/Profile';
|
|
5
6
|
import SipLine from '../domain/SipLine';
|
|
6
7
|
import ExternalApp from '../domain/ExternalApp';
|
|
7
8
|
import Meeting from '../domain/Meeting';
|
|
9
|
+
import MeetingAuthorization from '../domain/MeetingAuthorization';
|
|
10
|
+
import { convertKeysFromCamelToUnderscore } from '../utils/object';
|
|
8
11
|
|
|
9
12
|
export default (client: ApiRequester, baseUrl: string) => ({
|
|
10
13
|
listUsers: (): Promise<ListConfdUsersResponse> => client.get(`${baseUrl}/users`, null),
|
|
@@ -72,8 +75,18 @@ export default (client: ApiRequester, baseUrl: string) => ({
|
|
|
72
75
|
getMyMeetings: (): Promise<Meeting> =>
|
|
73
76
|
client.get(`${baseUrl}/users/me/meetings`).then(response => Meeting.parseMany(response.items)),
|
|
74
77
|
|
|
75
|
-
createMyMeeting: (
|
|
76
|
-
client
|
|
78
|
+
createMyMeeting: (args: MeetingCreateArguments): Promise<Meeting> =>
|
|
79
|
+
client
|
|
80
|
+
.post(`${baseUrl}/users/me/meetings`, convertKeysFromCamelToUnderscore(args))
|
|
81
|
+
.then(Meeting.parse),
|
|
82
|
+
|
|
83
|
+
updateMyMeeting: (meetingUuid: string, data: MeetingUpdateArguments): Promise<Boolean> =>
|
|
84
|
+
client.put(
|
|
85
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}`,
|
|
86
|
+
convertKeysFromCamelToUnderscore(data),
|
|
87
|
+
null,
|
|
88
|
+
ApiRequester.successResponseParser,
|
|
89
|
+
),
|
|
77
90
|
|
|
78
91
|
deleteMyMeeting: (meetingUuid: string): Promise<Meeting> =>
|
|
79
92
|
client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
|
|
@@ -81,6 +94,34 @@ export default (client: ApiRequester, baseUrl: string) => ({
|
|
|
81
94
|
getMeeting: (meetingUuid: string): Promise<Meeting> =>
|
|
82
95
|
client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
83
96
|
|
|
97
|
+
meetingAuthorizations: (meetingUuid: string): Promise<Array<MeetingAuthorization>> =>
|
|
98
|
+
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations`, null).then(MeetingAuthorization.parseMany),
|
|
99
|
+
|
|
100
|
+
meetingAuthorizationReject: (meetingUuid: string, authorizationUuid: string): Promise<Boolean> =>
|
|
101
|
+
client.put(
|
|
102
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/reject`,
|
|
103
|
+
{},
|
|
104
|
+
null,
|
|
105
|
+
ApiRequester.successResponseParser,
|
|
106
|
+
),
|
|
107
|
+
|
|
108
|
+
meetingAuthorizationAccept: (meetingUuid: string, authorizationUuid: string): Promise<Boolean> =>
|
|
109
|
+
client.put(
|
|
110
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/accept`,
|
|
111
|
+
{},
|
|
112
|
+
null,
|
|
113
|
+
ApiRequester.successResponseParser,
|
|
114
|
+
),
|
|
115
|
+
|
|
84
116
|
guestGetMeeting: (meetingUuid: string): Promise<Meeting> =>
|
|
85
117
|
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
118
|
+
|
|
119
|
+
guestAuthorizationRequest: (userUuid: string, meetingUuid: string, username: string): Promise<> =>
|
|
120
|
+
client
|
|
121
|
+
.post(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations`, { guest_name: username })
|
|
122
|
+
.then(MeetingAuthorization.parse),
|
|
123
|
+
|
|
124
|
+
guestAuthorizationCheck: (userUuid: string, meetingUuid: string, authorizationUuid: string): Promise<> =>
|
|
125
|
+
client.get(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations/${authorizationUuid}`, null),
|
|
126
|
+
|
|
86
127
|
});
|
package/src/domain/Meeting.js
CHANGED
|
@@ -3,6 +3,19 @@ import moment from 'moment';
|
|
|
3
3
|
|
|
4
4
|
import newFrom from '../utils/new-from';
|
|
5
5
|
|
|
6
|
+
import MeetingAuthorization from './MeetingAuthorization';
|
|
7
|
+
|
|
8
|
+
export type MeetingCreateArguments = {
|
|
9
|
+
name: string,
|
|
10
|
+
requireAuthorization: boolean,
|
|
11
|
+
persistent: boolean,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type MeetingUpdateArguments = {
|
|
15
|
+
name?: string,
|
|
16
|
+
requireAuthorization?: boolean,
|
|
17
|
+
}
|
|
18
|
+
|
|
6
19
|
export type MeetingCreationResponse = {
|
|
7
20
|
guest_sip_authorization: string,
|
|
8
21
|
ingress_http_uri: string,
|
|
@@ -13,6 +26,7 @@ export type MeetingCreationResponse = {
|
|
|
13
26
|
exten: string,
|
|
14
27
|
persistent: boolean,
|
|
15
28
|
creation_time: string,
|
|
29
|
+
require_authorization: boolean,
|
|
16
30
|
}
|
|
17
31
|
|
|
18
32
|
export default class Meeting {
|
|
@@ -27,6 +41,8 @@ export default class Meeting {
|
|
|
27
41
|
persistent: boolean;
|
|
28
42
|
ownerUuids: Array<string>;
|
|
29
43
|
creationTime: Date;
|
|
44
|
+
pendingAuthorizations: Array<MeetingAuthorization>
|
|
45
|
+
requireAuthorization: boolean;
|
|
30
46
|
|
|
31
47
|
static parse(plain: MeetingCreationResponse): Meeting {
|
|
32
48
|
return new Meeting({
|
|
@@ -39,6 +55,7 @@ export default class Meeting {
|
|
|
39
55
|
extension: plain.exten,
|
|
40
56
|
persistent: plain.persistent,
|
|
41
57
|
creationTime: moment(plain.creation_time).toDate(),
|
|
58
|
+
requireAuthorization: plain.require_authorization,
|
|
42
59
|
});
|
|
43
60
|
}
|
|
44
61
|
|
|
@@ -63,6 +80,7 @@ export default class Meeting {
|
|
|
63
80
|
extension,
|
|
64
81
|
persistent,
|
|
65
82
|
creationTime,
|
|
83
|
+
requireAuthorization,
|
|
66
84
|
}: Object = {}) {
|
|
67
85
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
68
86
|
this.uri = uri;
|
|
@@ -73,6 +91,7 @@ export default class Meeting {
|
|
|
73
91
|
this.extension = extension;
|
|
74
92
|
this.persistent = persistent;
|
|
75
93
|
this.creationTime = creationTime;
|
|
94
|
+
this.requireAuthorization = requireAuthorization;
|
|
76
95
|
|
|
77
96
|
// Useful to compare instead of instanceof with minified code
|
|
78
97
|
this.type = 'Meeting';
|
|
@@ -83,4 +102,5 @@ export default class Meeting {
|
|
|
83
102
|
const [username, secret] = atob(this.guestSipAuthorization).split(':');
|
|
84
103
|
return { username, secret };
|
|
85
104
|
}
|
|
105
|
+
|
|
86
106
|
}
|