botium-connector-voip 0.0.6 → 0.0.8
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.
|
@@ -57,7 +57,13 @@ const Capabilities = {
|
|
|
57
57
|
VOIP_ICE_TURN_SERVER: 'VOIP_ICE_TURN_SERVER',
|
|
58
58
|
VOIP_ICE_TURN_USER: 'VOIP_ICE_TURN_USER',
|
|
59
59
|
VOIP_ICE_TURN_PASSWORD: 'VOIP_ICE_TURN_PASSWORD',
|
|
60
|
-
VOIP_ICE_TURN_PROTOCOL: 'VOIP_ICE_TURN_PROTOCOL'
|
|
60
|
+
VOIP_ICE_TURN_PROTOCOL: 'VOIP_ICE_TURN_PROTOCOL',
|
|
61
|
+
VOIP_WEBSOCKET_CONNECT_MAXRETRIES: 'VOIP_WEBSOCKET_CONNECT_MAXRETRIES',
|
|
62
|
+
VOIP_WEBSOCKET_CONNECT_TIMEOUT: 'VOIP_WEBSOCKET_CONNECT_TIMEOUT',
|
|
63
|
+
VOIP_SILENCE_DURATION_TIMEOUT_ENABLE: 'VOIP_SILENCE_DURATION_TIMEOUT_ENABLE',
|
|
64
|
+
VOIP_SILENCE_DURATION_TIMEOUT: 'VOIP_SILENCE_DURATION_TIMEOUT',
|
|
65
|
+
VOIP_SILENCE_DURATION_TIMEOUT_START_ENABLE: 'VOIP_SILENCE_DURATION_TIMEOUT_START_ENABLE',
|
|
66
|
+
VOIP_SILENCE_DURATION_TIMEOUT_START: 'VOIP_SILENCE_DURATION_TIMEOUT_START'
|
|
61
67
|
};
|
|
62
68
|
const Defaults = {
|
|
63
69
|
VOIP_STT_METHOD: 'POST',
|
|
@@ -65,17 +71,25 @@ const Defaults = {
|
|
|
65
71
|
VOIP_TTS_METHOD: 'GET',
|
|
66
72
|
VOIP_TTS_TIMEOUT: 10000,
|
|
67
73
|
VOIP_STT_MESSAGE_HANDLING: 'ORIGINAL',
|
|
68
|
-
VOIP_STT_MESSAGE_HANDLING_TIMEOUT:
|
|
74
|
+
VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 500,
|
|
69
75
|
VOIP_STT_MESSAGE_HANDLING_DELIMITER: '. ',
|
|
70
|
-
VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: '.!?'
|
|
76
|
+
VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: '.!?',
|
|
77
|
+
VOIP_WEBSOCKET_CONNECT_TIMEOUT: 4000,
|
|
78
|
+
VOIP_WEBSOCKET_CONNECT_MAXRETRIES: 20,
|
|
79
|
+
VOIP_SILENCE_DURATION_TIMEOUT: 2500,
|
|
80
|
+
VOIP_SILENCE_DURATION_TIMEOUT_ENABLE: false,
|
|
81
|
+
VOIP_SILENCE_DURATION_TIMEOUT_START: 1000,
|
|
82
|
+
VOIP_SILENCE_DURATION_TIMEOUT_START_ENABLE: false
|
|
71
83
|
};
|
|
72
84
|
|
|
73
85
|
class BotiumConnectorVoip {
|
|
74
86
|
constructor({
|
|
75
87
|
queueBotSays,
|
|
76
88
|
eventEmitter,
|
|
77
|
-
caps
|
|
89
|
+
caps,
|
|
90
|
+
setAsync
|
|
78
91
|
}) {
|
|
92
|
+
setAsync(true);
|
|
79
93
|
this.queueBotSays = queueBotSays;
|
|
80
94
|
this.caps = caps;
|
|
81
95
|
this.eventEmitter = eventEmitter;
|
|
@@ -133,20 +147,29 @@ class BotiumConnectorVoip {
|
|
|
133
147
|
this.stopCalled = false;
|
|
134
148
|
this.fullRecord = '';
|
|
135
149
|
this.end = false;
|
|
150
|
+
this.connected = false;
|
|
136
151
|
|
|
137
152
|
const sendBotMsg = botMsg => {
|
|
138
153
|
setTimeout(() => this.queueBotSays(botMsg), 0);
|
|
139
154
|
};
|
|
140
155
|
|
|
141
|
-
const
|
|
142
|
-
if (botMsgs.length === 1) return botMsgs[0];
|
|
156
|
+
const joinBotMsg = (botMsgs, joinLastPrevMsg) => {
|
|
143
157
|
const botMsg = {};
|
|
144
158
|
botMsg.messageText = botMsgs.map(m => m.messageText).join(this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_DELIMITER]);
|
|
145
159
|
botMsg.sourceData = botMsgs.map(m => m.sourceData);
|
|
160
|
+
|
|
161
|
+
if (lodash__default["default"].isNil(joinLastPrevMsg)) {
|
|
162
|
+
botMsg.sourceData[0].silenceDuration = botMsgs[0].sourceData.data.start;
|
|
163
|
+
botMsg.sourceData[0].voiceDuration = botMsgs[botMsgs.length - 1].sourceData.data.end - botMsgs[0].sourceData.data.start;
|
|
164
|
+
} else {
|
|
165
|
+
botMsg.sourceData[0].silenceDuration = botMsgs[0].sourceData.data.start - joinLastPrevMsg.sourceData.data.end;
|
|
166
|
+
botMsg.sourceData[0].voiceDuration = botMsgs[botMsgs.length - 1].sourceData.data.end - botMsgs[0].sourceData.data.start;
|
|
167
|
+
}
|
|
168
|
+
|
|
146
169
|
return botMsg;
|
|
147
170
|
};
|
|
148
171
|
|
|
149
|
-
const
|
|
172
|
+
const splitBotMsgs = botMsgs => {
|
|
150
173
|
const splitSentences = s => s.match(new RegExp(`[^${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+[${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+`, 'g'));
|
|
151
174
|
|
|
152
175
|
const botMsgsFinal = [];
|
|
@@ -157,11 +180,14 @@ class BotiumConnectorVoip {
|
|
|
157
180
|
if (lodash__default["default"].isNil(sentences)) {
|
|
158
181
|
botMsgsFinal.push(botMsg);
|
|
159
182
|
} else {
|
|
183
|
+
let botMsgCount = 0;
|
|
184
|
+
|
|
160
185
|
for (const sentence of sentences) {
|
|
161
186
|
botMsgsFinal.push({
|
|
162
187
|
messageText: sentence,
|
|
163
|
-
sourceData: botMsg.sourceData
|
|
188
|
+
sourceData: botMsgCount === 0 ? botMsg.sourceData : lodash__default["default"].omit(botMsg.sourceData, ['silenceDuration'])
|
|
164
189
|
});
|
|
190
|
+
botMsgCount++;
|
|
165
191
|
}
|
|
166
192
|
}
|
|
167
193
|
}
|
|
@@ -169,37 +195,76 @@ class BotiumConnectorVoip {
|
|
|
169
195
|
return botMsgsFinal;
|
|
170
196
|
};
|
|
171
197
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
198
|
+
let data = null;
|
|
199
|
+
let headers = null;
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
const res = await axios__default["default"]({
|
|
203
|
+
method: 'post',
|
|
204
|
+
data: {
|
|
205
|
+
API_KEY: this.caps[Capabilities.VOIP_WORKER_APIKEY]
|
|
206
|
+
},
|
|
207
|
+
url: new URL(path__default["default"].join(`${this.caps[Capabilities.VOIP_WORKER_URL].replace('wss', 'https').replace('ws', 'http')}`, 'initCall')).toString()
|
|
208
|
+
});
|
|
209
|
+
data = res.data;
|
|
210
|
+
headers = res.headers;
|
|
211
|
+
} catch (err) {
|
|
212
|
+
return Promise.reject(new Error(`Connecting to VOIP Worker failed: ${err.response.data.message || 'Not reachable'}`));
|
|
213
|
+
}
|
|
214
|
+
|
|
184
215
|
return new Promise((resolve, reject) => {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
216
|
+
const wsEndpoint = `${this.caps[Capabilities.VOIP_WORKER_URL]}/ws/${data.port}`;
|
|
217
|
+
|
|
218
|
+
const connect = retryIndex => {
|
|
219
|
+
retryIndex = retryIndex || 0;
|
|
220
|
+
return new Promise((resolve, reject) => {
|
|
221
|
+
if ('set-cookie' in headers) {
|
|
222
|
+
this.ws = new ws__default["default"](wsEndpoint, {
|
|
223
|
+
headers: {
|
|
224
|
+
Cookie: headers['set-cookie']
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
} else {
|
|
228
|
+
this.ws = new ws__default["default"](wsEndpoint);
|
|
229
|
+
}
|
|
188
230
|
|
|
189
|
-
|
|
231
|
+
this.ws.on('open', () => {
|
|
232
|
+
resolve();
|
|
233
|
+
});
|
|
234
|
+
this.ws.on('error', () => {
|
|
235
|
+
if (retryIndex === this.caps[Capabilities.VOIP_WEBSOCKET_CONNECT_MAXRETRIES]) {
|
|
236
|
+
reject(new Error(`Websocket connection failed to ${wsEndpoint}`));
|
|
237
|
+
}
|
|
190
238
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
239
|
+
setTimeout(() => connect(retryIndex + 1).then(resolve).catch(reject), this.caps[Capabilities.VOIP_WEBSOCKET_CONNECT_TIMEOUT]);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
connect().then(() => {
|
|
245
|
+
this.eventEmitter.on('RETRY_CONVO_ASYNC_RETRIED', () => {
|
|
246
|
+
debug('Retry event received');
|
|
247
|
+
const request = JSON.stringify({
|
|
248
|
+
METHOD: 'stopCall',
|
|
249
|
+
sessionId: this.sessionId
|
|
250
|
+
});
|
|
251
|
+
this.ws.send(request);
|
|
252
|
+
this.ws.close();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
if (!lodash__default["default"].isArray(this.caps[Capabilities.VOIP_ICE_STUN_SERVERS])) {
|
|
256
|
+
if (this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] === '') {
|
|
257
|
+
this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = [];
|
|
258
|
+
} else {
|
|
259
|
+
this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = this.caps[Capabilities.VOIP_ICE_STUN_SERVERS].split(',');
|
|
260
|
+
}
|
|
196
261
|
}
|
|
197
|
-
}
|
|
198
262
|
|
|
199
|
-
|
|
200
|
-
|
|
263
|
+
this.silence = null;
|
|
264
|
+
this.msgCount = 0;
|
|
265
|
+
this.firstMsg = true;
|
|
201
266
|
this.wsOpened = true;
|
|
202
|
-
debug(`Websocket connection to ${
|
|
267
|
+
debug(`Websocket connection to ${wsEndpoint} opened.`);
|
|
203
268
|
const request = {
|
|
204
269
|
METHOD: 'initCall',
|
|
205
270
|
SIP_CALLER_AUTO: this.caps[Capabilities.VOIP_SIP_POOL_CALLER_ENABLE],
|
|
@@ -218,6 +283,7 @@ class BotiumConnectorVoip {
|
|
|
218
283
|
ICE_TURN_USERNAME: this.caps[Capabilities.VOIP_ICE_TURN_USER],
|
|
219
284
|
ICE_TURN_PASSWORD: this.caps[Capabilities.VOIP_ICE_TURN_PASSWORD],
|
|
220
285
|
ICE_TURN_PROTOCOL: this.caps[Capabilities.VOIP_ICE_TURN_PROTOCOL] || 'TCP',
|
|
286
|
+
MIN_SILENCE_DURATION: this.caps[Capabilities.VOIP_SILENCE_DURATION_TIMEOUT_ENABLE] ? this.caps[Capabilities.VOIP_SILENCE_DURATION_TIMEOUT] : null,
|
|
221
287
|
STT_CONFIG: {
|
|
222
288
|
stt_url: this.caps[Capabilities.VOIP_STT_URL_STREAM],
|
|
223
289
|
stt_params: this.caps[Capabilities.VOIP_STT_PARAMS_STREAM],
|
|
@@ -231,110 +297,162 @@ class BotiumConnectorVoip {
|
|
|
231
297
|
};
|
|
232
298
|
debug(JSON.stringify(request, null, 2));
|
|
233
299
|
this.ws.send(JSON.stringify(request));
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
debug(`${this.sessionId} - Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} closed.`);
|
|
237
|
-
});
|
|
238
|
-
this.ws.on('error', err => {
|
|
239
|
-
debug(err);
|
|
300
|
+
this.ws.on('error', err => {
|
|
301
|
+
debug(err);
|
|
240
302
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
303
|
+
if (!this.wsOpened) {
|
|
304
|
+
this.end = true;
|
|
305
|
+
reject(new Error(`${this.sessionId} - Websocket connection to ${wsEndpoint} error: ${err.message || err}`));
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
this.ws.on('message', async data => {
|
|
309
|
+
const parsedData = JSON.parse(data);
|
|
248
310
|
|
|
249
|
-
|
|
311
|
+
const parsedDataLog = lodash__default["default"].cloneDeep(parsedData);
|
|
250
312
|
|
|
251
|
-
|
|
252
|
-
|
|
313
|
+
parsedDataLog.fullRecord = '<full_record_buffer>';
|
|
314
|
+
debug(JSON.stringify(parsedDataLog, null, 2));
|
|
253
315
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
316
|
+
if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'initialized') {
|
|
317
|
+
this.sessionId = parsedData.voipConfig.sessionId;
|
|
318
|
+
}
|
|
257
319
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
320
|
+
if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'unauthorized') {
|
|
321
|
+
reject(new Error('Error: Cannot open a call: SIP Authorization failed'));
|
|
322
|
+
}
|
|
261
323
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
324
|
+
if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event === 'onCallRegState') {
|
|
325
|
+
reject(new Error('Error: Sip Registration failed'));
|
|
326
|
+
}
|
|
265
327
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
328
|
+
if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'connected') {
|
|
329
|
+
resolve();
|
|
330
|
+
}
|
|
269
331
|
|
|
270
|
-
|
|
271
|
-
|
|
332
|
+
if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'disconnected') {
|
|
333
|
+
const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_STT_BODY));
|
|
272
334
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
335
|
+
if (parsedData.connectDuration && parsedData.connectDuration > 0) {
|
|
336
|
+
this.eventEmitter.emit('CONSUMPTION_METADATA', this, {
|
|
337
|
+
type: lodash__default["default"].isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',
|
|
338
|
+
metricName: 'consumption.e2e.voip.stt.seconds',
|
|
339
|
+
credits: parsedData.connectDuration,
|
|
340
|
+
apiKey
|
|
341
|
+
});
|
|
342
|
+
}
|
|
280
343
|
}
|
|
281
|
-
}
|
|
282
344
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
345
|
+
if (parsedData && parsedData.type === 'error') {
|
|
346
|
+
this.end = true;
|
|
347
|
+
reject(new Error(`Error: ${parsedData.message}`));
|
|
348
|
+
sendBotMsg(new Error(`Error: ${parsedData.message}`));
|
|
349
|
+
}
|
|
288
350
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
this.eventEmitter.emit('MESSAGE_ATTACHMENT', this.container, {
|
|
292
|
-
name: 'full_record.wav',
|
|
293
|
-
mimeType: 'audio/wav',
|
|
294
|
-
base64: parsedData.fullRecord
|
|
295
|
-
});
|
|
296
|
-
this.Stop();
|
|
297
|
-
}
|
|
351
|
+
if (parsedData && parsedData.type === 'silence') {
|
|
352
|
+
this.end = true;
|
|
298
353
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
354
|
+
if (parsedData.data.silence.length > 0) {
|
|
355
|
+
sendBotMsg(new Error(`Silence Duration of ${parsedData.data.silence[0][2].toFixed(2)}s exceeded General Silence Duration Timeout of ${this.caps[Capabilities.VOIP_SILENCE_DURATION_TIMEOUT] / 1000}s`));
|
|
356
|
+
this.Stop();
|
|
357
|
+
}
|
|
303
358
|
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
if (parsedData && parsedData.data && parsedData.data.final) {
|
|
307
|
-
const botMsg = {
|
|
308
|
-
messageText: parsedData.data.message,
|
|
309
|
-
sourceData: parsedData
|
|
310
|
-
};
|
|
311
|
-
this.botMsgs.push(botMsg);
|
|
312
359
|
|
|
313
|
-
if (
|
|
314
|
-
this.
|
|
315
|
-
|
|
360
|
+
if (parsedData && parsedData.type === 'fullRecord') {
|
|
361
|
+
this.eventEmitter.emit('MESSAGE_ATTACHMENT', this.container, {
|
|
362
|
+
name: 'full_record.wav',
|
|
363
|
+
mimeType: 'audio/wav',
|
|
364
|
+
base64: parsedData.fullRecord
|
|
365
|
+
});
|
|
316
366
|
}
|
|
317
367
|
|
|
318
|
-
if (
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
368
|
+
if (parsedData && parsedData.data && parsedData.data.final === false) {
|
|
369
|
+
if (this.caps[Capabilities.VOIP_SILENCE_DURATION_TIMEOUT_START_ENABLE] && parsedData.data.start && parsedData.data.start * 1000 > this.caps[Capabilities.VOIP_SILENCE_DURATION_TIMEOUT_START]) {
|
|
370
|
+
sendBotMsg(new Error(`Silence Duration of ${parsedData.data.start}s exceeded Start Silence Duration Timeout of ${this.caps[Capabilities.VOIP_SILENCE_DURATION_TIMEOUT_START] / 1000}s`));
|
|
371
|
+
this.Stop();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (this.prevData) {
|
|
375
|
+
if (!lodash__default["default"].isNil(parsedData.data.start) && parsedData.data.start - this.prevData.data.end > parseInt(this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_TIMEOUT]) / 1000) {
|
|
376
|
+
if (this.botMsgs.length > 0) {
|
|
377
|
+
sendBotMsg(joinBotMsg(this.botMsgs, this.joinLastPrevMsg));
|
|
378
|
+
this.firstMsg = false;
|
|
379
|
+
this.joinLastPrevMsg = this.botMsgs[this.botMsgs.length - 1];
|
|
380
|
+
this.botMsgs = [];
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
322
384
|
}
|
|
323
385
|
|
|
324
|
-
if (
|
|
325
|
-
this.
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
386
|
+
if (parsedData && parsedData.data && parsedData.data.type === 'stt' && parsedData.data.final) {
|
|
387
|
+
if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'ORIGINAL') {
|
|
388
|
+
let botMsg = {
|
|
389
|
+
messageText: parsedData.data.message
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
if (this.firstMsg) {
|
|
393
|
+
const sourceData = parsedData;
|
|
394
|
+
sourceData.silenceDuration = parsedData.data.start;
|
|
395
|
+
sourceData.voiceDuration = parsedData.data.end - parsedData.data.start;
|
|
396
|
+
botMsg = Object.assign({}, botMsg, {
|
|
397
|
+
sourceData
|
|
398
|
+
});
|
|
399
|
+
this.firstMsg = false;
|
|
400
|
+
} else {
|
|
401
|
+
const sourceData = parsedData;
|
|
402
|
+
sourceData.silenceDuration = parsedData.data.start - this.prevData.data.end;
|
|
403
|
+
sourceData.voiceDuration = parsedData.data.end - parsedData.data.start;
|
|
404
|
+
botMsg = Object.assign({}, botMsg, {
|
|
405
|
+
sourceData
|
|
406
|
+
});
|
|
334
407
|
}
|
|
335
|
-
|
|
408
|
+
|
|
409
|
+
this.prevData = parsedData;
|
|
410
|
+
this.botMsgs.push(botMsg);
|
|
411
|
+
this.botMsgs.forEach(botMsg => sendBotMsg(botMsg));
|
|
412
|
+
this.botMsgs = [];
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'SPLIT' || this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'EXPAND') {
|
|
416
|
+
let botMsg = {
|
|
417
|
+
messageText: parsedData.data.message
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
if (this.firstMsg) {
|
|
421
|
+
const sourceData = parsedData;
|
|
422
|
+
sourceData.silenceDuration = parsedData.data.start;
|
|
423
|
+
sourceData.voiceDuration = parsedData.data.end - parsedData.data.start;
|
|
424
|
+
botMsg = Object.assign({}, botMsg, {
|
|
425
|
+
sourceData
|
|
426
|
+
});
|
|
427
|
+
this.firstMsg = false;
|
|
428
|
+
} else {
|
|
429
|
+
const sourceData = parsedData;
|
|
430
|
+
sourceData.silenceDuration = parsedData.data.start - this.prevData.data.end;
|
|
431
|
+
sourceData.voiceDuration = parsedData.data.end - parsedData.data.start;
|
|
432
|
+
botMsg = Object.assign({}, botMsg, {
|
|
433
|
+
sourceData
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
this.prevData = parsedData;
|
|
438
|
+
this.botMsgs.push(botMsg);
|
|
439
|
+
const botMsgsExpanded = splitBotMsgs(this.botMsgs);
|
|
440
|
+
botMsgsExpanded.forEach(botMsg => sendBotMsg(botMsg));
|
|
441
|
+
this.botMsgs = [];
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'JOIN' || this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'CONCAT') {
|
|
445
|
+
const botMsg = {
|
|
446
|
+
messageText: parsedData.data.message,
|
|
447
|
+
sourceData: parsedData
|
|
448
|
+
};
|
|
449
|
+
this.botMsgs.push(botMsg);
|
|
450
|
+
this.prevData = parsedData;
|
|
451
|
+
}
|
|
336
452
|
}
|
|
337
|
-
}
|
|
453
|
+
});
|
|
454
|
+
}).catch(err => {
|
|
455
|
+
reject(new Error('Error: ' + err));
|
|
338
456
|
});
|
|
339
457
|
});
|
|
340
458
|
}
|
|
@@ -447,35 +565,29 @@ class BotiumConnectorVoip {
|
|
|
447
565
|
}
|
|
448
566
|
|
|
449
567
|
async Stop() {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
} */
|
|
474
|
-
} else {
|
|
475
|
-
this.wsOpened = false;
|
|
476
|
-
this.ws = null;
|
|
477
|
-
this.view = {};
|
|
478
|
-
}
|
|
568
|
+
debug(`${this.sessionId} - Stop called`);
|
|
569
|
+
|
|
570
|
+
if (this.ws && this.ws.readyState !== ws__default["default"].CLOSED) {
|
|
571
|
+
const request = JSON.stringify({
|
|
572
|
+
METHOD: 'stopCall',
|
|
573
|
+
sessionId: this.sessionId
|
|
574
|
+
});
|
|
575
|
+
this.ws.send(request);
|
|
576
|
+
await new Promise(resolve => {
|
|
577
|
+
setTimeout(resolve, 10000);
|
|
578
|
+
setInterval(() => {
|
|
579
|
+
if (this.end) {
|
|
580
|
+
this.wsOpened = false;
|
|
581
|
+
this.ws = null;
|
|
582
|
+
this.view = {};
|
|
583
|
+
resolve();
|
|
584
|
+
}
|
|
585
|
+
}, 1000);
|
|
586
|
+
});
|
|
587
|
+
} else {
|
|
588
|
+
this.wsOpened = false;
|
|
589
|
+
this.ws = null;
|
|
590
|
+
this.view = {};
|
|
479
591
|
}
|
|
480
592
|
}
|
|
481
593
|
|