@tiledesk/tiledesk-voice-twilio-connector 0.1.26-rc5 → 0.1.26-rc6
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 +196 -76
- package/package.json +1 -1
- package/tiledesk/TiledeskChannel.js +66 -0
- package/tiledesk/VoiceChannel.js +11 -11
package/index.js
CHANGED
|
@@ -200,13 +200,12 @@ router.post('/webhook/:id_project', async (req, res) => {
|
|
|
200
200
|
return res.status(500).send({ message: "Redis not ready. Check redis connection..." })
|
|
201
201
|
}
|
|
202
202
|
//for (const [key, value] of Object.entries(redis_data)){
|
|
203
|
-
// await redis_client.hSet('tiledesk:
|
|
203
|
+
// await redis_client.hSet('tiledesk:voice:'+callId, key, JSON.stringify(value))
|
|
204
204
|
//}
|
|
205
|
-
//await redis_client.expire('tiledesk:
|
|
205
|
+
//await redis_client.expire('tiledesk:voice:'+callId, 86400)
|
|
206
206
|
|
|
207
|
-
await redis_client.set('tiledesk:
|
|
207
|
+
await redis_client.set('tiledesk:voice:'+callSid+':session', JSON.stringify(session_data), {'EX': 86400});
|
|
208
208
|
|
|
209
|
-
let start4 = new Date().getTime();
|
|
210
209
|
let tiledeskMessage= {
|
|
211
210
|
text:'/start',
|
|
212
211
|
senderFullname: from,
|
|
@@ -221,18 +220,22 @@ router.post('/webhook/:id_project', async (req, res) => {
|
|
|
221
220
|
departmentid: settings.department_id
|
|
222
221
|
};
|
|
223
222
|
|
|
224
|
-
let
|
|
225
|
-
if(!
|
|
223
|
+
let response = await tdChannel.send(tiledeskMessage, user.token, conversation_id)
|
|
224
|
+
if(!response){
|
|
226
225
|
return res.status(503).send({ message: "Bad response: Quota exceeded" })
|
|
227
226
|
}
|
|
228
|
-
|
|
229
|
-
|
|
227
|
+
|
|
228
|
+
//await for a response message from tiledesk queue
|
|
229
|
+
let start_time_get_message = new Date()
|
|
230
|
+
let message = await getMessage(callId, ani, project_id, conversation_id)
|
|
231
|
+
let end_time_get_message = new Date()
|
|
232
|
+
winston.verbose('Time to getMessage from queue in /:project_id/start : ' + end_time_get_message-start_time_get_message + '[ms] --- at time:' + new Date())
|
|
230
233
|
|
|
231
|
-
//generate Tiledesk wait message
|
|
232
|
-
let delayTime = await voiceChannel.getNextDelayTimeForCallId(callSid)
|
|
233
|
-
let waitTiledeskMessage = await tdChannel.generateWaitTdMessage(from, delayTime)
|
|
234
|
-
//update delayIndex for wait command message time
|
|
235
|
-
await voiceChannel.saveDelayIndexForCallId(from)
|
|
234
|
+
// //generate Tiledesk wait message
|
|
235
|
+
// let delayTime = await voiceChannel.getNextDelayTimeForCallId(callSid)
|
|
236
|
+
// let waitTiledeskMessage = await tdChannel.generateWaitTdMessage(from, delayTime)
|
|
237
|
+
// //update delayIndex for wait command message time
|
|
238
|
+
// await voiceChannel.saveDelayIndexForCallId(from)
|
|
236
239
|
|
|
237
240
|
// send standard wait vxml message
|
|
238
241
|
let messageToVXML = await tdTranslator.toVXML(waitTiledeskMessage, callSid, vxmlAttributes, session_data)
|
|
@@ -249,7 +252,7 @@ router.post('/webhook/:id_project', async (req, res) => {
|
|
|
249
252
|
});
|
|
250
253
|
|
|
251
254
|
|
|
252
|
-
router.post('/
|
|
255
|
+
router.post('/nextblock_old/:callSid/', async(req, res) => {
|
|
253
256
|
let start_call = new Date()
|
|
254
257
|
winston.debug("(voice) called POST /nextblock ", req.body);
|
|
255
258
|
winston.debug("(voice) called POST /nextblock query ", req.query);
|
|
@@ -263,8 +266,8 @@ router.post('/nextblock/:callSid/', async(req, res) => {
|
|
|
263
266
|
let project_id, conversation_id, user;
|
|
264
267
|
let from, to;
|
|
265
268
|
|
|
266
|
-
let redis_data = await redis_client.get('tiledesk:
|
|
267
|
-
//let redis_data = await redis_client.hGetAll('tiledesk:
|
|
269
|
+
let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
|
|
270
|
+
//let redis_data = await redis_client.hGetAll('tiledesk:voice:'+callId);
|
|
268
271
|
if (!redis_data) {
|
|
269
272
|
return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
|
|
270
273
|
}
|
|
@@ -338,7 +341,108 @@ router.post('/nextblock/:callSid/', async(req, res) => {
|
|
|
338
341
|
|
|
339
342
|
})
|
|
340
343
|
|
|
341
|
-
|
|
344
|
+
router.post('/nextblock/:callSid/', async(req, res) => {
|
|
345
|
+
let start_call = new Date()
|
|
346
|
+
winston.debug("(voice) called POST /nextblock ", req.body);
|
|
347
|
+
winston.debug("(voice) called POST /nextblock query ", req.query);
|
|
348
|
+
console.log("(voice) called POST /nextblock at" + new Date() + "with text: " + req.body.SpeechResult)
|
|
349
|
+
|
|
350
|
+
let usertext = req.body.SpeechResult;
|
|
351
|
+
let confidence = req.body.Confidence
|
|
352
|
+
let callSid = req.params.callSid;
|
|
353
|
+
|
|
354
|
+
let sessionInfo;
|
|
355
|
+
let project_id, conversation_id, user;
|
|
356
|
+
let from, to;
|
|
357
|
+
|
|
358
|
+
let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
|
|
359
|
+
//let redis_data = await redis_client.hGetAll('tiledesk:voice:'+callId);
|
|
360
|
+
if (!redis_data) {
|
|
361
|
+
return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
|
|
362
|
+
}
|
|
363
|
+
sessionInfo = JSON.parse(redis_data)
|
|
364
|
+
project_id = sessionInfo.project_id;
|
|
365
|
+
from = sessionInfo.from;
|
|
366
|
+
to = sessionInfo.to;
|
|
367
|
+
conversation_id = sessionInfo.conversation_id;
|
|
368
|
+
user = sessionInfo.user;
|
|
369
|
+
|
|
370
|
+
let vxmlAttributes = {
|
|
371
|
+
TTS_VOICE_LANGUAGE: VOICE_LANGUAGE,
|
|
372
|
+
TTS_VOICE_NAME: VOICE_NAME,
|
|
373
|
+
callSid: callSid,
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
const tdChannel = new TiledeskChannel({
|
|
378
|
+
API_URL: API_URL,
|
|
379
|
+
redis_client: redis_client
|
|
380
|
+
})
|
|
381
|
+
tdChannel.setProjectId(project_id);
|
|
382
|
+
|
|
383
|
+
const tdTranslator = new TiledeskTwilioTranslator({
|
|
384
|
+
BASE_URL: BASE_URL,
|
|
385
|
+
aiService: aiService,
|
|
386
|
+
uploadService: uploadService
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
let start_promise_message= new Date();
|
|
391
|
+
let message = await new Promise(async (resolve, reject) => {
|
|
392
|
+
winston.debug('******* user text -->'+ usertext)
|
|
393
|
+
if(usertext === '' || !usertext){
|
|
394
|
+
|
|
395
|
+
let start_time_get_message = new Date()
|
|
396
|
+
let message = await getMessage(callSid, from, project_id, conversation_id)
|
|
397
|
+
let end_time_get_message = new Date()
|
|
398
|
+
winston.verbose(`(if) Time to getMessage from queue in /nextblock/${callSid} : ` + end_time_get_message-start_time_get_message + '[ms]')
|
|
399
|
+
resolve(message)
|
|
400
|
+
}else{
|
|
401
|
+
//CASE:usertext is not empty and queue is empty --> send message to tiledesk and manage delayTime
|
|
402
|
+
let tiledeskMessage= {
|
|
403
|
+
text:usertext,
|
|
404
|
+
senderFullname: from,
|
|
405
|
+
type: 'text',
|
|
406
|
+
channel: { name: CHANNEL_NAME }
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
let start_time_send_message = new Date()
|
|
410
|
+
let tdMessage = await tdChannel.send(tiledeskMessage, user.token, conversation_id);
|
|
411
|
+
let end_time_send_message = new Date()
|
|
412
|
+
winston.debug("message sent : ", tdMessage);
|
|
413
|
+
winston.verbose(`(else) Time to send message to tiledesk in /nextblock/${callSid} : ` + end_time_send_message-start_time_send_message + '[ms] with text ' + tdMessage.text + ' --- at time:' + new Date())
|
|
414
|
+
|
|
415
|
+
let start_time_get_message = new Date()
|
|
416
|
+
let message = await getMessage(callSid, from, project_id, conversation_id)
|
|
417
|
+
let end_time_get_message = new Date()
|
|
418
|
+
winston.verbose(`(else) Time to getMessage from queue in /nextblock/${callSid} : ` + end_time_get_message-start_time_get_message + '[ms] --- at time:' + new Date())
|
|
419
|
+
resolve(message)
|
|
420
|
+
|
|
421
|
+
//generate Tiledesk wait message
|
|
422
|
+
// let delayTime = await voiceChannel.getNextDelayTimeForCallId(callSid)
|
|
423
|
+
// let message = await tdChannel.generateWaitTdMessage(from, delayTime)
|
|
424
|
+
// //update delayIndex for wait command message time
|
|
425
|
+
// await voiceChannel.saveDelayIndexForCallId(callSid)
|
|
426
|
+
// resolve(message)
|
|
427
|
+
}
|
|
428
|
+
})
|
|
429
|
+
let end_promise_message = new Date()
|
|
430
|
+
winston.verbose(`Time to manage message in Promise /nextblock/${callSid}: ` + end_promise_message-start_promise_message + '[ms] with text' + message.text + ' --- at time --' + new Date())
|
|
431
|
+
|
|
432
|
+
// convert response to vxml
|
|
433
|
+
let messageToVXML = await tdTranslator.toVXML(message, callSid, vxmlAttributes, sessionInfo)
|
|
434
|
+
winston.debug("(voice) VXML to SEND: "+ messageToVXML);
|
|
435
|
+
|
|
436
|
+
let end_call = new Date()
|
|
437
|
+
console.log(`Time to responde to /nextblock/${callSid} : `, end_call-start_call, '[ms]')
|
|
438
|
+
|
|
439
|
+
// Render the response as XML in reply to the webhook request
|
|
440
|
+
res.set('Content-Type', 'application/xml');
|
|
441
|
+
res.status(200).send(messageToVXML);
|
|
442
|
+
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
async function getMessage(callId, ani, project_id, conversation_id){
|
|
342
446
|
const startTime = Date.now();
|
|
343
447
|
|
|
344
448
|
const tdChannel = new TiledeskChannel({
|
|
@@ -348,62 +452,78 @@ async function getMessage(callSid, from, project_id, conversation_id){
|
|
|
348
452
|
tdChannel.setProjectId(project_id);
|
|
349
453
|
|
|
350
454
|
let message = {}, queue = []
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
//
|
|
455
|
+
|
|
456
|
+
//get queue
|
|
457
|
+
//if queue exist and has at least one message
|
|
458
|
+
//get message from queue, remove it from queue and clear delayTime
|
|
459
|
+
//else
|
|
460
|
+
//subscribe to topic
|
|
461
|
+
//create promise that resolve after MAX_POLLING_TIME s
|
|
462
|
+
//race between subscription and timeout and return a message
|
|
463
|
+
//if subscription resolve first and queue has at least one message
|
|
355
464
|
//get message from queue, remove it from queue and clear delayTime
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
465
|
+
|
|
466
|
+
try{
|
|
467
|
+
|
|
468
|
+
// 1. First attempt: read from queue
|
|
469
|
+
queue = await tdChannel.getMessagesFromQueue(conversation_id)
|
|
470
|
+
console.log('[getMessage] /NEXT check queue length--> '+ queue.length)
|
|
471
|
+
|
|
472
|
+
if (queue && queue.length > 0) {
|
|
473
|
+
//CASE: queue has at least one message to reproduce --> get message from tiledesk queue and reset delayTime
|
|
474
|
+
message = queue[0]
|
|
475
|
+
winston.debug('[getMessage] QUEUE --> '+ queue[0].text, queue[0])
|
|
476
|
+
|
|
477
|
+
// remove message from queue and reset delayIndex
|
|
478
|
+
await tdChannel.removeMessageFromQueue(conversation_id, message._id)
|
|
479
|
+
await voiceChannel.clearDelayTimeForCallId(callId)
|
|
480
|
+
|
|
481
|
+
return message;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// 2. If queue is empty: subscribe with timeout
|
|
485
|
+
if(queue && queue.length === 0){
|
|
486
|
+
winston.debug("[getMessage] Queue is empty, starting subscription...");
|
|
487
|
+
const subscriptionPromise = (async () => {
|
|
488
|
+
await tdChannel.subscribeToTopic(conversation_id);
|
|
489
|
+
queue = await tdChannel.getMessagesFromQueue(conversation_id)
|
|
490
|
+
|
|
491
|
+
if (!queue || queue.length === 0) {
|
|
492
|
+
throw new Error("No message received after subscription");
|
|
493
|
+
}
|
|
494
|
+
|
|
367
495
|
message = queue[0]
|
|
368
|
-
winston.debug(
|
|
369
|
-
|
|
496
|
+
winston.debug(`[getMessage] Message received from subscription: ${message.text}`, message);
|
|
497
|
+
|
|
498
|
+
// remove message from queue and reset delayIndex
|
|
370
499
|
await tdChannel.removeMessageFromQueue(conversation_id, message._id)
|
|
371
|
-
|
|
372
|
-
await voiceChannel.clearDelayTimeForCallId(callSid)
|
|
373
|
-
//manage attributes for current callId
|
|
374
|
-
await voiceChannel.saveSettingsForCallId(message.attributes, callSid)
|
|
500
|
+
await voiceChannel.clearDelayTimeForCallId(callId)
|
|
375
501
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
502
|
+
return message;
|
|
503
|
+
})();
|
|
379
504
|
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
let delayTime = await voiceChannel.getNextDelayTimeForCallId(callSid)
|
|
384
|
-
message = await tdChannel.generateWaitTdMessage(from, delayTime)
|
|
385
|
-
//update delayIndex for wait command message time
|
|
386
|
-
await voiceChannel.saveDelayIndexForCallId(callSid)
|
|
505
|
+
const timeoutPromise = new Promise(async (resolve) => {
|
|
506
|
+
setTimeout(async () => {
|
|
507
|
+
winston.debug("[getMessage] Subscription timeout, generating waitTdMessage...");
|
|
387
508
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
509
|
+
//CASE: queue is empty --> generate Tiledesk wait message and manage delayTime
|
|
510
|
+
const delayTime = await voiceChannel.getNextDelayTimeForCallId(callId);
|
|
511
|
+
const waitMessage = await tdChannel.generateWaitTdMessage(ani, delayTime);
|
|
512
|
+
//update delayIndex for wait command message time
|
|
513
|
+
await voiceChannel.saveDelayIndexForCallId(callId);
|
|
391
514
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
messageTimeout = setTimeout(checkQueue, delayTime);
|
|
515
|
+
resolve(waitMessage);
|
|
516
|
+
}, MAX_POLLING_TIME * 1000); // MAX_POLLING_TIME is in seconds
|
|
517
|
+
});
|
|
396
518
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
reject(err);
|
|
400
|
-
return;
|
|
519
|
+
// Vince chi arriva prima: subscription o timeout
|
|
520
|
+
return await Promise.race([subscriptionPromise, timeoutPromise]);
|
|
401
521
|
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
522
|
+
}catch(err){
|
|
523
|
+
winston.debug("[getMessage] Error occurred: ", err);
|
|
524
|
+
reject(err);
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
407
527
|
|
|
408
528
|
}
|
|
409
529
|
|
|
@@ -422,8 +542,8 @@ router.post('/speechresult/:callSid', async (req, res) => {
|
|
|
422
542
|
let project_id, conversation_id, user;
|
|
423
543
|
let from, to;
|
|
424
544
|
|
|
425
|
-
let redis_data = await redis_client.get('tiledesk:
|
|
426
|
-
//let redis_data = await redis_client.hGetAll('tiledesk:
|
|
545
|
+
let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
|
|
546
|
+
//let redis_data = await redis_client.hGetAll('tiledesk:voice:'+callId);
|
|
427
547
|
if (!redis_data) {
|
|
428
548
|
return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
|
|
429
549
|
}
|
|
@@ -548,7 +668,7 @@ router.post('/menublock/:callSid', async (req, res) => {
|
|
|
548
668
|
let project_id, conversation_id, user;
|
|
549
669
|
let from, to;
|
|
550
670
|
|
|
551
|
-
let redis_data = await redis_client.get('tiledesk:
|
|
671
|
+
let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
|
|
552
672
|
if (!redis_data) {
|
|
553
673
|
return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
|
|
554
674
|
}
|
|
@@ -622,7 +742,7 @@ router.post('/handle/:callSid/:event', async (req, res) => {
|
|
|
622
742
|
let project_id, conversation_id, user;
|
|
623
743
|
let from, to;
|
|
624
744
|
|
|
625
|
-
let redis_data = await redis_client.get('tiledesk:
|
|
745
|
+
let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
|
|
626
746
|
if (!redis_data) {
|
|
627
747
|
return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
|
|
628
748
|
}
|
|
@@ -707,7 +827,7 @@ router.post('/event/:callSid/:event', async(req, res)=> {
|
|
|
707
827
|
let project_id, conversation_id, user;
|
|
708
828
|
let from, to;
|
|
709
829
|
|
|
710
|
-
let redis_data = await redis_client.get('tiledesk:
|
|
830
|
+
let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
|
|
711
831
|
if (!redis_data) {
|
|
712
832
|
return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
|
|
713
833
|
}
|
|
@@ -806,7 +926,7 @@ router.post('/twilio/status',async (req, res) => {
|
|
|
806
926
|
let project_id, conversation_id, user;
|
|
807
927
|
let from, to;
|
|
808
928
|
|
|
809
|
-
let redis_data = await redis_client.get('tiledesk:
|
|
929
|
+
let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
|
|
810
930
|
if (!redis_data) {
|
|
811
931
|
return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
|
|
812
932
|
}
|
|
@@ -858,8 +978,8 @@ router.post('/twilio/status',async (req, res) => {
|
|
|
858
978
|
let tdMessage = await tdChannel.send(tiledeskMessage, user.token, conversation_id);
|
|
859
979
|
|
|
860
980
|
//remove session data for current callId and relative queue data
|
|
861
|
-
await redis_client.del('tiledesk:
|
|
862
|
-
await redis_client.del('tiledesk:
|
|
981
|
+
await redis_client.del('tiledesk:voice:'+callSid+':session');
|
|
982
|
+
await redis_client.del('tiledesk:voice:'+callSid+':delayIndex');
|
|
863
983
|
await tdChannel.clearQueue(conversation_id);
|
|
864
984
|
break;
|
|
865
985
|
}
|
|
@@ -891,7 +1011,7 @@ router.post('/record/:callSid/',async (req, res) => {
|
|
|
891
1011
|
let project_id, conversation_id, user;
|
|
892
1012
|
let from, to;
|
|
893
1013
|
|
|
894
|
-
let redis_data = await redis_client.get('tiledesk:
|
|
1014
|
+
let redis_data = await redis_client.get('tiledesk:voice:'+callSid+':session');
|
|
895
1015
|
if (!redis_data) {
|
|
896
1016
|
return res.status(500).send({ success: "false", message: "Can't retrive data for callSid ->" + callSid });
|
|
897
1017
|
}
|
|
@@ -1048,8 +1168,8 @@ async function generateSTT(audioFileUrl, attributes, sessionInfo, settings){
|
|
|
1048
1168
|
|
|
1049
1169
|
|
|
1050
1170
|
router.get('/addon/transcript', async (req, res) => {
|
|
1051
|
-
winston.verbose("(
|
|
1052
|
-
winston.debug("(
|
|
1171
|
+
winston.verbose("(voice) called GET /transcript query-->" , req.query);
|
|
1172
|
+
winston.debug("(voice) called GET /transcript body -->" , req.body);
|
|
1053
1173
|
|
|
1054
1174
|
res.status(200).send('ok');
|
|
1055
1175
|
|
|
@@ -1297,7 +1417,7 @@ async function startApp(settings, callback) {
|
|
|
1297
1417
|
}
|
|
1298
1418
|
|
|
1299
1419
|
if(settings.MAX_POLLING_TIME){
|
|
1300
|
-
MAX_POLLING_TIME = settings.MAX_POLLING_TIME/
|
|
1420
|
+
MAX_POLLING_TIME = settings.MAX_POLLING_TIME/1000; //convert in seconds
|
|
1301
1421
|
}
|
|
1302
1422
|
|
|
1303
1423
|
if (settings.REDIS_HOST && settings.REDIS_PORT) {
|
package/package.json
CHANGED
|
@@ -221,6 +221,7 @@ class TiledeskChannel {
|
|
|
221
221
|
//push element to queue list and set expiration time
|
|
222
222
|
await this.redis_client.rPush('tiledesk:queue:'+conversation_id, JSON.stringify(message));
|
|
223
223
|
this.redis_client.expire('tiledesk:queue:'+conversation_id, 86400)
|
|
224
|
+
await this.redis_client.publish('tiledesk:conversation:'+conversation_id, JSON.stringify(message));
|
|
224
225
|
|
|
225
226
|
}
|
|
226
227
|
|
|
@@ -239,6 +240,71 @@ class TiledeskChannel {
|
|
|
239
240
|
}
|
|
240
241
|
return messages;
|
|
241
242
|
}
|
|
243
|
+
|
|
244
|
+
/** PUBLISH MESSAGE TO REDIS TOPIC **/
|
|
245
|
+
async publishMessageToTopic(message){
|
|
246
|
+
|
|
247
|
+
/*SKIP INFO MESSAGES*/
|
|
248
|
+
if(utils.messageType(TYPE_MESSAGE.INFO, message)){
|
|
249
|
+
winston.verbose("> SKIPPING INFO message: " + JSON.stringify(message) );
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/*SKIP CURRENT USER MESSAGES*/
|
|
254
|
+
if (message.sender.indexOf("vxml") > -1) {
|
|
255
|
+
winston.verbose("> SKIPPING ECHO message: " + JSON.stringify(message) );
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
winston.verbose("> SAVE message TO QUEUE: " + JSON.stringify(message) );
|
|
260
|
+
|
|
261
|
+
let conversation_id = message.recipient
|
|
262
|
+
//PUBLISH MESSAGE TO REDIS TOPIC WITH KET tiledesk:queue:+conversation_id
|
|
263
|
+
await this.redis_client.publish('tiledesk:conversation:'+conversation_id, JSON.stringify(message));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** SUBSCRIBE TO REDIS TOPIC */
|
|
267
|
+
async subscribeToTopic(conversation_id){
|
|
268
|
+
const topic = `tiledesk:conversation:${conversation_id}`;
|
|
269
|
+
console.log("subscribeToTopic: " + topic);
|
|
270
|
+
|
|
271
|
+
// duplichi il client principale
|
|
272
|
+
const subscriber = this.redis_client.duplicate();
|
|
273
|
+
await subscriber.connect();
|
|
274
|
+
|
|
275
|
+
let resolved = false; // flag per assicurarsi che risolva solo una volta
|
|
276
|
+
|
|
277
|
+
return new Promise((resolve, reject) => {
|
|
278
|
+
const cleanup = async () => {
|
|
279
|
+
try {
|
|
280
|
+
await subscriber.unsubscribe(topic);
|
|
281
|
+
await subscriber.quit();
|
|
282
|
+
} catch (err) {
|
|
283
|
+
// ignora errori di chiusura
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
subscriber.subscribe(topic, async (message) => {
|
|
288
|
+
if (resolved) return; // se già risolto, ignora altri messaggi
|
|
289
|
+
resolved = true;
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
const json = JSON.parse(message);
|
|
293
|
+
resolve(json);
|
|
294
|
+
} catch (err) {
|
|
295
|
+
reject(err);
|
|
296
|
+
} finally {
|
|
297
|
+
cleanup(); // chiudi il subscriber appena arriva il primo messaggio
|
|
298
|
+
}
|
|
299
|
+
}).catch(async (err) => {
|
|
300
|
+
if (!resolved) {
|
|
301
|
+
resolved = true;
|
|
302
|
+
reject(err);
|
|
303
|
+
await cleanup();
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
}
|
|
242
308
|
|
|
243
309
|
/** REMOVE MESSAGE FROM REDIS QUEUE LIST **/
|
|
244
310
|
async removeMessageFromQueue(conversation_id, message_id){
|
package/tiledesk/VoiceChannel.js
CHANGED
|
@@ -53,7 +53,7 @@ class VoiceChannel {
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
async getNextDelayTimeForCallId(callId){
|
|
56
|
-
const index = await this.redis_client.get('tiledesk:
|
|
56
|
+
const index = await this.redis_client.get('tiledesk:voice:'+callId + ':delayIndex');
|
|
57
57
|
if(index){
|
|
58
58
|
return this.getNextDelayTime(index)
|
|
59
59
|
}
|
|
@@ -64,31 +64,31 @@ class VoiceChannel {
|
|
|
64
64
|
async saveDelayIndexForCallId(callId){
|
|
65
65
|
|
|
66
66
|
//get value for current callId
|
|
67
|
-
const index = await this.redis_client.get('tiledesk:
|
|
67
|
+
const index = await this.redis_client.get('tiledesk:voice:'+callId + ':delayIndex');
|
|
68
68
|
if(index){
|
|
69
69
|
//increment
|
|
70
70
|
const delayIndex = (+index) +1
|
|
71
71
|
//save new index to redis
|
|
72
|
-
await this.redis_client.set('tiledesk:
|
|
72
|
+
await this.redis_client.set('tiledesk:voice:'+callId + ':delayIndex', delayIndex, {'EX': 86400});
|
|
73
73
|
return;
|
|
74
74
|
}
|
|
75
75
|
//if index is not present: set to default (0)
|
|
76
|
-
await this.redis_client.set('tiledesk:
|
|
76
|
+
await this.redis_client.set('tiledesk:voice:'+callId + ':delayIndex', 0, {'EX': 86400});
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/** RESET INDEX INTO REDIS DATA FOR CURRENT CALLID **/
|
|
80
80
|
async clearDelayTimeForCallId(callId){
|
|
81
81
|
|
|
82
82
|
//get value for current callId
|
|
83
|
-
const index = await this.redis_client.get('tiledesk:
|
|
83
|
+
const index = await this.redis_client.get('tiledesk:voice:'+callId + ':delayIndex');
|
|
84
84
|
winston.debug('clearDelayTimeForCallId: index -->'+index)
|
|
85
85
|
if(index){
|
|
86
86
|
//set index to default (0)
|
|
87
|
-
await this.redis_client.set('tiledesk:
|
|
87
|
+
await this.redis_client.set('tiledesk:voice:'+callId + ':delayIndex', 0, {'EX': 86400});
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
90
|
//if index is not present: set to default (0)
|
|
91
|
-
await this.redis_client.set('tiledesk:
|
|
91
|
+
await this.redis_client.set('tiledesk:voice:'+callId + ':delayIndex', 0, {'EX': 86400});
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
|
|
@@ -118,21 +118,21 @@ class VoiceChannel {
|
|
|
118
118
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
const index = await this.redis_client.get('tiledesk:
|
|
121
|
+
const index = await this.redis_client.get('tiledesk:voice:'+callId + ':attributes');
|
|
122
122
|
winston.debug('saveSettingsForCallId: attributes found -->'+index)
|
|
123
123
|
if(index){
|
|
124
124
|
//set index to default (0)
|
|
125
|
-
await this.redis_client.set('tiledesk:
|
|
125
|
+
await this.redis_client.set('tiledesk:voice:'+callId + ':attributes', JSON.stringify(flowAttributes), {'EX': 86400});
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
128
|
//if index is not present: set to default (0)
|
|
129
|
-
await this.redis_client.set('tiledesk:
|
|
129
|
+
await this.redis_client.set('tiledesk:voice:'+callId + ':attributes', JSON.stringify(flowAttributes), {'EX': 86400});
|
|
130
130
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
|
|
134
134
|
async getSettingsForCallId(callId){
|
|
135
|
-
const attributes = await this.redis_client.get('tiledesk:
|
|
135
|
+
const attributes = await this.redis_client.get('tiledesk:voice:'+callId + ':attributes');
|
|
136
136
|
if(attributes){
|
|
137
137
|
return JSON.parse(attributes)
|
|
138
138
|
}
|