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