botium-connector-voip 0.0.5 → 0.0.7
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.
|
@@ -7,6 +7,7 @@ var ws = require('ws');
|
|
|
7
7
|
var lodash = require('lodash');
|
|
8
8
|
var axios = require('axios');
|
|
9
9
|
var debug$1 = require('debug');
|
|
10
|
+
var path = require('path');
|
|
10
11
|
|
|
11
12
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
12
13
|
|
|
@@ -15,6 +16,7 @@ var ws__default = /*#__PURE__*/_interopDefaultLegacy(ws);
|
|
|
15
16
|
var lodash__default = /*#__PURE__*/_interopDefaultLegacy(lodash);
|
|
16
17
|
var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
|
|
17
18
|
var debug__default = /*#__PURE__*/_interopDefaultLegacy(debug$1);
|
|
19
|
+
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
18
20
|
|
|
19
21
|
const {
|
|
20
22
|
v4: uuidv4
|
|
@@ -55,7 +57,13 @@ const Capabilities = {
|
|
|
55
57
|
VOIP_ICE_TURN_SERVER: 'VOIP_ICE_TURN_SERVER',
|
|
56
58
|
VOIP_ICE_TURN_USER: 'VOIP_ICE_TURN_USER',
|
|
57
59
|
VOIP_ICE_TURN_PASSWORD: 'VOIP_ICE_TURN_PASSWORD',
|
|
58
|
-
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'
|
|
59
67
|
};
|
|
60
68
|
const Defaults = {
|
|
61
69
|
VOIP_STT_METHOD: 'POST',
|
|
@@ -63,9 +71,15 @@ const Defaults = {
|
|
|
63
71
|
VOIP_TTS_METHOD: 'GET',
|
|
64
72
|
VOIP_TTS_TIMEOUT: 10000,
|
|
65
73
|
VOIP_STT_MESSAGE_HANDLING: 'ORIGINAL',
|
|
66
|
-
VOIP_STT_MESSAGE_HANDLING_TIMEOUT:
|
|
74
|
+
VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 500,
|
|
67
75
|
VOIP_STT_MESSAGE_HANDLING_DELIMITER: '. ',
|
|
68
|
-
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
|
|
69
83
|
};
|
|
70
84
|
|
|
71
85
|
class BotiumConnectorVoip {
|
|
@@ -128,22 +142,32 @@ class BotiumConnectorVoip {
|
|
|
128
142
|
stepId: null
|
|
129
143
|
}
|
|
130
144
|
};
|
|
145
|
+
this.stopCalled = false;
|
|
131
146
|
this.fullRecord = '';
|
|
132
147
|
this.end = false;
|
|
148
|
+
this.connected = false;
|
|
133
149
|
|
|
134
150
|
const sendBotMsg = botMsg => {
|
|
135
151
|
setTimeout(() => this.queueBotSays(botMsg), 0);
|
|
136
152
|
};
|
|
137
153
|
|
|
138
|
-
const
|
|
139
|
-
if (botMsgs.length === 1) return botMsgs[0];
|
|
154
|
+
const joinBotMsg = (botMsgs, joinLastPrevMsg) => {
|
|
140
155
|
const botMsg = {};
|
|
141
156
|
botMsg.messageText = botMsgs.map(m => m.messageText).join(this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_DELIMITER]);
|
|
142
157
|
botMsg.sourceData = botMsgs.map(m => m.sourceData);
|
|
158
|
+
|
|
159
|
+
if (lodash__default["default"].isNil(joinLastPrevMsg)) {
|
|
160
|
+
botMsg.sourceData[0].silenceDuration = botMsgs[0].sourceData.data.start;
|
|
161
|
+
botMsg.sourceData[0].voiceDuration = botMsgs[botMsgs.length - 1].sourceData.data.end - botMsgs[0].sourceData.data.start;
|
|
162
|
+
} else {
|
|
163
|
+
botMsg.sourceData[0].silenceDuration = botMsgs[0].sourceData.data.start - joinLastPrevMsg.sourceData.data.end;
|
|
164
|
+
botMsg.sourceData[0].voiceDuration = botMsgs[botMsgs.length - 1].sourceData.data.end - botMsgs[0].sourceData.data.start;
|
|
165
|
+
}
|
|
166
|
+
|
|
143
167
|
return botMsg;
|
|
144
168
|
};
|
|
145
169
|
|
|
146
|
-
const
|
|
170
|
+
const splitBotMsgs = botMsgs => {
|
|
147
171
|
const splitSentences = s => s.match(new RegExp(`[^${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+[${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+`, 'g'));
|
|
148
172
|
|
|
149
173
|
const botMsgsFinal = [];
|
|
@@ -154,11 +178,14 @@ class BotiumConnectorVoip {
|
|
|
154
178
|
if (lodash__default["default"].isNil(sentences)) {
|
|
155
179
|
botMsgsFinal.push(botMsg);
|
|
156
180
|
} else {
|
|
181
|
+
let botMsgCount = 0;
|
|
182
|
+
|
|
157
183
|
for (const sentence of sentences) {
|
|
158
184
|
botMsgsFinal.push({
|
|
159
185
|
messageText: sentence,
|
|
160
|
-
sourceData: botMsg.sourceData
|
|
186
|
+
sourceData: botMsgCount === 0 ? botMsg.sourceData : lodash__default["default"].omit(botMsg.sourceData, ['silenceDuration'])
|
|
161
187
|
});
|
|
188
|
+
botMsgCount++;
|
|
162
189
|
}
|
|
163
190
|
}
|
|
164
191
|
}
|
|
@@ -166,24 +193,68 @@ class BotiumConnectorVoip {
|
|
|
166
193
|
return botMsgsFinal;
|
|
167
194
|
};
|
|
168
195
|
|
|
196
|
+
let data = null;
|
|
197
|
+
let headers = null;
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
const res = await axios__default["default"]({
|
|
201
|
+
method: 'post',
|
|
202
|
+
data: {
|
|
203
|
+
API_KEY: this.caps[Capabilities.VOIP_WORKER_APIKEY]
|
|
204
|
+
},
|
|
205
|
+
url: new URL(path__default["default"].join(`${this.caps[Capabilities.VOIP_WORKER_URL].replace('wss', 'https').replace('ws', 'http')}`, 'initCall')).toString()
|
|
206
|
+
});
|
|
207
|
+
data = res.data;
|
|
208
|
+
headers = res.headers;
|
|
209
|
+
} catch (err) {
|
|
210
|
+
return Promise.reject(new Error(`Connecting to VOIP Worker failed: ${err.response.data.message || 'Not reachable'}`));
|
|
211
|
+
}
|
|
212
|
+
|
|
169
213
|
return new Promise((resolve, reject) => {
|
|
170
|
-
|
|
214
|
+
const wsEndpoint = `${this.caps[Capabilities.VOIP_WORKER_URL]}/ws/${data.port}`;
|
|
215
|
+
|
|
216
|
+
const connect = retryIndex => {
|
|
217
|
+
retryIndex = retryIndex || 0;
|
|
218
|
+
return new Promise((resolve, reject) => {
|
|
219
|
+
if ('set-cookie' in headers) {
|
|
220
|
+
this.ws = new ws__default["default"](wsEndpoint, {
|
|
221
|
+
headers: {
|
|
222
|
+
Cookie: headers['set-cookie']
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
} else {
|
|
226
|
+
this.ws = new ws__default["default"](wsEndpoint);
|
|
227
|
+
}
|
|
171
228
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
229
|
+
this.ws.on('open', () => {
|
|
230
|
+
resolve();
|
|
231
|
+
});
|
|
232
|
+
this.ws.on('error', () => {
|
|
233
|
+
if (retryIndex === this.caps[Capabilities.VOIP_WEBSOCKET_CONNECT_MAXRETRIES]) {
|
|
234
|
+
reject(new Error(`Websocket connection failed to ${wsEndpoint}`));
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
setTimeout(() => connect(retryIndex + 1).then(resolve).catch(reject), this.caps[Capabilities.VOIP_WEBSOCKET_CONNECT_TIMEOUT]);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
connect().then(() => {
|
|
243
|
+
if (!lodash__default["default"].isArray(this.caps[Capabilities.VOIP_ICE_STUN_SERVERS])) {
|
|
244
|
+
if (this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] === '') {
|
|
245
|
+
this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = [];
|
|
246
|
+
} else {
|
|
247
|
+
this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = this.caps[Capabilities.VOIP_ICE_STUN_SERVERS].split(',');
|
|
248
|
+
}
|
|
177
249
|
}
|
|
178
|
-
}
|
|
179
250
|
|
|
180
|
-
|
|
181
|
-
|
|
251
|
+
this.silence = null;
|
|
252
|
+
this.msgCount = 0;
|
|
253
|
+
this.firstMsg = true;
|
|
182
254
|
this.wsOpened = true;
|
|
183
|
-
debug(`Websocket connection to ${
|
|
255
|
+
debug(`Websocket connection to ${wsEndpoint} opened.`);
|
|
184
256
|
const request = {
|
|
185
257
|
METHOD: 'initCall',
|
|
186
|
-
API_KEY: this.caps[Capabilities.VOIP_WORKER_APIKEY],
|
|
187
258
|
SIP_CALLER_AUTO: this.caps[Capabilities.VOIP_SIP_POOL_CALLER_ENABLE],
|
|
188
259
|
SIP_PROXY: this.caps[Capabilities.VOIP_SIP_PROXY],
|
|
189
260
|
SIP_CALLER_URI: this.caps[Capabilities.VOIP_SIP_CALLER_URI],
|
|
@@ -200,6 +271,7 @@ class BotiumConnectorVoip {
|
|
|
200
271
|
ICE_TURN_USERNAME: this.caps[Capabilities.VOIP_ICE_TURN_USER],
|
|
201
272
|
ICE_TURN_PASSWORD: this.caps[Capabilities.VOIP_ICE_TURN_PASSWORD],
|
|
202
273
|
ICE_TURN_PROTOCOL: this.caps[Capabilities.VOIP_ICE_TURN_PROTOCOL] || 'TCP',
|
|
274
|
+
MIN_SILENCE_DURATION: this.caps[Capabilities.VOIP_SILENCE_DURATION_TIMEOUT_ENABLE] ? this.caps[Capabilities.VOIP_SILENCE_DURATION_TIMEOUT] : null,
|
|
203
275
|
STT_CONFIG: {
|
|
204
276
|
stt_url: this.caps[Capabilities.VOIP_STT_URL_STREAM],
|
|
205
277
|
stt_params: this.caps[Capabilities.VOIP_STT_PARAMS_STREAM],
|
|
@@ -213,112 +285,162 @@ class BotiumConnectorVoip {
|
|
|
213
285
|
};
|
|
214
286
|
debug(JSON.stringify(request, null, 2));
|
|
215
287
|
this.ws.send(JSON.stringify(request));
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
debug(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} closed.`);
|
|
219
|
-
});
|
|
220
|
-
this.ws.on('error', err => {
|
|
221
|
-
debug(err);
|
|
288
|
+
this.ws.on('error', err => {
|
|
289
|
+
debug(err);
|
|
222
290
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
291
|
+
if (!this.wsOpened) {
|
|
292
|
+
this.end = true;
|
|
293
|
+
reject(new Error(`${this.sessionId} - Websocket connection to ${wsEndpoint} error: ${err.message || err}`));
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
this.ws.on('message', async data => {
|
|
297
|
+
const parsedData = JSON.parse(data);
|
|
230
298
|
|
|
231
|
-
|
|
299
|
+
const parsedDataLog = lodash__default["default"].cloneDeep(parsedData);
|
|
232
300
|
|
|
233
|
-
|
|
234
|
-
|
|
301
|
+
parsedDataLog.fullRecord = '<full_record_buffer>';
|
|
302
|
+
debug(JSON.stringify(parsedDataLog, null, 2));
|
|
235
303
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
304
|
+
if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'initialized') {
|
|
305
|
+
this.sessionId = parsedData.voipConfig.sessionId;
|
|
306
|
+
}
|
|
239
307
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
308
|
+
if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'unauthorized') {
|
|
309
|
+
reject(new Error('Error: Cannot open a call: SIP Authorization failed'));
|
|
310
|
+
}
|
|
243
311
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
312
|
+
if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event === 'onCallRegState') {
|
|
313
|
+
reject(new Error('Error: Sip Registration failed'));
|
|
314
|
+
}
|
|
247
315
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
316
|
+
if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'connected') {
|
|
317
|
+
resolve();
|
|
318
|
+
}
|
|
251
319
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
320
|
+
if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'disconnected') {
|
|
321
|
+
const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_STT_BODY));
|
|
255
322
|
|
|
256
|
-
|
|
257
|
-
|
|
323
|
+
if (parsedData.connectDuration && parsedData.connectDuration > 0) {
|
|
324
|
+
this.eventEmitter.emit('CONSUMPTION_METADATA', this, {
|
|
325
|
+
type: lodash__default["default"].isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',
|
|
326
|
+
metricName: 'consumption.e2e.voip.stt.seconds',
|
|
327
|
+
credits: parsedData.connectDuration,
|
|
328
|
+
apiKey
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
258
332
|
|
|
259
|
-
if (parsedData
|
|
260
|
-
this.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
credits: parsedData.connectDuration,
|
|
264
|
-
apiKey
|
|
265
|
-
});
|
|
333
|
+
if (parsedData && parsedData.type === 'error') {
|
|
334
|
+
this.end = true;
|
|
335
|
+
reject(new Error(`Error: ${parsedData.message}`));
|
|
336
|
+
sendBotMsg(new Error(`Error: ${parsedData.message}`));
|
|
266
337
|
}
|
|
267
|
-
}
|
|
268
338
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
}
|
|
339
|
+
if (parsedData && parsedData.type === 'silence') {
|
|
340
|
+
this.end = true;
|
|
272
341
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
base64: parsedData.fullRecord
|
|
279
|
-
});
|
|
280
|
-
this.Stop();
|
|
281
|
-
}
|
|
342
|
+
if (parsedData.data.silence.length > 0) {
|
|
343
|
+
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`));
|
|
344
|
+
this.Stop();
|
|
345
|
+
}
|
|
346
|
+
}
|
|
282
347
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
348
|
+
if (parsedData && parsedData.type === 'fullRecord') {
|
|
349
|
+
this.eventEmitter.emit('MESSAGE_ATTACHMENT', this.container, {
|
|
350
|
+
name: 'full_record.wav',
|
|
351
|
+
mimeType: 'audio/wav',
|
|
352
|
+
base64: parsedData.fullRecord
|
|
353
|
+
});
|
|
287
354
|
}
|
|
288
|
-
}
|
|
289
355
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
this.botMsgs.push(botMsg);
|
|
356
|
+
if (parsedData && parsedData.data && parsedData.data.final === false) {
|
|
357
|
+
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]) {
|
|
358
|
+
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`));
|
|
359
|
+
this.Stop();
|
|
360
|
+
}
|
|
296
361
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
362
|
+
if (this.prevData) {
|
|
363
|
+
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) {
|
|
364
|
+
if (this.botMsgs.length > 0) {
|
|
365
|
+
sendBotMsg(joinBotMsg(this.botMsgs, this.joinLastPrevMsg));
|
|
366
|
+
this.firstMsg = false;
|
|
367
|
+
this.joinLastPrevMsg = this.botMsgs[this.botMsgs.length - 1];
|
|
368
|
+
this.botMsgs = [];
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
300
372
|
}
|
|
301
373
|
|
|
302
|
-
if (
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
374
|
+
if (parsedData && parsedData.data && parsedData.data.type === 'stt' && parsedData.data.final) {
|
|
375
|
+
if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'ORIGINAL') {
|
|
376
|
+
let botMsg = {
|
|
377
|
+
messageText: parsedData.data.message
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
if (this.firstMsg) {
|
|
381
|
+
const sourceData = parsedData;
|
|
382
|
+
sourceData.silenceDuration = parsedData.data.start;
|
|
383
|
+
sourceData.voiceDuration = parsedData.data.end - parsedData.data.start;
|
|
384
|
+
botMsg = Object.assign({}, botMsg, {
|
|
385
|
+
sourceData
|
|
386
|
+
});
|
|
387
|
+
this.firstMsg = false;
|
|
388
|
+
} else {
|
|
389
|
+
const sourceData = parsedData;
|
|
390
|
+
sourceData.silenceDuration = parsedData.data.start - this.prevData.data.end;
|
|
391
|
+
sourceData.voiceDuration = parsedData.data.end - parsedData.data.start;
|
|
392
|
+
botMsg = Object.assign({}, botMsg, {
|
|
393
|
+
sourceData
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
this.prevData = parsedData;
|
|
398
|
+
this.botMsgs.push(botMsg);
|
|
399
|
+
this.botMsgs.forEach(botMsg => sendBotMsg(botMsg));
|
|
400
|
+
this.botMsgs = [];
|
|
401
|
+
}
|
|
307
402
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
if (this.
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
403
|
+
if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'SPLIT' || this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'EXPAND') {
|
|
404
|
+
let botMsg = {
|
|
405
|
+
messageText: parsedData.data.message
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
if (this.firstMsg) {
|
|
409
|
+
const sourceData = parsedData;
|
|
410
|
+
sourceData.silenceDuration = parsedData.data.start;
|
|
411
|
+
sourceData.voiceDuration = parsedData.data.end - parsedData.data.start;
|
|
412
|
+
botMsg = Object.assign({}, botMsg, {
|
|
413
|
+
sourceData
|
|
414
|
+
});
|
|
415
|
+
this.firstMsg = false;
|
|
416
|
+
} else {
|
|
417
|
+
const sourceData = parsedData;
|
|
418
|
+
sourceData.silenceDuration = parsedData.data.start - this.prevData.data.end;
|
|
419
|
+
sourceData.voiceDuration = parsedData.data.end - parsedData.data.start;
|
|
420
|
+
botMsg = Object.assign({}, botMsg, {
|
|
421
|
+
sourceData
|
|
422
|
+
});
|
|
318
423
|
}
|
|
319
|
-
|
|
424
|
+
|
|
425
|
+
this.prevData = parsedData;
|
|
426
|
+
this.botMsgs.push(botMsg);
|
|
427
|
+
const botMsgsExpanded = splitBotMsgs(this.botMsgs);
|
|
428
|
+
botMsgsExpanded.forEach(botMsg => sendBotMsg(botMsg));
|
|
429
|
+
this.botMsgs = [];
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'JOIN' || this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'CONCAT') {
|
|
433
|
+
const botMsg = {
|
|
434
|
+
messageText: parsedData.data.message,
|
|
435
|
+
sourceData: parsedData
|
|
436
|
+
};
|
|
437
|
+
this.botMsgs.push(botMsg);
|
|
438
|
+
this.prevData = parsedData;
|
|
439
|
+
}
|
|
320
440
|
}
|
|
321
|
-
}
|
|
441
|
+
});
|
|
442
|
+
}).catch(err => {
|
|
443
|
+
reject(new Error('Error: ' + err));
|
|
322
444
|
});
|
|
323
445
|
});
|
|
324
446
|
}
|
|
@@ -394,6 +516,17 @@ class BotiumConnectorVoip {
|
|
|
394
516
|
}
|
|
395
517
|
|
|
396
518
|
if (msg && msg.media && msg.media.length > 0 && msg.media[0].buffer) {
|
|
519
|
+
const request = JSON.stringify({
|
|
520
|
+
METHOD: 'sendAudio',
|
|
521
|
+
sessionId: this.sessionId,
|
|
522
|
+
b64_buffer: msg.media[0].buffer.toString('base64')
|
|
523
|
+
});
|
|
524
|
+
this.ws.send(request);
|
|
525
|
+
msg.attachments.push({
|
|
526
|
+
name: msg.media[0].mediaUri,
|
|
527
|
+
mimeType: msg.media[0].mimeType,
|
|
528
|
+
base64: msg.media[0].buffer.toString('base64')
|
|
529
|
+
});
|
|
397
530
|
const {
|
|
398
531
|
data
|
|
399
532
|
} = await axios__default["default"]({
|
|
@@ -409,19 +542,9 @@ class BotiumConnectorVoip {
|
|
|
409
542
|
|
|
410
543
|
if (data && data.duration) {
|
|
411
544
|
duration = parseInt(data.duration);
|
|
545
|
+
} else {
|
|
546
|
+
reject(new Error('Getting audio duration from Speech Api failed'));
|
|
412
547
|
}
|
|
413
|
-
|
|
414
|
-
const request = JSON.stringify({
|
|
415
|
-
METHOD: 'sendAudio',
|
|
416
|
-
sessionId: this.sessionId,
|
|
417
|
-
b64_buffer: msg.media[0].buffer.toString('base64')
|
|
418
|
-
});
|
|
419
|
-
msg.attachments.push({
|
|
420
|
-
name: msg.media[0].mediaUri,
|
|
421
|
-
mimeType: msg.media[0].mimeType,
|
|
422
|
-
base64: msg.media[0].buffer.toString('base64')
|
|
423
|
-
});
|
|
424
|
-
this.ws.send(request);
|
|
425
548
|
}
|
|
426
549
|
|
|
427
550
|
setTimeout(resolve, duration * 1000);
|
|
@@ -430,28 +553,30 @@ class BotiumConnectorVoip {
|
|
|
430
553
|
}
|
|
431
554
|
|
|
432
555
|
async Stop() {
|
|
433
|
-
debug(
|
|
434
|
-
const request = JSON.stringify({
|
|
435
|
-
METHOD: 'stopCall',
|
|
436
|
-
sessionId: this.sessionId
|
|
437
|
-
});
|
|
438
|
-
this.ws.send(request);
|
|
439
|
-
await new Promise(resolve => {
|
|
440
|
-
setTimeout(resolve, 50000);
|
|
441
|
-
setInterval(() => {
|
|
442
|
-
if (this.end) {
|
|
443
|
-
resolve();
|
|
444
|
-
}
|
|
445
|
-
}, 1000);
|
|
446
|
-
});
|
|
556
|
+
debug(`${this.sessionId} - Stop called`);
|
|
447
557
|
|
|
448
|
-
if (this.ws) {
|
|
449
|
-
|
|
558
|
+
if (this.ws && this.ws.readyState !== ws__default["default"].CLOSED) {
|
|
559
|
+
const request = JSON.stringify({
|
|
560
|
+
METHOD: 'stopCall',
|
|
561
|
+
sessionId: this.sessionId
|
|
562
|
+
});
|
|
563
|
+
this.ws.send(request);
|
|
564
|
+
await new Promise(resolve => {
|
|
565
|
+
setTimeout(resolve, 10000);
|
|
566
|
+
setInterval(() => {
|
|
567
|
+
if (this.end) {
|
|
568
|
+
this.wsOpened = false;
|
|
569
|
+
this.ws = null;
|
|
570
|
+
this.view = {};
|
|
571
|
+
resolve();
|
|
572
|
+
}
|
|
573
|
+
}, 1000);
|
|
574
|
+
});
|
|
575
|
+
} else {
|
|
576
|
+
this.wsOpened = false;
|
|
577
|
+
this.ws = null;
|
|
578
|
+
this.view = {};
|
|
450
579
|
}
|
|
451
|
-
|
|
452
|
-
this.wsOpened = false;
|
|
453
|
-
this.ws = null;
|
|
454
|
-
this.view = {};
|
|
455
580
|
}
|
|
456
581
|
|
|
457
582
|
_getParams(capParams) {
|