@tiledesk/tiledesk-voice-twilio-connector 0.1.26 → 0.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -157,32 +157,48 @@ router.post('/webhook/:id_project', async (req, res) => {
157
157
  }
158
158
  let end2 = new Date().getTime();
159
159
 
160
- //let conversation_id = await tdChannel.getConversation(ani, callId, user.token);
161
- let conversation_id = await tdChannel.generateConversation(from, callSid, user.token);
160
+ // Parallelizza generateConversation e recupero chiavi di integrazione
161
+ let [conversation_id, openaiKeyResult, elevenLabsKey] = await Promise.all([
162
+ //let conversation_id = await tdChannel.getConversation(ani, callId, user.token);
163
+ tdChannel.generateConversation(from, callSid, user.token),
164
+
165
+ // Recupero chiave OpenAI (con fallback sequenziale)
166
+ (async () => {
167
+ try {
168
+ let key = await integrationService.getKeyFromIntegrations(project_id, 'openai', settings.token)
169
+ if (!key) {
170
+ winston.debug("(voice) - Key not found in Integrations. Searching in kb settings...");
171
+ key = await integrationService.getKeyFromKbSettings(project_id, settings.token);
172
+ }
173
+ if (!key) {
174
+ winston.debug("(voice) - Retrieve public gptkey")
175
+ key = GPT_KEY;
176
+ return { key, publicKey: true };
177
+ }
178
+ return { key, publicKey: false };
179
+ } catch (error) {
180
+ winston.error('(voice) - Error retrieving OpenAI key:', error);
181
+ return { key: GPT_KEY, publicKey: true };
182
+ }
183
+ })(),
184
+
185
+ // Recupero chiave ElevenLabs in parallelo
186
+ integrationService.getKeyFromIntegrations(project_id, 'elevenlabs', settings.token).catch((error) => {
187
+ winston.error('(voice) - Error retrieving ElevenLabs key:', error);
188
+ return null;
189
+ })
190
+ ]);
191
+
162
192
  winston.debug("(voice) conversation returned:"+ conversation_id);
163
193
 
164
- let integrations = [], publicKey = false;
165
- try {
166
- //GET AND SAVE GPT-KET IF
167
- let key = await integrationService.getKeyFromIntegrations(project_id, 'openai', settings.token)
168
- if (!key) {
169
- winston.debug("(voice) - Key not found in Integrations. Searching in kb settings...");
170
- key = await integrationService.getKeyFromKbSettings(project_id, settings.token);
171
- }
172
- if (!key) {
173
- winston.debug("(voice) - Retrieve public gptkey")
174
- key = GPT_KEY;
175
- publicKey = true;
176
- }
177
- integrations.push({type: 'openai', key: key, publicKey: publicKey})
178
-
179
- let eleven_labs = await integrationService.getKeyFromIntegrations(project_id, 'elevenlabs', settings.token)
180
- if (eleven_labs) {
181
- winston.debug("(voice) - Key found in Integrations: "+ eleven_labs);
182
- integrations.push({type: 'elevenlabs', key: eleven_labs, publicKey: false})
183
- }
184
- } catch (error) {
185
- winston.error('(voice) - Error retrieving integrations keys:', error);
194
+ // Costruisci array integrations
195
+ let integrations = [];
196
+ if (openaiKeyResult && openaiKeyResult.key) {
197
+ integrations.push({type: 'openai', key: openaiKeyResult.key, publicKey: openaiKeyResult.publicKey})
198
+ }
199
+ if (elevenLabsKey) {
200
+ winston.debug("(voice) - Key found in Integrations: "+ elevenLabsKey);
201
+ integrations.push({type: 'elevenlabs', key: elevenLabsKey, publicKey: false})
186
202
  }
187
203
 
188
204
  //save data to redis
@@ -195,16 +211,8 @@ router.post('/webhook/:id_project', async (req, res) => {
195
211
  conversation_id: conversation_id,
196
212
  integrations: integrations
197
213
  }
198
- if (!redis_client) {
199
- return res.status(500).send({ message: "Redis not ready. Check redis connection..." })
200
- }
201
- //for (const [key, value] of Object.entries(redis_data)){
202
- // await redis_client.hSet('tiledesk:voice:'+callId, key, JSON.stringify(value))
203
- //}
204
- //await redis_client.expire('tiledesk:voice:'+callId, 86400)
205
-
206
- await redis_client.set('tiledesk:voice:'+callSid+':session', JSON.stringify(session_data), {'EX': 86400});
207
-
214
+ voiceChannel.setSessionForCallId(callSid, session_data)
215
+
208
216
  let tiledeskMessage= {
209
217
  text:'/start',
210
218
  senderFullname: from,
@@ -240,12 +248,16 @@ router.post('/webhook/:id_project', async (req, res) => {
240
248
  let messageToVXML = await tdTranslator.toVXML(message, callSid, vxmlAttributes, session_data)
241
249
  winston.debug('(voice) /webhook/:id_project messageVXML-->'+ messageToVXML)
242
250
 
243
- let end_call = new Date().getTime();
244
- winston.info(`Time to respond to /webhook/${project_id}: ${(end_call-start_call)}[ms]`)
251
+ let end_call1 = new Date().getTime();
252
+ winston.info(`Time to respond to /webhook/${project_id} before response: ${(end_call1-start_call)}[ms]`)
245
253
 
254
+
246
255
  // Render the response as XML in reply to the webhook request
247
256
  res.set('Content-Type', 'text/xml');
248
257
  res.status(200).send(messageToVXML);
258
+
259
+ let end_call2 = new Date().getTime();
260
+ winston.info(`Time to respond to /webhook/${project_id}: ${(end_call2-start_call)}[ms]`)
249
261
  });
250
262
 
251
263
 
@@ -262,8 +274,7 @@ router.post('/nextblock_old/:callSid/', async(req, res) => {
262
274
  let project_id, conversation_id, user;
263
275
  let from, to;
264
276
 
265
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
266
- //let redis_data = await redis_client.hGetAll('tiledesk:voice:'+callId);
277
+ let redis_data = await voiceChannel.getSessionForCallId(callSid)
267
278
  if (!redis_data) {
268
279
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
269
280
  }
@@ -345,16 +356,13 @@ router.post('/nextblock/:callSid/', async(req, res) => {
345
356
  let confidence = req.body.Confidence
346
357
  let callSid = req.params.callSid;
347
358
 
348
- let sessionInfo;
349
359
  let project_id, conversation_id, user;
350
360
  let from, to;
351
361
 
352
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
353
- //let redis_data = await redis_client.hGetAll('tiledesk:voice:'+callId);
354
- if (!redis_data) {
362
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
363
+ if (!sessionInfo) {
355
364
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
356
365
  }
357
- sessionInfo = JSON.parse(redis_data)
358
366
  project_id = sessionInfo.project_id;
359
367
  from = sessionInfo.from;
360
368
  to = sessionInfo.to;
@@ -465,7 +473,7 @@ async function getMessage(callSid, ani, project_id, conversation_id){
465
473
  if (queue && queue.length > 0) {
466
474
  //CASE: queue has at least one message to reproduce --> get message from tiledesk queue and reset delayTime
467
475
  message = queue[0]
468
- winston.debug('[getMessage] QUEUE --> '+ queue[0].text, queue[0])
476
+ winston.verbose('[getMessage] QUEUE --> '+ queue[0].text)
469
477
 
470
478
  // remove message from queue and reset delayIndex
471
479
  await tdChannel.removeMessageFromQueue(conversation_id, message._id)
@@ -486,7 +494,7 @@ async function getMessage(callSid, ani, project_id, conversation_id){
486
494
  }
487
495
 
488
496
  message = queue[0]
489
- winston.debug(`[getMessage] Message received from subscription: ${message.text}`, message);
497
+ winston.verbose(`[getMessage] Message received from subscription: ${message.text}`);
490
498
 
491
499
  // remove message from queue and reset delayIndex
492
500
  await tdChannel.removeMessageFromQueue(conversation_id, message._id)
@@ -528,16 +536,13 @@ router.post('/speechresult/:callSid', async (req, res) => {
528
536
  let confidence = req.body.Confidence
529
537
  let callSid = req.params.callSid;
530
538
 
531
- let sessionInfo;
532
539
  let project_id, conversation_id, user;
533
540
  let from, to;
534
541
 
535
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
536
- //let redis_data = await redis_client.hGetAll('tiledesk:voice:'+callId);
537
- if (!redis_data) {
542
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
543
+ if (!sessionInfo) {
538
544
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
539
545
  }
540
- sessionInfo = JSON.parse(redis_data)
541
546
  project_id = sessionInfo.project_id;
542
547
  from = sessionInfo.from;
543
548
  to = sessionInfo.to;
@@ -623,15 +628,13 @@ router.post('/record/action/:callSid/',async (req, res) => {
623
628
  let start_call = new Date();
624
629
 
625
630
  let callSid = req.body.CallSid;
626
- let sessionInfo;
627
631
  let project_id, conversation_id, user;
628
632
  let from, to;
629
633
 
630
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
631
- if (!redis_data) {
634
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
635
+ if (!sessionInfo) {
632
636
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
633
637
  }
634
- sessionInfo = JSON.parse(redis_data)
635
638
  project_id = sessionInfo.project_id;
636
639
  from = sessionInfo.from;
637
640
  to = sessionInfo.to;
@@ -692,16 +695,13 @@ router.post('/record/callback/:callSid/',async (req, res) => {
692
695
  let button_action = req.query.button_action ? '#' + req.query.button_action : '';
693
696
  let previousIntentName = req.query.intentName || '';
694
697
 
695
-
696
- let sessionInfo;
697
698
  let project_id, conversation_id, user;
698
699
  let from, to;
699
700
 
700
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
701
- if (!redis_data) {
701
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
702
+ if (!sessionInfo) {
702
703
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
703
704
  }
704
- sessionInfo = JSON.parse(redis_data)
705
705
  project_id = sessionInfo.project_id;
706
706
  from = sessionInfo.from;
707
707
  to = sessionInfo.to;
@@ -799,16 +799,13 @@ router.post('/menublock/:callSid', async (req, res) => {
799
799
  winston.debug("(voice) button menu: ", button);
800
800
  winston.debug("(voice) message_text menu: "+ message_text);
801
801
 
802
-
803
- let sessionInfo;
804
802
  let project_id, conversation_id, user;
805
803
  let from, to;
806
804
 
807
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
808
- if (!redis_data) {
805
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
806
+ if (!sessionInfo) {
809
807
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
810
808
  }
811
- sessionInfo = JSON.parse(redis_data)
812
809
  project_id = sessionInfo.project_id;
813
810
  from = sessionInfo.from;
814
811
  to = sessionInfo.to;
@@ -878,15 +875,13 @@ router.post('/handle/:callSid/:event', async (req, res) => {
878
875
  let button_action = '#' + req.query.button_action;
879
876
  let previousIntentName = req.query.intentName;
880
877
 
881
- let sessionInfo;
882
878
  let project_id, conversation_id, user;
883
879
  let from, to;
884
880
 
885
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
886
- if (!redis_data) {
881
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
882
+ if (!sessionInfo) {
887
883
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
888
884
  }
889
- sessionInfo = JSON.parse(redis_data)
890
885
  project_id = sessionInfo.project_id;
891
886
  from = sessionInfo.from;
892
887
  to = sessionInfo.to;
@@ -962,16 +957,13 @@ router.post('/event/:callSid/:event', async(req, res)=> {
962
957
  let currentIntentName = req.query.intentName;
963
958
  let currentIntentTimestamp = req.query.previousIntentTimestamp;
964
959
 
965
-
966
- let sessionInfo;
967
960
  let project_id, conversation_id, user;
968
961
  let from, to;
969
962
 
970
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
971
- if (!redis_data) {
963
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
964
+ if (!sessionInfo) {
972
965
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
973
966
  }
974
- sessionInfo = JSON.parse(redis_data)
975
967
  project_id = sessionInfo.project_id;
976
968
  from = sessionInfo.from;
977
969
  to = sessionInfo.to;
@@ -1062,15 +1054,13 @@ router.post('/twilio/status',async (req, res) => {
1062
1054
  clearTimeout(messageTimeout)
1063
1055
  }
1064
1056
 
1065
- let sessionInfo;
1066
1057
  let project_id, conversation_id, user;
1067
1058
  let from, to;
1068
1059
 
1069
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
1070
- if (!redis_data) {
1060
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
1061
+ if (!sessionInfo) {
1071
1062
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
1072
1063
  }
1073
- sessionInfo = JSON.parse(redis_data)
1074
1064
  project_id = sessionInfo.project_id;
1075
1065
  from = sessionInfo.from;
1076
1066
  to = sessionInfo.to;
@@ -1476,12 +1466,22 @@ async function startApp(settings, callback) {
1476
1466
  if(settings.OPENAI_ENDPOINT){
1477
1467
  OPENAI_ENDPOINT = settings.OPENAI_ENDPOINT
1478
1468
  }
1479
- if(settings.ELEVENLABS_ENDPOINT){
1480
- ELEVENLABS_ENDPOINT = settings.ELEVENLABS_ENDPOINT
1469
+
1470
+ // Read ELEVENLABS_ENDPOINT from process.env (not from settings)
1471
+ if(process.env.ELEVENLABS_ENDPOINT){
1472
+ ELEVENLABS_ENDPOINT = process.env.ELEVENLABS_ENDPOINT
1473
+ } else {
1474
+ ELEVENLABS_ENDPOINT = "https://api.elevenlabs.io" // default
1481
1475
  }
1482
1476
 
1483
- if(settings.MAX_POLLING_TIME){
1484
- MAX_POLLING_TIME = settings.MAX_POLLING_TIME/1000; //convert in seconds
1477
+ // Read MAX_POLLING_TIME from process.env (not from settings)
1478
+ if(process.env.MAX_POLLING_TIME){
1479
+ MAX_POLLING_TIME = process.env.MAX_POLLING_TIME/1000; //convert in seconds
1480
+ }
1481
+
1482
+ // Read BASE_POOLING_DELAY from process.env (not from settings)
1483
+ if(process.env.BASE_POOLING_DELAY){
1484
+ BASE_POOLING_DELAY = process.env.BASE_POOLING_DELAY;
1485
1485
  }
1486
1486
 
1487
1487
  if (settings.REDIS_HOST && settings.REDIS_PORT) {
@@ -1493,9 +1493,12 @@ async function startApp(settings, callback) {
1493
1493
  winston.error("(voice) Missing redis parameters --> REDIS_HOST and REDIS_PORT");
1494
1494
  }
1495
1495
 
1496
+
1497
+
1498
+
1496
1499
  //init VOICE CHANNEL
1497
1500
  voiceChannel = new VoiceChannel({
1498
- BASE_POOLING_DELAY: settings.BASE_POOLING_DELAY || BASE_POOLING_DELAY,
1501
+ BASE_POOLING_DELAY: BASE_POOLING_DELAY,
1499
1502
  redis_client: redis_client,
1500
1503
  })
1501
1504
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-voice-twilio-connector",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "description": "Tiledesk VOICE Twilio connector",
5
5
  "license": "MIT",
6
6
  "author": "Gabriele Panico",
@@ -36,6 +36,7 @@
36
36
  "redis": "^4.6.13",
37
37
  "redis-lock": "^1.0.0",
38
38
  "redlock": "^4.2.0",
39
+ "remove-markdown": "^0.6.2",
39
40
  "twilio": "^5.2.1",
40
41
  "uuid": "^8.3.2",
41
42
  "winston": "^3.3.3",
@@ -3,7 +3,8 @@ const winston = require("../winston");
3
3
  const xmlbuilder = require("xmlbuilder");
4
4
  const querystring = require("querystring");
5
5
 
6
- const utils = require("./utils-message.js");
6
+ const utils = require("./utils.js");
7
+ const utils_message = require("./utils-message.js");
7
8
  const MENU_CHOICE = require("./constants.js").MENU_CHOICE;
8
9
  const WAIT_MESSAGE = require("./constants.js").WAIT_MESSAGE;
9
10
  const TEXT_MESSAGE = require("./constants.js").TEXT_MESSAGE;
@@ -123,9 +124,9 @@ class TiledeskTwilioTranslator {
123
124
 
124
125
 
125
126
  //MANAGE CLOSE info message
126
- const isInfoSupport = utils.messageType(TYPE_MESSAGE.INFO_SUPPORT, msg)
127
+ const isInfoSupport = utils_message.messageType(TYPE_MESSAGE.INFO_SUPPORT, msg)
127
128
  winston.debug("[TiledeskVXMLTranslator] isInfoSupport:"+ isInfoSupport);
128
- if(isInfoSupport && utils.infoMessageType(msg) === INFO_MESSAGE_TYPE.CHAT_CLOSED){
129
+ if(isInfoSupport && utils_message.infoMessageType(msg) === INFO_MESSAGE_TYPE.CHAT_CLOSED){
129
130
  const hangUp = this.hangupCall(xml)
130
131
  return hangUp;
131
132
  }
@@ -305,9 +306,19 @@ class TiledeskTwilioTranslator {
305
306
 
306
307
  async playPromptVXMLConverter(rootEle, message, xmlAttributes){
307
308
 
309
+ const gather = rootEle.ele("Gather", { input: "speech"})
310
+
311
+ const queryUrl = '?intentName='+ querystring.encode(xmlAttributes.intentName) + '&previousIntentTimestamp='+Date.now();
312
+ gather.att("action", this.BASE_URL + '/nextBlock/' + xmlAttributes.callSid + queryUrl)
313
+ // gather.att("action", this.BASE_URL + '/speechresult/' + xmlAttributes.callSid + queryUrl)
314
+ .att("method", "POST")
315
+ .att("language", xmlAttributes.TTS_VOICE_LANGUAGE)
316
+ .att('speechTimeout', "auto")
317
+ .att("enhanced", "true") // enable enhanced recognition
318
+
308
319
  const prompt = await this.promptVXML(rootEle, message, xmlAttributes);
309
320
 
310
- const queryUrl = '?intentName='+ querystring.encode(xmlAttributes.intentName) + '&previousIntentTimestamp='+Date.now();
321
+ /** fallback se non parla --> redirige alla nextblock */
311
322
  rootEle.ele("Redirect", {method: "POST"}, this.BASE_URL + '/nextblock/' + xmlAttributes.callSid + queryUrl).up()
312
323
  //prompt.ele("submit", { fetchhint: "safe", expr: "proxyBaseUrl +'/nextblock/' + session.connection.calltoken", method: "post", namelist: "usertext session intentName previousIntentTimestamp" });
313
324
 
@@ -319,7 +330,6 @@ class TiledeskTwilioTranslator {
319
330
  async speechFormVXMLConverter(rootEle, message, xmlAttributes) {
320
331
 
321
332
  if(this.voiceProvider === VOICE_PROVIDER.TWILIO){
322
-
323
333
  const gather = rootEle.ele("Gather", { input: "speech"})
324
334
 
325
335
  const queryUrl = '?intentName='+ querystring.encode(xmlAttributes.intentName) + "&previousIntentTimestamp="+Date.now();
@@ -328,6 +338,7 @@ class TiledeskTwilioTranslator {
328
338
  .att("method", "POST")
329
339
  .att("language", xmlAttributes.TTS_VOICE_LANGUAGE)
330
340
  .att('speechTimeout', "auto")
341
+ .att("enhanced", "true") // enable enhanced recognition
331
342
 
332
343
  //if(xmlAttributes && xmlAttributes.noInputTimeout){
333
344
  // gather.att("timeout", Math.round(xmlAttributes.noInputTimeout/1000) ).up();
@@ -552,19 +563,19 @@ class TiledeskTwilioTranslator {
552
563
  if (command.type === "message") {
553
564
  //case type: TEXT
554
565
  if(command.message.type === 'text'){
566
+ let text = utils.markdownToTwilioSpeech(command.message.text);
555
567
  if(that.voiceProvider !== VOICE_PROVIDER.TWILIO){
556
- let voiceMessageUrl = await that.generateTTS(command.message.text, attributes)
568
+ let voiceMessageUrl = await that.generateTTS(text, attributes)
557
569
  rootEle.ele('Play', {}, voiceMessageUrl )
558
570
  }else{
559
- rootEle.ele("Say", { voice: attributes.TTS_VOICE_NAME, language: attributes.TTS_VOICE_LANGUAGE }, command.message.text);
571
+ rootEle.ele("Say", { voice: attributes.TTS_VOICE_NAME, language: attributes.TTS_VOICE_LANGUAGE }, text);
560
572
  }
561
573
 
562
-
563
574
  }
564
575
  //case type: FRAME
565
576
  if(command.message.type === 'frame' && command.message.metadata.src !== ""){
566
577
  if(command.message.text != ''){
567
- rootEle.ele("Say", { voice: attributes.TTS_VOICE_NAME, language: attributes.TTS_VOICE_LANGUAGE }, command.message.text);
578
+ rootEle.ele("Say", { voice: attributes.TTS_VOICE_NAME, language: attributes.TTS_VOICE_LANGUAGE }, text);
568
579
  }
569
580
  rootEle.ele('Play', {}, command.message.metadata.src )
570
581
  }
@@ -75,11 +75,11 @@ class VoiceChannel {
75
75
  //increment
76
76
  const delayIndex = (+index) +1
77
77
  //save new index to redis
78
- await this.redis_client.set('tiledesk:voice:'+callId + ':delayIndex', delayIndex, 'EX', 86400);
78
+ await this.redis_client.set('tiledesk:voice:'+callId + ':delayIndex', delayIndex, {'EX': 86400});
79
79
  return;
80
80
  }
81
81
  //if index is not present: set to default (0)
82
- await this.redis_client.set('tiledesk:voice:'+callId + ':delayIndex', 0, 'EX', 86400);
82
+ await this.redis_client.set('tiledesk:voice:'+callId + ':delayIndex', 0, {'EX': 86400});
83
83
  }
84
84
 
85
85
  /** RESET INDEX INTO REDIS DATA FOR CURRENT CALLID **/
@@ -106,11 +106,11 @@ class VoiceChannel {
106
106
  winston.debug('[VoiceChannel] saveSettingsForCallId: attributes found -->'+index)
107
107
  if(index){
108
108
  //set index to default (0)
109
- await this.redis_client.set('tiledesk:voice:'+callId + ':attributes', JSON.stringify(attributes), 'EX', 86400);
109
+ await this.redis_client.set('tiledesk:voice:'+callId + ':attributes', JSON.stringify(attributes), {'EX': 86400});
110
110
  return;
111
111
  }
112
112
  //if index is not present: set to default (0)
113
- await this.redis_client.set('tiledesk:voice:'+callId + ':attributes', JSON.stringify(attributes), 'EX', 86400);
113
+ await this.redis_client.set('tiledesk:voice:'+callId + ':attributes', JSON.stringify(attributes), {'EX': 86400});
114
114
 
115
115
  }
116
116
 
@@ -125,6 +125,25 @@ class VoiceChannel {
125
125
  }
126
126
 
127
127
 
128
+ async setSessionForCallId(callSid, session) {
129
+ await this.redis_client.set(`tiledesk:voice:${callSid}:session`, JSON.stringify(session), { 'EX': 86400 });
130
+ //for (const [key, value] of Object.entries(redis_data)){
131
+ // await redis_client.hSet('tiledesk:voice:'+callId, key, JSON.stringify(value))
132
+ //}
133
+ //await redis_client.expire('tiledesk:voice:'+callId, 86400)
134
+ }
135
+
136
+ async getSessionForCallId(callSid) {
137
+ const sessionData = await this.redis_client.get(`tiledesk:voice:${callSid}:session`);
138
+ //let redis_data = await redis_client.hGetAll('tiledesk:voice:'+callId);
139
+ if (sessionData) {
140
+ return JSON.parse(sessionData);
141
+ }
142
+ return null;
143
+
144
+ }
145
+
146
+
128
147
  async deleteCallKeys(callSid) {
129
148
  const pattern = `tiledesk:voice:${callSid}:*`;
130
149
  let cursor = 0;
package/tiledesk/utils.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const NON_SPEECH_TOKENS = require('./constants').NON_SPEECH_TOKENS
2
+ const removeMarkdown = require('remove-markdown');
2
3
 
3
4
  function getNumber(phoneNumber){
4
5
  if(phoneNumber.startsWith('+')){
@@ -31,5 +32,13 @@ function normalizeSTT(text) {
31
32
  return cleaned;
32
33
  }
33
34
 
35
+ function markdownToTwilioSpeech(text) {
36
+ return removeMarkdown(text)
37
+ .replace(/:/g, ': ')
38
+ .replace(/\n+/g, '. ')
39
+ .replace(/\s+/g, ' ')
40
+ .trim();
41
+ }
42
+
34
43
 
35
- module.exports = {getNumber, buildQueryString, normalizeSTT}
44
+ module.exports = {getNumber, buildQueryString, normalizeSTT, markdownToTwilioSpeech}