@wazo/sdk 0.37.23 → 0.37.27
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/README.md +95 -57
- package/dist/wazo-sdk.js +3 -3
- package/esm/__tests__/api-client.test.js +12 -7
- package/esm/__tests__/web-rtc-client.test.js +47 -20
- package/esm/api/agentd.js +1 -1
- package/esm/api/amid.js +1 -1
- package/esm/api/application.js +1 -1
- package/esm/api/auth.js +1 -1
- package/esm/api/call-logd.js +1 -1
- package/esm/api/calld.js +1 -1
- package/esm/api/chatd.js +1 -1
- package/esm/api/confd.js +11 -6
- package/esm/api/ctid-ng.js +1 -1
- package/esm/api/dird.js +2 -2
- package/esm/api/webhookd.js +1 -1
- package/esm/api-client.js +12 -7
- package/esm/checker/Checker.js +47 -20
- package/esm/checker/checks/aor.js +12 -7
- package/esm/checker/checks/api.js +12 -7
- package/esm/checker/checks/index.js +47 -20
- package/esm/checker/checks/wazo-websocket.js +1 -1
- package/esm/checker/checks/webrtc-transport.js +47 -20
- package/esm/checker/checks/webrtc.js +47 -20
- package/esm/domain/AdHocAPIConference.js +12 -7
- package/esm/domain/Contact.js +1 -1
- package/esm/domain/Features.js +12 -7
- package/esm/domain/Meeting.js +12 -5
- package/esm/domain/Phone/CTIPhone.js +12 -7
- package/esm/domain/Phone/WebRTCPhone.js +34 -6
- package/esm/domain/__tests__/Contact.test.js +1 -1
- package/esm/domain/__tests__/Meeting.test.js +144 -0
- package/esm/index.js +80 -25
- package/esm/lib/WazoSessionDescriptionHandler.js +9 -4
- package/esm/service/CallApi.js +12 -7
- package/esm/service/IssueReporter.js +1 -1
- package/esm/service/__tests__/IssueReporter.test.js +1 -1
- package/esm/service/getApiClient.js +12 -7
- package/esm/simple/Auth.js +80 -25
- package/esm/simple/Configuration.js +80 -25
- package/esm/simple/Directory.js +12 -7
- package/esm/simple/Phone.js +80 -25
- package/esm/simple/Websocket.js +1 -1
- package/esm/simple/index.js +80 -25
- package/esm/simple/room/LocalParticipant.js +80 -25
- package/esm/simple/room/Participant.js +80 -25
- package/esm/simple/room/RemoteParticipant.js +80 -25
- package/esm/simple/room/Room.js +80 -25
- package/esm/simple/room/SipRoom.js +80 -25
- package/esm/simple/room/Stream.js +80 -25
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +80 -25
- package/esm/simple/utils.js +80 -25
- package/esm/types/WebSocketMessage.js +1 -1
- package/esm/utils/__tests__/api-requester.test.js +1 -1
- package/esm/utils/api-requester.js +1 -1
- package/esm/web-rtc-client.js +47 -20
- package/esm/websocket-client.js +1 -1
- package/lib/__tests__/api-client.test.js +12 -7
- package/lib/__tests__/web-rtc-client.test.js +47 -20
- package/lib/api/agentd.js +1 -1
- package/lib/api/amid.js +1 -1
- package/lib/api/application.js +1 -1
- package/lib/api/auth.js +1 -1
- package/lib/api/call-logd.js +1 -1
- package/lib/api/calld.js +1 -1
- package/lib/api/chatd.js +1 -1
- package/lib/api/confd.js +11 -6
- package/lib/api/ctid-ng.js +1 -1
- package/lib/api/dird.js +2 -2
- package/lib/api/webhookd.js +1 -1
- package/lib/api-client.js +12 -7
- package/lib/checker/Checker.js +47 -20
- package/lib/checker/checks/aor.js +12 -7
- package/lib/checker/checks/api.js +12 -7
- package/lib/checker/checks/index.js +47 -20
- package/lib/checker/checks/wazo-websocket.js +1 -1
- package/lib/checker/checks/webrtc-transport.js +47 -20
- package/lib/checker/checks/webrtc.js +47 -20
- package/lib/domain/AdHocAPIConference.js +12 -7
- package/lib/domain/Contact.js +1 -1
- package/lib/domain/Features.js +12 -7
- package/lib/domain/Meeting.js +16 -5
- package/lib/domain/Phone/CTIPhone.js +12 -7
- package/lib/domain/Phone/WebRTCPhone.js +34 -6
- package/lib/domain/__tests__/Contact.test.js +1 -1
- package/lib/domain/__tests__/Meeting.test.js +150 -0
- package/lib/index.js +80 -25
- package/lib/lib/WazoSessionDescriptionHandler.js +9 -4
- package/lib/service/CallApi.js +12 -7
- package/lib/service/IssueReporter.js +1 -1
- package/lib/service/__tests__/IssueReporter.test.js +1 -1
- package/lib/service/getApiClient.js +12 -7
- package/lib/simple/Auth.js +80 -25
- package/lib/simple/Configuration.js +80 -25
- package/lib/simple/Directory.js +12 -7
- package/lib/simple/Phone.js +80 -25
- package/lib/simple/Websocket.js +1 -1
- package/lib/simple/index.js +80 -25
- package/lib/simple/room/LocalParticipant.js +80 -25
- package/lib/simple/room/Participant.js +80 -25
- package/lib/simple/room/RemoteParticipant.js +80 -25
- package/lib/simple/room/Room.js +80 -25
- package/lib/simple/room/SipRoom.js +80 -25
- package/lib/simple/room/Stream.js +80 -25
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +80 -25
- package/lib/simple/utils.js +80 -25
- package/lib/types/WebSocketMessage.js +2 -0
- package/lib/utils/__tests__/api-requester.test.js +1 -1
- package/lib/utils/api-requester.js +1 -1
- package/lib/web-rtc-client.js +47 -20
- package/lib/websocket-client.js +1 -1
- package/package.json +1 -1
- package/src/domain/Contact.js +1 -1
- package/src/domain/Meeting.js +12 -5
- package/src/domain/Phone/WebRTCPhone.js +33 -5
- package/src/domain/__tests__/Meeting.test.js +50 -0
- package/src/lib/WazoSessionDescriptionHandler.js +8 -3
- package/src/utils/api-requester.js +1 -1
- package/src/web-rtc-client.js +27 -10
package/esm/simple/Directory.js
CHANGED
|
@@ -444,7 +444,7 @@ const logger$1 = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
|
444
444
|
|
|
445
445
|
// Use a function here to be able to mock it in tests
|
|
446
446
|
const realFetch = () => {
|
|
447
|
-
if (typeof document !== 'undefined') {
|
|
447
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
448
448
|
// Browser
|
|
449
449
|
return window.fetch;
|
|
450
450
|
}
|
|
@@ -1904,7 +1904,7 @@ class Contact {
|
|
|
1904
1904
|
this[key] = old[key] || this[key];
|
|
1905
1905
|
});
|
|
1906
1906
|
|
|
1907
|
-
if (old.lineState
|
|
1907
|
+
if (old.lineState) {
|
|
1908
1908
|
this.lineState = old.lineState;
|
|
1909
1909
|
}
|
|
1910
1910
|
|
|
@@ -2611,8 +2611,9 @@ class ExternalApp {
|
|
|
2611
2611
|
|
|
2612
2612
|
|
|
2613
2613
|
|
|
2614
|
-
|
|
2614
|
+
|
|
2615
2615
|
|
|
2616
|
+
|
|
2616
2617
|
|
|
2617
2618
|
|
|
2618
2619
|
class Meeting {
|
|
@@ -2623,9 +2624,10 @@ class Meeting {
|
|
|
2623
2624
|
|
|
2624
2625
|
|
|
2625
2626
|
|
|
2626
|
-
|
|
2627
|
+
|
|
2627
2628
|
|
|
2628
2629
|
|
|
2630
|
+
|
|
2629
2631
|
|
|
2630
2632
|
static parse(plain ) {
|
|
2631
2633
|
return new Meeting({
|
|
@@ -2635,8 +2637,9 @@ class Meeting {
|
|
|
2635
2637
|
ownerUuids: plain.owner_uuids,
|
|
2636
2638
|
port: plain.port,
|
|
2637
2639
|
uuid: plain.uuid,
|
|
2638
|
-
|
|
2640
|
+
extension: plain.exten,
|
|
2639
2641
|
persistent: plain.persistent,
|
|
2642
|
+
creationTime: moment(plain.creation_time).toDate(),
|
|
2640
2643
|
});
|
|
2641
2644
|
}
|
|
2642
2645
|
|
|
@@ -2658,8 +2661,9 @@ class Meeting {
|
|
|
2658
2661
|
ownerUuids,
|
|
2659
2662
|
port,
|
|
2660
2663
|
uri,
|
|
2661
|
-
|
|
2664
|
+
extension,
|
|
2662
2665
|
persistent,
|
|
2666
|
+
creationTime,
|
|
2663
2667
|
} = {}) {
|
|
2664
2668
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2665
2669
|
this.uri = uri;
|
|
@@ -2667,8 +2671,9 @@ class Meeting {
|
|
|
2667
2671
|
this.ownerUuids = ownerUuids;
|
|
2668
2672
|
this.port = port;
|
|
2669
2673
|
this.uuid = uuid;
|
|
2670
|
-
this.
|
|
2674
|
+
this.extension = extension;
|
|
2671
2675
|
this.persistent = persistent;
|
|
2676
|
+
this.creationTime = creationTime;
|
|
2672
2677
|
|
|
2673
2678
|
// Useful to compare instead of instanceof with minified code
|
|
2674
2679
|
this.type = 'Meeting';
|
package/esm/simple/Phone.js
CHANGED
|
@@ -1028,7 +1028,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
|
1028
1028
|
|
|
1029
1029
|
// Use a function here to be able to mock it in tests
|
|
1030
1030
|
const realFetch = () => {
|
|
1031
|
-
if (typeof document !== 'undefined') {
|
|
1031
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
1032
1032
|
// Browser
|
|
1033
1033
|
return window.fetch;
|
|
1034
1034
|
}
|
|
@@ -2477,7 +2477,7 @@ class Contact {
|
|
|
2477
2477
|
this[key] = old[key] || this[key];
|
|
2478
2478
|
});
|
|
2479
2479
|
|
|
2480
|
-
if (old.lineState
|
|
2480
|
+
if (old.lineState) {
|
|
2481
2481
|
this.lineState = old.lineState;
|
|
2482
2482
|
}
|
|
2483
2483
|
|
|
@@ -3184,8 +3184,9 @@ class ExternalApp {
|
|
|
3184
3184
|
|
|
3185
3185
|
|
|
3186
3186
|
|
|
3187
|
-
|
|
3187
|
+
|
|
3188
3188
|
|
|
3189
|
+
|
|
3189
3190
|
|
|
3190
3191
|
|
|
3191
3192
|
class Meeting {
|
|
@@ -3196,9 +3197,10 @@ class Meeting {
|
|
|
3196
3197
|
|
|
3197
3198
|
|
|
3198
3199
|
|
|
3199
|
-
|
|
3200
|
+
|
|
3200
3201
|
|
|
3201
3202
|
|
|
3203
|
+
|
|
3202
3204
|
|
|
3203
3205
|
static parse(plain ) {
|
|
3204
3206
|
return new Meeting({
|
|
@@ -3208,8 +3210,9 @@ class Meeting {
|
|
|
3208
3210
|
ownerUuids: plain.owner_uuids,
|
|
3209
3211
|
port: plain.port,
|
|
3210
3212
|
uuid: plain.uuid,
|
|
3211
|
-
|
|
3213
|
+
extension: plain.exten,
|
|
3212
3214
|
persistent: plain.persistent,
|
|
3215
|
+
creationTime: moment(plain.creation_time).toDate(),
|
|
3213
3216
|
});
|
|
3214
3217
|
}
|
|
3215
3218
|
|
|
@@ -3231,8 +3234,9 @@ class Meeting {
|
|
|
3231
3234
|
ownerUuids,
|
|
3232
3235
|
port,
|
|
3233
3236
|
uri,
|
|
3234
|
-
|
|
3237
|
+
extension,
|
|
3235
3238
|
persistent,
|
|
3239
|
+
creationTime,
|
|
3236
3240
|
} = {}) {
|
|
3237
3241
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
3238
3242
|
this.uri = uri;
|
|
@@ -3240,8 +3244,9 @@ class Meeting {
|
|
|
3240
3244
|
this.ownerUuids = ownerUuids;
|
|
3241
3245
|
this.port = port;
|
|
3242
3246
|
this.uuid = uuid;
|
|
3243
|
-
this.
|
|
3247
|
+
this.extension = extension;
|
|
3244
3248
|
this.persistent = persistent;
|
|
3249
|
+
this.creationTime = creationTime;
|
|
3245
3250
|
|
|
3246
3251
|
// Useful to compare instead of instanceof with minified code
|
|
3247
3252
|
this.type = 'Meeting';
|
|
@@ -5793,11 +5798,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
5793
5798
|
|
|
5794
5799
|
// $FlowFixMe
|
|
5795
5800
|
setRemoteSessionDescription(sessionDescription ) {
|
|
5796
|
-
|
|
5801
|
+
try {
|
|
5802
|
+
const result = super.setRemoteSessionDescription(sessionDescription);
|
|
5797
5803
|
|
|
5798
|
-
|
|
5804
|
+
this.eventEmitter.emit('setDescription', sessionDescription);
|
|
5799
5805
|
|
|
5800
|
-
|
|
5806
|
+
return result;
|
|
5807
|
+
} catch (error) {
|
|
5808
|
+
this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
|
|
5809
|
+
throw error;
|
|
5810
|
+
}
|
|
5801
5811
|
}
|
|
5802
5812
|
|
|
5803
5813
|
// Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
|
|
@@ -6702,7 +6712,7 @@ class WebRTCClient extends Emitter {
|
|
|
6702
6712
|
}
|
|
6703
6713
|
|
|
6704
6714
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
6705
|
-
logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
6715
|
+
logger$9.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
|
|
6706
6716
|
const inviterOptions = {
|
|
6707
6717
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
6708
6718
|
conference,
|
|
@@ -7778,6 +7788,7 @@ class WebRTCClient extends Emitter {
|
|
|
7778
7788
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
7779
7789
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
7780
7790
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
7791
|
+
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
7781
7792
|
|
|
7782
7793
|
logger$9.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
|
|
7783
7794
|
|
|
@@ -7785,7 +7796,8 @@ class WebRTCClient extends Emitter {
|
|
|
7785
7796
|
constraints: {
|
|
7786
7797
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
7787
7798
|
audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
|
|
7788
|
-
video: screenSharing ? (isDesktop
|
|
7799
|
+
video: screenSharing ? (isDesktop
|
|
7800
|
+
? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
|
|
7789
7801
|
: this._getVideoConstraints(enableVideo),
|
|
7790
7802
|
screen: screenSharing,
|
|
7791
7803
|
desktop: isDesktop,
|
|
@@ -8120,12 +8132,14 @@ class WebRTCClient extends Emitter {
|
|
|
8120
8132
|
|
|
8121
8133
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
8122
8134
|
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8135
|
+
if (pc) {
|
|
8136
|
+
pc.oniceconnectionstatechange = () => {
|
|
8137
|
+
logger$9.info('on ice connection state changed', { state: pc.iceConnectionState });
|
|
8138
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
8139
|
+
this.eventEmitter.emit(ON_DISCONNECTED$1);
|
|
8140
|
+
}
|
|
8141
|
+
};
|
|
8142
|
+
}
|
|
8129
8143
|
|
|
8130
8144
|
if (withEvent) {
|
|
8131
8145
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
@@ -8335,13 +8349,17 @@ class WebRTCClient extends Emitter {
|
|
|
8335
8349
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
8336
8350
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
8337
8351
|
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
8352
|
+
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
8338
8353
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
8339
8354
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
8355
|
+
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
8340
8356
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
8341
8357
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
8342
8358
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
8343
|
-
let audioBytesSent = 0;
|
|
8344
|
-
let audioBytesReceived = 0;
|
|
8359
|
+
let audioBytesSent = 0; // content + header
|
|
8360
|
+
let audioBytesReceived = 0; // content + header
|
|
8361
|
+
let audioContentSent = 0; // useful to detect blank call
|
|
8362
|
+
let audioContentReceived = 0;
|
|
8345
8363
|
let videoBytesSent = 0;
|
|
8346
8364
|
let videoBytesReceived = 0;
|
|
8347
8365
|
let transportSent = 0;
|
|
@@ -8351,6 +8369,7 @@ class WebRTCClient extends Emitter {
|
|
|
8351
8369
|
stats.forEach(report => {
|
|
8352
8370
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
8353
8371
|
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
8372
|
+
audioContentSent += Number(report.bytesSent);
|
|
8354
8373
|
}
|
|
8355
8374
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
8356
8375
|
audioBytesSent += Number(report.bytesSent);
|
|
@@ -8362,6 +8381,7 @@ class WebRTCClient extends Emitter {
|
|
|
8362
8381
|
packetsLost += Number(report.packetsLost);
|
|
8363
8382
|
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
8364
8383
|
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
8384
|
+
audioContentReceived += Number(report.bytesReceived);
|
|
8365
8385
|
}
|
|
8366
8386
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
8367
8387
|
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
@@ -8390,10 +8410,17 @@ class WebRTCClient extends Emitter {
|
|
|
8390
8410
|
});
|
|
8391
8411
|
|
|
8392
8412
|
networkStats.packetsLost = packetsLost;
|
|
8413
|
+
|
|
8393
8414
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
8394
8415
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
8395
8416
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
8396
8417
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
8418
|
+
|
|
8419
|
+
networkStats.totalAudioContentSent = audioContentSent;
|
|
8420
|
+
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
8421
|
+
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
8422
|
+
networkStats.audioContentReceived = audioContentReceived;
|
|
8423
|
+
|
|
8397
8424
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
8398
8425
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
8399
8426
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|
|
@@ -8605,6 +8632,7 @@ class WebRTCPhone extends Emitter {
|
|
|
8605
8632
|
constraints,
|
|
8606
8633
|
audioOnly,
|
|
8607
8634
|
conference,
|
|
8635
|
+
iceRestart,
|
|
8608
8636
|
});
|
|
8609
8637
|
|
|
8610
8638
|
if (!sipSession) {
|
|
@@ -8708,6 +8736,11 @@ class WebRTCPhone extends Emitter {
|
|
|
8708
8736
|
|
|
8709
8737
|
this.client.downgradeToAudio(sipSession);
|
|
8710
8738
|
|
|
8739
|
+
if (callSession) {
|
|
8740
|
+
callSession.cameraEnabled = false;
|
|
8741
|
+
this._updateCallSession(callSession);
|
|
8742
|
+
}
|
|
8743
|
+
|
|
8711
8744
|
if (withMessage) {
|
|
8712
8745
|
this._sendReinviteMessage(callSession, false);
|
|
8713
8746
|
}
|
|
@@ -8735,6 +8768,11 @@ class WebRTCPhone extends Emitter {
|
|
|
8735
8768
|
|
|
8736
8769
|
const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
|
|
8737
8770
|
|
|
8771
|
+
if (callSession) {
|
|
8772
|
+
callSession.cameraEnabled = true;
|
|
8773
|
+
this._updateCallSession(callSession);
|
|
8774
|
+
}
|
|
8775
|
+
|
|
8738
8776
|
// If no stream is returned, it means we have to reinvite
|
|
8739
8777
|
if (!newStream) {
|
|
8740
8778
|
return true;
|
|
@@ -9004,7 +9042,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9004
9042
|
}
|
|
9005
9043
|
|
|
9006
9044
|
_onCallAccepted(sipSession , cameraEnabled ) {
|
|
9007
|
-
logger$8.info('WebRTC phone -
|
|
9045
|
+
logger$8.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
|
|
9008
9046
|
|
|
9009
9047
|
const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
|
|
9010
9048
|
this.currentSipSession = sipSession;
|
|
@@ -9073,6 +9111,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9073
9111
|
_onCallTerminated(sipSession ) {
|
|
9074
9112
|
logger$8.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
|
|
9075
9113
|
|
|
9114
|
+
const sipSessionId = this.getSipSessionId(sipSession);
|
|
9076
9115
|
const callSession = this._createCallSession(sipSession);
|
|
9077
9116
|
const isCurrentSession = this.isCurrentCallSipSession(callSession);
|
|
9078
9117
|
const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
|
|
@@ -9090,7 +9129,6 @@ class WebRTCPhone extends Emitter {
|
|
|
9090
9129
|
}, 5);
|
|
9091
9130
|
}
|
|
9092
9131
|
|
|
9093
|
-
const sipSessionId = this.getSipSessionId(sipSession);
|
|
9094
9132
|
if (sipSessionId) {
|
|
9095
9133
|
this.removeIncomingSessions(sipSessionId);
|
|
9096
9134
|
}
|
|
@@ -9516,7 +9554,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9516
9554
|
// @TODO: line is not used here
|
|
9517
9555
|
async makeCall(number , line , cameraEnabled ,
|
|
9518
9556
|
audioOnly = false, conference = false) {
|
|
9519
|
-
logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
|
|
9557
|
+
logger$8.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
|
|
9520
9558
|
if (!number) {
|
|
9521
9559
|
return Promise.resolve(null);
|
|
9522
9560
|
}
|
|
@@ -9735,8 +9773,12 @@ class WebRTCPhone extends Emitter {
|
|
|
9735
9773
|
}
|
|
9736
9774
|
|
|
9737
9775
|
const sessionId = this.incomingSessions[0];
|
|
9776
|
+
const sipSession = this.client.getSipSession(sessionId);
|
|
9777
|
+
if (!sipSession) {
|
|
9778
|
+
return null;
|
|
9779
|
+
}
|
|
9738
9780
|
|
|
9739
|
-
return this._createCallSession(
|
|
9781
|
+
return this._createCallSession(sipSession);
|
|
9740
9782
|
}
|
|
9741
9783
|
|
|
9742
9784
|
sendMessage(sipSession = null, body , contentType = 'text/plain') {
|
|
@@ -9877,9 +9919,13 @@ class WebRTCPhone extends Emitter {
|
|
|
9877
9919
|
if (this.shouldSendReinvite && this.currentSipSession
|
|
9878
9920
|
&& this.currentSipSession.state === SessionState.Established) {
|
|
9879
9921
|
this.shouldSendReinvite = false;
|
|
9922
|
+
const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
|
|
9923
|
+
const isConference = pc ? pc.sfu : false;
|
|
9924
|
+
const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
|
|
9925
|
+
|
|
9880
9926
|
try {
|
|
9881
9927
|
// Send reinvite with iceRestart
|
|
9882
|
-
this.sendReinvite(this.currentCallSession, null,
|
|
9928
|
+
this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
|
|
9883
9929
|
} catch (e) {
|
|
9884
9930
|
logger$8.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
|
|
9885
9931
|
}
|
|
@@ -9963,6 +10009,15 @@ class WebRTCPhone extends Emitter {
|
|
|
9963
10009
|
return this.client.getSipSessionId(sipSession);
|
|
9964
10010
|
}
|
|
9965
10011
|
|
|
10012
|
+
_updateCallSession(callSession ) {
|
|
10013
|
+
const sipSession = this.findSipSession(callSession);
|
|
10014
|
+
const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
|
|
10015
|
+
|
|
10016
|
+
if (sipSessionId) {
|
|
10017
|
+
this.callSessions[sipSessionId] = callSession;
|
|
10018
|
+
}
|
|
10019
|
+
}
|
|
10020
|
+
|
|
9966
10021
|
_onMessage(message ) {
|
|
9967
10022
|
if (!message || message.method !== 'MESSAGE') {
|
|
9968
10023
|
return;
|
package/esm/simple/Websocket.js
CHANGED
|
@@ -39,7 +39,7 @@ IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
|
39
39
|
|
|
40
40
|
// Use a function here to be able to mock it in tests
|
|
41
41
|
const realFetch = () => {
|
|
42
|
-
if (typeof document !== 'undefined') {
|
|
42
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
43
43
|
// Browser
|
|
44
44
|
return window.fetch;
|
|
45
45
|
}
|
package/esm/simple/index.js
CHANGED
|
@@ -1236,7 +1236,7 @@ class Contact {
|
|
|
1236
1236
|
this[key] = old[key] || this[key];
|
|
1237
1237
|
});
|
|
1238
1238
|
|
|
1239
|
-
if (old.lineState
|
|
1239
|
+
if (old.lineState) {
|
|
1240
1240
|
this.lineState = old.lineState;
|
|
1241
1241
|
}
|
|
1242
1242
|
|
|
@@ -1951,7 +1951,7 @@ const logger$c = IssueReporter$1 ? IssueReporter$1.loggerFor('api') : console;
|
|
|
1951
1951
|
|
|
1952
1952
|
// Use a function here to be able to mock it in tests
|
|
1953
1953
|
const realFetch = () => {
|
|
1954
|
-
if (typeof document !== 'undefined') {
|
|
1954
|
+
if (typeof document !== 'undefined' && window.fetch) {
|
|
1955
1955
|
// Browser
|
|
1956
1956
|
return window.fetch;
|
|
1957
1957
|
}
|
|
@@ -2630,8 +2630,9 @@ class ExternalApp {
|
|
|
2630
2630
|
|
|
2631
2631
|
|
|
2632
2632
|
|
|
2633
|
-
|
|
2633
|
+
|
|
2634
2634
|
|
|
2635
|
+
|
|
2635
2636
|
|
|
2636
2637
|
|
|
2637
2638
|
class Meeting {
|
|
@@ -2642,9 +2643,10 @@ class Meeting {
|
|
|
2642
2643
|
|
|
2643
2644
|
|
|
2644
2645
|
|
|
2645
|
-
|
|
2646
|
+
|
|
2646
2647
|
|
|
2647
2648
|
|
|
2649
|
+
|
|
2648
2650
|
|
|
2649
2651
|
static parse(plain ) {
|
|
2650
2652
|
return new Meeting({
|
|
@@ -2654,8 +2656,9 @@ class Meeting {
|
|
|
2654
2656
|
ownerUuids: plain.owner_uuids,
|
|
2655
2657
|
port: plain.port,
|
|
2656
2658
|
uuid: plain.uuid,
|
|
2657
|
-
|
|
2659
|
+
extension: plain.exten,
|
|
2658
2660
|
persistent: plain.persistent,
|
|
2661
|
+
creationTime: moment(plain.creation_time).toDate(),
|
|
2659
2662
|
});
|
|
2660
2663
|
}
|
|
2661
2664
|
|
|
@@ -2677,8 +2680,9 @@ class Meeting {
|
|
|
2677
2680
|
ownerUuids,
|
|
2678
2681
|
port,
|
|
2679
2682
|
uri,
|
|
2680
|
-
|
|
2683
|
+
extension,
|
|
2681
2684
|
persistent,
|
|
2685
|
+
creationTime,
|
|
2682
2686
|
} = {}) {
|
|
2683
2687
|
this.guestSipAuthorization = guestSipAuthorization;
|
|
2684
2688
|
this.uri = uri;
|
|
@@ -2686,8 +2690,9 @@ class Meeting {
|
|
|
2686
2690
|
this.ownerUuids = ownerUuids;
|
|
2687
2691
|
this.port = port;
|
|
2688
2692
|
this.uuid = uuid;
|
|
2689
|
-
this.
|
|
2693
|
+
this.extension = extension;
|
|
2690
2694
|
this.persistent = persistent;
|
|
2695
|
+
this.creationTime = creationTime;
|
|
2691
2696
|
|
|
2692
2697
|
// Useful to compare instead of instanceof with minified code
|
|
2693
2698
|
this.type = 'Meeting';
|
|
@@ -6057,11 +6062,16 @@ class WazoSessionDescriptionHandler extends SessionDescriptionHandler {
|
|
|
6057
6062
|
|
|
6058
6063
|
// $FlowFixMe
|
|
6059
6064
|
setRemoteSessionDescription(sessionDescription ) {
|
|
6060
|
-
|
|
6065
|
+
try {
|
|
6066
|
+
const result = super.setRemoteSessionDescription(sessionDescription);
|
|
6061
6067
|
|
|
6062
|
-
|
|
6068
|
+
this.eventEmitter.emit('setDescription', sessionDescription);
|
|
6063
6069
|
|
|
6064
|
-
|
|
6070
|
+
return result;
|
|
6071
|
+
} catch (error) {
|
|
6072
|
+
this.logger.error('SessionDescriptionHandler.setRemoteSessionDescription error', error);
|
|
6073
|
+
throw error;
|
|
6074
|
+
}
|
|
6065
6075
|
}
|
|
6066
6076
|
|
|
6067
6077
|
// Overridden to avoid to fix ice-candidates missing in the SDP in react-native and chrome canary.
|
|
@@ -6966,7 +6976,7 @@ class WebRTCClient extends Emitter {
|
|
|
6966
6976
|
}
|
|
6967
6977
|
|
|
6968
6978
|
call(number , enableVideo , audioOnly = false, conference = false) {
|
|
6969
|
-
logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly });
|
|
6979
|
+
logger$8.info('sdk webrtc creating call', { number, enableVideo, audioOnly, conference });
|
|
6970
6980
|
const inviterOptions = {
|
|
6971
6981
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
6972
6982
|
conference,
|
|
@@ -8042,6 +8052,7 @@ class WebRTCClient extends Emitter {
|
|
|
8042
8052
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
8043
8053
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
8044
8054
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
8055
|
+
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
8045
8056
|
|
|
8046
8057
|
logger$8.info('Retrieving media a configuration', { enableVideo, screenSharing, isDesktop, withAudio, constraints });
|
|
8047
8058
|
|
|
@@ -8049,7 +8060,8 @@ class WebRTCClient extends Emitter {
|
|
|
8049
8060
|
constraints: {
|
|
8050
8061
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
8051
8062
|
audio: screenSharing ? !isDesktop : (withAudio ? this._getAudioConstraints() : false),
|
|
8052
|
-
video: screenSharing ? (isDesktop
|
|
8063
|
+
video: screenSharing ? (isDesktop
|
|
8064
|
+
? ({ mandatory: { chromeMediaSource: 'desktop', ...(mandatoryVideo || {}) } }) : { cursor: 'always' })
|
|
8053
8065
|
: this._getVideoConstraints(enableVideo),
|
|
8054
8066
|
screen: screenSharing,
|
|
8055
8067
|
desktop: isDesktop,
|
|
@@ -8384,12 +8396,14 @@ class WebRTCClient extends Emitter {
|
|
|
8384
8396
|
|
|
8385
8397
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
8386
8398
|
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8399
|
+
if (pc) {
|
|
8400
|
+
pc.oniceconnectionstatechange = () => {
|
|
8401
|
+
logger$8.info('on ice connection state changed', { state: pc.iceConnectionState });
|
|
8402
|
+
if (pc.iceConnectionState === 'disconnected') {
|
|
8403
|
+
this.eventEmitter.emit(ON_DISCONNECTED$1);
|
|
8404
|
+
}
|
|
8405
|
+
};
|
|
8406
|
+
}
|
|
8393
8407
|
|
|
8394
8408
|
if (withEvent) {
|
|
8395
8409
|
this.eventEmitter.emit(ACCEPTED, session, sessionDialog);
|
|
@@ -8599,13 +8613,17 @@ class WebRTCClient extends Emitter {
|
|
|
8599
8613
|
const nbStats = this.sessionNetworkStats[sessionId].length;
|
|
8600
8614
|
const lastNetworkStats = this.sessionNetworkStats[sessionId][nbStats - 1];
|
|
8601
8615
|
const lastAudioSent = lastNetworkStats ? lastNetworkStats.audioBytesSent : 0;
|
|
8616
|
+
const lastAudioContentSent = lastNetworkStats ? lastNetworkStats.audioContentSent : 0;
|
|
8602
8617
|
const lastVideoSent = lastNetworkStats ? lastNetworkStats.videoBytesSent : 0;
|
|
8603
8618
|
const lastAudioReceived = lastNetworkStats ? lastNetworkStats.audioBytesReceived : 0;
|
|
8619
|
+
const lastAudioContentReceived = lastNetworkStats ? lastNetworkStats.audioContentReceived : 0;
|
|
8604
8620
|
const lastVideoReceived = lastNetworkStats ? lastNetworkStats.videoBytesReceived : 0;
|
|
8605
8621
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
8606
8622
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
8607
|
-
let audioBytesSent = 0;
|
|
8608
|
-
let audioBytesReceived = 0;
|
|
8623
|
+
let audioBytesSent = 0; // content + header
|
|
8624
|
+
let audioBytesReceived = 0; // content + header
|
|
8625
|
+
let audioContentSent = 0; // useful to detect blank call
|
|
8626
|
+
let audioContentReceived = 0;
|
|
8609
8627
|
let videoBytesSent = 0;
|
|
8610
8628
|
let videoBytesReceived = 0;
|
|
8611
8629
|
let transportSent = 0;
|
|
@@ -8615,6 +8633,7 @@ class WebRTCClient extends Emitter {
|
|
|
8615
8633
|
stats.forEach(report => {
|
|
8616
8634
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
8617
8635
|
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
8636
|
+
audioContentSent += Number(report.bytesSent);
|
|
8618
8637
|
}
|
|
8619
8638
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
8620
8639
|
audioBytesSent += Number(report.bytesSent);
|
|
@@ -8626,6 +8645,7 @@ class WebRTCClient extends Emitter {
|
|
|
8626
8645
|
packetsLost += Number(report.packetsLost);
|
|
8627
8646
|
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
8628
8647
|
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
8648
|
+
audioContentReceived += Number(report.bytesReceived);
|
|
8629
8649
|
}
|
|
8630
8650
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
8631
8651
|
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
@@ -8654,10 +8674,17 @@ class WebRTCClient extends Emitter {
|
|
|
8654
8674
|
});
|
|
8655
8675
|
|
|
8656
8676
|
networkStats.packetsLost = packetsLost;
|
|
8677
|
+
|
|
8657
8678
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
8658
8679
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
8659
8680
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
8660
8681
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
8682
|
+
|
|
8683
|
+
networkStats.totalAudioContentSent = audioContentSent;
|
|
8684
|
+
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
8685
|
+
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
8686
|
+
networkStats.audioContentReceived = audioContentReceived;
|
|
8687
|
+
|
|
8661
8688
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
8662
8689
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
8663
8690
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|
|
@@ -8869,6 +8896,7 @@ class WebRTCPhone extends Emitter {
|
|
|
8869
8896
|
constraints,
|
|
8870
8897
|
audioOnly,
|
|
8871
8898
|
conference,
|
|
8899
|
+
iceRestart,
|
|
8872
8900
|
});
|
|
8873
8901
|
|
|
8874
8902
|
if (!sipSession) {
|
|
@@ -8972,6 +9000,11 @@ class WebRTCPhone extends Emitter {
|
|
|
8972
9000
|
|
|
8973
9001
|
this.client.downgradeToAudio(sipSession);
|
|
8974
9002
|
|
|
9003
|
+
if (callSession) {
|
|
9004
|
+
callSession.cameraEnabled = false;
|
|
9005
|
+
this._updateCallSession(callSession);
|
|
9006
|
+
}
|
|
9007
|
+
|
|
8975
9008
|
if (withMessage) {
|
|
8976
9009
|
this._sendReinviteMessage(callSession, false);
|
|
8977
9010
|
}
|
|
@@ -8999,6 +9032,11 @@ class WebRTCPhone extends Emitter {
|
|
|
8999
9032
|
|
|
9000
9033
|
const newStream = await this.client.upgradeToVideo(sipSession, constraints, isConference);
|
|
9001
9034
|
|
|
9035
|
+
if (callSession) {
|
|
9036
|
+
callSession.cameraEnabled = true;
|
|
9037
|
+
this._updateCallSession(callSession);
|
|
9038
|
+
}
|
|
9039
|
+
|
|
9002
9040
|
// If no stream is returned, it means we have to reinvite
|
|
9003
9041
|
if (!newStream) {
|
|
9004
9042
|
return true;
|
|
@@ -9268,7 +9306,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9268
9306
|
}
|
|
9269
9307
|
|
|
9270
9308
|
_onCallAccepted(sipSession , cameraEnabled ) {
|
|
9271
|
-
logger$7.info('WebRTC phone -
|
|
9309
|
+
logger$7.info('WebRTC phone - on call accepted', { sipId: sipSession.id, cameraEnabled });
|
|
9272
9310
|
|
|
9273
9311
|
const callSession = this._createAcceptedCallSession(sipSession, cameraEnabled);
|
|
9274
9312
|
this.currentSipSession = sipSession;
|
|
@@ -9337,6 +9375,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9337
9375
|
_onCallTerminated(sipSession ) {
|
|
9338
9376
|
logger$7.info('WebRTC phone - on call terminated', { sipId: sipSession.id });
|
|
9339
9377
|
|
|
9378
|
+
const sipSessionId = this.getSipSessionId(sipSession);
|
|
9340
9379
|
const callSession = this._createCallSession(sipSession);
|
|
9341
9380
|
const isCurrentSession = this.isCurrentCallSipSession(callSession);
|
|
9342
9381
|
const isCurrentIncomingCall = callSession.is(this.getIncomingCallSession());
|
|
@@ -9354,7 +9393,6 @@ class WebRTCPhone extends Emitter {
|
|
|
9354
9393
|
}, 5);
|
|
9355
9394
|
}
|
|
9356
9395
|
|
|
9357
|
-
const sipSessionId = this.getSipSessionId(sipSession);
|
|
9358
9396
|
if (sipSessionId) {
|
|
9359
9397
|
this.removeIncomingSessions(sipSessionId);
|
|
9360
9398
|
}
|
|
@@ -9780,7 +9818,7 @@ class WebRTCPhone extends Emitter {
|
|
|
9780
9818
|
// @TODO: line is not used here
|
|
9781
9819
|
async makeCall(number , line , cameraEnabled ,
|
|
9782
9820
|
audioOnly = false, conference = false) {
|
|
9783
|
-
logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled });
|
|
9821
|
+
logger$7.info('make WebRTC call', { number, lineId: line ? line.id : null, cameraEnabled, audioOnly, conference });
|
|
9784
9822
|
if (!number) {
|
|
9785
9823
|
return Promise.resolve(null);
|
|
9786
9824
|
}
|
|
@@ -9999,8 +10037,12 @@ class WebRTCPhone extends Emitter {
|
|
|
9999
10037
|
}
|
|
10000
10038
|
|
|
10001
10039
|
const sessionId = this.incomingSessions[0];
|
|
10040
|
+
const sipSession = this.client.getSipSession(sessionId);
|
|
10041
|
+
if (!sipSession) {
|
|
10042
|
+
return null;
|
|
10043
|
+
}
|
|
10002
10044
|
|
|
10003
|
-
return this._createCallSession(
|
|
10045
|
+
return this._createCallSession(sipSession);
|
|
10004
10046
|
}
|
|
10005
10047
|
|
|
10006
10048
|
sendMessage(sipSession = null, body , contentType = 'text/plain') {
|
|
@@ -10141,9 +10183,13 @@ class WebRTCPhone extends Emitter {
|
|
|
10141
10183
|
if (this.shouldSendReinvite && this.currentSipSession
|
|
10142
10184
|
&& this.currentSipSession.state === SessionState.Established) {
|
|
10143
10185
|
this.shouldSendReinvite = false;
|
|
10186
|
+
const pc = this.currentSipSession.sessionDescriptionHandler.peerConnection;
|
|
10187
|
+
const isConference = pc ? pc.sfu : false;
|
|
10188
|
+
const hasVideo = this.currentCallSession && this.currentCallSession.cameraEnabled;
|
|
10189
|
+
|
|
10144
10190
|
try {
|
|
10145
10191
|
// Send reinvite with iceRestart
|
|
10146
|
-
this.sendReinvite(this.currentCallSession, null,
|
|
10192
|
+
this.sendReinvite(this.currentCallSession, null, isConference, !hasVideo, true);
|
|
10147
10193
|
} catch (e) {
|
|
10148
10194
|
logger$7.error('WebRTC reinvite after register, error', { message: e.message, stack: e.stack });
|
|
10149
10195
|
}
|
|
@@ -10227,6 +10273,15 @@ class WebRTCPhone extends Emitter {
|
|
|
10227
10273
|
return this.client.getSipSessionId(sipSession);
|
|
10228
10274
|
}
|
|
10229
10275
|
|
|
10276
|
+
_updateCallSession(callSession ) {
|
|
10277
|
+
const sipSession = this.findSipSession(callSession);
|
|
10278
|
+
const sipSessionId = sipSession ? this.getSipSessionId(sipSession) : null;
|
|
10279
|
+
|
|
10280
|
+
if (sipSessionId) {
|
|
10281
|
+
this.callSessions[sipSessionId] = callSession;
|
|
10282
|
+
}
|
|
10283
|
+
}
|
|
10284
|
+
|
|
10230
10285
|
_onMessage(message ) {
|
|
10231
10286
|
if (!message || message.method !== 'MESSAGE') {
|
|
10232
10287
|
return;
|