botium-connector-voip 0.0.3 → 0.0.5

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.
@@ -25,8 +25,13 @@ const Capabilities = {
25
25
  VOIP_STT_PARAMS_STREAM: 'VOIP_STT_PARAMS_STREAM',
26
26
  VOIP_STT_METHOD_STREAM: 'VOIP_STT_METHOD_STREAM',
27
27
  VOIP_STT_BODY_STREAM: 'VOIP_STT_BODY_STREAM',
28
+ VOIP_STT_BODY: 'VOIP_STT_BODY',
28
29
  VOIP_STT_HEADERS: 'VOIP_STT_HEADERS',
29
30
  VOIP_STT_TIMEOUT: 'VOIP_STT_TIMEOUT',
31
+ VOIP_STT_MESSAGE_HANDLING: 'VOIP_STT_MESSAGE_HANDLING',
32
+ VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 'VOIP_STT_MESSAGE_HANDLING_TIMEOUT',
33
+ VOIP_STT_MESSAGE_HANDLING_DELIMITER: 'VOIP_STT_MESSAGE_HANDLING_DELIMITER',
34
+ VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: 'VOIP_STT_MESSAGE_HANDLING_PUNCTUATION',
30
35
  VOIP_TTS_URL: 'VOIP_TTS_URL',
31
36
  VOIP_TTS_PARAMS: 'VOIP_TTS_PARAMS',
32
37
  VOIP_TTS_METHOD: 'VOIP_TTS_METHOD',
@@ -56,7 +61,11 @@ const Defaults = {
56
61
  VOIP_STT_METHOD: 'POST',
57
62
  VOIP_STT_TIMEOUT: 10000,
58
63
  VOIP_TTS_METHOD: 'GET',
59
- VOIP_TTS_TIMEOUT: 10000
64
+ VOIP_TTS_TIMEOUT: 10000,
65
+ VOIP_STT_MESSAGE_HANDLING: 'ORIGINAL',
66
+ VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 5000,
67
+ VOIP_STT_MESSAGE_HANDLING_DELIMITER: '. ',
68
+ VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: '.!?'
60
69
  };
61
70
 
62
71
  class BotiumConnectorVoip {
@@ -68,10 +77,15 @@ class BotiumConnectorVoip {
68
77
  this.queueBotSays = queueBotSays;
69
78
  this.caps = caps;
70
79
  this.eventEmitter = eventEmitter;
80
+ this.botMsgs = [];
81
+ this.sentencesBuilding = 0;
82
+ this.sentencesFinal = 0;
83
+ this.sentenceBuilding = false;
71
84
  }
72
85
 
73
86
  async Validate() {
74
87
  debug('Validate called');
88
+ debug(this.caps.VOIP_STT_MESSAGE_HANDLING);
75
89
 
76
90
  if (this.caps.VOIP_TTS_URL) {
77
91
  this.axiosTtsParams = {
@@ -116,6 +130,42 @@ class BotiumConnectorVoip {
116
130
  };
117
131
  this.fullRecord = '';
118
132
  this.end = false;
133
+
134
+ const sendBotMsg = botMsg => {
135
+ setTimeout(() => this.queueBotSays(botMsg), 0);
136
+ };
137
+
138
+ const buildBotMsg = botMsgs => {
139
+ if (botMsgs.length === 1) return botMsgs[0];
140
+ const botMsg = {};
141
+ botMsg.messageText = botMsgs.map(m => m.messageText).join(this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_DELIMITER]);
142
+ botMsg.sourceData = botMsgs.map(m => m.sourceData);
143
+ return botMsg;
144
+ };
145
+
146
+ const expandBotMsgs = botMsgs => {
147
+ 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
+
149
+ const botMsgsFinal = [];
150
+
151
+ for (const botMsg of botMsgs) {
152
+ const sentences = splitSentences(botMsg.messageText);
153
+
154
+ if (lodash__default["default"].isNil(sentences)) {
155
+ botMsgsFinal.push(botMsg);
156
+ } else {
157
+ for (const sentence of sentences) {
158
+ botMsgsFinal.push({
159
+ messageText: sentence,
160
+ sourceData: botMsg.sourceData
161
+ });
162
+ }
163
+ }
164
+ }
165
+
166
+ return botMsgsFinal;
167
+ };
168
+
119
169
  return new Promise((resolve, reject) => {
120
170
  this.ws = new ws__default["default"](this.caps[Capabilities.VOIP_WORKER_URL]);
121
171
 
@@ -161,7 +211,7 @@ class BotiumConnectorVoip {
161
211
  tts_body: this.caps[Capabilities.VOIP_TTS_BODY] || null
162
212
  }
163
213
  };
164
- debug(request);
214
+ debug(JSON.stringify(request, null, 2));
165
215
  this.ws.send(JSON.stringify(request));
166
216
  });
167
217
  this.ws.on('close', async () => {
@@ -171,37 +221,53 @@ class BotiumConnectorVoip {
171
221
  debug(err);
172
222
 
173
223
  if (!this.wsOpened) {
224
+ this.end = true;
174
225
  reject(new Error(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} error: ${err.message || err}`));
175
226
  }
176
227
  });
177
228
  this.ws.on('message', async data => {
178
229
  const parsedData = JSON.parse(data);
179
- const botMsgs = [];
180
- debug(parsedData);
230
+
231
+ const parsedDataLog = lodash__default["default"].cloneDeep(parsedData);
232
+
233
+ parsedDataLog.fullRecord = '<full_record_buffer>';
234
+ debug(JSON.stringify(parsedDataLog, null, 2));
181
235
 
182
236
  if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'initialized') {
183
237
  this.sessionId = parsedData.voipConfig.sessionId;
184
238
  }
185
239
 
186
240
  if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'unauthorized') {
187
- reject(new Error('Cannot open a call: SIP Authorization failed'));
241
+ reject(new Error('Error: Cannot open a call: SIP Authorization failed'));
188
242
  }
189
243
 
190
- if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden') {
191
- reject(new Error('Cannot connect to VOIP Worker because of wrong API key'));
244
+ if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event !== 'onCallRegState') {
245
+ reject(new Error('Error: Cannot connect to VOIP Worker because of wrong API key'));
192
246
  }
193
247
 
194
- if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden') {
195
- debug('error');
196
- reject(new Error('Cannot connect to VOIP Worker because of wrong API key'));
248
+ if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event === 'onCallRegState') {
249
+ reject(new Error('Error: Sip Registration failed'));
197
250
  }
198
251
 
199
252
  if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'connected') {
200
253
  resolve();
201
254
  }
202
255
 
256
+ if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'disconnected') {
257
+ const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_STT_BODY));
258
+
259
+ if (parsedData.connectDuration && parsedData.connectDuration > 0) {
260
+ this.eventEmitter.emit('CONSUMPTION_METADATA', this.container, {
261
+ type: lodash__default["default"].isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',
262
+ metricName: 'consumption.e2e.voip.stt.seconds',
263
+ credits: parsedData.connectDuration,
264
+ apiKey
265
+ });
266
+ }
267
+ }
268
+
203
269
  if (parsedData && parsedData.type === 'error') {
204
- reject(new Error(parsedData.message));
270
+ reject(new Error(`Error: ${parsedData.message}`));
205
271
  }
206
272
 
207
273
  if (parsedData && parsedData.type === 'fullRecord') {
@@ -214,15 +280,45 @@ class BotiumConnectorVoip {
214
280
  this.Stop();
215
281
  }
216
282
 
283
+ if (parsedData && parsedData.data && parsedData.data.final === false) {
284
+ if (!this.sentenceBuilding) {
285
+ this.sentenceBuilding = true;
286
+ this.sentencesBuilding++;
287
+ }
288
+ }
289
+
217
290
  if (parsedData && parsedData.data && parsedData.data.final) {
218
291
  const botMsg = {
219
292
  messageText: parsedData.data.message,
220
293
  sourceData: parsedData
221
294
  };
222
- botMsgs.push(botMsg);
223
- }
295
+ this.botMsgs.push(botMsg);
296
+
297
+ if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'ORIGINAL') {
298
+ this.botMsgs.forEach(botMsg => sendBotMsg(botMsg));
299
+ this.botMsgs = [];
300
+ }
224
301
 
225
- botMsgs.forEach(botMsg => setTimeout(() => this.queueBotSays(botMsg), 0));
302
+ if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'EXPAND') {
303
+ const botMsgsExpanded = expandBotMsgs(this.botMsgs);
304
+ botMsgsExpanded.forEach(botMsg => sendBotMsg(botMsg));
305
+ this.botMsgs = [];
306
+ }
307
+
308
+ if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'CONCAT') {
309
+ this.sentenceBuilding = false;
310
+ this.sentencesFinal++;
311
+ clearTimeout(this.sendMessageTimeout);
312
+ this.sendMessageTimeout = setTimeout(() => {
313
+ if (this.sentenceBuilding === false && this.sentencesBuilding === this.sentencesFinal) {
314
+ sendBotMsg(buildBotMsg(this.botMsgs));
315
+ this.botMsgs = [];
316
+ this.sentencesBuilding = 0;
317
+ this.sentencesFinal = 0;
318
+ }
319
+ }, this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_TIMEOUT]);
320
+ }
321
+ }
226
322
  });
227
323
  });
228
324
  }
@@ -237,6 +333,8 @@ class BotiumConnectorVoip {
237
333
 
238
334
  return new Promise((resolve, reject) => {
239
335
  setTimeout(async () => {
336
+ let duration = 0;
337
+
240
338
  if (msg && msg.buttons && msg.buttons.length > 0) {
241
339
  const request = JSON.stringify({
242
340
  METHOD: 'sendDtmf',
@@ -252,7 +350,7 @@ class BotiumConnectorVoip {
252
350
  params: { ...(this.axiosTtsParams.params || {}),
253
351
  text: msg.messageText
254
352
  },
255
- data: this._getBody(Capabilities.BSP_TTS_BODY),
353
+ data: this._getBody(Capabilities.VOIP_TTS_BODY),
256
354
  responseType: 'arraybuffer'
257
355
  };
258
356
  msg.sourceData = ttsRequest;
@@ -264,7 +362,19 @@ class BotiumConnectorVoip {
264
362
  reject(new Error(`TTS "${msg.messageText}" failed - ${this._getAxiosErrOutput(err)}`));
265
363
  }
266
364
 
365
+ if (msg && msg.messageText && msg.messageText.length > 0) {
366
+ const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_TTS_BODY));
367
+
368
+ this.eventEmitter.emit('CONSUMPTION_METADATA', this.container, {
369
+ type: lodash__default["default"].isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',
370
+ metricName: 'consumption.e2e.voip.tts.characters',
371
+ credits: msg.messageText.length,
372
+ apiKey
373
+ });
374
+ }
375
+
267
376
  if (Buffer.isBuffer(ttsResponse.data)) {
377
+ duration = ttsResponse.headers['content-duration'];
268
378
  const request = JSON.stringify({
269
379
  METHOD: 'sendAudio',
270
380
  PESQ: false,
@@ -284,6 +394,23 @@ class BotiumConnectorVoip {
284
394
  }
285
395
 
286
396
  if (msg && msg.media && msg.media.length > 0 && msg.media[0].buffer) {
397
+ const {
398
+ data
399
+ } = await axios__default["default"]({
400
+ method: 'post',
401
+ data: msg.media[0].buffer,
402
+ headers: { ...this._getHeaders(Capabilities.VOIP_TTS_HEADERS),
403
+ 'Content-Type': 'audio/wave'
404
+ },
405
+ url: this._getAxiosUrl(this.caps.VOIP_TTS_URL, '/api/audio/info'),
406
+ maxContentLength: Infinity,
407
+ maxBodyLength: Infinity
408
+ });
409
+
410
+ if (data && data.duration) {
411
+ duration = parseInt(data.duration);
412
+ }
413
+
287
414
  const request = JSON.stringify({
288
415
  METHOD: 'sendAudio',
289
416
  sessionId: this.sessionId,
@@ -297,8 +424,8 @@ class BotiumConnectorVoip {
297
424
  this.ws.send(request);
298
425
  }
299
426
 
300
- resolve();
301
- }, 500);
427
+ setTimeout(resolve, duration * 1000);
428
+ }, 0);
302
429
  });
303
430
  }
304
431
 
@@ -379,6 +506,10 @@ class BotiumConnectorVoip {
379
506
  }
380
507
  }
381
508
 
509
+ _extractApiKey(body) {
510
+ return lodash__default["default"].get(body, 'polly.credentials.accessKeyId') || lodash__default["default"].get(body, 'google.credentials.client_email') || lodash__default["default"].get(body, 'ibm.credentials.apikey') || lodash__default["default"].get(body, 'awstranscribe.credentials.accessKeyId') || lodash__default["default"].get(body, 'azure.credentials.subscriptionKey') || null;
511
+ }
512
+
382
513
  }
383
514
 
384
515
  var connector = BotiumConnectorVoip;
@@ -390,7 +521,8 @@ var botiumConnectorVoip = {
390
521
  name: 'Voice over IP',
391
522
  provider: 'Botium',
392
523
  features: {
393
- audioInput: true
524
+ audioInput: true,
525
+ e2eTesting: true
394
526
  },
395
527
  capabilities: [{
396
528
  name: 'VOIP_STT',
@@ -1 +1 @@
1
- {"version":3,"file":"botium-connector-voip-cjs.js","sources":["../src/connector.js","../index.js"],"sourcesContent":["const { v4: uuidv4 } = require('uuid')\nconst WebSocket = require('ws')\nconst _ = require('lodash')\nconst axios = require('axios')\nconst debug = require('debug')('botium-connector-voip')\n\nconst Capabilities = {\n VOIP_STT_URL_STREAM: 'VOIP_STT_URL_STREAM',\n VOIP_STT_PARAMS_STREAM: 'VOIP_STT_PARAMS_STREAM',\n VOIP_STT_METHOD_STREAM: 'VOIP_STT_METHOD_STREAM',\n VOIP_STT_BODY_STREAM: 'VOIP_STT_BODY_STREAM',\n VOIP_STT_HEADERS: 'VOIP_STT_HEADERS',\n VOIP_STT_TIMEOUT: 'VOIP_STT_TIMEOUT',\n VOIP_TTS_URL: 'VOIP_TTS_URL',\n VOIP_TTS_PARAMS: 'VOIP_TTS_PARAMS',\n VOIP_TTS_METHOD: 'VOIP_TTS_METHOD',\n VOIP_TTS_BODY: 'VOIP_TTS_BODY',\n VOIP_TTS_HEADERS: 'VOIP_TTS_HEADERS',\n VOIP_TTS_TIMEOUT: 'VOIP_TTS_TIMEOUT',\n VOIP_WORKER_URL: 'VOIP_WORKER_URL',\n VOIP_WORKER_APIKEY: 'VOIP_WORKER_APIKEY',\n VOIP_SIP_POOL_CALLER_ENABLE: 'VOIP_SIP_POOL_CALLER_ENABLE',\n VOIP_SIP_CALLER_REGISTRAR_URI: 'VOIP_SIP_CALLER_REGISTRAR_URI',\n VOIP_SIP_CALLER_ADDRESS: 'VOIP_SIP_CALLER_ADDRESS',\n VOIP_SIP_CALLER_USERNAME: 'VOIP_SIP_CALLER_USERNAME',\n VOIP_SIP_CALLER_PASSWORD: 'VOIP_SIP_CALLER_PASSWORD',\n VOIP_SIP_PROXY: 'VOIP_SIP_PROXY',\n VOIP_SIP_REG_HEADERS: 'VOIP_SIP_REG_HEADERS',\n VOIP_SIP_INVITE_HEADERS: 'VOIP_SIP_INVITE_HEADERS',\n VOIP_SIP_CALLEE_URI: 'VOIP_SIP_CALLEE_URI',\n VOIP_ICE_ENABLE: 'VOIP_ICE_ENABLE',\n VOIP_ICE_STUN_SERVERS: 'VOIP_ICE_STUN_SERVERS',\n VOIP_ICE_TURN_ENABLE: 'VOIP_ICE_TURN_ENABLE',\n VOIP_ICE_TURN_SERVER: 'VOIP_ICE_TURN_SERVER',\n VOIP_ICE_TURN_USER: 'VOIP_ICE_TURN_USER',\n VOIP_ICE_TURN_PASSWORD: 'VOIP_ICE_TURN_PASSWORD',\n VOIP_ICE_TURN_PROTOCOL: 'VOIP_ICE_TURN_PROTOCOL'\n}\n\nconst Defaults = {\n VOIP_STT_METHOD: 'POST',\n VOIP_STT_TIMEOUT: 10000,\n VOIP_TTS_METHOD: 'GET',\n VOIP_TTS_TIMEOUT: 10000\n}\n\nclass BotiumConnectorVoip {\n constructor ({ queueBotSays, eventEmitter, caps }) {\n this.queueBotSays = queueBotSays\n this.caps = caps\n this.eventEmitter = eventEmitter\n }\n\n async Validate () {\n debug('Validate called')\n\n if (this.caps.VOIP_TTS_URL) {\n this.axiosTtsParams = {\n url: this.caps.VOIP_TTS_URL,\n params: this._getParams(Capabilities.VOIP_TTS_PARAMS),\n method: this.caps.VOIP_TTS_METHOD,\n timeout: this.caps.VOIP_TTS_TIMEOUT,\n headers: this._getHeaders(Capabilities.VOIP_TTS_HEADERS)\n }\n try {\n const { data } = await axios({\n ...this.axiosTtsParams,\n url: this._getAxiosUrl(this.caps.VOIP_TTS_URL, '/api/status')\n })\n if (data && data.status === 'OK') {\n debug(`Checking TTS Status response: ${this._getAxiosShortenedOutput(data)}`)\n } else {\n throw new Error(`Checking TTS Status failed, response is: ${this._getAxiosShortenedOutput(data)}`)\n }\n } catch (err) {\n throw new Error(`Checking TTS Status failed - ${this._getAxiosErrOutput(err)}`)\n }\n }\n\n this.caps = Object.assign({}, Defaults, this.caps)\n }\n\n async Start () {\n debug('Start called')\n debug(this.caps[Capabilities.VOIP_TTS_URL])\n\n this.view = {\n container: this,\n context: {},\n msg: {},\n botium: {\n conversationId: uuidv4(),\n stepId: null\n }\n }\n\n this.fullRecord = ''\n this.end = false\n\n return new Promise((resolve, reject) => {\n this.ws = new WebSocket(this.caps[Capabilities.VOIP_WORKER_URL])\n\n if (!_.isArray(this.caps[Capabilities.VOIP_ICE_STUN_SERVERS])) {\n if (this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] === '') {\n this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = []\n } else {\n this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = this.caps[Capabilities.VOIP_ICE_STUN_SERVERS].split(',')\n }\n }\n\n this.wsOpened = false\n this.ws.on('open', () => {\n this.wsOpened = true\n debug(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_ENDPOINT]} opened.`)\n const request = {\n METHOD: 'initCall',\n API_KEY: this.caps[Capabilities.VOIP_WORKER_APIKEY],\n SIP_CALLER_AUTO: this.caps[Capabilities.VOIP_SIP_POOL_CALLER_ENABLE],\n SIP_PROXY: this.caps[Capabilities.VOIP_SIP_PROXY],\n SIP_CALLER_URI: this.caps[Capabilities.VOIP_SIP_CALLER_URI],\n SIP_CALLER_USERNAME: this.caps[Capabilities.VOIP_SIP_CALLER_USERNAME],\n SIP_CALLER_PASSWORD: this.caps[Capabilities.VOIP_SIP_CALLER_PASSWORD],\n SIP_CALLER_ADDRESS: this.caps[Capabilities.VOIP_SIP_CALLER_ADDRESS],\n SIP_CALLER_REGISTRAR_URI: this.caps[Capabilities.VOIP_SIP_CALLER_REGISTRAR_URI],\n SIP_CALLEE_URI: this.caps[Capabilities.VOIP_SIP_CALLEE_URI],\n SIP_REG_HEADERS: this.caps[Capabilities.VOIP_SIP_REG_HEADERS],\n SIP_INVITE_HEADERS: this.caps[Capabilities.VOIP_SIP_INVITE_HEADERS],\n ICE_ENABLE: this.caps[Capabilities.VOIP_ICE_ENABLE],\n ICE_STUN_SERVERS: this.caps[Capabilities.VOIP_ICE_STUN_SERVERS],\n ICE_TURN_SERVER: this.caps[Capabilities.VOIP_ICE_TURN_SERVER],\n ICE_TURN_USERNAME: this.caps[Capabilities.VOIP_ICE_TURN_USER],\n ICE_TURN_PASSWORD: this.caps[Capabilities.VOIP_ICE_TURN_PASSWORD],\n ICE_TURN_PROTOCOL: this.caps[Capabilities.VOIP_ICE_TURN_PROTOCOL] || 'TCP',\n STT_CONFIG: {\n stt_url: this.caps[Capabilities.VOIP_STT_URL_STREAM],\n stt_params: this.caps[Capabilities.VOIP_STT_PARAMS_STREAM],\n stt_body: this.caps[Capabilities.VOIP_STT_BODY_STREAM] || null\n },\n TTS_CONFIG: {\n tts_url: this.caps[Capabilities.VOIP_TTS_URL],\n tts_params: this.caps[Capabilities.VOIP_TTS_PARAMS],\n tts_body: this.caps[Capabilities.VOIP_TTS_BODY] || null\n }\n }\n debug(request)\n this.ws.send(JSON.stringify(request))\n })\n this.ws.on('close', async () => {\n debug(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} closed.`)\n })\n this.ws.on('error', (err) => {\n debug(err)\n if (!this.wsOpened) {\n reject(new Error(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} error: ${err.message || err}`))\n }\n })\n this.ws.on('message', async (data) => {\n const parsedData = JSON.parse(data)\n const botMsgs = []\n\n debug(parsedData)\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'initialized') {\n this.sessionId = parsedData.voipConfig.sessionId\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'unauthorized') {\n reject(new Error('Cannot open a call: SIP Authorization failed'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden') {\n reject(new Error('Cannot connect to VOIP Worker because of wrong API key'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden') {\n debug('error')\n reject(new Error('Cannot connect to VOIP Worker because of wrong API key'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'connected') {\n resolve()\n }\n\n if (parsedData && parsedData.type === 'error') {\n reject(new Error(parsedData.message))\n }\n\n if (parsedData && parsedData.type === 'fullRecord') {\n this.end = true\n this.eventEmitter.emit('MESSAGE_ATTACHMENT', this.container, {\n name: 'full_record.wav',\n mimeType: 'audio/wav',\n base64: parsedData.fullRecord\n })\n this.Stop()\n }\n\n if (parsedData && parsedData.data && parsedData.data.final) {\n const botMsg = { messageText: parsedData.data.message, sourceData: parsedData }\n botMsgs.push(botMsg)\n }\n\n botMsgs.forEach(botMsg => setTimeout(() => this.queueBotSays(botMsg), 0))\n })\n })\n }\n\n async UserSays (msg) {\n debug('UserSays called')\n\n debug(msg)\n\n if (!msg.attachments) {\n msg.attachments = []\n }\n return new Promise((resolve, reject) => {\n setTimeout(async () => {\n if (msg && msg.buttons && msg.buttons.length > 0) {\n const request = JSON.stringify({\n METHOD: 'sendDtmf',\n digits: msg.buttons[0].payload,\n sessionId: this.sessionId\n })\n this.ws.send(request)\n } else if (msg && msg.messageText) {\n if (!this.axiosTtsParams) reject(new Error('TTS not configured, only audio input supported'))\n if (this.axiosTtsParams) {\n const ttsRequest = {\n ...this.axiosTtsParams,\n params: {\n ...(this.axiosTtsParams.params || {}),\n text: msg.messageText\n },\n data: this._getBody(Capabilities.BSP_TTS_BODY),\n responseType: 'arraybuffer'\n }\n msg.sourceData = ttsRequest\n\n let ttsResponse = null\n try {\n ttsResponse = await axios(ttsRequest)\n } catch (err) {\n reject(new Error(`TTS \"${msg.messageText}\" failed - ${this._getAxiosErrOutput(err)}`))\n }\n if (Buffer.isBuffer(ttsResponse.data)) {\n const request = JSON.stringify({\n METHOD: 'sendAudio',\n PESQ: false,\n sessionId: this.sessionId,\n b64_buffer: ttsResponse.data.toString('base64')\n })\n msg.attachments.push({\n name: 'tts.wav',\n mimeType: 'audio/wav',\n base64: ttsResponse.data.toString('base64')\n })\n this.ws.send(request)\n } else {\n reject(new Error(`TTS failed, response is: ${this._getAxiosShortenedOutput(ttsResponse.data)}`))\n }\n }\n }\n if (msg && msg.media && msg.media.length > 0 && msg.media[0].buffer) {\n const request = JSON.stringify({\n METHOD: 'sendAudio',\n sessionId: this.sessionId,\n b64_buffer: msg.media[0].buffer.toString('base64')\n })\n msg.attachments.push({\n name: msg.media[0].mediaUri,\n mimeType: msg.media[0].mimeType,\n base64: msg.media[0].buffer.toString('base64')\n })\n this.ws.send(request)\n }\n resolve()\n }, 500)\n })\n }\n\n async Stop () {\n debug('Stop called')\n const request = JSON.stringify({\n METHOD: 'stopCall',\n sessionId: this.sessionId\n })\n this.ws.send(request)\n await new Promise(resolve => {\n setTimeout(resolve, 50000)\n setInterval(() => {\n if (this.end) {\n resolve()\n }\n }, 1000)\n })\n\n if (this.ws) {\n this.ws.close()\n }\n this.wsOpened = false\n this.ws = null\n this.view = {}\n }\n\n _getParams (capParams) {\n if (this.caps[capParams]) {\n if (_.isString(this.caps[capParams])) return JSON.parse(this.caps[capParams])\n else return this.caps[capParams]\n }\n return {}\n }\n\n _getBody (capBody) {\n if (this.caps[capBody]) {\n if (_.isString(this.caps[capBody])) return JSON.parse(this.caps[capBody])\n else return this.caps[capBody]\n }\n return null\n }\n\n _getHeaders (capHeaders) {\n if (this.caps[capHeaders]) {\n if (_.isString(this.caps[capHeaders])) return JSON.parse(this.caps[capHeaders])\n else return this.caps[capHeaders]\n }\n return {}\n }\n\n _getAxiosUrl (baseUrl, extUrl) {\n return baseUrl.substr(0, baseUrl.indexOf('/', 8)) + extUrl\n }\n\n _getAxiosShortenedOutput (data) {\n if (data) {\n if (_.isBuffer(data)) {\n try {\n data = data.toString()\n } catch (err) {\n }\n }\n return _.truncate(_.isString(data) ? data : JSON.stringify(data), { length: 200 })\n } else {\n return ''\n }\n }\n\n _getAxiosErrOutput (err) {\n if (err && err.response) {\n return `Status: ${err.response.status} / Response: ${this._getAxiosShortenedOutput(err.response.data)}`\n } else {\n return err.message\n }\n }\n}\n\nmodule.exports = BotiumConnectorVoip\n","const BotiumConnectorVoip = require('./src/connector')\n\nmodule.exports = {\n PluginVersion: 1,\n PluginClass: BotiumConnectorVoip,\n PluginDesc: {\n name: 'Voice over IP',\n provider: 'Botium',\n features: {\n audioInput: true\n },\n capabilities: [\n {\n name: 'VOIP_STT',\n label: 'Speech Recognition Profile',\n type: 'speechrecognitionprofile',\n required: true\n },\n {\n name: 'VOIP_TTS',\n label: 'Speech Synthesis Profile',\n type: 'speechsynthesisprofile',\n required: true\n }\n ]\n }\n}\n"],"names":["v4","uuidv4","require$$0","debug","require$$1","Capabilities","VOIP_STT_URL_STREAM","VOIP_STT_PARAMS_STREAM","VOIP_STT_METHOD_STREAM","VOIP_STT_BODY_STREAM","VOIP_STT_HEADERS","VOIP_STT_TIMEOUT","VOIP_TTS_URL","VOIP_TTS_PARAMS","VOIP_TTS_METHOD","VOIP_TTS_BODY","VOIP_TTS_HEADERS","VOIP_TTS_TIMEOUT","VOIP_WORKER_URL","VOIP_WORKER_APIKEY","VOIP_SIP_POOL_CALLER_ENABLE","VOIP_SIP_CALLER_REGISTRAR_URI","VOIP_SIP_CALLER_ADDRESS","VOIP_SIP_CALLER_USERNAME","VOIP_SIP_CALLER_PASSWORD","VOIP_SIP_PROXY","VOIP_SIP_REG_HEADERS","VOIP_SIP_INVITE_HEADERS","VOIP_SIP_CALLEE_URI","VOIP_ICE_ENABLE","VOIP_ICE_STUN_SERVERS","VOIP_ICE_TURN_ENABLE","VOIP_ICE_TURN_SERVER","VOIP_ICE_TURN_USER","VOIP_ICE_TURN_PASSWORD","VOIP_ICE_TURN_PROTOCOL","Defaults","VOIP_STT_METHOD","BotiumConnectorVoip","constructor","queueBotSays","eventEmitter","caps","Validate","axiosTtsParams","url","params","_getParams","method","timeout","headers","_getHeaders","data","axios","_getAxiosUrl","status","_getAxiosShortenedOutput","Error","err","_getAxiosErrOutput","Object","assign","Start","view","container","context","msg","botium","conversationId","stepId","fullRecord","end","Promise","resolve","reject","ws","WebSocket","_","isArray","split","wsOpened","on","VOIP_WORKER_ENDPOINT","request","METHOD","API_KEY","SIP_CALLER_AUTO","SIP_PROXY","SIP_CALLER_URI","VOIP_SIP_CALLER_URI","SIP_CALLER_USERNAME","SIP_CALLER_PASSWORD","SIP_CALLER_ADDRESS","SIP_CALLER_REGISTRAR_URI","SIP_CALLEE_URI","SIP_REG_HEADERS","SIP_INVITE_HEADERS","ICE_ENABLE","ICE_STUN_SERVERS","ICE_TURN_SERVER","ICE_TURN_USERNAME","ICE_TURN_PASSWORD","ICE_TURN_PROTOCOL","STT_CONFIG","stt_url","stt_params","stt_body","TTS_CONFIG","tts_url","tts_params","tts_body","send","JSON","stringify","message","parsedData","parse","botMsgs","type","sessionId","voipConfig","emit","name","mimeType","base64","Stop","final","botMsg","messageText","sourceData","push","forEach","setTimeout","UserSays","attachments","buttons","length","digits","payload","ttsRequest","text","_getBody","BSP_TTS_BODY","responseType","ttsResponse","Buffer","isBuffer","PESQ","b64_buffer","toString","media","buffer","mediaUri","setInterval","close","capParams","isString","capBody","capHeaders","baseUrl","extUrl","substr","indexOf","truncate","response","PluginVersion","PluginClass","PluginDesc","provider","features","audioInput","capabilities","label","required"],"mappings":"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"}
1
+ {"version":3,"file":"botium-connector-voip-cjs.js","sources":["../src/connector.js","../index.js"],"sourcesContent":["const { v4: uuidv4 } = require('uuid')\nconst WebSocket = require('ws')\nconst _ = require('lodash')\nconst axios = require('axios')\nconst debug = require('debug')('botium-connector-voip')\n\nconst Capabilities = {\n VOIP_STT_URL_STREAM: 'VOIP_STT_URL_STREAM',\n VOIP_STT_PARAMS_STREAM: 'VOIP_STT_PARAMS_STREAM',\n VOIP_STT_METHOD_STREAM: 'VOIP_STT_METHOD_STREAM',\n VOIP_STT_BODY_STREAM: 'VOIP_STT_BODY_STREAM',\n VOIP_STT_BODY: 'VOIP_STT_BODY',\n VOIP_STT_HEADERS: 'VOIP_STT_HEADERS',\n VOIP_STT_TIMEOUT: 'VOIP_STT_TIMEOUT',\n VOIP_STT_MESSAGE_HANDLING: 'VOIP_STT_MESSAGE_HANDLING',\n VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 'VOIP_STT_MESSAGE_HANDLING_TIMEOUT',\n VOIP_STT_MESSAGE_HANDLING_DELIMITER: 'VOIP_STT_MESSAGE_HANDLING_DELIMITER',\n VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: 'VOIP_STT_MESSAGE_HANDLING_PUNCTUATION',\n VOIP_TTS_URL: 'VOIP_TTS_URL',\n VOIP_TTS_PARAMS: 'VOIP_TTS_PARAMS',\n VOIP_TTS_METHOD: 'VOIP_TTS_METHOD',\n VOIP_TTS_BODY: 'VOIP_TTS_BODY',\n VOIP_TTS_HEADERS: 'VOIP_TTS_HEADERS',\n VOIP_TTS_TIMEOUT: 'VOIP_TTS_TIMEOUT',\n VOIP_WORKER_URL: 'VOIP_WORKER_URL',\n VOIP_WORKER_APIKEY: 'VOIP_WORKER_APIKEY',\n VOIP_SIP_POOL_CALLER_ENABLE: 'VOIP_SIP_POOL_CALLER_ENABLE',\n VOIP_SIP_CALLER_REGISTRAR_URI: 'VOIP_SIP_CALLER_REGISTRAR_URI',\n VOIP_SIP_CALLER_ADDRESS: 'VOIP_SIP_CALLER_ADDRESS',\n VOIP_SIP_CALLER_USERNAME: 'VOIP_SIP_CALLER_USERNAME',\n VOIP_SIP_CALLER_PASSWORD: 'VOIP_SIP_CALLER_PASSWORD',\n VOIP_SIP_PROXY: 'VOIP_SIP_PROXY',\n VOIP_SIP_REG_HEADERS: 'VOIP_SIP_REG_HEADERS',\n VOIP_SIP_INVITE_HEADERS: 'VOIP_SIP_INVITE_HEADERS',\n VOIP_SIP_CALLEE_URI: 'VOIP_SIP_CALLEE_URI',\n VOIP_ICE_ENABLE: 'VOIP_ICE_ENABLE',\n VOIP_ICE_STUN_SERVERS: 'VOIP_ICE_STUN_SERVERS',\n VOIP_ICE_TURN_ENABLE: 'VOIP_ICE_TURN_ENABLE',\n VOIP_ICE_TURN_SERVER: 'VOIP_ICE_TURN_SERVER',\n VOIP_ICE_TURN_USER: 'VOIP_ICE_TURN_USER',\n VOIP_ICE_TURN_PASSWORD: 'VOIP_ICE_TURN_PASSWORD',\n VOIP_ICE_TURN_PROTOCOL: 'VOIP_ICE_TURN_PROTOCOL'\n}\n\nconst Defaults = {\n VOIP_STT_METHOD: 'POST',\n VOIP_STT_TIMEOUT: 10000,\n VOIP_TTS_METHOD: 'GET',\n VOIP_TTS_TIMEOUT: 10000,\n VOIP_STT_MESSAGE_HANDLING: 'ORIGINAL',\n VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 5000,\n VOIP_STT_MESSAGE_HANDLING_DELIMITER: '. ',\n VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: '.!?'\n}\n\nclass BotiumConnectorVoip {\n constructor ({ queueBotSays, eventEmitter, caps }) {\n this.queueBotSays = queueBotSays\n this.caps = caps\n this.eventEmitter = eventEmitter\n this.botMsgs = []\n this.sentencesBuilding = 0\n this.sentencesFinal = 0\n this.sentenceBuilding = false\n }\n\n async Validate () {\n debug('Validate called')\n debug(this.caps.VOIP_STT_MESSAGE_HANDLING)\n\n if (this.caps.VOIP_TTS_URL) {\n this.axiosTtsParams = {\n url: this.caps.VOIP_TTS_URL,\n params: this._getParams(Capabilities.VOIP_TTS_PARAMS),\n method: this.caps.VOIP_TTS_METHOD,\n timeout: this.caps.VOIP_TTS_TIMEOUT,\n headers: this._getHeaders(Capabilities.VOIP_TTS_HEADERS)\n }\n try {\n const { data } = await axios({\n ...this.axiosTtsParams,\n url: this._getAxiosUrl(this.caps.VOIP_TTS_URL, '/api/status')\n })\n if (data && data.status === 'OK') {\n debug(`Checking TTS Status response: ${this._getAxiosShortenedOutput(data)}`)\n } else {\n throw new Error(`Checking TTS Status failed, response is: ${this._getAxiosShortenedOutput(data)}`)\n }\n } catch (err) {\n throw new Error(`Checking TTS Status failed - ${this._getAxiosErrOutput(err)}`)\n }\n }\n\n this.caps = Object.assign({}, Defaults, this.caps)\n }\n\n async Start () {\n debug('Start called')\n debug(this.caps[Capabilities.VOIP_TTS_URL])\n\n this.view = {\n container: this,\n context: {},\n msg: {},\n botium: {\n conversationId: uuidv4(),\n stepId: null\n }\n }\n\n this.fullRecord = ''\n this.end = false\n\n const sendBotMsg = (botMsg) => { setTimeout(() => this.queueBotSays(botMsg), 0) }\n\n const buildBotMsg = botMsgs => {\n if (botMsgs.length === 1) return botMsgs[0]\n const botMsg = {}\n botMsg.messageText = botMsgs.map(m => m.messageText).join(this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_DELIMITER])\n botMsg.sourceData = botMsgs.map(m => m.sourceData)\n return botMsg\n }\n\n const expandBotMsgs = botMsgs => {\n const splitSentences = s => s.match(new RegExp(`[^${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+[${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+`, 'g'))\n const botMsgsFinal = []\n for (const botMsg of botMsgs) {\n const sentences = splitSentences(botMsg.messageText)\n if (_.isNil(sentences)) {\n botMsgsFinal.push(botMsg)\n } else {\n for (const sentence of sentences) {\n botMsgsFinal.push({\n messageText: sentence,\n sourceData: botMsg.sourceData\n })\n }\n }\n }\n return botMsgsFinal\n }\n\n return new Promise((resolve, reject) => {\n this.ws = new WebSocket(this.caps[Capabilities.VOIP_WORKER_URL])\n\n if (!_.isArray(this.caps[Capabilities.VOIP_ICE_STUN_SERVERS])) {\n if (this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] === '') {\n this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = []\n } else {\n this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = this.caps[Capabilities.VOIP_ICE_STUN_SERVERS].split(',')\n }\n }\n\n this.wsOpened = false\n this.ws.on('open', () => {\n this.wsOpened = true\n debug(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_ENDPOINT]} opened.`)\n const request = {\n METHOD: 'initCall',\n API_KEY: this.caps[Capabilities.VOIP_WORKER_APIKEY],\n SIP_CALLER_AUTO: this.caps[Capabilities.VOIP_SIP_POOL_CALLER_ENABLE],\n SIP_PROXY: this.caps[Capabilities.VOIP_SIP_PROXY],\n SIP_CALLER_URI: this.caps[Capabilities.VOIP_SIP_CALLER_URI],\n SIP_CALLER_USERNAME: this.caps[Capabilities.VOIP_SIP_CALLER_USERNAME],\n SIP_CALLER_PASSWORD: this.caps[Capabilities.VOIP_SIP_CALLER_PASSWORD],\n SIP_CALLER_ADDRESS: this.caps[Capabilities.VOIP_SIP_CALLER_ADDRESS],\n SIP_CALLER_REGISTRAR_URI: this.caps[Capabilities.VOIP_SIP_CALLER_REGISTRAR_URI],\n SIP_CALLEE_URI: this.caps[Capabilities.VOIP_SIP_CALLEE_URI],\n SIP_REG_HEADERS: this.caps[Capabilities.VOIP_SIP_REG_HEADERS],\n SIP_INVITE_HEADERS: this.caps[Capabilities.VOIP_SIP_INVITE_HEADERS],\n ICE_ENABLE: this.caps[Capabilities.VOIP_ICE_ENABLE],\n ICE_STUN_SERVERS: this.caps[Capabilities.VOIP_ICE_STUN_SERVERS],\n ICE_TURN_SERVER: this.caps[Capabilities.VOIP_ICE_TURN_SERVER],\n ICE_TURN_USERNAME: this.caps[Capabilities.VOIP_ICE_TURN_USER],\n ICE_TURN_PASSWORD: this.caps[Capabilities.VOIP_ICE_TURN_PASSWORD],\n ICE_TURN_PROTOCOL: this.caps[Capabilities.VOIP_ICE_TURN_PROTOCOL] || 'TCP',\n STT_CONFIG: {\n stt_url: this.caps[Capabilities.VOIP_STT_URL_STREAM],\n stt_params: this.caps[Capabilities.VOIP_STT_PARAMS_STREAM],\n stt_body: this.caps[Capabilities.VOIP_STT_BODY_STREAM] || null\n },\n TTS_CONFIG: {\n tts_url: this.caps[Capabilities.VOIP_TTS_URL],\n tts_params: this.caps[Capabilities.VOIP_TTS_PARAMS],\n tts_body: this.caps[Capabilities.VOIP_TTS_BODY] || null\n }\n }\n debug(JSON.stringify(request, null, 2))\n this.ws.send(JSON.stringify(request))\n })\n this.ws.on('close', async () => {\n debug(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} closed.`)\n })\n this.ws.on('error', (err) => {\n debug(err)\n if (!this.wsOpened) {\n this.end = true\n reject(new Error(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} error: ${err.message || err}`))\n }\n })\n this.ws.on('message', async (data) => {\n const parsedData = JSON.parse(data)\n\n const parsedDataLog = _.cloneDeep(parsedData)\n parsedDataLog.fullRecord = '<full_record_buffer>'\n\n debug(JSON.stringify(parsedDataLog, null, 2))\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'initialized') {\n this.sessionId = parsedData.voipConfig.sessionId\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'unauthorized') {\n reject(new Error('Error: Cannot open a call: SIP Authorization failed'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event !== 'onCallRegState') {\n reject(new Error('Error: Cannot connect to VOIP Worker because of wrong API key'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event === 'onCallRegState') {\n reject(new Error('Error: Sip Registration failed'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'connected') {\n resolve()\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'disconnected') {\n const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_STT_BODY))\n if (parsedData.connectDuration && parsedData.connectDuration > 0) {\n this.eventEmitter.emit('CONSUMPTION_METADATA', this.container, {\n type: _.isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',\n metricName: 'consumption.e2e.voip.stt.seconds',\n credits: parsedData.connectDuration,\n apiKey\n })\n }\n }\n\n if (parsedData && parsedData.type === 'error') {\n reject(new Error(`Error: ${parsedData.message}`))\n }\n\n if (parsedData && parsedData.type === 'fullRecord') {\n this.end = true\n this.eventEmitter.emit('MESSAGE_ATTACHMENT', this.container, {\n name: 'full_record.wav',\n mimeType: 'audio/wav',\n base64: parsedData.fullRecord\n })\n this.Stop()\n }\n\n if (parsedData && parsedData.data && parsedData.data.final === false) {\n if (!this.sentenceBuilding) {\n this.sentenceBuilding = true\n this.sentencesBuilding++\n }\n }\n\n if (parsedData && parsedData.data && parsedData.data.final) {\n const botMsg = { messageText: parsedData.data.message, sourceData: parsedData }\n this.botMsgs.push(botMsg)\n if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'ORIGINAL') {\n this.botMsgs.forEach(botMsg => sendBotMsg(botMsg))\n this.botMsgs = []\n }\n if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'EXPAND') {\n const botMsgsExpanded = expandBotMsgs(this.botMsgs)\n botMsgsExpanded.forEach(botMsg => sendBotMsg(botMsg))\n this.botMsgs = []\n }\n if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'CONCAT') {\n this.sentenceBuilding = false\n this.sentencesFinal++\n\n clearTimeout(this.sendMessageTimeout)\n this.sendMessageTimeout = setTimeout(() => {\n if (this.sentenceBuilding === false && this.sentencesBuilding === this.sentencesFinal) {\n sendBotMsg(buildBotMsg(this.botMsgs))\n this.botMsgs = []\n this.sentencesBuilding = 0\n this.sentencesFinal = 0\n }\n }, this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_TIMEOUT])\n }\n }\n })\n })\n }\n\n async UserSays (msg) {\n debug('UserSays called')\n\n debug(msg)\n\n if (!msg.attachments) {\n msg.attachments = []\n }\n return new Promise((resolve, reject) => {\n setTimeout(async () => {\n let duration = 0\n if (msg && msg.buttons && msg.buttons.length > 0) {\n const request = JSON.stringify({\n METHOD: 'sendDtmf',\n digits: msg.buttons[0].payload,\n sessionId: this.sessionId\n })\n this.ws.send(request)\n } else if (msg && msg.messageText) {\n if (!this.axiosTtsParams) reject(new Error('TTS not configured, only audio input supported'))\n if (this.axiosTtsParams) {\n const ttsRequest = {\n ...this.axiosTtsParams,\n params: {\n ...(this.axiosTtsParams.params || {}),\n text: msg.messageText\n },\n data: this._getBody(Capabilities.VOIP_TTS_BODY),\n responseType: 'arraybuffer'\n }\n msg.sourceData = ttsRequest\n\n let ttsResponse = null\n try {\n ttsResponse = await axios(ttsRequest)\n } catch (err) {\n reject(new Error(`TTS \"${msg.messageText}\" failed - ${this._getAxiosErrOutput(err)}`))\n }\n if (msg && msg.messageText && msg.messageText.length > 0) {\n const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_TTS_BODY))\n this.eventEmitter.emit('CONSUMPTION_METADATA', this.container, {\n type: _.isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',\n metricName: 'consumption.e2e.voip.tts.characters',\n credits: msg.messageText.length,\n apiKey\n })\n }\n if (Buffer.isBuffer(ttsResponse.data)) {\n duration = ttsResponse.headers['content-duration']\n const request = JSON.stringify({\n METHOD: 'sendAudio',\n PESQ: false,\n sessionId: this.sessionId,\n b64_buffer: ttsResponse.data.toString('base64')\n })\n msg.attachments.push({\n name: 'tts.wav',\n mimeType: 'audio/wav',\n base64: ttsResponse.data.toString('base64')\n })\n this.ws.send(request)\n } else {\n reject(new Error(`TTS failed, response is: ${this._getAxiosShortenedOutput(ttsResponse.data)}`))\n }\n }\n }\n if (msg && msg.media && msg.media.length > 0 && msg.media[0].buffer) {\n const { data } = await axios({\n method: 'post',\n data: msg.media[0].buffer,\n headers: {\n ...this._getHeaders(Capabilities.VOIP_TTS_HEADERS),\n 'Content-Type': 'audio/wave'\n },\n url: this._getAxiosUrl(this.caps.VOIP_TTS_URL, '/api/audio/info'),\n maxContentLength: Infinity,\n maxBodyLength: Infinity\n })\n if (data && data.duration) {\n duration = parseInt(data.duration)\n }\n const request = JSON.stringify({\n METHOD: 'sendAudio',\n sessionId: this.sessionId,\n b64_buffer: msg.media[0].buffer.toString('base64')\n })\n msg.attachments.push({\n name: msg.media[0].mediaUri,\n mimeType: msg.media[0].mimeType,\n base64: msg.media[0].buffer.toString('base64')\n })\n this.ws.send(request)\n }\n setTimeout(resolve, duration * 1000)\n }, 0)\n })\n }\n\n async Stop () {\n debug('Stop called')\n const request = JSON.stringify({\n METHOD: 'stopCall',\n sessionId: this.sessionId\n })\n this.ws.send(request)\n await new Promise(resolve => {\n setTimeout(resolve, 50000)\n setInterval(() => {\n if (this.end) {\n resolve()\n }\n }, 1000)\n })\n\n if (this.ws) {\n this.ws.close()\n }\n this.wsOpened = false\n this.ws = null\n this.view = {}\n }\n\n _getParams (capParams) {\n if (this.caps[capParams]) {\n if (_.isString(this.caps[capParams])) return JSON.parse(this.caps[capParams])\n else return this.caps[capParams]\n }\n return {}\n }\n\n _getBody (capBody) {\n if (this.caps[capBody]) {\n if (_.isString(this.caps[capBody])) return JSON.parse(this.caps[capBody])\n else return this.caps[capBody]\n }\n return null\n }\n\n _getHeaders (capHeaders) {\n if (this.caps[capHeaders]) {\n if (_.isString(this.caps[capHeaders])) return JSON.parse(this.caps[capHeaders])\n else return this.caps[capHeaders]\n }\n return {}\n }\n\n _getAxiosUrl (baseUrl, extUrl) {\n return baseUrl.substr(0, baseUrl.indexOf('/', 8)) + extUrl\n }\n\n _getAxiosShortenedOutput (data) {\n if (data) {\n if (_.isBuffer(data)) {\n try {\n data = data.toString()\n } catch (err) {\n }\n }\n return _.truncate(_.isString(data) ? data : JSON.stringify(data), { length: 200 })\n } else {\n return ''\n }\n }\n\n _getAxiosErrOutput (err) {\n if (err && err.response) {\n return `Status: ${err.response.status} / Response: ${this._getAxiosShortenedOutput(err.response.data)}`\n } else {\n return err.message\n }\n }\n\n _extractApiKey (body) {\n return _.get(body, 'polly.credentials.accessKeyId') ||\n _.get(body, 'google.credentials.client_email') ||\n _.get(body, 'ibm.credentials.apikey') ||\n _.get(body, 'awstranscribe.credentials.accessKeyId') ||\n _.get(body, 'azure.credentials.subscriptionKey') ||\n null\n }\n}\n\nmodule.exports = BotiumConnectorVoip\n","const BotiumConnectorVoip = require('./src/connector')\n\nmodule.exports = {\n PluginVersion: 1,\n PluginClass: BotiumConnectorVoip,\n PluginDesc: {\n name: 'Voice over IP',\n provider: 'Botium',\n features: {\n audioInput: true,\n e2eTesting: true\n },\n capabilities: [\n {\n name: 'VOIP_STT',\n label: 'Speech Recognition Profile',\n type: 'speechrecognitionprofile',\n required: true\n },\n {\n name: 'VOIP_TTS',\n label: 'Speech Synthesis Profile',\n type: 'speechsynthesisprofile',\n required: true\n }\n ]\n }\n}\n"],"names":["v4","uuidv4","require$$0","debug","require$$1","Capabilities","VOIP_STT_URL_STREAM","VOIP_STT_PARAMS_STREAM","VOIP_STT_METHOD_STREAM","VOIP_STT_BODY_STREAM","VOIP_STT_BODY","VOIP_STT_HEADERS","VOIP_STT_TIMEOUT","VOIP_STT_MESSAGE_HANDLING","VOIP_STT_MESSAGE_HANDLING_TIMEOUT","VOIP_STT_MESSAGE_HANDLING_DELIMITER","VOIP_STT_MESSAGE_HANDLING_PUNCTUATION","VOIP_TTS_URL","VOIP_TTS_PARAMS","VOIP_TTS_METHOD","VOIP_TTS_BODY","VOIP_TTS_HEADERS","VOIP_TTS_TIMEOUT","VOIP_WORKER_URL","VOIP_WORKER_APIKEY","VOIP_SIP_POOL_CALLER_ENABLE","VOIP_SIP_CALLER_REGISTRAR_URI","VOIP_SIP_CALLER_ADDRESS","VOIP_SIP_CALLER_USERNAME","VOIP_SIP_CALLER_PASSWORD","VOIP_SIP_PROXY","VOIP_SIP_REG_HEADERS","VOIP_SIP_INVITE_HEADERS","VOIP_SIP_CALLEE_URI","VOIP_ICE_ENABLE","VOIP_ICE_STUN_SERVERS","VOIP_ICE_TURN_ENABLE","VOIP_ICE_TURN_SERVER","VOIP_ICE_TURN_USER","VOIP_ICE_TURN_PASSWORD","VOIP_ICE_TURN_PROTOCOL","Defaults","VOIP_STT_METHOD","BotiumConnectorVoip","constructor","queueBotSays","eventEmitter","caps","botMsgs","sentencesBuilding","sentencesFinal","sentenceBuilding","Validate","axiosTtsParams","url","params","_getParams","method","timeout","headers","_getHeaders","data","axios","_getAxiosUrl","status","_getAxiosShortenedOutput","Error","err","_getAxiosErrOutput","Object","assign","Start","view","container","context","msg","botium","conversationId","stepId","fullRecord","end","sendBotMsg","botMsg","setTimeout","buildBotMsg","length","messageText","map","m","join","sourceData","expandBotMsgs","splitSentences","s","match","RegExp","botMsgsFinal","sentences","_","isNil","push","sentence","Promise","resolve","reject","ws","WebSocket","isArray","split","wsOpened","on","VOIP_WORKER_ENDPOINT","request","METHOD","API_KEY","SIP_CALLER_AUTO","SIP_PROXY","SIP_CALLER_URI","VOIP_SIP_CALLER_URI","SIP_CALLER_USERNAME","SIP_CALLER_PASSWORD","SIP_CALLER_ADDRESS","SIP_CALLER_REGISTRAR_URI","SIP_CALLEE_URI","SIP_REG_HEADERS","SIP_INVITE_HEADERS","ICE_ENABLE","ICE_STUN_SERVERS","ICE_TURN_SERVER","ICE_TURN_USERNAME","ICE_TURN_PASSWORD","ICE_TURN_PROTOCOL","STT_CONFIG","stt_url","stt_params","stt_body","TTS_CONFIG","tts_url","tts_params","tts_body","JSON","stringify","send","message","parsedData","parse","parsedDataLog","cloneDeep","type","sessionId","voipConfig","event","apiKey","_extractApiKey","_getBody","connectDuration","emit","metricName","credits","name","mimeType","base64","Stop","final","forEach","botMsgsExpanded","clearTimeout","sendMessageTimeout","UserSays","attachments","duration","buttons","digits","payload","ttsRequest","text","responseType","ttsResponse","Buffer","isBuffer","PESQ","b64_buffer","toString","media","buffer","maxContentLength","Infinity","maxBodyLength","parseInt","mediaUri","setInterval","close","capParams","isString","capBody","capHeaders","baseUrl","extUrl","substr","indexOf","truncate","response","body","get","PluginVersion","PluginClass","PluginDesc","provider","features","audioInput","e2eTesting","capabilities","label","required"],"mappings":"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"}
@@ -13,8 +13,13 @@ const Capabilities = {
13
13
  VOIP_STT_PARAMS_STREAM: 'VOIP_STT_PARAMS_STREAM',
14
14
  VOIP_STT_METHOD_STREAM: 'VOIP_STT_METHOD_STREAM',
15
15
  VOIP_STT_BODY_STREAM: 'VOIP_STT_BODY_STREAM',
16
+ VOIP_STT_BODY: 'VOIP_STT_BODY',
16
17
  VOIP_STT_HEADERS: 'VOIP_STT_HEADERS',
17
18
  VOIP_STT_TIMEOUT: 'VOIP_STT_TIMEOUT',
19
+ VOIP_STT_MESSAGE_HANDLING: 'VOIP_STT_MESSAGE_HANDLING',
20
+ VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 'VOIP_STT_MESSAGE_HANDLING_TIMEOUT',
21
+ VOIP_STT_MESSAGE_HANDLING_DELIMITER: 'VOIP_STT_MESSAGE_HANDLING_DELIMITER',
22
+ VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: 'VOIP_STT_MESSAGE_HANDLING_PUNCTUATION',
18
23
  VOIP_TTS_URL: 'VOIP_TTS_URL',
19
24
  VOIP_TTS_PARAMS: 'VOIP_TTS_PARAMS',
20
25
  VOIP_TTS_METHOD: 'VOIP_TTS_METHOD',
@@ -44,7 +49,11 @@ const Defaults = {
44
49
  VOIP_STT_METHOD: 'POST',
45
50
  VOIP_STT_TIMEOUT: 10000,
46
51
  VOIP_TTS_METHOD: 'GET',
47
- VOIP_TTS_TIMEOUT: 10000
52
+ VOIP_TTS_TIMEOUT: 10000,
53
+ VOIP_STT_MESSAGE_HANDLING: 'ORIGINAL',
54
+ VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 5000,
55
+ VOIP_STT_MESSAGE_HANDLING_DELIMITER: '. ',
56
+ VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: '.!?'
48
57
  };
49
58
 
50
59
  class BotiumConnectorVoip {
@@ -56,10 +65,15 @@ class BotiumConnectorVoip {
56
65
  this.queueBotSays = queueBotSays;
57
66
  this.caps = caps;
58
67
  this.eventEmitter = eventEmitter;
68
+ this.botMsgs = [];
69
+ this.sentencesBuilding = 0;
70
+ this.sentencesFinal = 0;
71
+ this.sentenceBuilding = false;
59
72
  }
60
73
 
61
74
  async Validate() {
62
75
  debug('Validate called');
76
+ debug(this.caps.VOIP_STT_MESSAGE_HANDLING);
63
77
 
64
78
  if (this.caps.VOIP_TTS_URL) {
65
79
  this.axiosTtsParams = {
@@ -104,6 +118,42 @@ class BotiumConnectorVoip {
104
118
  };
105
119
  this.fullRecord = '';
106
120
  this.end = false;
121
+
122
+ const sendBotMsg = botMsg => {
123
+ setTimeout(() => this.queueBotSays(botMsg), 0);
124
+ };
125
+
126
+ const buildBotMsg = botMsgs => {
127
+ if (botMsgs.length === 1) return botMsgs[0];
128
+ const botMsg = {};
129
+ botMsg.messageText = botMsgs.map(m => m.messageText).join(this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_DELIMITER]);
130
+ botMsg.sourceData = botMsgs.map(m => m.sourceData);
131
+ return botMsg;
132
+ };
133
+
134
+ const expandBotMsgs = botMsgs => {
135
+ const splitSentences = s => s.match(new RegExp(`[^${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+[${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+`, 'g'));
136
+
137
+ const botMsgsFinal = [];
138
+
139
+ for (const botMsg of botMsgs) {
140
+ const sentences = splitSentences(botMsg.messageText);
141
+
142
+ if (lodash.isNil(sentences)) {
143
+ botMsgsFinal.push(botMsg);
144
+ } else {
145
+ for (const sentence of sentences) {
146
+ botMsgsFinal.push({
147
+ messageText: sentence,
148
+ sourceData: botMsg.sourceData
149
+ });
150
+ }
151
+ }
152
+ }
153
+
154
+ return botMsgsFinal;
155
+ };
156
+
107
157
  return new Promise((resolve, reject) => {
108
158
  this.ws = new ws(this.caps[Capabilities.VOIP_WORKER_URL]);
109
159
 
@@ -149,7 +199,7 @@ class BotiumConnectorVoip {
149
199
  tts_body: this.caps[Capabilities.VOIP_TTS_BODY] || null
150
200
  }
151
201
  };
152
- debug(request);
202
+ debug(JSON.stringify(request, null, 2));
153
203
  this.ws.send(JSON.stringify(request));
154
204
  });
155
205
  this.ws.on('close', async () => {
@@ -159,37 +209,53 @@ class BotiumConnectorVoip {
159
209
  debug(err);
160
210
 
161
211
  if (!this.wsOpened) {
212
+ this.end = true;
162
213
  reject(new Error(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} error: ${err.message || err}`));
163
214
  }
164
215
  });
165
216
  this.ws.on('message', async data => {
166
217
  const parsedData = JSON.parse(data);
167
- const botMsgs = [];
168
- debug(parsedData);
218
+
219
+ const parsedDataLog = lodash.cloneDeep(parsedData);
220
+
221
+ parsedDataLog.fullRecord = '<full_record_buffer>';
222
+ debug(JSON.stringify(parsedDataLog, null, 2));
169
223
 
170
224
  if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'initialized') {
171
225
  this.sessionId = parsedData.voipConfig.sessionId;
172
226
  }
173
227
 
174
228
  if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'unauthorized') {
175
- reject(new Error('Cannot open a call: SIP Authorization failed'));
229
+ reject(new Error('Error: Cannot open a call: SIP Authorization failed'));
176
230
  }
177
231
 
178
- if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden') {
179
- reject(new Error('Cannot connect to VOIP Worker because of wrong API key'));
232
+ if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event !== 'onCallRegState') {
233
+ reject(new Error('Error: Cannot connect to VOIP Worker because of wrong API key'));
180
234
  }
181
235
 
182
- if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden') {
183
- debug('error');
184
- reject(new Error('Cannot connect to VOIP Worker because of wrong API key'));
236
+ if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event === 'onCallRegState') {
237
+ reject(new Error('Error: Sip Registration failed'));
185
238
  }
186
239
 
187
240
  if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'connected') {
188
241
  resolve();
189
242
  }
190
243
 
244
+ if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'disconnected') {
245
+ const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_STT_BODY));
246
+
247
+ if (parsedData.connectDuration && parsedData.connectDuration > 0) {
248
+ this.eventEmitter.emit('CONSUMPTION_METADATA', this.container, {
249
+ type: lodash.isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',
250
+ metricName: 'consumption.e2e.voip.stt.seconds',
251
+ credits: parsedData.connectDuration,
252
+ apiKey
253
+ });
254
+ }
255
+ }
256
+
191
257
  if (parsedData && parsedData.type === 'error') {
192
- reject(new Error(parsedData.message));
258
+ reject(new Error(`Error: ${parsedData.message}`));
193
259
  }
194
260
 
195
261
  if (parsedData && parsedData.type === 'fullRecord') {
@@ -202,15 +268,45 @@ class BotiumConnectorVoip {
202
268
  this.Stop();
203
269
  }
204
270
 
271
+ if (parsedData && parsedData.data && parsedData.data.final === false) {
272
+ if (!this.sentenceBuilding) {
273
+ this.sentenceBuilding = true;
274
+ this.sentencesBuilding++;
275
+ }
276
+ }
277
+
205
278
  if (parsedData && parsedData.data && parsedData.data.final) {
206
279
  const botMsg = {
207
280
  messageText: parsedData.data.message,
208
281
  sourceData: parsedData
209
282
  };
210
- botMsgs.push(botMsg);
211
- }
283
+ this.botMsgs.push(botMsg);
284
+
285
+ if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'ORIGINAL') {
286
+ this.botMsgs.forEach(botMsg => sendBotMsg(botMsg));
287
+ this.botMsgs = [];
288
+ }
212
289
 
213
- botMsgs.forEach(botMsg => setTimeout(() => this.queueBotSays(botMsg), 0));
290
+ if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'EXPAND') {
291
+ const botMsgsExpanded = expandBotMsgs(this.botMsgs);
292
+ botMsgsExpanded.forEach(botMsg => sendBotMsg(botMsg));
293
+ this.botMsgs = [];
294
+ }
295
+
296
+ if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'CONCAT') {
297
+ this.sentenceBuilding = false;
298
+ this.sentencesFinal++;
299
+ clearTimeout(this.sendMessageTimeout);
300
+ this.sendMessageTimeout = setTimeout(() => {
301
+ if (this.sentenceBuilding === false && this.sentencesBuilding === this.sentencesFinal) {
302
+ sendBotMsg(buildBotMsg(this.botMsgs));
303
+ this.botMsgs = [];
304
+ this.sentencesBuilding = 0;
305
+ this.sentencesFinal = 0;
306
+ }
307
+ }, this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_TIMEOUT]);
308
+ }
309
+ }
214
310
  });
215
311
  });
216
312
  }
@@ -225,6 +321,8 @@ class BotiumConnectorVoip {
225
321
 
226
322
  return new Promise((resolve, reject) => {
227
323
  setTimeout(async () => {
324
+ let duration = 0;
325
+
228
326
  if (msg && msg.buttons && msg.buttons.length > 0) {
229
327
  const request = JSON.stringify({
230
328
  METHOD: 'sendDtmf',
@@ -240,7 +338,7 @@ class BotiumConnectorVoip {
240
338
  params: { ...(this.axiosTtsParams.params || {}),
241
339
  text: msg.messageText
242
340
  },
243
- data: this._getBody(Capabilities.BSP_TTS_BODY),
341
+ data: this._getBody(Capabilities.VOIP_TTS_BODY),
244
342
  responseType: 'arraybuffer'
245
343
  };
246
344
  msg.sourceData = ttsRequest;
@@ -252,7 +350,19 @@ class BotiumConnectorVoip {
252
350
  reject(new Error(`TTS "${msg.messageText}" failed - ${this._getAxiosErrOutput(err)}`));
253
351
  }
254
352
 
353
+ if (msg && msg.messageText && msg.messageText.length > 0) {
354
+ const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_TTS_BODY));
355
+
356
+ this.eventEmitter.emit('CONSUMPTION_METADATA', this.container, {
357
+ type: lodash.isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',
358
+ metricName: 'consumption.e2e.voip.tts.characters',
359
+ credits: msg.messageText.length,
360
+ apiKey
361
+ });
362
+ }
363
+
255
364
  if (Buffer.isBuffer(ttsResponse.data)) {
365
+ duration = ttsResponse.headers['content-duration'];
256
366
  const request = JSON.stringify({
257
367
  METHOD: 'sendAudio',
258
368
  PESQ: false,
@@ -272,6 +382,23 @@ class BotiumConnectorVoip {
272
382
  }
273
383
 
274
384
  if (msg && msg.media && msg.media.length > 0 && msg.media[0].buffer) {
385
+ const {
386
+ data
387
+ } = await axios({
388
+ method: 'post',
389
+ data: msg.media[0].buffer,
390
+ headers: { ...this._getHeaders(Capabilities.VOIP_TTS_HEADERS),
391
+ 'Content-Type': 'audio/wave'
392
+ },
393
+ url: this._getAxiosUrl(this.caps.VOIP_TTS_URL, '/api/audio/info'),
394
+ maxContentLength: Infinity,
395
+ maxBodyLength: Infinity
396
+ });
397
+
398
+ if (data && data.duration) {
399
+ duration = parseInt(data.duration);
400
+ }
401
+
275
402
  const request = JSON.stringify({
276
403
  METHOD: 'sendAudio',
277
404
  sessionId: this.sessionId,
@@ -285,8 +412,8 @@ class BotiumConnectorVoip {
285
412
  this.ws.send(request);
286
413
  }
287
414
 
288
- resolve();
289
- }, 500);
415
+ setTimeout(resolve, duration * 1000);
416
+ }, 0);
290
417
  });
291
418
  }
292
419
 
@@ -367,6 +494,10 @@ class BotiumConnectorVoip {
367
494
  }
368
495
  }
369
496
 
497
+ _extractApiKey(body) {
498
+ return lodash.get(body, 'polly.credentials.accessKeyId') || lodash.get(body, 'google.credentials.client_email') || lodash.get(body, 'ibm.credentials.apikey') || lodash.get(body, 'awstranscribe.credentials.accessKeyId') || lodash.get(body, 'azure.credentials.subscriptionKey') || null;
499
+ }
500
+
370
501
  }
371
502
 
372
503
  var connector = BotiumConnectorVoip;
@@ -378,7 +509,8 @@ var botiumConnectorVoip = {
378
509
  name: 'Voice over IP',
379
510
  provider: 'Botium',
380
511
  features: {
381
- audioInput: true
512
+ audioInput: true,
513
+ e2eTesting: true
382
514
  },
383
515
  capabilities: [{
384
516
  name: 'VOIP_STT',
@@ -1 +1 @@
1
- {"version":3,"file":"botium-connector-voip-es.js","sources":["../src/connector.js","../index.js"],"sourcesContent":["const { v4: uuidv4 } = require('uuid')\nconst WebSocket = require('ws')\nconst _ = require('lodash')\nconst axios = require('axios')\nconst debug = require('debug')('botium-connector-voip')\n\nconst Capabilities = {\n VOIP_STT_URL_STREAM: 'VOIP_STT_URL_STREAM',\n VOIP_STT_PARAMS_STREAM: 'VOIP_STT_PARAMS_STREAM',\n VOIP_STT_METHOD_STREAM: 'VOIP_STT_METHOD_STREAM',\n VOIP_STT_BODY_STREAM: 'VOIP_STT_BODY_STREAM',\n VOIP_STT_HEADERS: 'VOIP_STT_HEADERS',\n VOIP_STT_TIMEOUT: 'VOIP_STT_TIMEOUT',\n VOIP_TTS_URL: 'VOIP_TTS_URL',\n VOIP_TTS_PARAMS: 'VOIP_TTS_PARAMS',\n VOIP_TTS_METHOD: 'VOIP_TTS_METHOD',\n VOIP_TTS_BODY: 'VOIP_TTS_BODY',\n VOIP_TTS_HEADERS: 'VOIP_TTS_HEADERS',\n VOIP_TTS_TIMEOUT: 'VOIP_TTS_TIMEOUT',\n VOIP_WORKER_URL: 'VOIP_WORKER_URL',\n VOIP_WORKER_APIKEY: 'VOIP_WORKER_APIKEY',\n VOIP_SIP_POOL_CALLER_ENABLE: 'VOIP_SIP_POOL_CALLER_ENABLE',\n VOIP_SIP_CALLER_REGISTRAR_URI: 'VOIP_SIP_CALLER_REGISTRAR_URI',\n VOIP_SIP_CALLER_ADDRESS: 'VOIP_SIP_CALLER_ADDRESS',\n VOIP_SIP_CALLER_USERNAME: 'VOIP_SIP_CALLER_USERNAME',\n VOIP_SIP_CALLER_PASSWORD: 'VOIP_SIP_CALLER_PASSWORD',\n VOIP_SIP_PROXY: 'VOIP_SIP_PROXY',\n VOIP_SIP_REG_HEADERS: 'VOIP_SIP_REG_HEADERS',\n VOIP_SIP_INVITE_HEADERS: 'VOIP_SIP_INVITE_HEADERS',\n VOIP_SIP_CALLEE_URI: 'VOIP_SIP_CALLEE_URI',\n VOIP_ICE_ENABLE: 'VOIP_ICE_ENABLE',\n VOIP_ICE_STUN_SERVERS: 'VOIP_ICE_STUN_SERVERS',\n VOIP_ICE_TURN_ENABLE: 'VOIP_ICE_TURN_ENABLE',\n VOIP_ICE_TURN_SERVER: 'VOIP_ICE_TURN_SERVER',\n VOIP_ICE_TURN_USER: 'VOIP_ICE_TURN_USER',\n VOIP_ICE_TURN_PASSWORD: 'VOIP_ICE_TURN_PASSWORD',\n VOIP_ICE_TURN_PROTOCOL: 'VOIP_ICE_TURN_PROTOCOL'\n}\n\nconst Defaults = {\n VOIP_STT_METHOD: 'POST',\n VOIP_STT_TIMEOUT: 10000,\n VOIP_TTS_METHOD: 'GET',\n VOIP_TTS_TIMEOUT: 10000\n}\n\nclass BotiumConnectorVoip {\n constructor ({ queueBotSays, eventEmitter, caps }) {\n this.queueBotSays = queueBotSays\n this.caps = caps\n this.eventEmitter = eventEmitter\n }\n\n async Validate () {\n debug('Validate called')\n\n if (this.caps.VOIP_TTS_URL) {\n this.axiosTtsParams = {\n url: this.caps.VOIP_TTS_URL,\n params: this._getParams(Capabilities.VOIP_TTS_PARAMS),\n method: this.caps.VOIP_TTS_METHOD,\n timeout: this.caps.VOIP_TTS_TIMEOUT,\n headers: this._getHeaders(Capabilities.VOIP_TTS_HEADERS)\n }\n try {\n const { data } = await axios({\n ...this.axiosTtsParams,\n url: this._getAxiosUrl(this.caps.VOIP_TTS_URL, '/api/status')\n })\n if (data && data.status === 'OK') {\n debug(`Checking TTS Status response: ${this._getAxiosShortenedOutput(data)}`)\n } else {\n throw new Error(`Checking TTS Status failed, response is: ${this._getAxiosShortenedOutput(data)}`)\n }\n } catch (err) {\n throw new Error(`Checking TTS Status failed - ${this._getAxiosErrOutput(err)}`)\n }\n }\n\n this.caps = Object.assign({}, Defaults, this.caps)\n }\n\n async Start () {\n debug('Start called')\n debug(this.caps[Capabilities.VOIP_TTS_URL])\n\n this.view = {\n container: this,\n context: {},\n msg: {},\n botium: {\n conversationId: uuidv4(),\n stepId: null\n }\n }\n\n this.fullRecord = ''\n this.end = false\n\n return new Promise((resolve, reject) => {\n this.ws = new WebSocket(this.caps[Capabilities.VOIP_WORKER_URL])\n\n if (!_.isArray(this.caps[Capabilities.VOIP_ICE_STUN_SERVERS])) {\n if (this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] === '') {\n this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = []\n } else {\n this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = this.caps[Capabilities.VOIP_ICE_STUN_SERVERS].split(',')\n }\n }\n\n this.wsOpened = false\n this.ws.on('open', () => {\n this.wsOpened = true\n debug(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_ENDPOINT]} opened.`)\n const request = {\n METHOD: 'initCall',\n API_KEY: this.caps[Capabilities.VOIP_WORKER_APIKEY],\n SIP_CALLER_AUTO: this.caps[Capabilities.VOIP_SIP_POOL_CALLER_ENABLE],\n SIP_PROXY: this.caps[Capabilities.VOIP_SIP_PROXY],\n SIP_CALLER_URI: this.caps[Capabilities.VOIP_SIP_CALLER_URI],\n SIP_CALLER_USERNAME: this.caps[Capabilities.VOIP_SIP_CALLER_USERNAME],\n SIP_CALLER_PASSWORD: this.caps[Capabilities.VOIP_SIP_CALLER_PASSWORD],\n SIP_CALLER_ADDRESS: this.caps[Capabilities.VOIP_SIP_CALLER_ADDRESS],\n SIP_CALLER_REGISTRAR_URI: this.caps[Capabilities.VOIP_SIP_CALLER_REGISTRAR_URI],\n SIP_CALLEE_URI: this.caps[Capabilities.VOIP_SIP_CALLEE_URI],\n SIP_REG_HEADERS: this.caps[Capabilities.VOIP_SIP_REG_HEADERS],\n SIP_INVITE_HEADERS: this.caps[Capabilities.VOIP_SIP_INVITE_HEADERS],\n ICE_ENABLE: this.caps[Capabilities.VOIP_ICE_ENABLE],\n ICE_STUN_SERVERS: this.caps[Capabilities.VOIP_ICE_STUN_SERVERS],\n ICE_TURN_SERVER: this.caps[Capabilities.VOIP_ICE_TURN_SERVER],\n ICE_TURN_USERNAME: this.caps[Capabilities.VOIP_ICE_TURN_USER],\n ICE_TURN_PASSWORD: this.caps[Capabilities.VOIP_ICE_TURN_PASSWORD],\n ICE_TURN_PROTOCOL: this.caps[Capabilities.VOIP_ICE_TURN_PROTOCOL] || 'TCP',\n STT_CONFIG: {\n stt_url: this.caps[Capabilities.VOIP_STT_URL_STREAM],\n stt_params: this.caps[Capabilities.VOIP_STT_PARAMS_STREAM],\n stt_body: this.caps[Capabilities.VOIP_STT_BODY_STREAM] || null\n },\n TTS_CONFIG: {\n tts_url: this.caps[Capabilities.VOIP_TTS_URL],\n tts_params: this.caps[Capabilities.VOIP_TTS_PARAMS],\n tts_body: this.caps[Capabilities.VOIP_TTS_BODY] || null\n }\n }\n debug(request)\n this.ws.send(JSON.stringify(request))\n })\n this.ws.on('close', async () => {\n debug(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} closed.`)\n })\n this.ws.on('error', (err) => {\n debug(err)\n if (!this.wsOpened) {\n reject(new Error(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} error: ${err.message || err}`))\n }\n })\n this.ws.on('message', async (data) => {\n const parsedData = JSON.parse(data)\n const botMsgs = []\n\n debug(parsedData)\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'initialized') {\n this.sessionId = parsedData.voipConfig.sessionId\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'unauthorized') {\n reject(new Error('Cannot open a call: SIP Authorization failed'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden') {\n reject(new Error('Cannot connect to VOIP Worker because of wrong API key'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden') {\n debug('error')\n reject(new Error('Cannot connect to VOIP Worker because of wrong API key'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'connected') {\n resolve()\n }\n\n if (parsedData && parsedData.type === 'error') {\n reject(new Error(parsedData.message))\n }\n\n if (parsedData && parsedData.type === 'fullRecord') {\n this.end = true\n this.eventEmitter.emit('MESSAGE_ATTACHMENT', this.container, {\n name: 'full_record.wav',\n mimeType: 'audio/wav',\n base64: parsedData.fullRecord\n })\n this.Stop()\n }\n\n if (parsedData && parsedData.data && parsedData.data.final) {\n const botMsg = { messageText: parsedData.data.message, sourceData: parsedData }\n botMsgs.push(botMsg)\n }\n\n botMsgs.forEach(botMsg => setTimeout(() => this.queueBotSays(botMsg), 0))\n })\n })\n }\n\n async UserSays (msg) {\n debug('UserSays called')\n\n debug(msg)\n\n if (!msg.attachments) {\n msg.attachments = []\n }\n return new Promise((resolve, reject) => {\n setTimeout(async () => {\n if (msg && msg.buttons && msg.buttons.length > 0) {\n const request = JSON.stringify({\n METHOD: 'sendDtmf',\n digits: msg.buttons[0].payload,\n sessionId: this.sessionId\n })\n this.ws.send(request)\n } else if (msg && msg.messageText) {\n if (!this.axiosTtsParams) reject(new Error('TTS not configured, only audio input supported'))\n if (this.axiosTtsParams) {\n const ttsRequest = {\n ...this.axiosTtsParams,\n params: {\n ...(this.axiosTtsParams.params || {}),\n text: msg.messageText\n },\n data: this._getBody(Capabilities.BSP_TTS_BODY),\n responseType: 'arraybuffer'\n }\n msg.sourceData = ttsRequest\n\n let ttsResponse = null\n try {\n ttsResponse = await axios(ttsRequest)\n } catch (err) {\n reject(new Error(`TTS \"${msg.messageText}\" failed - ${this._getAxiosErrOutput(err)}`))\n }\n if (Buffer.isBuffer(ttsResponse.data)) {\n const request = JSON.stringify({\n METHOD: 'sendAudio',\n PESQ: false,\n sessionId: this.sessionId,\n b64_buffer: ttsResponse.data.toString('base64')\n })\n msg.attachments.push({\n name: 'tts.wav',\n mimeType: 'audio/wav',\n base64: ttsResponse.data.toString('base64')\n })\n this.ws.send(request)\n } else {\n reject(new Error(`TTS failed, response is: ${this._getAxiosShortenedOutput(ttsResponse.data)}`))\n }\n }\n }\n if (msg && msg.media && msg.media.length > 0 && msg.media[0].buffer) {\n const request = JSON.stringify({\n METHOD: 'sendAudio',\n sessionId: this.sessionId,\n b64_buffer: msg.media[0].buffer.toString('base64')\n })\n msg.attachments.push({\n name: msg.media[0].mediaUri,\n mimeType: msg.media[0].mimeType,\n base64: msg.media[0].buffer.toString('base64')\n })\n this.ws.send(request)\n }\n resolve()\n }, 500)\n })\n }\n\n async Stop () {\n debug('Stop called')\n const request = JSON.stringify({\n METHOD: 'stopCall',\n sessionId: this.sessionId\n })\n this.ws.send(request)\n await new Promise(resolve => {\n setTimeout(resolve, 50000)\n setInterval(() => {\n if (this.end) {\n resolve()\n }\n }, 1000)\n })\n\n if (this.ws) {\n this.ws.close()\n }\n this.wsOpened = false\n this.ws = null\n this.view = {}\n }\n\n _getParams (capParams) {\n if (this.caps[capParams]) {\n if (_.isString(this.caps[capParams])) return JSON.parse(this.caps[capParams])\n else return this.caps[capParams]\n }\n return {}\n }\n\n _getBody (capBody) {\n if (this.caps[capBody]) {\n if (_.isString(this.caps[capBody])) return JSON.parse(this.caps[capBody])\n else return this.caps[capBody]\n }\n return null\n }\n\n _getHeaders (capHeaders) {\n if (this.caps[capHeaders]) {\n if (_.isString(this.caps[capHeaders])) return JSON.parse(this.caps[capHeaders])\n else return this.caps[capHeaders]\n }\n return {}\n }\n\n _getAxiosUrl (baseUrl, extUrl) {\n return baseUrl.substr(0, baseUrl.indexOf('/', 8)) + extUrl\n }\n\n _getAxiosShortenedOutput (data) {\n if (data) {\n if (_.isBuffer(data)) {\n try {\n data = data.toString()\n } catch (err) {\n }\n }\n return _.truncate(_.isString(data) ? data : JSON.stringify(data), { length: 200 })\n } else {\n return ''\n }\n }\n\n _getAxiosErrOutput (err) {\n if (err && err.response) {\n return `Status: ${err.response.status} / Response: ${this._getAxiosShortenedOutput(err.response.data)}`\n } else {\n return err.message\n }\n }\n}\n\nmodule.exports = BotiumConnectorVoip\n","const BotiumConnectorVoip = require('./src/connector')\n\nmodule.exports = {\n PluginVersion: 1,\n PluginClass: BotiumConnectorVoip,\n PluginDesc: {\n name: 'Voice over IP',\n provider: 'Botium',\n features: {\n audioInput: true\n },\n capabilities: [\n {\n name: 'VOIP_STT',\n label: 'Speech Recognition Profile',\n type: 'speechrecognitionprofile',\n required: true\n },\n {\n name: 'VOIP_TTS',\n label: 'Speech Synthesis Profile',\n type: 'speechsynthesisprofile',\n required: true\n }\n ]\n }\n}\n"],"names":["v4","uuidv4","require$$0","debug","require$$1","Capabilities","VOIP_STT_URL_STREAM","VOIP_STT_PARAMS_STREAM","VOIP_STT_METHOD_STREAM","VOIP_STT_BODY_STREAM","VOIP_STT_HEADERS","VOIP_STT_TIMEOUT","VOIP_TTS_URL","VOIP_TTS_PARAMS","VOIP_TTS_METHOD","VOIP_TTS_BODY","VOIP_TTS_HEADERS","VOIP_TTS_TIMEOUT","VOIP_WORKER_URL","VOIP_WORKER_APIKEY","VOIP_SIP_POOL_CALLER_ENABLE","VOIP_SIP_CALLER_REGISTRAR_URI","VOIP_SIP_CALLER_ADDRESS","VOIP_SIP_CALLER_USERNAME","VOIP_SIP_CALLER_PASSWORD","VOIP_SIP_PROXY","VOIP_SIP_REG_HEADERS","VOIP_SIP_INVITE_HEADERS","VOIP_SIP_CALLEE_URI","VOIP_ICE_ENABLE","VOIP_ICE_STUN_SERVERS","VOIP_ICE_TURN_ENABLE","VOIP_ICE_TURN_SERVER","VOIP_ICE_TURN_USER","VOIP_ICE_TURN_PASSWORD","VOIP_ICE_TURN_PROTOCOL","Defaults","VOIP_STT_METHOD","BotiumConnectorVoip","constructor","queueBotSays","eventEmitter","caps","Validate","axiosTtsParams","url","params","_getParams","method","timeout","headers","_getHeaders","data","axios","_getAxiosUrl","status","_getAxiosShortenedOutput","Error","err","_getAxiosErrOutput","Object","assign","Start","view","container","context","msg","botium","conversationId","stepId","fullRecord","end","Promise","resolve","reject","ws","WebSocket","_","isArray","split","wsOpened","on","VOIP_WORKER_ENDPOINT","request","METHOD","API_KEY","SIP_CALLER_AUTO","SIP_PROXY","SIP_CALLER_URI","VOIP_SIP_CALLER_URI","SIP_CALLER_USERNAME","SIP_CALLER_PASSWORD","SIP_CALLER_ADDRESS","SIP_CALLER_REGISTRAR_URI","SIP_CALLEE_URI","SIP_REG_HEADERS","SIP_INVITE_HEADERS","ICE_ENABLE","ICE_STUN_SERVERS","ICE_TURN_SERVER","ICE_TURN_USERNAME","ICE_TURN_PASSWORD","ICE_TURN_PROTOCOL","STT_CONFIG","stt_url","stt_params","stt_body","TTS_CONFIG","tts_url","tts_params","tts_body","send","JSON","stringify","message","parsedData","parse","botMsgs","type","sessionId","voipConfig","emit","name","mimeType","base64","Stop","final","botMsg","messageText","sourceData","push","forEach","setTimeout","UserSays","attachments","buttons","length","digits","payload","ttsRequest","text","_getBody","BSP_TTS_BODY","responseType","ttsResponse","Buffer","isBuffer","PESQ","b64_buffer","toString","media","buffer","mediaUri","setInterval","close","capParams","isString","capBody","capHeaders","baseUrl","extUrl","substr","indexOf","truncate","response","PluginVersion","PluginClass","PluginDesc","provider","features","audioInput","capabilities","label","required"],"mappings":"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"}
1
+ {"version":3,"file":"botium-connector-voip-es.js","sources":["../src/connector.js","../index.js"],"sourcesContent":["const { v4: uuidv4 } = require('uuid')\nconst WebSocket = require('ws')\nconst _ = require('lodash')\nconst axios = require('axios')\nconst debug = require('debug')('botium-connector-voip')\n\nconst Capabilities = {\n VOIP_STT_URL_STREAM: 'VOIP_STT_URL_STREAM',\n VOIP_STT_PARAMS_STREAM: 'VOIP_STT_PARAMS_STREAM',\n VOIP_STT_METHOD_STREAM: 'VOIP_STT_METHOD_STREAM',\n VOIP_STT_BODY_STREAM: 'VOIP_STT_BODY_STREAM',\n VOIP_STT_BODY: 'VOIP_STT_BODY',\n VOIP_STT_HEADERS: 'VOIP_STT_HEADERS',\n VOIP_STT_TIMEOUT: 'VOIP_STT_TIMEOUT',\n VOIP_STT_MESSAGE_HANDLING: 'VOIP_STT_MESSAGE_HANDLING',\n VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 'VOIP_STT_MESSAGE_HANDLING_TIMEOUT',\n VOIP_STT_MESSAGE_HANDLING_DELIMITER: 'VOIP_STT_MESSAGE_HANDLING_DELIMITER',\n VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: 'VOIP_STT_MESSAGE_HANDLING_PUNCTUATION',\n VOIP_TTS_URL: 'VOIP_TTS_URL',\n VOIP_TTS_PARAMS: 'VOIP_TTS_PARAMS',\n VOIP_TTS_METHOD: 'VOIP_TTS_METHOD',\n VOIP_TTS_BODY: 'VOIP_TTS_BODY',\n VOIP_TTS_HEADERS: 'VOIP_TTS_HEADERS',\n VOIP_TTS_TIMEOUT: 'VOIP_TTS_TIMEOUT',\n VOIP_WORKER_URL: 'VOIP_WORKER_URL',\n VOIP_WORKER_APIKEY: 'VOIP_WORKER_APIKEY',\n VOIP_SIP_POOL_CALLER_ENABLE: 'VOIP_SIP_POOL_CALLER_ENABLE',\n VOIP_SIP_CALLER_REGISTRAR_URI: 'VOIP_SIP_CALLER_REGISTRAR_URI',\n VOIP_SIP_CALLER_ADDRESS: 'VOIP_SIP_CALLER_ADDRESS',\n VOIP_SIP_CALLER_USERNAME: 'VOIP_SIP_CALLER_USERNAME',\n VOIP_SIP_CALLER_PASSWORD: 'VOIP_SIP_CALLER_PASSWORD',\n VOIP_SIP_PROXY: 'VOIP_SIP_PROXY',\n VOIP_SIP_REG_HEADERS: 'VOIP_SIP_REG_HEADERS',\n VOIP_SIP_INVITE_HEADERS: 'VOIP_SIP_INVITE_HEADERS',\n VOIP_SIP_CALLEE_URI: 'VOIP_SIP_CALLEE_URI',\n VOIP_ICE_ENABLE: 'VOIP_ICE_ENABLE',\n VOIP_ICE_STUN_SERVERS: 'VOIP_ICE_STUN_SERVERS',\n VOIP_ICE_TURN_ENABLE: 'VOIP_ICE_TURN_ENABLE',\n VOIP_ICE_TURN_SERVER: 'VOIP_ICE_TURN_SERVER',\n VOIP_ICE_TURN_USER: 'VOIP_ICE_TURN_USER',\n VOIP_ICE_TURN_PASSWORD: 'VOIP_ICE_TURN_PASSWORD',\n VOIP_ICE_TURN_PROTOCOL: 'VOIP_ICE_TURN_PROTOCOL'\n}\n\nconst Defaults = {\n VOIP_STT_METHOD: 'POST',\n VOIP_STT_TIMEOUT: 10000,\n VOIP_TTS_METHOD: 'GET',\n VOIP_TTS_TIMEOUT: 10000,\n VOIP_STT_MESSAGE_HANDLING: 'ORIGINAL',\n VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 5000,\n VOIP_STT_MESSAGE_HANDLING_DELIMITER: '. ',\n VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: '.!?'\n}\n\nclass BotiumConnectorVoip {\n constructor ({ queueBotSays, eventEmitter, caps }) {\n this.queueBotSays = queueBotSays\n this.caps = caps\n this.eventEmitter = eventEmitter\n this.botMsgs = []\n this.sentencesBuilding = 0\n this.sentencesFinal = 0\n this.sentenceBuilding = false\n }\n\n async Validate () {\n debug('Validate called')\n debug(this.caps.VOIP_STT_MESSAGE_HANDLING)\n\n if (this.caps.VOIP_TTS_URL) {\n this.axiosTtsParams = {\n url: this.caps.VOIP_TTS_URL,\n params: this._getParams(Capabilities.VOIP_TTS_PARAMS),\n method: this.caps.VOIP_TTS_METHOD,\n timeout: this.caps.VOIP_TTS_TIMEOUT,\n headers: this._getHeaders(Capabilities.VOIP_TTS_HEADERS)\n }\n try {\n const { data } = await axios({\n ...this.axiosTtsParams,\n url: this._getAxiosUrl(this.caps.VOIP_TTS_URL, '/api/status')\n })\n if (data && data.status === 'OK') {\n debug(`Checking TTS Status response: ${this._getAxiosShortenedOutput(data)}`)\n } else {\n throw new Error(`Checking TTS Status failed, response is: ${this._getAxiosShortenedOutput(data)}`)\n }\n } catch (err) {\n throw new Error(`Checking TTS Status failed - ${this._getAxiosErrOutput(err)}`)\n }\n }\n\n this.caps = Object.assign({}, Defaults, this.caps)\n }\n\n async Start () {\n debug('Start called')\n debug(this.caps[Capabilities.VOIP_TTS_URL])\n\n this.view = {\n container: this,\n context: {},\n msg: {},\n botium: {\n conversationId: uuidv4(),\n stepId: null\n }\n }\n\n this.fullRecord = ''\n this.end = false\n\n const sendBotMsg = (botMsg) => { setTimeout(() => this.queueBotSays(botMsg), 0) }\n\n const buildBotMsg = botMsgs => {\n if (botMsgs.length === 1) return botMsgs[0]\n const botMsg = {}\n botMsg.messageText = botMsgs.map(m => m.messageText).join(this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_DELIMITER])\n botMsg.sourceData = botMsgs.map(m => m.sourceData)\n return botMsg\n }\n\n const expandBotMsgs = botMsgs => {\n const splitSentences = s => s.match(new RegExp(`[^${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+[${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+`, 'g'))\n const botMsgsFinal = []\n for (const botMsg of botMsgs) {\n const sentences = splitSentences(botMsg.messageText)\n if (_.isNil(sentences)) {\n botMsgsFinal.push(botMsg)\n } else {\n for (const sentence of sentences) {\n botMsgsFinal.push({\n messageText: sentence,\n sourceData: botMsg.sourceData\n })\n }\n }\n }\n return botMsgsFinal\n }\n\n return new Promise((resolve, reject) => {\n this.ws = new WebSocket(this.caps[Capabilities.VOIP_WORKER_URL])\n\n if (!_.isArray(this.caps[Capabilities.VOIP_ICE_STUN_SERVERS])) {\n if (this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] === '') {\n this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = []\n } else {\n this.caps[Capabilities.VOIP_ICE_STUN_SERVERS] = this.caps[Capabilities.VOIP_ICE_STUN_SERVERS].split(',')\n }\n }\n\n this.wsOpened = false\n this.ws.on('open', () => {\n this.wsOpened = true\n debug(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_ENDPOINT]} opened.`)\n const request = {\n METHOD: 'initCall',\n API_KEY: this.caps[Capabilities.VOIP_WORKER_APIKEY],\n SIP_CALLER_AUTO: this.caps[Capabilities.VOIP_SIP_POOL_CALLER_ENABLE],\n SIP_PROXY: this.caps[Capabilities.VOIP_SIP_PROXY],\n SIP_CALLER_URI: this.caps[Capabilities.VOIP_SIP_CALLER_URI],\n SIP_CALLER_USERNAME: this.caps[Capabilities.VOIP_SIP_CALLER_USERNAME],\n SIP_CALLER_PASSWORD: this.caps[Capabilities.VOIP_SIP_CALLER_PASSWORD],\n SIP_CALLER_ADDRESS: this.caps[Capabilities.VOIP_SIP_CALLER_ADDRESS],\n SIP_CALLER_REGISTRAR_URI: this.caps[Capabilities.VOIP_SIP_CALLER_REGISTRAR_URI],\n SIP_CALLEE_URI: this.caps[Capabilities.VOIP_SIP_CALLEE_URI],\n SIP_REG_HEADERS: this.caps[Capabilities.VOIP_SIP_REG_HEADERS],\n SIP_INVITE_HEADERS: this.caps[Capabilities.VOIP_SIP_INVITE_HEADERS],\n ICE_ENABLE: this.caps[Capabilities.VOIP_ICE_ENABLE],\n ICE_STUN_SERVERS: this.caps[Capabilities.VOIP_ICE_STUN_SERVERS],\n ICE_TURN_SERVER: this.caps[Capabilities.VOIP_ICE_TURN_SERVER],\n ICE_TURN_USERNAME: this.caps[Capabilities.VOIP_ICE_TURN_USER],\n ICE_TURN_PASSWORD: this.caps[Capabilities.VOIP_ICE_TURN_PASSWORD],\n ICE_TURN_PROTOCOL: this.caps[Capabilities.VOIP_ICE_TURN_PROTOCOL] || 'TCP',\n STT_CONFIG: {\n stt_url: this.caps[Capabilities.VOIP_STT_URL_STREAM],\n stt_params: this.caps[Capabilities.VOIP_STT_PARAMS_STREAM],\n stt_body: this.caps[Capabilities.VOIP_STT_BODY_STREAM] || null\n },\n TTS_CONFIG: {\n tts_url: this.caps[Capabilities.VOIP_TTS_URL],\n tts_params: this.caps[Capabilities.VOIP_TTS_PARAMS],\n tts_body: this.caps[Capabilities.VOIP_TTS_BODY] || null\n }\n }\n debug(JSON.stringify(request, null, 2))\n this.ws.send(JSON.stringify(request))\n })\n this.ws.on('close', async () => {\n debug(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} closed.`)\n })\n this.ws.on('error', (err) => {\n debug(err)\n if (!this.wsOpened) {\n this.end = true\n reject(new Error(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} error: ${err.message || err}`))\n }\n })\n this.ws.on('message', async (data) => {\n const parsedData = JSON.parse(data)\n\n const parsedDataLog = _.cloneDeep(parsedData)\n parsedDataLog.fullRecord = '<full_record_buffer>'\n\n debug(JSON.stringify(parsedDataLog, null, 2))\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'initialized') {\n this.sessionId = parsedData.voipConfig.sessionId\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'unauthorized') {\n reject(new Error('Error: Cannot open a call: SIP Authorization failed'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event !== 'onCallRegState') {\n reject(new Error('Error: Cannot connect to VOIP Worker because of wrong API key'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event === 'onCallRegState') {\n reject(new Error('Error: Sip Registration failed'))\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'connected') {\n resolve()\n }\n\n if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'disconnected') {\n const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_STT_BODY))\n if (parsedData.connectDuration && parsedData.connectDuration > 0) {\n this.eventEmitter.emit('CONSUMPTION_METADATA', this.container, {\n type: _.isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',\n metricName: 'consumption.e2e.voip.stt.seconds',\n credits: parsedData.connectDuration,\n apiKey\n })\n }\n }\n\n if (parsedData && parsedData.type === 'error') {\n reject(new Error(`Error: ${parsedData.message}`))\n }\n\n if (parsedData && parsedData.type === 'fullRecord') {\n this.end = true\n this.eventEmitter.emit('MESSAGE_ATTACHMENT', this.container, {\n name: 'full_record.wav',\n mimeType: 'audio/wav',\n base64: parsedData.fullRecord\n })\n this.Stop()\n }\n\n if (parsedData && parsedData.data && parsedData.data.final === false) {\n if (!this.sentenceBuilding) {\n this.sentenceBuilding = true\n this.sentencesBuilding++\n }\n }\n\n if (parsedData && parsedData.data && parsedData.data.final) {\n const botMsg = { messageText: parsedData.data.message, sourceData: parsedData }\n this.botMsgs.push(botMsg)\n if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'ORIGINAL') {\n this.botMsgs.forEach(botMsg => sendBotMsg(botMsg))\n this.botMsgs = []\n }\n if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'EXPAND') {\n const botMsgsExpanded = expandBotMsgs(this.botMsgs)\n botMsgsExpanded.forEach(botMsg => sendBotMsg(botMsg))\n this.botMsgs = []\n }\n if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'CONCAT') {\n this.sentenceBuilding = false\n this.sentencesFinal++\n\n clearTimeout(this.sendMessageTimeout)\n this.sendMessageTimeout = setTimeout(() => {\n if (this.sentenceBuilding === false && this.sentencesBuilding === this.sentencesFinal) {\n sendBotMsg(buildBotMsg(this.botMsgs))\n this.botMsgs = []\n this.sentencesBuilding = 0\n this.sentencesFinal = 0\n }\n }, this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_TIMEOUT])\n }\n }\n })\n })\n }\n\n async UserSays (msg) {\n debug('UserSays called')\n\n debug(msg)\n\n if (!msg.attachments) {\n msg.attachments = []\n }\n return new Promise((resolve, reject) => {\n setTimeout(async () => {\n let duration = 0\n if (msg && msg.buttons && msg.buttons.length > 0) {\n const request = JSON.stringify({\n METHOD: 'sendDtmf',\n digits: msg.buttons[0].payload,\n sessionId: this.sessionId\n })\n this.ws.send(request)\n } else if (msg && msg.messageText) {\n if (!this.axiosTtsParams) reject(new Error('TTS not configured, only audio input supported'))\n if (this.axiosTtsParams) {\n const ttsRequest = {\n ...this.axiosTtsParams,\n params: {\n ...(this.axiosTtsParams.params || {}),\n text: msg.messageText\n },\n data: this._getBody(Capabilities.VOIP_TTS_BODY),\n responseType: 'arraybuffer'\n }\n msg.sourceData = ttsRequest\n\n let ttsResponse = null\n try {\n ttsResponse = await axios(ttsRequest)\n } catch (err) {\n reject(new Error(`TTS \"${msg.messageText}\" failed - ${this._getAxiosErrOutput(err)}`))\n }\n if (msg && msg.messageText && msg.messageText.length > 0) {\n const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_TTS_BODY))\n this.eventEmitter.emit('CONSUMPTION_METADATA', this.container, {\n type: _.isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',\n metricName: 'consumption.e2e.voip.tts.characters',\n credits: msg.messageText.length,\n apiKey\n })\n }\n if (Buffer.isBuffer(ttsResponse.data)) {\n duration = ttsResponse.headers['content-duration']\n const request = JSON.stringify({\n METHOD: 'sendAudio',\n PESQ: false,\n sessionId: this.sessionId,\n b64_buffer: ttsResponse.data.toString('base64')\n })\n msg.attachments.push({\n name: 'tts.wav',\n mimeType: 'audio/wav',\n base64: ttsResponse.data.toString('base64')\n })\n this.ws.send(request)\n } else {\n reject(new Error(`TTS failed, response is: ${this._getAxiosShortenedOutput(ttsResponse.data)}`))\n }\n }\n }\n if (msg && msg.media && msg.media.length > 0 && msg.media[0].buffer) {\n const { data } = await axios({\n method: 'post',\n data: msg.media[0].buffer,\n headers: {\n ...this._getHeaders(Capabilities.VOIP_TTS_HEADERS),\n 'Content-Type': 'audio/wave'\n },\n url: this._getAxiosUrl(this.caps.VOIP_TTS_URL, '/api/audio/info'),\n maxContentLength: Infinity,\n maxBodyLength: Infinity\n })\n if (data && data.duration) {\n duration = parseInt(data.duration)\n }\n const request = JSON.stringify({\n METHOD: 'sendAudio',\n sessionId: this.sessionId,\n b64_buffer: msg.media[0].buffer.toString('base64')\n })\n msg.attachments.push({\n name: msg.media[0].mediaUri,\n mimeType: msg.media[0].mimeType,\n base64: msg.media[0].buffer.toString('base64')\n })\n this.ws.send(request)\n }\n setTimeout(resolve, duration * 1000)\n }, 0)\n })\n }\n\n async Stop () {\n debug('Stop called')\n const request = JSON.stringify({\n METHOD: 'stopCall',\n sessionId: this.sessionId\n })\n this.ws.send(request)\n await new Promise(resolve => {\n setTimeout(resolve, 50000)\n setInterval(() => {\n if (this.end) {\n resolve()\n }\n }, 1000)\n })\n\n if (this.ws) {\n this.ws.close()\n }\n this.wsOpened = false\n this.ws = null\n this.view = {}\n }\n\n _getParams (capParams) {\n if (this.caps[capParams]) {\n if (_.isString(this.caps[capParams])) return JSON.parse(this.caps[capParams])\n else return this.caps[capParams]\n }\n return {}\n }\n\n _getBody (capBody) {\n if (this.caps[capBody]) {\n if (_.isString(this.caps[capBody])) return JSON.parse(this.caps[capBody])\n else return this.caps[capBody]\n }\n return null\n }\n\n _getHeaders (capHeaders) {\n if (this.caps[capHeaders]) {\n if (_.isString(this.caps[capHeaders])) return JSON.parse(this.caps[capHeaders])\n else return this.caps[capHeaders]\n }\n return {}\n }\n\n _getAxiosUrl (baseUrl, extUrl) {\n return baseUrl.substr(0, baseUrl.indexOf('/', 8)) + extUrl\n }\n\n _getAxiosShortenedOutput (data) {\n if (data) {\n if (_.isBuffer(data)) {\n try {\n data = data.toString()\n } catch (err) {\n }\n }\n return _.truncate(_.isString(data) ? data : JSON.stringify(data), { length: 200 })\n } else {\n return ''\n }\n }\n\n _getAxiosErrOutput (err) {\n if (err && err.response) {\n return `Status: ${err.response.status} / Response: ${this._getAxiosShortenedOutput(err.response.data)}`\n } else {\n return err.message\n }\n }\n\n _extractApiKey (body) {\n return _.get(body, 'polly.credentials.accessKeyId') ||\n _.get(body, 'google.credentials.client_email') ||\n _.get(body, 'ibm.credentials.apikey') ||\n _.get(body, 'awstranscribe.credentials.accessKeyId') ||\n _.get(body, 'azure.credentials.subscriptionKey') ||\n null\n }\n}\n\nmodule.exports = BotiumConnectorVoip\n","const BotiumConnectorVoip = require('./src/connector')\n\nmodule.exports = {\n PluginVersion: 1,\n PluginClass: BotiumConnectorVoip,\n PluginDesc: {\n name: 'Voice over IP',\n provider: 'Botium',\n features: {\n audioInput: true,\n e2eTesting: true\n },\n capabilities: [\n {\n name: 'VOIP_STT',\n label: 'Speech Recognition Profile',\n type: 'speechrecognitionprofile',\n required: true\n },\n {\n name: 'VOIP_TTS',\n label: 'Speech Synthesis Profile',\n type: 'speechsynthesisprofile',\n required: true\n }\n ]\n }\n}\n"],"names":["v4","uuidv4","require$$0","debug","require$$1","Capabilities","VOIP_STT_URL_STREAM","VOIP_STT_PARAMS_STREAM","VOIP_STT_METHOD_STREAM","VOIP_STT_BODY_STREAM","VOIP_STT_BODY","VOIP_STT_HEADERS","VOIP_STT_TIMEOUT","VOIP_STT_MESSAGE_HANDLING","VOIP_STT_MESSAGE_HANDLING_TIMEOUT","VOIP_STT_MESSAGE_HANDLING_DELIMITER","VOIP_STT_MESSAGE_HANDLING_PUNCTUATION","VOIP_TTS_URL","VOIP_TTS_PARAMS","VOIP_TTS_METHOD","VOIP_TTS_BODY","VOIP_TTS_HEADERS","VOIP_TTS_TIMEOUT","VOIP_WORKER_URL","VOIP_WORKER_APIKEY","VOIP_SIP_POOL_CALLER_ENABLE","VOIP_SIP_CALLER_REGISTRAR_URI","VOIP_SIP_CALLER_ADDRESS","VOIP_SIP_CALLER_USERNAME","VOIP_SIP_CALLER_PASSWORD","VOIP_SIP_PROXY","VOIP_SIP_REG_HEADERS","VOIP_SIP_INVITE_HEADERS","VOIP_SIP_CALLEE_URI","VOIP_ICE_ENABLE","VOIP_ICE_STUN_SERVERS","VOIP_ICE_TURN_ENABLE","VOIP_ICE_TURN_SERVER","VOIP_ICE_TURN_USER","VOIP_ICE_TURN_PASSWORD","VOIP_ICE_TURN_PROTOCOL","Defaults","VOIP_STT_METHOD","BotiumConnectorVoip","constructor","queueBotSays","eventEmitter","caps","botMsgs","sentencesBuilding","sentencesFinal","sentenceBuilding","Validate","axiosTtsParams","url","params","_getParams","method","timeout","headers","_getHeaders","data","axios","_getAxiosUrl","status","_getAxiosShortenedOutput","Error","err","_getAxiosErrOutput","Object","assign","Start","view","container","context","msg","botium","conversationId","stepId","fullRecord","end","sendBotMsg","botMsg","setTimeout","buildBotMsg","length","messageText","map","m","join","sourceData","expandBotMsgs","splitSentences","s","match","RegExp","botMsgsFinal","sentences","_","isNil","push","sentence","Promise","resolve","reject","ws","WebSocket","isArray","split","wsOpened","on","VOIP_WORKER_ENDPOINT","request","METHOD","API_KEY","SIP_CALLER_AUTO","SIP_PROXY","SIP_CALLER_URI","VOIP_SIP_CALLER_URI","SIP_CALLER_USERNAME","SIP_CALLER_PASSWORD","SIP_CALLER_ADDRESS","SIP_CALLER_REGISTRAR_URI","SIP_CALLEE_URI","SIP_REG_HEADERS","SIP_INVITE_HEADERS","ICE_ENABLE","ICE_STUN_SERVERS","ICE_TURN_SERVER","ICE_TURN_USERNAME","ICE_TURN_PASSWORD","ICE_TURN_PROTOCOL","STT_CONFIG","stt_url","stt_params","stt_body","TTS_CONFIG","tts_url","tts_params","tts_body","JSON","stringify","send","message","parsedData","parse","parsedDataLog","cloneDeep","type","sessionId","voipConfig","event","apiKey","_extractApiKey","_getBody","connectDuration","emit","metricName","credits","name","mimeType","base64","Stop","final","forEach","botMsgsExpanded","clearTimeout","sendMessageTimeout","UserSays","attachments","duration","buttons","digits","payload","ttsRequest","text","responseType","ttsResponse","Buffer","isBuffer","PESQ","b64_buffer","toString","media","buffer","maxContentLength","Infinity","maxBodyLength","parseInt","mediaUri","setInterval","close","capParams","isString","capBody","capHeaders","baseUrl","extUrl","substr","indexOf","truncate","response","body","get","PluginVersion","PluginClass","PluginDesc","provider","features","audioInput","e2eTesting","capabilities","label","required"],"mappings":"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"}
package/index.js CHANGED
@@ -7,7 +7,8 @@ module.exports = {
7
7
  name: 'Voice over IP',
8
8
  provider: 'Botium',
9
9
  features: {
10
- audioInput: true
10
+ audioInput: true,
11
+ e2eTesting: true
11
12
  },
12
13
  capabilities: [
13
14
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "botium-connector-voip",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Botium Voice over IP Connector",
5
5
  "main": "dist/botium-connector-voip-cjs.js",
6
6
  "module": "dist/botium-connector-voip-es.js",
package/src/connector.js CHANGED
@@ -9,8 +9,13 @@ const Capabilities = {
9
9
  VOIP_STT_PARAMS_STREAM: 'VOIP_STT_PARAMS_STREAM',
10
10
  VOIP_STT_METHOD_STREAM: 'VOIP_STT_METHOD_STREAM',
11
11
  VOIP_STT_BODY_STREAM: 'VOIP_STT_BODY_STREAM',
12
+ VOIP_STT_BODY: 'VOIP_STT_BODY',
12
13
  VOIP_STT_HEADERS: 'VOIP_STT_HEADERS',
13
14
  VOIP_STT_TIMEOUT: 'VOIP_STT_TIMEOUT',
15
+ VOIP_STT_MESSAGE_HANDLING: 'VOIP_STT_MESSAGE_HANDLING',
16
+ VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 'VOIP_STT_MESSAGE_HANDLING_TIMEOUT',
17
+ VOIP_STT_MESSAGE_HANDLING_DELIMITER: 'VOIP_STT_MESSAGE_HANDLING_DELIMITER',
18
+ VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: 'VOIP_STT_MESSAGE_HANDLING_PUNCTUATION',
14
19
  VOIP_TTS_URL: 'VOIP_TTS_URL',
15
20
  VOIP_TTS_PARAMS: 'VOIP_TTS_PARAMS',
16
21
  VOIP_TTS_METHOD: 'VOIP_TTS_METHOD',
@@ -41,7 +46,11 @@ const Defaults = {
41
46
  VOIP_STT_METHOD: 'POST',
42
47
  VOIP_STT_TIMEOUT: 10000,
43
48
  VOIP_TTS_METHOD: 'GET',
44
- VOIP_TTS_TIMEOUT: 10000
49
+ VOIP_TTS_TIMEOUT: 10000,
50
+ VOIP_STT_MESSAGE_HANDLING: 'ORIGINAL',
51
+ VOIP_STT_MESSAGE_HANDLING_TIMEOUT: 5000,
52
+ VOIP_STT_MESSAGE_HANDLING_DELIMITER: '. ',
53
+ VOIP_STT_MESSAGE_HANDLING_PUNCTUATION: '.!?'
45
54
  }
46
55
 
47
56
  class BotiumConnectorVoip {
@@ -49,10 +58,15 @@ class BotiumConnectorVoip {
49
58
  this.queueBotSays = queueBotSays
50
59
  this.caps = caps
51
60
  this.eventEmitter = eventEmitter
61
+ this.botMsgs = []
62
+ this.sentencesBuilding = 0
63
+ this.sentencesFinal = 0
64
+ this.sentenceBuilding = false
52
65
  }
53
66
 
54
67
  async Validate () {
55
68
  debug('Validate called')
69
+ debug(this.caps.VOIP_STT_MESSAGE_HANDLING)
56
70
 
57
71
  if (this.caps.VOIP_TTS_URL) {
58
72
  this.axiosTtsParams = {
@@ -97,6 +111,35 @@ class BotiumConnectorVoip {
97
111
  this.fullRecord = ''
98
112
  this.end = false
99
113
 
114
+ const sendBotMsg = (botMsg) => { setTimeout(() => this.queueBotSays(botMsg), 0) }
115
+
116
+ const buildBotMsg = botMsgs => {
117
+ if (botMsgs.length === 1) return botMsgs[0]
118
+ const botMsg = {}
119
+ botMsg.messageText = botMsgs.map(m => m.messageText).join(this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_DELIMITER])
120
+ botMsg.sourceData = botMsgs.map(m => m.sourceData)
121
+ return botMsg
122
+ }
123
+
124
+ const expandBotMsgs = botMsgs => {
125
+ const splitSentences = s => s.match(new RegExp(`[^${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+[${this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_PUNCTUATION]}]+`, 'g'))
126
+ const botMsgsFinal = []
127
+ for (const botMsg of botMsgs) {
128
+ const sentences = splitSentences(botMsg.messageText)
129
+ if (_.isNil(sentences)) {
130
+ botMsgsFinal.push(botMsg)
131
+ } else {
132
+ for (const sentence of sentences) {
133
+ botMsgsFinal.push({
134
+ messageText: sentence,
135
+ sourceData: botMsg.sourceData
136
+ })
137
+ }
138
+ }
139
+ }
140
+ return botMsgsFinal
141
+ }
142
+
100
143
  return new Promise((resolve, reject) => {
101
144
  this.ws = new WebSocket(this.caps[Capabilities.VOIP_WORKER_URL])
102
145
 
@@ -142,7 +185,7 @@ class BotiumConnectorVoip {
142
185
  tts_body: this.caps[Capabilities.VOIP_TTS_BODY] || null
143
186
  }
144
187
  }
145
- debug(request)
188
+ debug(JSON.stringify(request, null, 2))
146
189
  this.ws.send(JSON.stringify(request))
147
190
  })
148
191
  this.ws.on('close', async () => {
@@ -151,38 +194,52 @@ class BotiumConnectorVoip {
151
194
  this.ws.on('error', (err) => {
152
195
  debug(err)
153
196
  if (!this.wsOpened) {
197
+ this.end = true
154
198
  reject(new Error(`Websocket connection to ${this.caps[Capabilities.VOIP_WORKER_URL]} error: ${err.message || err}`))
155
199
  }
156
200
  })
157
201
  this.ws.on('message', async (data) => {
158
202
  const parsedData = JSON.parse(data)
159
- const botMsgs = []
160
203
 
161
- debug(parsedData)
204
+ const parsedDataLog = _.cloneDeep(parsedData)
205
+ parsedDataLog.fullRecord = '<full_record_buffer>'
206
+
207
+ debug(JSON.stringify(parsedDataLog, null, 2))
162
208
 
163
209
  if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'initialized') {
164
210
  this.sessionId = parsedData.voipConfig.sessionId
165
211
  }
166
212
 
167
213
  if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'unauthorized') {
168
- reject(new Error('Cannot open a call: SIP Authorization failed'))
214
+ reject(new Error('Error: Cannot open a call: SIP Authorization failed'))
169
215
  }
170
216
 
171
- if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden') {
172
- reject(new Error('Cannot connect to VOIP Worker because of wrong API key'))
217
+ if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event !== 'onCallRegState') {
218
+ reject(new Error('Error: Cannot connect to VOIP Worker because of wrong API key'))
173
219
  }
174
220
 
175
- if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden') {
176
- debug('error')
177
- reject(new Error('Cannot connect to VOIP Worker because of wrong API key'))
221
+ if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'forbidden' && parsedData.event === 'onCallRegState') {
222
+ reject(new Error('Error: Sip Registration failed'))
178
223
  }
179
224
 
180
225
  if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'connected') {
181
226
  resolve()
182
227
  }
183
228
 
229
+ if (parsedData && parsedData.type === 'callinfo' && parsedData.status === 'disconnected') {
230
+ const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_STT_BODY))
231
+ if (parsedData.connectDuration && parsedData.connectDuration > 0) {
232
+ this.eventEmitter.emit('CONSUMPTION_METADATA', this.container, {
233
+ type: _.isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',
234
+ metricName: 'consumption.e2e.voip.stt.seconds',
235
+ credits: parsedData.connectDuration,
236
+ apiKey
237
+ })
238
+ }
239
+ }
240
+
184
241
  if (parsedData && parsedData.type === 'error') {
185
- reject(new Error(parsedData.message))
242
+ reject(new Error(`Error: ${parsedData.message}`))
186
243
  }
187
244
 
188
245
  if (parsedData && parsedData.type === 'fullRecord') {
@@ -195,12 +252,40 @@ class BotiumConnectorVoip {
195
252
  this.Stop()
196
253
  }
197
254
 
255
+ if (parsedData && parsedData.data && parsedData.data.final === false) {
256
+ if (!this.sentenceBuilding) {
257
+ this.sentenceBuilding = true
258
+ this.sentencesBuilding++
259
+ }
260
+ }
261
+
198
262
  if (parsedData && parsedData.data && parsedData.data.final) {
199
263
  const botMsg = { messageText: parsedData.data.message, sourceData: parsedData }
200
- botMsgs.push(botMsg)
264
+ this.botMsgs.push(botMsg)
265
+ if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'ORIGINAL') {
266
+ this.botMsgs.forEach(botMsg => sendBotMsg(botMsg))
267
+ this.botMsgs = []
268
+ }
269
+ if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'EXPAND') {
270
+ const botMsgsExpanded = expandBotMsgs(this.botMsgs)
271
+ botMsgsExpanded.forEach(botMsg => sendBotMsg(botMsg))
272
+ this.botMsgs = []
273
+ }
274
+ if (this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING] === 'CONCAT') {
275
+ this.sentenceBuilding = false
276
+ this.sentencesFinal++
277
+
278
+ clearTimeout(this.sendMessageTimeout)
279
+ this.sendMessageTimeout = setTimeout(() => {
280
+ if (this.sentenceBuilding === false && this.sentencesBuilding === this.sentencesFinal) {
281
+ sendBotMsg(buildBotMsg(this.botMsgs))
282
+ this.botMsgs = []
283
+ this.sentencesBuilding = 0
284
+ this.sentencesFinal = 0
285
+ }
286
+ }, this.caps[Capabilities.VOIP_STT_MESSAGE_HANDLING_TIMEOUT])
287
+ }
201
288
  }
202
-
203
- botMsgs.forEach(botMsg => setTimeout(() => this.queueBotSays(botMsg), 0))
204
289
  })
205
290
  })
206
291
  }
@@ -215,6 +300,7 @@ class BotiumConnectorVoip {
215
300
  }
216
301
  return new Promise((resolve, reject) => {
217
302
  setTimeout(async () => {
303
+ let duration = 0
218
304
  if (msg && msg.buttons && msg.buttons.length > 0) {
219
305
  const request = JSON.stringify({
220
306
  METHOD: 'sendDtmf',
@@ -231,7 +317,7 @@ class BotiumConnectorVoip {
231
317
  ...(this.axiosTtsParams.params || {}),
232
318
  text: msg.messageText
233
319
  },
234
- data: this._getBody(Capabilities.BSP_TTS_BODY),
320
+ data: this._getBody(Capabilities.VOIP_TTS_BODY),
235
321
  responseType: 'arraybuffer'
236
322
  }
237
323
  msg.sourceData = ttsRequest
@@ -242,7 +328,17 @@ class BotiumConnectorVoip {
242
328
  } catch (err) {
243
329
  reject(new Error(`TTS "${msg.messageText}" failed - ${this._getAxiosErrOutput(err)}`))
244
330
  }
331
+ if (msg && msg.messageText && msg.messageText.length > 0) {
332
+ const apiKey = this._extractApiKey(this._getBody(Capabilities.VOIP_TTS_BODY))
333
+ this.eventEmitter.emit('CONSUMPTION_METADATA', this.container, {
334
+ type: _.isNil(apiKey) ? 'INBUILT' : 'THIRD_PARTY',
335
+ metricName: 'consumption.e2e.voip.tts.characters',
336
+ credits: msg.messageText.length,
337
+ apiKey
338
+ })
339
+ }
245
340
  if (Buffer.isBuffer(ttsResponse.data)) {
341
+ duration = ttsResponse.headers['content-duration']
246
342
  const request = JSON.stringify({
247
343
  METHOD: 'sendAudio',
248
344
  PESQ: false,
@@ -261,6 +357,20 @@ class BotiumConnectorVoip {
261
357
  }
262
358
  }
263
359
  if (msg && msg.media && msg.media.length > 0 && msg.media[0].buffer) {
360
+ const { data } = await axios({
361
+ method: 'post',
362
+ data: msg.media[0].buffer,
363
+ headers: {
364
+ ...this._getHeaders(Capabilities.VOIP_TTS_HEADERS),
365
+ 'Content-Type': 'audio/wave'
366
+ },
367
+ url: this._getAxiosUrl(this.caps.VOIP_TTS_URL, '/api/audio/info'),
368
+ maxContentLength: Infinity,
369
+ maxBodyLength: Infinity
370
+ })
371
+ if (data && data.duration) {
372
+ duration = parseInt(data.duration)
373
+ }
264
374
  const request = JSON.stringify({
265
375
  METHOD: 'sendAudio',
266
376
  sessionId: this.sessionId,
@@ -273,8 +383,8 @@ class BotiumConnectorVoip {
273
383
  })
274
384
  this.ws.send(request)
275
385
  }
276
- resolve()
277
- }, 500)
386
+ setTimeout(resolve, duration * 1000)
387
+ }, 0)
278
388
  })
279
389
  }
280
390
 
@@ -351,6 +461,15 @@ class BotiumConnectorVoip {
351
461
  return err.message
352
462
  }
353
463
  }
464
+
465
+ _extractApiKey (body) {
466
+ return _.get(body, 'polly.credentials.accessKeyId') ||
467
+ _.get(body, 'google.credentials.client_email') ||
468
+ _.get(body, 'ibm.credentials.apikey') ||
469
+ _.get(body, 'awstranscribe.credentials.accessKeyId') ||
470
+ _.get(body, 'azure.credentials.subscriptionKey') ||
471
+ null
472
+ }
354
473
  }
355
474
 
356
475
  module.exports = BotiumConnectorVoip