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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -195,16 +195,8 @@ router.post('/webhook/:id_project', async (req, res) => {
195
195
  conversation_id: conversation_id,
196
196
  integrations: integrations
197
197
  }
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
-
198
+ voiceChannel.setSessionForCallId(callSid, session_data)
199
+
208
200
  let tiledeskMessage= {
209
201
  text:'/start',
210
202
  senderFullname: from,
@@ -262,8 +254,7 @@ router.post('/nextblock_old/:callSid/', async(req, res) => {
262
254
  let project_id, conversation_id, user;
263
255
  let from, to;
264
256
 
265
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
266
- //let redis_data = await redis_client.hGetAll('tiledesk:voice:'+callId);
257
+ let redis_data = await voiceChannel.getSessionForCallId(callSid)
267
258
  if (!redis_data) {
268
259
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
269
260
  }
@@ -345,16 +336,13 @@ router.post('/nextblock/:callSid/', async(req, res) => {
345
336
  let confidence = req.body.Confidence
346
337
  let callSid = req.params.callSid;
347
338
 
348
- let sessionInfo;
349
339
  let project_id, conversation_id, user;
350
340
  let from, to;
351
341
 
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) {
342
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
343
+ if (!sessionInfo) {
355
344
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
356
345
  }
357
- sessionInfo = JSON.parse(redis_data)
358
346
  project_id = sessionInfo.project_id;
359
347
  from = sessionInfo.from;
360
348
  to = sessionInfo.to;
@@ -465,7 +453,7 @@ async function getMessage(callSid, ani, project_id, conversation_id){
465
453
  if (queue && queue.length > 0) {
466
454
  //CASE: queue has at least one message to reproduce --> get message from tiledesk queue and reset delayTime
467
455
  message = queue[0]
468
- winston.debug('[getMessage] QUEUE --> '+ queue[0].text, queue[0])
456
+ winston.verbose('[getMessage] QUEUE --> '+ queue[0].text)
469
457
 
470
458
  // remove message from queue and reset delayIndex
471
459
  await tdChannel.removeMessageFromQueue(conversation_id, message._id)
@@ -486,7 +474,7 @@ async function getMessage(callSid, ani, project_id, conversation_id){
486
474
  }
487
475
 
488
476
  message = queue[0]
489
- winston.debug(`[getMessage] Message received from subscription: ${message.text}`, message);
477
+ winston.verbose(`[getMessage] Message received from subscription: ${message.text}`);
490
478
 
491
479
  // remove message from queue and reset delayIndex
492
480
  await tdChannel.removeMessageFromQueue(conversation_id, message._id)
@@ -528,16 +516,13 @@ router.post('/speechresult/:callSid', async (req, res) => {
528
516
  let confidence = req.body.Confidence
529
517
  let callSid = req.params.callSid;
530
518
 
531
- let sessionInfo;
532
519
  let project_id, conversation_id, user;
533
520
  let from, to;
534
521
 
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) {
522
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
523
+ if (!sessionInfo) {
538
524
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
539
525
  }
540
- sessionInfo = JSON.parse(redis_data)
541
526
  project_id = sessionInfo.project_id;
542
527
  from = sessionInfo.from;
543
528
  to = sessionInfo.to;
@@ -623,15 +608,13 @@ router.post('/record/action/:callSid/',async (req, res) => {
623
608
  let start_call = new Date();
624
609
 
625
610
  let callSid = req.body.CallSid;
626
- let sessionInfo;
627
611
  let project_id, conversation_id, user;
628
612
  let from, to;
629
613
 
630
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
631
- if (!redis_data) {
614
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
615
+ if (!sessionInfo) {
632
616
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
633
617
  }
634
- sessionInfo = JSON.parse(redis_data)
635
618
  project_id = sessionInfo.project_id;
636
619
  from = sessionInfo.from;
637
620
  to = sessionInfo.to;
@@ -692,16 +675,13 @@ router.post('/record/callback/:callSid/',async (req, res) => {
692
675
  let button_action = req.query.button_action ? '#' + req.query.button_action : '';
693
676
  let previousIntentName = req.query.intentName || '';
694
677
 
695
-
696
- let sessionInfo;
697
678
  let project_id, conversation_id, user;
698
679
  let from, to;
699
680
 
700
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
701
- if (!redis_data) {
681
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
682
+ if (!sessionInfo) {
702
683
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
703
684
  }
704
- sessionInfo = JSON.parse(redis_data)
705
685
  project_id = sessionInfo.project_id;
706
686
  from = sessionInfo.from;
707
687
  to = sessionInfo.to;
@@ -799,16 +779,13 @@ router.post('/menublock/:callSid', async (req, res) => {
799
779
  winston.debug("(voice) button menu: ", button);
800
780
  winston.debug("(voice) message_text menu: "+ message_text);
801
781
 
802
-
803
- let sessionInfo;
804
782
  let project_id, conversation_id, user;
805
783
  let from, to;
806
784
 
807
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
808
- if (!redis_data) {
785
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
786
+ if (!sessionInfo) {
809
787
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
810
788
  }
811
- sessionInfo = JSON.parse(redis_data)
812
789
  project_id = sessionInfo.project_id;
813
790
  from = sessionInfo.from;
814
791
  to = sessionInfo.to;
@@ -878,15 +855,13 @@ router.post('/handle/:callSid/:event', async (req, res) => {
878
855
  let button_action = '#' + req.query.button_action;
879
856
  let previousIntentName = req.query.intentName;
880
857
 
881
- let sessionInfo;
882
858
  let project_id, conversation_id, user;
883
859
  let from, to;
884
860
 
885
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
886
- if (!redis_data) {
861
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
862
+ if (!sessionInfo) {
887
863
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
888
864
  }
889
- sessionInfo = JSON.parse(redis_data)
890
865
  project_id = sessionInfo.project_id;
891
866
  from = sessionInfo.from;
892
867
  to = sessionInfo.to;
@@ -962,16 +937,13 @@ router.post('/event/:callSid/:event', async(req, res)=> {
962
937
  let currentIntentName = req.query.intentName;
963
938
  let currentIntentTimestamp = req.query.previousIntentTimestamp;
964
939
 
965
-
966
- let sessionInfo;
967
940
  let project_id, conversation_id, user;
968
941
  let from, to;
969
942
 
970
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
971
- if (!redis_data) {
943
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
944
+ if (!sessionInfo) {
972
945
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
973
946
  }
974
- sessionInfo = JSON.parse(redis_data)
975
947
  project_id = sessionInfo.project_id;
976
948
  from = sessionInfo.from;
977
949
  to = sessionInfo.to;
@@ -1062,15 +1034,13 @@ router.post('/twilio/status',async (req, res) => {
1062
1034
  clearTimeout(messageTimeout)
1063
1035
  }
1064
1036
 
1065
- let sessionInfo;
1066
1037
  let project_id, conversation_id, user;
1067
1038
  let from, to;
1068
1039
 
1069
- let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
1070
- if (!redis_data) {
1040
+ let sessionInfo = await voiceChannel.getSessionForCallId(callSid)
1041
+ if (!sessionInfo) {
1071
1042
  return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
1072
1043
  }
1073
- sessionInfo = JSON.parse(redis_data)
1074
1044
  project_id = sessionInfo.project_id;
1075
1045
  from = sessionInfo.from;
1076
1046
  to = sessionInfo.to;
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.27",
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
  }
@@ -319,7 +320,6 @@ class TiledeskTwilioTranslator {
319
320
  async speechFormVXMLConverter(rootEle, message, xmlAttributes) {
320
321
 
321
322
  if(this.voiceProvider === VOICE_PROVIDER.TWILIO){
322
-
323
323
  const gather = rootEle.ele("Gather", { input: "speech"})
324
324
 
325
325
  const queryUrl = '?intentName='+ querystring.encode(xmlAttributes.intentName) + "&previousIntentTimestamp="+Date.now();
@@ -328,6 +328,7 @@ class TiledeskTwilioTranslator {
328
328
  .att("method", "POST")
329
329
  .att("language", xmlAttributes.TTS_VOICE_LANGUAGE)
330
330
  .att('speechTimeout', "auto")
331
+ .att("enhanced", "true") // enable enhanced recognition
331
332
 
332
333
  //if(xmlAttributes && xmlAttributes.noInputTimeout){
333
334
  // gather.att("timeout", Math.round(xmlAttributes.noInputTimeout/1000) ).up();
@@ -552,19 +553,19 @@ class TiledeskTwilioTranslator {
552
553
  if (command.type === "message") {
553
554
  //case type: TEXT
554
555
  if(command.message.type === 'text'){
556
+ let text = utils.markdownToTwilioSpeech(command.message.text);
555
557
  if(that.voiceProvider !== VOICE_PROVIDER.TWILIO){
556
- let voiceMessageUrl = await that.generateTTS(command.message.text, attributes)
558
+ let voiceMessageUrl = await that.generateTTS(text, attributes)
557
559
  rootEle.ele('Play', {}, voiceMessageUrl )
558
560
  }else{
559
- rootEle.ele("Say", { voice: attributes.TTS_VOICE_NAME, language: attributes.TTS_VOICE_LANGUAGE }, command.message.text);
561
+ rootEle.ele("Say", { voice: attributes.TTS_VOICE_NAME, language: attributes.TTS_VOICE_LANGUAGE }, text);
560
562
  }
561
563
 
562
-
563
564
  }
564
565
  //case type: FRAME
565
566
  if(command.message.type === 'frame' && command.message.metadata.src !== ""){
566
567
  if(command.message.text != ''){
567
- rootEle.ele("Say", { voice: attributes.TTS_VOICE_NAME, language: attributes.TTS_VOICE_LANGUAGE }, command.message.text);
568
+ rootEle.ele("Say", { voice: attributes.TTS_VOICE_NAME, language: attributes.TTS_VOICE_LANGUAGE }, text);
568
569
  }
569
570
  rootEle.ele('Play', {}, command.message.metadata.src )
570
571
  }
@@ -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}