@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/esm/simple/utils.js
CHANGED
|
@@ -2645,6 +2645,70 @@ class ExternalApp {
|
|
|
2645
2645
|
|
|
2646
2646
|
//
|
|
2647
2647
|
|
|
2648
|
+
class MeetingAuthorization {
|
|
2649
|
+
|
|
2650
|
+
|
|
2651
|
+
|
|
2652
|
+
|
|
2653
|
+
|
|
2654
|
+
|
|
2655
|
+
constructor({
|
|
2656
|
+
meetingUuid,
|
|
2657
|
+
uuid,
|
|
2658
|
+
userUuid,
|
|
2659
|
+
userName,
|
|
2660
|
+
} = {}) {
|
|
2661
|
+
this.meetingUuid = meetingUuid;
|
|
2662
|
+
this.uuid = uuid;
|
|
2663
|
+
this.userUuid = userUuid;
|
|
2664
|
+
this.userName = userName;
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2667
|
+
setStatus(status ) {
|
|
2668
|
+
this.status = status;
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
getStatus() {
|
|
2672
|
+
return this.status;
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2675
|
+
static parse(plain ) {
|
|
2676
|
+
const {
|
|
2677
|
+
meeting_uuid: meetingUuid,
|
|
2678
|
+
uuid,
|
|
2679
|
+
guest_uuid: userUuid,
|
|
2680
|
+
guest_name: userName,
|
|
2681
|
+
} = plain;
|
|
2682
|
+
|
|
2683
|
+
return new MeetingAuthorization({
|
|
2684
|
+
meetingUuid,
|
|
2685
|
+
uuid,
|
|
2686
|
+
userUuid,
|
|
2687
|
+
userName,
|
|
2688
|
+
});
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2691
|
+
static parseMany(items ) {
|
|
2692
|
+
if (!items) {
|
|
2693
|
+
return [];
|
|
2694
|
+
}
|
|
2695
|
+
return items.map(MeetingAuthorization.parse);
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2699
|
+
//
|
|
2700
|
+
|
|
2701
|
+
|
|
2702
|
+
|
|
2703
|
+
|
|
2704
|
+
|
|
2705
|
+
|
|
2706
|
+
|
|
2707
|
+
|
|
2708
|
+
|
|
2709
|
+
|
|
2710
|
+
|
|
2711
|
+
|
|
2648
2712
|
|
|
2649
2713
|
|
|
2650
2714
|
|
|
@@ -2655,6 +2719,7 @@ class ExternalApp {
|
|
|
2655
2719
|
|
|
2656
2720
|
|
|
2657
2721
|
|
|
2722
|
+
|
|
2658
2723
|
|
|
2659
2724
|
|
|
2660
2725
|
class Meeting {
|
|
@@ -2669,6 +2734,8 @@ class Meeting {
|
|
|
2669
2734
|
|
|
2670
2735
|
|
|
2671
2736
|
|
|
2737
|
+
|
|
2738
|
+
|
|
2672
2739
|
|
|
2673
2740
|
static parse(plain ) {
|
|
2674
2741
|
return new Meeting({
|
|
@@ -2681,6 +2748,7 @@ class Meeting {
|
|
|
2681
2748
|
extension: plain.exten,
|
|
2682
2749
|
persistent: plain.persistent,
|
|
2683
2750
|
creationTime: moment(plain.creation_time).toDate(),
|
|
2751
|
+
requireAuthorization: plain.require_authorization,
|
|
2684
2752
|
});
|
|
2685
2753
|
}
|
|
2686
2754
|
|
|
@@ -2705,6 +2773,7 @@ class Meeting {
|
|
|
2705
2773
|
extension,
|
|
2706
2774
|
persistent,
|
|
2707
2775
|
creationTime,
|
|
2776
|
+
requireAuthorization,
|
|
2708
2777
|
} = {}) {
|
|
2709
2778
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2710
2779
|
this.uri = uri;
|
|
@@ -2715,6 +2784,7 @@ class Meeting {
|
|
|
2715
2784
|
this.extension = extension;
|
|
2716
2785
|
this.persistent = persistent;
|
|
2717
2786
|
this.creationTime = creationTime;
|
|
2787
|
+
this.requireAuthorization = requireAuthorization;
|
|
2718
2788
|
|
|
2719
2789
|
// Useful to compare instead of instanceof with minified code
|
|
2720
2790
|
this.type = 'Meeting';
|
|
@@ -2725,8 +2795,32 @@ class Meeting {
|
|
|
2725
2795
|
const [username, secret] = atob(this.guestSipAuthorization).split(':');
|
|
2726
2796
|
return { username, secret };
|
|
2727
2797
|
}
|
|
2798
|
+
|
|
2728
2799
|
}
|
|
2729
2800
|
|
|
2801
|
+
//
|
|
2802
|
+
|
|
2803
|
+
const camelToUnderscore = (key ) => {
|
|
2804
|
+
if (typeof key !== 'string') {
|
|
2805
|
+
throw new Error('Input is not a string');
|
|
2806
|
+
}
|
|
2807
|
+
return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
2808
|
+
};
|
|
2809
|
+
|
|
2810
|
+
//
|
|
2811
|
+
|
|
2812
|
+
const convertKeysFromCamelToUnderscore = (args ) => {
|
|
2813
|
+
if (!args || typeof args !== 'object' || Array.isArray(args)) {
|
|
2814
|
+
throw new Error('Input is not an object');
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2817
|
+
return Object.keys(args).reduce((acc, key) => {
|
|
2818
|
+
acc[camelToUnderscore(key)] = typeof args[key] === 'object' && !Array.isArray(args[key])
|
|
2819
|
+
? convertKeysFromCamelToUnderscore(args[key]) : args[key];
|
|
2820
|
+
return acc;
|
|
2821
|
+
}, {});
|
|
2822
|
+
};
|
|
2823
|
+
|
|
2730
2824
|
/* */
|
|
2731
2825
|
|
|
2732
2826
|
var confdMethods = (client , baseUrl ) => ({
|
|
@@ -2795,8 +2889,18 @@ var confdMethods = (client , baseUrl ) => ({
|
|
|
2795
2889
|
getMyMeetings: () =>
|
|
2796
2890
|
client.get(`${baseUrl}/users/me/meetings`).then(response => Meeting.parseMany(response.items)),
|
|
2797
2891
|
|
|
2798
|
-
createMyMeeting: (
|
|
2799
|
-
client
|
|
2892
|
+
createMyMeeting: (args ) =>
|
|
2893
|
+
client
|
|
2894
|
+
.post(`${baseUrl}/users/me/meetings`, convertKeysFromCamelToUnderscore(args))
|
|
2895
|
+
.then(Meeting.parse),
|
|
2896
|
+
|
|
2897
|
+
updateMyMeeting: (meetingUuid , data ) =>
|
|
2898
|
+
client.put(
|
|
2899
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}`,
|
|
2900
|
+
convertKeysFromCamelToUnderscore(data),
|
|
2901
|
+
null,
|
|
2902
|
+
ApiRequester.successResponseParser,
|
|
2903
|
+
),
|
|
2800
2904
|
|
|
2801
2905
|
deleteMyMeeting: (meetingUuid ) =>
|
|
2802
2906
|
client.delete(`${baseUrl}/users/me/meetings/${meetingUuid}`, null),
|
|
@@ -2804,8 +2908,36 @@ var confdMethods = (client , baseUrl ) => ({
|
|
|
2804
2908
|
getMeeting: (meetingUuid ) =>
|
|
2805
2909
|
client.get(`${baseUrl}/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
2806
2910
|
|
|
2911
|
+
meetingAuthorizations: (meetingUuid ) =>
|
|
2912
|
+
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations`, null).then(MeetingAuthorization.parseMany),
|
|
2913
|
+
|
|
2914
|
+
meetingAuthorizationReject: (meetingUuid , authorizationUuid ) =>
|
|
2915
|
+
client.put(
|
|
2916
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/reject`,
|
|
2917
|
+
{},
|
|
2918
|
+
null,
|
|
2919
|
+
ApiRequester.successResponseParser,
|
|
2920
|
+
),
|
|
2921
|
+
|
|
2922
|
+
meetingAuthorizationAccept: (meetingUuid , authorizationUuid ) =>
|
|
2923
|
+
client.put(
|
|
2924
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/authorizations/${authorizationUuid}/accept`,
|
|
2925
|
+
{},
|
|
2926
|
+
null,
|
|
2927
|
+
ApiRequester.successResponseParser,
|
|
2928
|
+
),
|
|
2929
|
+
|
|
2807
2930
|
guestGetMeeting: (meetingUuid ) =>
|
|
2808
2931
|
client.get(`${baseUrl}/guests/me/meetings/${meetingUuid}`, null).then(Meeting.parse),
|
|
2932
|
+
|
|
2933
|
+
guestAuthorizationRequest: (userUuid , meetingUuid , username ) =>
|
|
2934
|
+
client
|
|
2935
|
+
.post(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations`, { guest_name: username })
|
|
2936
|
+
.then(MeetingAuthorization.parse),
|
|
2937
|
+
|
|
2938
|
+
guestAuthorizationCheck: (userUuid , meetingUuid , authorizationUuid ) =>
|
|
2939
|
+
client.get(`${baseUrl}/guests/${userUuid}/meetings/${meetingUuid}/authorizations/${authorizationUuid}`, null),
|
|
2940
|
+
|
|
2809
2941
|
});
|
|
2810
2942
|
|
|
2811
2943
|
//
|
|
@@ -5056,6 +5188,14 @@ var calldMethods = (client , baseUrl ) => ({
|
|
|
5056
5188
|
getMeetingParticipantsAsUser: async (meetingUuid ) =>
|
|
5057
5189
|
client.get(`${baseUrl}/users/me/meetings/${meetingUuid}/participants`),
|
|
5058
5190
|
|
|
5191
|
+
banMeetingParticipant: (meetingUuid , participantUuid ) =>
|
|
5192
|
+
client.delete(
|
|
5193
|
+
`${baseUrl}/users/me/meetings/${meetingUuid}/participants/${participantUuid}`,
|
|
5194
|
+
null,
|
|
5195
|
+
null,
|
|
5196
|
+
ApiRequester.successResponseParser,
|
|
5197
|
+
),
|
|
5198
|
+
|
|
5059
5199
|
listTrunks: () => client.get(`${baseUrl}/trunks`),
|
|
5060
5200
|
|
|
5061
5201
|
mute: (callId ) =>
|
|
@@ -6204,6 +6344,24 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
6204
6344
|
return fixed;
|
|
6205
6345
|
};
|
|
6206
6346
|
|
|
6347
|
+
const addIcesInAllBundles = (sdp ) => {
|
|
6348
|
+
const parsedSdp = sdpParser.parse(sdp);
|
|
6349
|
+
|
|
6350
|
+
const mediaWithCandidate = parsedSdp.media.find(media => !!media.candidates);
|
|
6351
|
+
if (!mediaWithCandidate) {
|
|
6352
|
+
return sdp;
|
|
6353
|
+
}
|
|
6354
|
+
|
|
6355
|
+
const { candidates } = mediaWithCandidate;
|
|
6356
|
+
|
|
6357
|
+
parsedSdp.media = parsedSdp.media.map(media => ({
|
|
6358
|
+
...media,
|
|
6359
|
+
candidates: media.candidates || candidates,
|
|
6360
|
+
}));
|
|
6361
|
+
|
|
6362
|
+
return sdpParser.write(parsedSdp);
|
|
6363
|
+
};
|
|
6364
|
+
|
|
6207
6365
|
/* global RTCSessionDescriptionInit, navigator */
|
|
6208
6366
|
|
|
6209
6367
|
const wazoLogger = IssueReporter$1 ? IssueReporter$1.loggerFor('webrtc-sdh') : console;
|
|
@@ -6333,7 +6491,10 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
6333
6491
|
|
|
6334
6492
|
// Check if we got ICEs
|
|
6335
6493
|
if (sdp.indexOf('a=candidate') !== -1) {
|
|
6336
|
-
return
|
|
6494
|
+
return {
|
|
6495
|
+
type: description.type,
|
|
6496
|
+
sdp: addIcesInAllBundles(sdp),
|
|
6497
|
+
};
|
|
6337
6498
|
}
|
|
6338
6499
|
|
|
6339
6500
|
wazoLogger.info('No ICE candidates found in SDP, fixing it with gathered ices', this.gatheredCandidates);
|
|
@@ -7793,7 +7954,7 @@ class WebRTCClient extends Emitter {
|
|
|
7793
7954
|
});
|
|
7794
7955
|
}
|
|
7795
7956
|
|
|
7796
|
-
changeAudioInputDevice(id , session , force ) {
|
|
7957
|
+
async changeAudioInputDevice(id , session , force ) {
|
|
7797
7958
|
const currentId = this.getAudioDeviceId();
|
|
7798
7959
|
logger$8.info('setting audio input device', { id, currentId, session: !!session });
|
|
7799
7960
|
|
|
@@ -7801,33 +7962,50 @@ class WebRTCClient extends Emitter {
|
|
|
7801
7962
|
return null;
|
|
7802
7963
|
}
|
|
7803
7964
|
|
|
7965
|
+
// in order to handle an audio track change for default devices
|
|
7966
|
+
// we need the actual id of the device (not 'default')
|
|
7967
|
+
let deviceId = id;
|
|
7968
|
+
if (id === 'default' && navigator.mediaDevices) {
|
|
7969
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
7970
|
+
const defaultDevice = devices.find(device => device.deviceId === 'default');
|
|
7971
|
+
if (defaultDevice) {
|
|
7972
|
+
const deviceLabel = defaultDevice.label.replace('Default - ', '');
|
|
7973
|
+
const targetDevice = devices.find(device => device.label === deviceLabel);
|
|
7974
|
+
if (targetDevice) {
|
|
7975
|
+
deviceId = targetDevice.deviceId;
|
|
7976
|
+
if (!force && deviceId === currentId) {
|
|
7977
|
+
return null;
|
|
7978
|
+
}
|
|
7979
|
+
}
|
|
7980
|
+
}
|
|
7981
|
+
}
|
|
7982
|
+
|
|
7804
7983
|
// let's update the local audio value
|
|
7805
7984
|
if (this.audio) {
|
|
7806
7985
|
this.audio = {
|
|
7807
7986
|
deviceId: {
|
|
7808
|
-
exact:
|
|
7987
|
+
exact: deviceId,
|
|
7809
7988
|
},
|
|
7810
7989
|
};
|
|
7811
7990
|
}
|
|
7812
7991
|
|
|
7813
|
-
if (session) {
|
|
7992
|
+
if (session && navigator.mediaDevices) {
|
|
7814
7993
|
const sdh = session.sessionDescriptionHandler;
|
|
7815
7994
|
const pc = sdh.peerConnection;
|
|
7816
7995
|
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
|
|
7996
|
+
const constraints = { audio: { deviceId: { exact: deviceId } } };
|
|
7997
|
+
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
7998
|
+
const audioTrack = stream.getAudioTracks()[0];
|
|
7999
|
+
const sender = pc && pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
7821
8000
|
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
}
|
|
7826
|
-
sender.replaceTrack(audioTrack);
|
|
8001
|
+
if (sender) {
|
|
8002
|
+
if (sender.track) {
|
|
8003
|
+
audioTrack.enabled = sender.track.enabled;
|
|
7827
8004
|
}
|
|
8005
|
+
sender.replaceTrack(audioTrack);
|
|
8006
|
+
}
|
|
7828
8007
|
|
|
7829
|
-
|
|
7830
|
-
});
|
|
8008
|
+
return stream;
|
|
7831
8009
|
}
|
|
7832
8010
|
}
|
|
7833
8011
|
|
|
@@ -7847,14 +8025,14 @@ class WebRTCClient extends Emitter {
|
|
|
7847
8025
|
return null;
|
|
7848
8026
|
}
|
|
7849
8027
|
|
|
7850
|
-
// let's
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
}
|
|
7857
|
-
}
|
|
8028
|
+
// let's make sure we don't lose other video constraints settings -- width, height, frameRate...
|
|
8029
|
+
const videoObject = typeof this.video === 'object' ? this.video : {};
|
|
8030
|
+
this.video = {
|
|
8031
|
+
...videoObject,
|
|
8032
|
+
deviceId: {
|
|
8033
|
+
exact: id,
|
|
8034
|
+
},
|
|
8035
|
+
};
|
|
7858
8036
|
}
|
|
7859
8037
|
|
|
7860
8038
|
changeSessionVideoInputDevice(id , session ) {
|
|
@@ -9456,9 +9634,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9456
9634
|
|
|
9457
9635
|
try {
|
|
9458
9636
|
if (this.currentScreenShare.stream) {
|
|
9459
|
-
this.currentScreenShare.stream.getTracks()
|
|
9460
|
-
.filter(track => track.kind === 'video')
|
|
9461
|
-
.forEach(track => track.stop());
|
|
9637
|
+
this.currentScreenShare.stream.getTracks().forEach(track => track.stop());
|
|
9462
9638
|
}
|
|
9463
9639
|
|
|
9464
9640
|
if (restoreLocalStream) {
|
|
@@ -11249,6 +11425,7 @@ const AGENT_UNPAUSED = 'agent_unpaused';
|
|
|
11249
11425
|
const CONFERENCE_ADHOC_PARTICIPANT_LEFT = 'conference_adhoc_participant_left';
|
|
11250
11426
|
const CONFERENCE_ADHOC_DELETED = 'conference_adhoc_deleted';
|
|
11251
11427
|
const MEETING_USER_PROGRESS = 'meeting_user_progress';
|
|
11428
|
+
const MEETING_USER_GUEST_AUTHORIZATION_CREATED = 'meeting_user_guest_authorization_created';
|
|
11252
11429
|
|
|
11253
11430
|
const BLACKLIST_EVENTS = [
|
|
11254
11431
|
CHAT_MESSAGE_SENT,
|
|
@@ -11600,6 +11777,7 @@ WebSocketClient.eventLists = [
|
|
|
11600
11777
|
CONFERENCE_ADHOC_PARTICIPANT_LEFT,
|
|
11601
11778
|
CONFERENCE_ADHOC_DELETED,
|
|
11602
11779
|
MEETING_USER_PROGRESS,
|
|
11780
|
+
MEETING_USER_GUEST_AUTHORIZATION_CREATED,
|
|
11603
11781
|
];
|
|
11604
11782
|
|
|
11605
11783
|
var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
|
|
@@ -11671,6 +11849,7 @@ var WebSocketClient$1 = /*#__PURE__*/Object.freeze({
|
|
|
11671
11849
|
CONFERENCE_ADHOC_PARTICIPANT_LEFT: CONFERENCE_ADHOC_PARTICIPANT_LEFT,
|
|
11672
11850
|
CONFERENCE_ADHOC_DELETED: CONFERENCE_ADHOC_DELETED,
|
|
11673
11851
|
MEETING_USER_PROGRESS: MEETING_USER_PROGRESS,
|
|
11852
|
+
MEETING_USER_GUEST_AUTHORIZATION_CREATED: MEETING_USER_GUEST_AUTHORIZATION_CREATED,
|
|
11674
11853
|
HEARTBEAT_ENGINE_VERSION: HEARTBEAT_ENGINE_VERSION,
|
|
11675
11854
|
'default': WebSocketClient
|
|
11676
11855
|
});
|
|
@@ -11775,6 +11954,7 @@ class Participant extends Emitter {
|
|
|
11775
11954
|
|
|
11776
11955
|
|
|
11777
11956
|
|
|
11957
|
+
|
|
11778
11958
|
|
|
11779
11959
|
|
|
11780
11960
|
|
|
@@ -11792,6 +11972,7 @@ class Participant extends Emitter {
|
|
|
11792
11972
|
|
|
11793
11973
|
|
|
11794
11974
|
|
|
11975
|
+
|
|
11795
11976
|
|
|
11796
11977
|
/**
|
|
11797
11978
|
* @param room Room The room where the participant is
|
|
@@ -11815,6 +11996,7 @@ class Participant extends Emitter {
|
|
|
11815
11996
|
this.screensharing = false;
|
|
11816
11997
|
this.isOnHold = false;
|
|
11817
11998
|
this.extra = extra;
|
|
11999
|
+
this.banned = false;
|
|
11818
12000
|
|
|
11819
12001
|
this.ON_UPDATED = 'participant/ON_UPDATED';
|
|
11820
12002
|
this.ON_START_TALKING = 'participant/ON_START_TALKING';
|
|
@@ -11831,6 +12013,7 @@ class Participant extends Emitter {
|
|
|
11831
12013
|
this.ON_EXTRA_CHANGE = 'participant/ON_EXTRA_CHANGE';
|
|
11832
12014
|
this.ON_HOLD = 'participant/ON_HOLD';
|
|
11833
12015
|
this.ON_RESUME = 'participant/ON_RESUME';
|
|
12016
|
+
this.ON_BAN = 'participant/ON_BAN';
|
|
11834
12017
|
}
|
|
11835
12018
|
|
|
11836
12019
|
triggerEvent(name , ...args ) {
|
|
@@ -11871,6 +12054,10 @@ class Participant extends Emitter {
|
|
|
11871
12054
|
status.extra = this.extra;
|
|
11872
12055
|
break;
|
|
11873
12056
|
}
|
|
12057
|
+
case this.ON_BAN: {
|
|
12058
|
+
status.banned = true;
|
|
12059
|
+
break;
|
|
12060
|
+
}
|
|
11874
12061
|
}
|
|
11875
12062
|
|
|
11876
12063
|
if (broadcast) {
|
|
@@ -11973,6 +12160,11 @@ class Participant extends Emitter {
|
|
|
11973
12160
|
this.triggerUpdate(this.ON_RESUME, broadcast);
|
|
11974
12161
|
}
|
|
11975
12162
|
|
|
12163
|
+
onBan(broadcast = true) {
|
|
12164
|
+
this.banned = true;
|
|
12165
|
+
this.triggerUpdate(this.ON_BAN, broadcast);
|
|
12166
|
+
}
|
|
12167
|
+
|
|
11976
12168
|
getStatus() {
|
|
11977
12169
|
return {
|
|
11978
12170
|
callId: this.callId,
|
|
@@ -12019,6 +12211,10 @@ class Participant extends Emitter {
|
|
|
12019
12211
|
}
|
|
12020
12212
|
}
|
|
12021
12213
|
|
|
12214
|
+
if (status.banned) {
|
|
12215
|
+
this.onBan(false);
|
|
12216
|
+
}
|
|
12217
|
+
|
|
12022
12218
|
// Poor man's object comparison
|
|
12023
12219
|
if (typeof status.extra !== 'undefined' && JSON.stringify(this.extra) !== JSON.stringify(status.extra)) {
|
|
12024
12220
|
this.extra = { ...this.extra, ...status.extra };
|
|
@@ -12046,6 +12242,28 @@ class Participant extends Emitter {
|
|
|
12046
12242
|
this.streams = streams;
|
|
12047
12243
|
this.videoStreams = streams;
|
|
12048
12244
|
}
|
|
12245
|
+
|
|
12246
|
+
async ban(apiRequestDelay = null) {
|
|
12247
|
+
const { meetingUuid } = this.room;
|
|
12248
|
+
if (!meetingUuid) {
|
|
12249
|
+
throw new Error('Attempting to ban a participant without a `meetingUuid`');
|
|
12250
|
+
}
|
|
12251
|
+
|
|
12252
|
+
// this notifies all that someone is being banned
|
|
12253
|
+
this.onBan(true);
|
|
12254
|
+
|
|
12255
|
+
// this allows to delay the actual ban, in order for the banned participant as well as others to react to the situation
|
|
12256
|
+
if (apiRequestDelay) {
|
|
12257
|
+
await this.delay(apiRequestDelay);
|
|
12258
|
+
}
|
|
12259
|
+
|
|
12260
|
+
// proceed with the actual kick
|
|
12261
|
+
return getApiClient().calld.banMeetingParticipant(meetingUuid, this.callId);
|
|
12262
|
+
}
|
|
12263
|
+
|
|
12264
|
+
async delay(ms ) {
|
|
12265
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
12266
|
+
}
|
|
12049
12267
|
}
|
|
12050
12268
|
|
|
12051
12269
|
//
|
|
@@ -12198,7 +12416,7 @@ class Room$1 extends Emitter {
|
|
|
12198
12416
|
logger$2.info('connecting to room', { extension, audioOnly, room: !!room });
|
|
12199
12417
|
|
|
12200
12418
|
if (!room) {
|
|
12201
|
-
await Wazo.Phone.connect();
|
|
12419
|
+
await Wazo.Phone.connect({ media: constraints });
|
|
12202
12420
|
|
|
12203
12421
|
const withCamera = constraints && !!constraints.video;
|
|
12204
12422
|
|
|
@@ -12643,7 +12861,7 @@ class Room$1 extends Emitter {
|
|
|
12643
12861
|
const participant = this._getParticipantFromCallId(status.callId);
|
|
12644
12862
|
|
|
12645
12863
|
if (participant) {
|
|
12646
|
-
// we're
|
|
12864
|
+
// we're receiving, so no need to broadcast
|
|
12647
12865
|
participant.updateStatus(status, false);
|
|
12648
12866
|
}
|
|
12649
12867
|
break;
|
|
@@ -12910,7 +13128,7 @@ class SipRoom extends Room$1 {
|
|
|
12910
13128
|
logger$1.info('connecting to sip room', { extension, audioOnly, room: !!room });
|
|
12911
13129
|
|
|
12912
13130
|
if (!room) {
|
|
12913
|
-
await Wazo.Phone.connect();
|
|
13131
|
+
await Wazo.Phone.connect({ media: constraints });
|
|
12914
13132
|
|
|
12915
13133
|
const withCamera = constraints && !!constraints.video;
|
|
12916
13134
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
const camelToUnderscore = (key ) => {
|
|
4
|
+
if (typeof key !== 'string') {
|
|
5
|
+
throw new Error('Input is not a string');
|
|
6
|
+
}
|
|
7
|
+
return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
//
|
|
11
|
+
|
|
12
|
+
const convertKeysFromCamelToUnderscore = (args ) => {
|
|
13
|
+
if (!args || typeof args !== 'object' || Array.isArray(args)) {
|
|
14
|
+
throw new Error('Input is not an object');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return Object.keys(args).reduce((acc, key) => {
|
|
18
|
+
acc[camelToUnderscore(key)] = typeof args[key] === 'object' && !Array.isArray(args[key])
|
|
19
|
+
? convertKeysFromCamelToUnderscore(args[key]) : args[key];
|
|
20
|
+
return acc;
|
|
21
|
+
}, {});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//
|
|
25
|
+
|
|
26
|
+
describe('object utils', () => {
|
|
27
|
+
describe('convertKeysFromCamelToUnderscore', () => {
|
|
28
|
+
it('should throw an error when input is not an object', () => {
|
|
29
|
+
const msg = 'Input is not an object';
|
|
30
|
+
expect(() => convertKeysFromCamelToUnderscore(true)).toThrow(msg);
|
|
31
|
+
expect(() => convertKeysFromCamelToUnderscore(null)).toThrow(msg);
|
|
32
|
+
expect(() => convertKeysFromCamelToUnderscore(undefined)).toThrow(msg);
|
|
33
|
+
expect(() => convertKeysFromCamelToUnderscore([])).toThrow(msg);
|
|
34
|
+
expect(() => convertKeysFromCamelToUnderscore('some-string')).toThrow(msg);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should convert camel-cased keys to underscore', () => {
|
|
38
|
+
let value = Math.random();
|
|
39
|
+
expect(convertKeysFromCamelToUnderscore({ LoremIpsum: value })).toEqual({ lorem_ipsum: value });
|
|
40
|
+
value = Math.random();
|
|
41
|
+
expect(convertKeysFromCamelToUnderscore({ loremIpsum: value })).toEqual({ lorem_ipsum: value });
|
|
42
|
+
value = Math.random();
|
|
43
|
+
expect(convertKeysFromCamelToUnderscore({ 'lorem-ipsum': value })).toEqual({ 'lorem-ipsum': value });
|
|
44
|
+
value = Math.random();
|
|
45
|
+
expect(convertKeysFromCamelToUnderscore({ L123: value })).toEqual({ l123: value });
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should handle multi-leveled object', () => {
|
|
49
|
+
const value = Math.random();
|
|
50
|
+
expect(convertKeysFromCamelToUnderscore({ LoremIpsum: { DoloreSit: { Amet: value }, regular: 'reg' } }))
|
|
51
|
+
.toEqual({ lorem_ipsum: { dolore_sit: { amet: value }, regular: 'reg' } });
|
|
52
|
+
|
|
53
|
+
expect(convertKeysFromCamelToUnderscore({ LoremIpsum: { DoloreSit: { Amet: [value] }, regular: ['something'] } }))
|
|
54
|
+
.toEqual({ lorem_ipsum: { dolore_sit: { amet: [value] }, regular: ['something'] } });
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -98,6 +98,24 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
98
98
|
return fixed;
|
|
99
99
|
};
|
|
100
100
|
|
|
101
|
+
const addIcesInAllBundles = (sdp ) => {
|
|
102
|
+
const parsedSdp = sdpParser.parse(sdp);
|
|
103
|
+
|
|
104
|
+
const mediaWithCandidate = parsedSdp.media.find(media => !!media.candidates);
|
|
105
|
+
if (!mediaWithCandidate) {
|
|
106
|
+
return sdp;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const { candidates } = mediaWithCandidate;
|
|
110
|
+
|
|
111
|
+
parsedSdp.media = parsedSdp.media.map(media => ({
|
|
112
|
+
...media,
|
|
113
|
+
candidates: media.candidates || candidates,
|
|
114
|
+
}));
|
|
115
|
+
|
|
116
|
+
return sdpParser.write(parsedSdp);
|
|
117
|
+
};
|
|
118
|
+
|
|
101
119
|
/* eslint-disable max-len */
|
|
102
120
|
|
|
103
121
|
const goodSdp = `
|
|
@@ -262,4 +280,36 @@ describe('SDP utils', () => {
|
|
|
262
280
|
expect(hasAnActiveVideo(inactiveVideo)).toBeFalsy();
|
|
263
281
|
});
|
|
264
282
|
});
|
|
283
|
+
|
|
284
|
+
describe('Adding candidate in all bundles ', () => {
|
|
285
|
+
it('should add candidate everywhere', async () => {
|
|
286
|
+
const audioWithoutCandidate = `
|
|
287
|
+
c=IN IP4 203.0.113.1
|
|
288
|
+
m=audio 54400 RTP/SAVPF 0 96
|
|
289
|
+
m=video 54400 RTP/SAVPF 0 96
|
|
290
|
+
a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host
|
|
291
|
+
a=candidate:3996450952 1 udp 41819903 14.72.21.2 65092 typ relay raddr 0.0.0.0 rport 0 generation 0 network-id 3 network-cost 10
|
|
292
|
+
`;
|
|
293
|
+
const fixedAudioWithoutCandidate = sdpParser.parse(addIcesInAllBundles(audioWithoutCandidate));
|
|
294
|
+
|
|
295
|
+
expect(fixedAudioWithoutCandidate.media[0].candidates[0].type).toBe('host');
|
|
296
|
+
expect(fixedAudioWithoutCandidate.media[0].candidates[1].type).toBe('relay');
|
|
297
|
+
expect(fixedAudioWithoutCandidate.media[1].candidates[0].type).toBe('host');
|
|
298
|
+
expect(fixedAudioWithoutCandidate.media[1].candidates[1].type).toBe('relay');
|
|
299
|
+
|
|
300
|
+
// It should not add candidate if already present
|
|
301
|
+
const audioWithCandidate = `
|
|
302
|
+
c=IN IP4 203.0.113.1
|
|
303
|
+
m=audio 54400 RTP/SAVPF 0 96
|
|
304
|
+
a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ srflx
|
|
305
|
+
|
|
306
|
+
m=video 54400 RTP/SAVPF 0 96
|
|
307
|
+
a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host
|
|
308
|
+
`;
|
|
309
|
+
const fixedAudioWithCandidate = sdpParser.parse(addIcesInAllBundles(audioWithCandidate));
|
|
310
|
+
|
|
311
|
+
expect(fixedAudioWithCandidate.media[0].candidates[0].type).toBe('srflx');
|
|
312
|
+
expect(fixedAudioWithCandidate.media[1].candidates[0].type).toBe('host');
|
|
313
|
+
});
|
|
314
|
+
});
|
|
265
315
|
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
const camelToUnderscore = (key ) => {
|
|
4
|
+
if (typeof key !== 'string') {
|
|
5
|
+
throw new Error('Input is not a string');
|
|
6
|
+
}
|
|
7
|
+
return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
describe('string utils', () => {
|
|
11
|
+
describe('camelToUnderscore', () => {
|
|
12
|
+
it('', () => {
|
|
13
|
+
expect(() => camelToUnderscore(null)).toThrow('Input is not a string');
|
|
14
|
+
expect(() => camelToUnderscore(undefined)).toThrow('Input is not a string');
|
|
15
|
+
expect(() => camelToUnderscore({})).toThrow('Input is not a string');
|
|
16
|
+
expect(() => camelToUnderscore([])).toThrow('Input is not a string');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should convert camel-cased string to underscore', () => {
|
|
20
|
+
expect(camelToUnderscore('loremIpsum')).toEqual('lorem_ipsum');
|
|
21
|
+
expect(camelToUnderscore('lorem-ipsum')).toEqual('lorem-ipsum');
|
|
22
|
+
expect(camelToUnderscore('')).toEqual('');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should not prefix string with an underscore', () => {
|
|
26
|
+
expect(camelToUnderscore('LoremIpsum')).toEqual('lorem_ipsum');
|
|
27
|
+
expect(camelToUnderscore('L123')).toEqual('l123');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
const camelToUnderscore = (key ) => {
|
|
4
|
+
if (typeof key !== 'string') {
|
|
5
|
+
throw new Error('Input is not a string');
|
|
6
|
+
}
|
|
7
|
+
return key.charAt(0).toLowerCase() + key.substring(1).replace(/([A-Z])/g, '_$1').toLowerCase();
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
//
|
|
11
|
+
|
|
12
|
+
const convertKeysFromCamelToUnderscore = (args ) => {
|
|
13
|
+
if (!args || typeof args !== 'object' || Array.isArray(args)) {
|
|
14
|
+
throw new Error('Input is not an object');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return Object.keys(args).reduce((acc, key) => {
|
|
18
|
+
acc[camelToUnderscore(key)] = typeof args[key] === 'object' && !Array.isArray(args[key])
|
|
19
|
+
? convertKeysFromCamelToUnderscore(args[key]) : args[key];
|
|
20
|
+
return acc;
|
|
21
|
+
}, {});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export { convertKeysFromCamelToUnderscore };
|
package/esm/utils/sdp.js
CHANGED
|
@@ -122,4 +122,22 @@ const fixSdp = (sdp , candidates , forcePort = true)
|
|
|
122
122
|
return fixed;
|
|
123
123
|
};
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
const addIcesInAllBundles = (sdp ) => {
|
|
126
|
+
const parsedSdp = sdpParser.parse(sdp);
|
|
127
|
+
|
|
128
|
+
const mediaWithCandidate = parsedSdp.media.find(media => !!media.candidates);
|
|
129
|
+
if (!mediaWithCandidate) {
|
|
130
|
+
return sdp;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const { candidates } = mediaWithCandidate;
|
|
134
|
+
|
|
135
|
+
parsedSdp.media = parsedSdp.media.map(media => ({
|
|
136
|
+
...media,
|
|
137
|
+
candidates: media.candidates || candidates,
|
|
138
|
+
}));
|
|
139
|
+
|
|
140
|
+
return sdpParser.write(parsedSdp);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export { activateVideoModifier, addIcesInAllBundles, areCandidateValid, deactivateVideoModifier, fixBundle, fixSdp, getCandidates, getVideoDirection, hasAnActiveVideo, isSdpValid, parseCandidate, toggleVideoDirection };
|