@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
|
@@ -787,6 +787,24 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
787
787
|
return fixed;
|
|
788
788
|
};
|
|
789
789
|
|
|
790
|
+
const addIcesInAllBundles = (sdp ) => {
|
|
791
|
+
const parsedSdp = sdpParser__default['default'].parse(sdp);
|
|
792
|
+
|
|
793
|
+
const mediaWithCandidate = parsedSdp.media.find(media => !!media.candidates);
|
|
794
|
+
if (!mediaWithCandidate) {
|
|
795
|
+
return sdp;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
const { candidates } = mediaWithCandidate;
|
|
799
|
+
|
|
800
|
+
parsedSdp.media = parsedSdp.media.map(media => ({
|
|
801
|
+
...media,
|
|
802
|
+
candidates: media.candidates || candidates,
|
|
803
|
+
}));
|
|
804
|
+
|
|
805
|
+
return sdpParser__default['default'].write(parsedSdp);
|
|
806
|
+
};
|
|
807
|
+
|
|
790
808
|
/* global RTCSessionDescriptionInit, navigator */
|
|
791
809
|
|
|
792
810
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
@@ -916,7 +934,10 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
916
934
|
|
|
917
935
|
// Check if we got ICEs
|
|
918
936
|
if (sdp.indexOf('a=candidate') !== -1) {
|
|
919
|
-
return
|
|
937
|
+
return {
|
|
938
|
+
type: description.type,
|
|
939
|
+
sdp: addIcesInAllBundles(sdp),
|
|
940
|
+
};
|
|
920
941
|
}
|
|
921
942
|
|
|
922
943
|
wazoLogger.info('No ICE candidates found in SDP, fixing it with gathered ices', this.gatheredCandidates);
|
|
@@ -3190,6 +3211,70 @@ class ExternalApp {
|
|
|
3190
3211
|
|
|
3191
3212
|
//
|
|
3192
3213
|
|
|
3214
|
+
class MeetingAuthorization {
|
|
3215
|
+
|
|
3216
|
+
|
|
3217
|
+
|
|
3218
|
+
|
|
3219
|
+
|
|
3220
|
+
|
|
3221
|
+
constructor({
|
|
3222
|
+
meetingUuid,
|
|
3223
|
+
uuid,
|
|
3224
|
+
userUuid,
|
|
3225
|
+
userName,
|
|
3226
|
+
} = {}) {
|
|
3227
|
+
this.meetingUuid = meetingUuid;
|
|
3228
|
+
this.uuid = uuid;
|
|
3229
|
+
this.userUuid = userUuid;
|
|
3230
|
+
this.userName = userName;
|
|
3231
|
+
}
|
|
3232
|
+
|
|
3233
|
+
setStatus(status ) {
|
|
3234
|
+
this.status = status;
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
getStatus() {
|
|
3238
|
+
return this.status;
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
static parse(plain ) {
|
|
3242
|
+
const {
|
|
3243
|
+
meeting_uuid: meetingUuid,
|
|
3244
|
+
uuid,
|
|
3245
|
+
guest_uuid: userUuid,
|
|
3246
|
+
guest_name: userName,
|
|
3247
|
+
} = plain;
|
|
3248
|
+
|
|
3249
|
+
return new MeetingAuthorization({
|
|
3250
|
+
meetingUuid,
|
|
3251
|
+
uuid,
|
|
3252
|
+
userUuid,
|
|
3253
|
+
userName,
|
|
3254
|
+
});
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
static parseMany(items ) {
|
|
3258
|
+
if (!items) {
|
|
3259
|
+
return [];
|
|
3260
|
+
}
|
|
3261
|
+
return items.map(MeetingAuthorization.parse);
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3265
|
+
//
|
|
3266
|
+
|
|
3267
|
+
|
|
3268
|
+
|
|
3269
|
+
|
|
3270
|
+
|
|
3271
|
+
|
|
3272
|
+
|
|
3273
|
+
|
|
3274
|
+
|
|
3275
|
+
|
|
3276
|
+
|
|
3277
|
+
|
|
3193
3278
|
|
|
3194
3279
|
|
|
3195
3280
|
|
|
@@ -3200,6 +3285,7 @@ class ExternalApp {
|
|
|
3200
3285
|
|
|
3201
3286
|
|
|
3202
3287
|
|
|
3288
|
+
|
|
3203
3289
|
|
|
3204
3290
|
|
|
3205
3291
|
class Meeting {
|
|
@@ -3214,6 +3300,8 @@ class Meeting {
|
|
|
3214
3300
|
|
|
3215
3301
|
|
|
3216
3302
|
|
|
3303
|
+
|
|
3304
|
+
|
|
3217
3305
|
|
|
3218
3306
|
static parse(plain ) {
|
|
3219
3307
|
return new Meeting({
|
|
@@ -3226,6 +3314,7 @@ class Meeting {
|
|
|
3226
3314
|
extension: plain.exten,
|
|
3227
3315
|
persistent: plain.persistent,
|
|
3228
3316
|
creationTime: moment__default['default'](plain.creation_time).toDate(),
|
|
3317
|
+
requireAuthorization: plain.require_authorization,
|
|
3229
3318
|
});
|
|
3230
3319
|
}
|
|
3231
3320
|
|
|
@@ -3250,6 +3339,7 @@ class Meeting {
|
|
|
3250
3339
|
extension,
|
|
3251
3340
|
persistent,
|
|
3252
3341
|
creationTime,
|
|
3342
|
+
requireAuthorization,
|
|
3253
3343
|
} = {}) {
|
|
3254
3344
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
3255
3345
|
this.uri = uri;
|
|
@@ -3260,6 +3350,7 @@ class Meeting {
|
|
|
3260
3350
|
this.extension = extension;
|
|
3261
3351
|
this.persistent = persistent;
|
|
3262
3352
|
this.creationTime = creationTime;
|
|
3353
|
+
this.requireAuthorization = requireAuthorization;
|
|
3263
3354
|
|
|
3264
3355
|
// Useful to compare instead of instanceof with minified code
|
|
3265
3356
|
this.type = 'Meeting';
|
|
@@ -3270,8 +3361,32 @@ class Meeting {
|
|
|
3270
3361
|
const [username, secret] = atob(this.guestSipAuthorization).split(':');
|
|
3271
3362
|
return { username, secret };
|
|
3272
3363
|
}
|
|
3364
|
+
|
|
3273
3365
|
}
|
|
3274
3366
|
|
|
3367
|
+
//
|
|
3368
|
+
|
|
3369
|
+
const camelToUnderscore = (key ) => {
|
|
3370
|
+
if (typeof key !== 'string') {
|
|
3371
|
+
throw new Error('Input is not a string');
|
|
3372
|
+
}
|
|
3373
|
+
return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
3374
|
+
};
|
|
3375
|
+
|
|
3376
|
+
//
|
|
3377
|
+
|
|
3378
|
+
const convertKeysFromCamelToUnderscore = (args ) => {
|
|
3379
|
+
if (!args || typeof args !== 'object' || Array.isArray(args)) {
|
|
3380
|
+
throw new Error('Input is not an object');
|
|
3381
|
+
}
|
|
3382
|
+
|
|
3383
|
+
return Object.keys(args).reduce((acc, key) => {
|
|
3384
|
+
acc[camelToUnderscore(key)] = typeof args[key] === 'object' && !Array.isArray(args[key])
|
|
3385
|
+
? convertKeysFromCamelToUnderscore(args[key]) : args[key];
|
|
3386
|
+
return acc;
|
|
3387
|
+
}, {});
|
|
3388
|
+
};
|
|
3389
|
+
|
|
3275
3390
|
/* */
|
|
3276
3391
|
|
|
3277
3392
|
var confdMethods = (client , baseUrl ) => ({
|
|
@@ -3340,8 +3455,18 @@ var confdMethods = (client , baseUrl ) => ({
|
|
|
3340
3455
|
getMyMeetings: () =>
|
|
3341
3456
|
client.get(`${baseUrl}/users/me/meetings`).then(response => Meeting.parseMany(response.items)),
|
|
3342
3457
|
|
|
3343
|
-
createMyMeeting: (
|
|
3344
|
-
client
|
|
3458
|
+
createMyMeeting: (args ) =>
|
|
3459
|
+
client
|
|
3460
|
+
.post(`${baseUrl}/users/me/meetings`, convertKeysFromCamelToUnderscore(args))
|
|
3461
|
+
.then(Meeting.parse),
|
|
3462
|
+
|
|
3463
|
+
updateMyMeeting: (meetingUuid , data ) =>
|
|
3464
|
+
client.put(
|
|
3465
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}`,
|
|
3466
|
+
convertKeysFromCamelToUnderscore(data),
|
|
3467
|
+
null,
|
|
3468
|
+
ApiRequester.successResponseParser,
|
|
3469
|
+
),
|
|
3345
3470
|
|
|
3346
3471
|
deleteMyMeeting: (meetingUuid ) =>
|
|
3347
3472
|
client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
|
|
@@ -3349,8 +3474,36 @@ var confdMethods = (client , baseUrl ) => ({
|
|
|
3349
3474
|
getMeeting: (meetingUuid ) =>
|
|
3350
3475
|
client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
3351
3476
|
|
|
3477
|
+
meetingAuthorizations: (meetingUuid ) =>
|
|
3478
|
+
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations`, null).then(MeetingAuthorization.parseMany),
|
|
3479
|
+
|
|
3480
|
+
meetingAuthorizationReject: (meetingUuid , authorizationUuid ) =>
|
|
3481
|
+
client.put(
|
|
3482
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/reject`,
|
|
3483
|
+
{},
|
|
3484
|
+
null,
|
|
3485
|
+
ApiRequester.successResponseParser,
|
|
3486
|
+
),
|
|
3487
|
+
|
|
3488
|
+
meetingAuthorizationAccept: (meetingUuid , authorizationUuid ) =>
|
|
3489
|
+
client.put(
|
|
3490
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/accept`,
|
|
3491
|
+
{},
|
|
3492
|
+
null,
|
|
3493
|
+
ApiRequester.successResponseParser,
|
|
3494
|
+
),
|
|
3495
|
+
|
|
3352
3496
|
guestGetMeeting: (meetingUuid ) =>
|
|
3353
3497
|
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
3498
|
+
|
|
3499
|
+
guestAuthorizationRequest: (userUuid , meetingUuid , username ) =>
|
|
3500
|
+
client
|
|
3501
|
+
.post(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations`, { guest_name: username })
|
|
3502
|
+
.then(MeetingAuthorization.parse),
|
|
3503
|
+
|
|
3504
|
+
guestAuthorizationCheck: (userUuid , meetingUuid , authorizationUuid ) =>
|
|
3505
|
+
client.get(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations/${authorizationUuid}`, null),
|
|
3506
|
+
|
|
3354
3507
|
});
|
|
3355
3508
|
|
|
3356
3509
|
//
|
|
@@ -4789,6 +4942,14 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
4789
4942
|
getMeetingParticipantsAsUser: async (meetingUuid ) =>
|
|
4790
4943
|
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
|
|
4791
4944
|
|
|
4945
|
+
banMeetingParticipant: (meetingUuid , participantUuid ) =>
|
|
4946
|
+
client.delete(
|
|
4947
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/participants/${participantUuid}`,
|
|
4948
|
+
null,
|
|
4949
|
+
null,
|
|
4950
|
+
ApiRequester.successResponseParser,
|
|
4951
|
+
),
|
|
4952
|
+
|
|
4792
4953
|
listTrunks: () => client.get(`${baseUrl}/trunks`),
|
|
4793
4954
|
|
|
4794
4955
|
mute: (callId ) =>
|
|
@@ -6429,7 +6590,7 @@ class WebRTCClient extends Emitter {
|
|
|
6429
6590
|
});
|
|
6430
6591
|
}
|
|
6431
6592
|
|
|
6432
|
-
changeAudioInputDevice(id , session , force ) {
|
|
6593
|
+
async changeAudioInputDevice(id , session , force ) {
|
|
6433
6594
|
const currentId = this.getAudioDeviceId();
|
|
6434
6595
|
logger.info('setting audio input device', { id, currentId, session: !!session });
|
|
6435
6596
|
|
|
@@ -6437,33 +6598,50 @@ class WebRTCClient extends Emitter {
|
|
|
6437
6598
|
return null;
|
|
6438
6599
|
}
|
|
6439
6600
|
|
|
6601
|
+
// in order to handle an audio track change for default devices
|
|
6602
|
+
// we need the actual id of the device (not 'default')
|
|
6603
|
+
let deviceId = id;
|
|
6604
|
+
if (id === 'default' && navigator.mediaDevices) {
|
|
6605
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
6606
|
+
const defaultDevice = devices.find(device => device.deviceId === 'default');
|
|
6607
|
+
if (defaultDevice) {
|
|
6608
|
+
const deviceLabel = defaultDevice.label.replace('Default - ', '');
|
|
6609
|
+
const targetDevice = devices.find(device => device.label === deviceLabel);
|
|
6610
|
+
if (targetDevice) {
|
|
6611
|
+
deviceId = targetDevice.deviceId;
|
|
6612
|
+
if (!force && deviceId === currentId) {
|
|
6613
|
+
return null;
|
|
6614
|
+
}
|
|
6615
|
+
}
|
|
6616
|
+
}
|
|
6617
|
+
}
|
|
6618
|
+
|
|
6440
6619
|
// let's update the local audio value
|
|
6441
6620
|
if (this.audio) {
|
|
6442
6621
|
this.audio = {
|
|
6443
6622
|
deviceId: {
|
|
6444
|
-
exact:
|
|
6623
|
+
exact: deviceId,
|
|
6445
6624
|
},
|
|
6446
6625
|
};
|
|
6447
6626
|
}
|
|
6448
6627
|
|
|
6449
|
-
if (session) {
|
|
6628
|
+
if (session && navigator.mediaDevices) {
|
|
6450
6629
|
const sdh = session.sessionDescriptionHandler;
|
|
6451
6630
|
const pc = sdh.peerConnection;
|
|
6452
6631
|
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6632
|
+
const constraints = { audio: { deviceId: { exact: deviceId } } };
|
|
6633
|
+
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
6634
|
+
const audioTrack = stream.getAudioTracks()[0];
|
|
6635
|
+
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
6457
6636
|
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
}
|
|
6462
|
-
sender.replaceTrack(audioTrack);
|
|
6637
|
+
if (sender) {
|
|
6638
|
+
if (sender.track) {
|
|
6639
|
+
audioTrack.enabled = sender.track.enabled;
|
|
6463
6640
|
}
|
|
6641
|
+
sender.replaceTrack(audioTrack);
|
|
6642
|
+
}
|
|
6464
6643
|
|
|
6465
|
-
|
|
6466
|
-
});
|
|
6644
|
+
return stream;
|
|
6467
6645
|
}
|
|
6468
6646
|
}
|
|
6469
6647
|
|
|
@@ -6483,14 +6661,14 @@ class WebRTCClient extends Emitter {
|
|
|
6483
6661
|
return null;
|
|
6484
6662
|
}
|
|
6485
6663
|
|
|
6486
|
-
// let's
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
}
|
|
6493
|
-
}
|
|
6664
|
+
// let's make sure we don't lose other video constraints settings -- width, height, frameRate...
|
|
6665
|
+
const videoObject = typeof this.video === 'object' ? this.video : {};
|
|
6666
|
+
this.video = {
|
|
6667
|
+
...videoObject,
|
|
6668
|
+
deviceId: {
|
|
6669
|
+
exact: id,
|
|
6670
|
+
},
|
|
6671
|
+
};
|
|
6494
6672
|
}
|
|
6495
6673
|
|
|
6496
6674
|
changeSessionVideoInputDevice(id , session ) {
|
|
@@ -787,6 +787,24 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
787
787
|
return fixed;
|
|
788
788
|
};
|
|
789
789
|
|
|
790
|
+
const addIcesInAllBundles = (sdp ) => {
|
|
791
|
+
const parsedSdp = sdpParser__default['default'].parse(sdp);
|
|
792
|
+
|
|
793
|
+
const mediaWithCandidate = parsedSdp.media.find(media => !!media.candidates);
|
|
794
|
+
if (!mediaWithCandidate) {
|
|
795
|
+
return sdp;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
const { candidates } = mediaWithCandidate;
|
|
799
|
+
|
|
800
|
+
parsedSdp.media = parsedSdp.media.map(media => ({
|
|
801
|
+
...media,
|
|
802
|
+
candidates: media.candidates || candidates,
|
|
803
|
+
}));
|
|
804
|
+
|
|
805
|
+
return sdpParser__default['default'].write(parsedSdp);
|
|
806
|
+
};
|
|
807
|
+
|
|
790
808
|
/* global RTCSessionDescriptionInit, navigator */
|
|
791
809
|
|
|
792
810
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
@@ -916,7 +934,10 @@ class WazoSessionDescriptionHandler extends sessionDescriptionHandler.SessionDes
|
|
|
916
934
|
|
|
917
935
|
// Check if we got ICEs
|
|
918
936
|
if (sdp.indexOf('a=candidate') !== -1) {
|
|
919
|
-
return
|
|
937
|
+
return {
|
|
938
|
+
type: description.type,
|
|
939
|
+
sdp: addIcesInAllBundles(sdp),
|
|
940
|
+
};
|
|
920
941
|
}
|
|
921
942
|
|
|
922
943
|
wazoLogger.info('No ICE candidates found in SDP, fixing it with gathered ices', this.gatheredCandidates);
|
|
@@ -3190,6 +3211,70 @@ class ExternalApp {
|
|
|
3190
3211
|
|
|
3191
3212
|
//
|
|
3192
3213
|
|
|
3214
|
+
class MeetingAuthorization {
|
|
3215
|
+
|
|
3216
|
+
|
|
3217
|
+
|
|
3218
|
+
|
|
3219
|
+
|
|
3220
|
+
|
|
3221
|
+
constructor({
|
|
3222
|
+
meetingUuid,
|
|
3223
|
+
uuid,
|
|
3224
|
+
userUuid,
|
|
3225
|
+
userName,
|
|
3226
|
+
} = {}) {
|
|
3227
|
+
this.meetingUuid = meetingUuid;
|
|
3228
|
+
this.uuid = uuid;
|
|
3229
|
+
this.userUuid = userUuid;
|
|
3230
|
+
this.userName = userName;
|
|
3231
|
+
}
|
|
3232
|
+
|
|
3233
|
+
setStatus(status ) {
|
|
3234
|
+
this.status = status;
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
getStatus() {
|
|
3238
|
+
return this.status;
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
static parse(plain ) {
|
|
3242
|
+
const {
|
|
3243
|
+
meeting_uuid: meetingUuid,
|
|
3244
|
+
uuid,
|
|
3245
|
+
guest_uuid: userUuid,
|
|
3246
|
+
guest_name: userName,
|
|
3247
|
+
} = plain;
|
|
3248
|
+
|
|
3249
|
+
return new MeetingAuthorization({
|
|
3250
|
+
meetingUuid,
|
|
3251
|
+
uuid,
|
|
3252
|
+
userUuid,
|
|
3253
|
+
userName,
|
|
3254
|
+
});
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
static parseMany(items ) {
|
|
3258
|
+
if (!items) {
|
|
3259
|
+
return [];
|
|
3260
|
+
}
|
|
3261
|
+
return items.map(MeetingAuthorization.parse);
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3265
|
+
//
|
|
3266
|
+
|
|
3267
|
+
|
|
3268
|
+
|
|
3269
|
+
|
|
3270
|
+
|
|
3271
|
+
|
|
3272
|
+
|
|
3273
|
+
|
|
3274
|
+
|
|
3275
|
+
|
|
3276
|
+
|
|
3277
|
+
|
|
3193
3278
|
|
|
3194
3279
|
|
|
3195
3280
|
|
|
@@ -3200,6 +3285,7 @@ class ExternalApp {
|
|
|
3200
3285
|
|
|
3201
3286
|
|
|
3202
3287
|
|
|
3288
|
+
|
|
3203
3289
|
|
|
3204
3290
|
|
|
3205
3291
|
class Meeting {
|
|
@@ -3214,6 +3300,8 @@ class Meeting {
|
|
|
3214
3300
|
|
|
3215
3301
|
|
|
3216
3302
|
|
|
3303
|
+
|
|
3304
|
+
|
|
3217
3305
|
|
|
3218
3306
|
static parse(plain ) {
|
|
3219
3307
|
return new Meeting({
|
|
@@ -3226,6 +3314,7 @@ class Meeting {
|
|
|
3226
3314
|
extension: plain.exten,
|
|
3227
3315
|
persistent: plain.persistent,
|
|
3228
3316
|
creationTime: moment__default['default'](plain.creation_time).toDate(),
|
|
3317
|
+
requireAuthorization: plain.require_authorization,
|
|
3229
3318
|
});
|
|
3230
3319
|
}
|
|
3231
3320
|
|
|
@@ -3250,6 +3339,7 @@ class Meeting {
|
|
|
3250
3339
|
extension,
|
|
3251
3340
|
persistent,
|
|
3252
3341
|
creationTime,
|
|
3342
|
+
requireAuthorization,
|
|
3253
3343
|
} = {}) {
|
|
3254
3344
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
3255
3345
|
this.uri = uri;
|
|
@@ -3260,6 +3350,7 @@ class Meeting {
|
|
|
3260
3350
|
this.extension = extension;
|
|
3261
3351
|
this.persistent = persistent;
|
|
3262
3352
|
this.creationTime = creationTime;
|
|
3353
|
+
this.requireAuthorization = requireAuthorization;
|
|
3263
3354
|
|
|
3264
3355
|
// Useful to compare instead of instanceof with minified code
|
|
3265
3356
|
this.type = 'Meeting';
|
|
@@ -3270,8 +3361,32 @@ class Meeting {
|
|
|
3270
3361
|
const [username, secret] = atob(this.guestSipAuthorization).split(':');
|
|
3271
3362
|
return { username, secret };
|
|
3272
3363
|
}
|
|
3364
|
+
|
|
3273
3365
|
}
|
|
3274
3366
|
|
|
3367
|
+
//
|
|
3368
|
+
|
|
3369
|
+
const camelToUnderscore = (key ) => {
|
|
3370
|
+
if (typeof key !== 'string') {
|
|
3371
|
+
throw new Error('Input is not a string');
|
|
3372
|
+
}
|
|
3373
|
+
return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
3374
|
+
};
|
|
3375
|
+
|
|
3376
|
+
//
|
|
3377
|
+
|
|
3378
|
+
const convertKeysFromCamelToUnderscore = (args ) => {
|
|
3379
|
+
if (!args || typeof args !== 'object' || Array.isArray(args)) {
|
|
3380
|
+
throw new Error('Input is not an object');
|
|
3381
|
+
}
|
|
3382
|
+
|
|
3383
|
+
return Object.keys(args).reduce((acc, key) => {
|
|
3384
|
+
acc[camelToUnderscore(key)] = typeof args[key] === 'object' && !Array.isArray(args[key])
|
|
3385
|
+
? convertKeysFromCamelToUnderscore(args[key]) : args[key];
|
|
3386
|
+
return acc;
|
|
3387
|
+
}, {});
|
|
3388
|
+
};
|
|
3389
|
+
|
|
3275
3390
|
/* */
|
|
3276
3391
|
|
|
3277
3392
|
var confdMethods = (client , baseUrl ) => ({
|
|
@@ -3340,8 +3455,18 @@ var confdMethods = (client , baseUrl ) => ({
|
|
|
3340
3455
|
getMyMeetings: () =>
|
|
3341
3456
|
client.get(`${baseUrl}/users/me/meetings`).then(response => Meeting.parseMany(response.items)),
|
|
3342
3457
|
|
|
3343
|
-
createMyMeeting: (
|
|
3344
|
-
client
|
|
3458
|
+
createMyMeeting: (args ) =>
|
|
3459
|
+
client
|
|
3460
|
+
.post(`${baseUrl}/users/me/meetings`, convertKeysFromCamelToUnderscore(args))
|
|
3461
|
+
.then(Meeting.parse),
|
|
3462
|
+
|
|
3463
|
+
updateMyMeeting: (meetingUuid , data ) =>
|
|
3464
|
+
client.put(
|
|
3465
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}`,
|
|
3466
|
+
convertKeysFromCamelToUnderscore(data),
|
|
3467
|
+
null,
|
|
3468
|
+
ApiRequester.successResponseParser,
|
|
3469
|
+
),
|
|
3345
3470
|
|
|
3346
3471
|
deleteMyMeeting: (meetingUuid ) =>
|
|
3347
3472
|
client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
|
|
@@ -3349,8 +3474,36 @@ var confdMethods = (client , baseUrl ) => ({
|
|
|
3349
3474
|
getMeeting: (meetingUuid ) =>
|
|
3350
3475
|
client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
3351
3476
|
|
|
3477
|
+
meetingAuthorizations: (meetingUuid ) =>
|
|
3478
|
+
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations`, null).then(MeetingAuthorization.parseMany),
|
|
3479
|
+
|
|
3480
|
+
meetingAuthorizationReject: (meetingUuid , authorizationUuid ) =>
|
|
3481
|
+
client.put(
|
|
3482
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/reject`,
|
|
3483
|
+
{},
|
|
3484
|
+
null,
|
|
3485
|
+
ApiRequester.successResponseParser,
|
|
3486
|
+
),
|
|
3487
|
+
|
|
3488
|
+
meetingAuthorizationAccept: (meetingUuid , authorizationUuid ) =>
|
|
3489
|
+
client.put(
|
|
3490
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/accept`,
|
|
3491
|
+
{},
|
|
3492
|
+
null,
|
|
3493
|
+
ApiRequester.successResponseParser,
|
|
3494
|
+
),
|
|
3495
|
+
|
|
3352
3496
|
guestGetMeeting: (meetingUuid ) =>
|
|
3353
3497
|
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
3498
|
+
|
|
3499
|
+
guestAuthorizationRequest: (userUuid , meetingUuid , username ) =>
|
|
3500
|
+
client
|
|
3501
|
+
.post(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations`, { guest_name: username })
|
|
3502
|
+
.then(MeetingAuthorization.parse),
|
|
3503
|
+
|
|
3504
|
+
guestAuthorizationCheck: (userUuid , meetingUuid , authorizationUuid ) =>
|
|
3505
|
+
client.get(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations/${authorizationUuid}`, null),
|
|
3506
|
+
|
|
3354
3507
|
});
|
|
3355
3508
|
|
|
3356
3509
|
//
|
|
@@ -4789,6 +4942,14 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
4789
4942
|
getMeetingParticipantsAsUser: async (meetingUuid ) =>
|
|
4790
4943
|
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
|
|
4791
4944
|
|
|
4945
|
+
banMeetingParticipant: (meetingUuid , participantUuid ) =>
|
|
4946
|
+
client.delete(
|
|
4947
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/participants/${participantUuid}`,
|
|
4948
|
+
null,
|
|
4949
|
+
null,
|
|
4950
|
+
ApiRequester.successResponseParser,
|
|
4951
|
+
),
|
|
4952
|
+
|
|
4792
4953
|
listTrunks: () => client.get(`${baseUrl}/trunks`),
|
|
4793
4954
|
|
|
4794
4955
|
mute: (callId ) =>
|
|
@@ -6429,7 +6590,7 @@ class WebRTCClient extends Emitter {
|
|
|
6429
6590
|
});
|
|
6430
6591
|
}
|
|
6431
6592
|
|
|
6432
|
-
changeAudioInputDevice(id , session , force ) {
|
|
6593
|
+
async changeAudioInputDevice(id , session , force ) {
|
|
6433
6594
|
const currentId = this.getAudioDeviceId();
|
|
6434
6595
|
logger.info('setting audio input device', { id, currentId, session: !!session });
|
|
6435
6596
|
|
|
@@ -6437,33 +6598,50 @@ class WebRTCClient extends Emitter {
|
|
|
6437
6598
|
return null;
|
|
6438
6599
|
}
|
|
6439
6600
|
|
|
6601
|
+
// in order to handle an audio track change for default devices
|
|
6602
|
+
// we need the actual id of the device (not 'default')
|
|
6603
|
+
let deviceId = id;
|
|
6604
|
+
if (id === 'default' && navigator.mediaDevices) {
|
|
6605
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
6606
|
+
const defaultDevice = devices.find(device => device.deviceId === 'default');
|
|
6607
|
+
if (defaultDevice) {
|
|
6608
|
+
const deviceLabel = defaultDevice.label.replace('Default - ', '');
|
|
6609
|
+
const targetDevice = devices.find(device => device.label === deviceLabel);
|
|
6610
|
+
if (targetDevice) {
|
|
6611
|
+
deviceId = targetDevice.deviceId;
|
|
6612
|
+
if (!force && deviceId === currentId) {
|
|
6613
|
+
return null;
|
|
6614
|
+
}
|
|
6615
|
+
}
|
|
6616
|
+
}
|
|
6617
|
+
}
|
|
6618
|
+
|
|
6440
6619
|
// let's update the local audio value
|
|
6441
6620
|
if (this.audio) {
|
|
6442
6621
|
this.audio = {
|
|
6443
6622
|
deviceId: {
|
|
6444
|
-
exact:
|
|
6623
|
+
exact: deviceId,
|
|
6445
6624
|
},
|
|
6446
6625
|
};
|
|
6447
6626
|
}
|
|
6448
6627
|
|
|
6449
|
-
if (session) {
|
|
6628
|
+
if (session && navigator.mediaDevices) {
|
|
6450
6629
|
const sdh = session.sessionDescriptionHandler;
|
|
6451
6630
|
const pc = sdh.peerConnection;
|
|
6452
6631
|
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6632
|
+
const constraints = { audio: { deviceId: { exact: deviceId } } };
|
|
6633
|
+
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
6634
|
+
const audioTrack = stream.getAudioTracks()[0];
|
|
6635
|
+
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
6457
6636
|
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
}
|
|
6462
|
-
sender.replaceTrack(audioTrack);
|
|
6637
|
+
if (sender) {
|
|
6638
|
+
if (sender.track) {
|
|
6639
|
+
audioTrack.enabled = sender.track.enabled;
|
|
6463
6640
|
}
|
|
6641
|
+
sender.replaceTrack(audioTrack);
|
|
6642
|
+
}
|
|
6464
6643
|
|
|
6465
|
-
|
|
6466
|
-
});
|
|
6644
|
+
return stream;
|
|
6467
6645
|
}
|
|
6468
6646
|
}
|
|
6469
6647
|
|
|
@@ -6483,14 +6661,14 @@ class WebRTCClient extends Emitter {
|
|
|
6483
6661
|
return null;
|
|
6484
6662
|
}
|
|
6485
6663
|
|
|
6486
|
-
// let's
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
}
|
|
6493
|
-
}
|
|
6664
|
+
// let's make sure we don't lose other video constraints settings -- width, height, frameRate...
|
|
6665
|
+
const videoObject = typeof this.video === 'object' ? this.video : {};
|
|
6666
|
+
this.video = {
|
|
6667
|
+
...videoObject,
|
|
6668
|
+
deviceId: {
|
|
6669
|
+
exact: id,
|
|
6670
|
+
},
|
|
6671
|
+
};
|
|
6494
6672
|
}
|
|
6495
6673
|
|
|
6496
6674
|
changeSessionVideoInputDevice(id , session ) {
|