@tiledesk/tiledesk-server 2.2.24 → 2.2.26
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/CHANGELOG.md +13 -3
- package/README.md +5 -0
- package/config/email.js +1 -1
- package/config/labels/widget.json +781 -611
- package/models/project_user.js +2 -0
- package/package.json +2 -2
- package/pubmodules/scheduler/tasks/closeBotUnresponsiveRequestTask.js +12 -3
- package/routes/faq_kb.js +2 -3
- package/routes/project_user.js +9 -2
- package/routes/widget.js +1 -1
- package/services/departmentService.js +5 -4
- package/services/emailService.js +2 -2
- package/services/faqService.js +62 -29
- package/config/labels/widget copy.json +0 -624
- package/services/faqBotSupport copy.js_consplit +0 -453
@@ -1,453 +0,0 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
'use strict';
|
4
|
-
|
5
|
-
const Faq = require('../models/faq');
|
6
|
-
const Faq_kb = require('../models/faq_kb');
|
7
|
-
const MessageConstants = require('../models/messageConstants');
|
8
|
-
var winston = require('../config/winston');
|
9
|
-
|
10
|
-
var jwt = require('jsonwebtoken');
|
11
|
-
const uuidv4 = require('uuid/v4');
|
12
|
-
|
13
|
-
const { TiledeskChatbotUtil } = require('@tiledesk/tiledesk-chatbot-util');
|
14
|
-
|
15
|
-
var request = require('retry-request', {
|
16
|
-
request: require('request')
|
17
|
-
});
|
18
|
-
|
19
|
-
|
20
|
-
var webhook_origin = process.env.WEBHOOK_ORIGIN || "http://localhost:3000";
|
21
|
-
winston.debug("webhook_origin: "+webhook_origin);
|
22
|
-
|
23
|
-
class FaqBotSupport {
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
getMessage(key, lang, labelsObject) {
|
29
|
-
|
30
|
-
|
31
|
-
if (!lang) {
|
32
|
-
lang = "EN";
|
33
|
-
}
|
34
|
-
|
35
|
-
lang = lang.toUpperCase();
|
36
|
-
|
37
|
-
winston.debug('getMessage: ' + key + ' ' + lang+ ' ' + JSON.stringify(labelsObject) );
|
38
|
-
|
39
|
-
var label = "";
|
40
|
-
|
41
|
-
try {
|
42
|
-
// winston.debug("1");
|
43
|
-
label = labelsObject[lang][key];
|
44
|
-
// winston.debug("2");
|
45
|
-
} catch(e) {
|
46
|
-
// winston.debug("Error", e);
|
47
|
-
label = labelsObject["EN"][key];
|
48
|
-
}
|
49
|
-
winston.debug('label: ' + label );
|
50
|
-
return label;
|
51
|
-
|
52
|
-
}
|
53
|
-
// usa api di sponziello parseReply: https://github.com/Tiledesk/tiledesk-nodejs-libs/blob/master/tiledesk-chatbot-util/index.js
|
54
|
-
|
55
|
-
parseMicrolanguage(text, message, bot, faq, disableWebHook, json) {
|
56
|
-
var that = this;
|
57
|
-
return new Promise(async (resolve, reject) => {
|
58
|
-
winston.info('parseMicrolanguage message: ' + JSON.stringify(message) );
|
59
|
-
|
60
|
-
winston.info('text: '+text);
|
61
|
-
var commands = TiledeskChatbotUtil.findSplits(text)
|
62
|
-
winston.info('commands: ' + JSON.stringify(commands) );
|
63
|
-
|
64
|
-
let messageReply;
|
65
|
-
// da mettere anche in microlanguage = true
|
66
|
-
if (commands.length > 1) {
|
67
|
-
commands.forEach(command => {
|
68
|
-
if (command.type === "message" && command.text != null) {
|
69
|
-
let replyCommand = TiledeskChatbotUtil.parseReply(command.text);
|
70
|
-
winston.info('replyCommand: ' + JSON.stringify(replyCommand) );
|
71
|
-
let messageCommandReply = replyCommand.message;
|
72
|
-
|
73
|
-
//TODO merge degli attributi dopo. fai lo stesso codice di giù
|
74
|
-
command.message = messageCommandReply;
|
75
|
-
}
|
76
|
-
});
|
77
|
-
|
78
|
-
messageReply = message.toObject();
|
79
|
-
messageReply.attributes = {commands: commands};
|
80
|
-
|
81
|
-
winston.info('messageReply: ' + JSON.stringify(messageReply) );
|
82
|
-
|
83
|
-
} else {
|
84
|
-
|
85
|
-
var reply = TiledeskChatbotUtil.parseReply(text);
|
86
|
-
winston.debug('parseReply: ' + JSON.stringify(reply) );
|
87
|
-
|
88
|
-
messageReply = reply.message;
|
89
|
-
|
90
|
-
}
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
var msg_attributes = {"_raw_message": text};
|
96
|
-
|
97
|
-
// prendi attributi e li mergi
|
98
|
-
// metadata prendi da messageReply SOLO SE CI SONO (DIVERSI NULL). Se riesci fai il merge
|
99
|
-
// prendi type e text
|
100
|
-
|
101
|
-
// if (message && message.attributes) {
|
102
|
-
// for(const [key, value] of Object.entries(message.attributes)) {
|
103
|
-
// msg_attributes[key] = value
|
104
|
-
// }
|
105
|
-
// }
|
106
|
-
|
107
|
-
if (json && json.attributes) {
|
108
|
-
for(const [key, value] of Object.entries(json.attributes)) {
|
109
|
-
msg_attributes[key] = value
|
110
|
-
}
|
111
|
-
}
|
112
|
-
|
113
|
-
if (messageReply && messageReply.attributes) {
|
114
|
-
for(const [key, value] of Object.entries(messageReply.attributes)) {
|
115
|
-
msg_attributes[key] = value
|
116
|
-
}
|
117
|
-
}
|
118
|
-
|
119
|
-
messageReply.attributes = msg_attributes;
|
120
|
-
|
121
|
-
// not used in faqBotHandler but used when the message is returned by webhook (subscription). So you must clone(add) all message fields here.
|
122
|
-
// winston.debug('message.language: '+ message.language );
|
123
|
-
// if (message.language) {
|
124
|
-
// messageReply.language = message.language;
|
125
|
-
// }
|
126
|
-
|
127
|
-
if (json && json.language) {
|
128
|
-
messageReply.language = json.language;
|
129
|
-
}
|
130
|
-
|
131
|
-
if (json && json.type) {
|
132
|
-
messageReply.type = json.type;
|
133
|
-
}
|
134
|
-
|
135
|
-
if (json && json.metadata) {
|
136
|
-
messageReply.metadata = json.metadata;
|
137
|
-
}
|
138
|
-
|
139
|
-
|
140
|
-
winston.debug('faq: ', faq );
|
141
|
-
if (disableWebHook === false && bot.webhook_enabled ===true && (faq.webhook_enabled === true ))
|
142
|
-
//|| reply.webhook))
|
143
|
-
{
|
144
|
-
|
145
|
-
winston.debug("bot.webhook_url "+ bot.webhook_url)
|
146
|
-
var webhookurl = bot.webhook_url;
|
147
|
-
|
148
|
-
|
149
|
-
// winston.debug("reply.webhook "+ reply.webhook )
|
150
|
-
|
151
|
-
// if (reply.webhook) {
|
152
|
-
// if (reply.webhook === true) {
|
153
|
-
webhookurl = bot.webhook_url;
|
154
|
-
// } else {
|
155
|
-
// webhookurl = reply.webhook;
|
156
|
-
// }
|
157
|
-
// }
|
158
|
-
|
159
|
-
if (!webhookurl) {
|
160
|
-
winston.debug("webhookurl is undefined return standard");
|
161
|
-
return resolve(messageReply);
|
162
|
-
}
|
163
|
-
|
164
|
-
var botWithSecret = await Faq_kb.findById(bot._id).select('+secret').exec();
|
165
|
-
|
166
|
-
var signOptions = {
|
167
|
-
issuer: 'https://tiledesk.com',
|
168
|
-
subject: 'bot',
|
169
|
-
audience: 'https://tiledesk.com/bots/'+bot._id,
|
170
|
-
jwtid: uuidv4()
|
171
|
-
};
|
172
|
-
|
173
|
-
// TODO metti bot_? a user._id
|
174
|
-
var token = jwt.sign(bot.toObject(), botWithSecret.secret, signOptions);
|
175
|
-
|
176
|
-
|
177
|
-
winston.debug("webhookurl "+ webhookurl)
|
178
|
-
|
179
|
-
return request({
|
180
|
-
uri : webhookurl,
|
181
|
-
headers: {
|
182
|
-
'Content-Type' : 'application/json',
|
183
|
-
'User-Agent': 'tiledesk-bot',
|
184
|
-
'Origin': webhook_origin
|
185
|
-
//'x-hook-secret': s.secret
|
186
|
-
},
|
187
|
-
method: 'POST',
|
188
|
-
json: true,
|
189
|
-
body: {payload:{text: text, bot: bot, message: message, intent: faq}, token: token},
|
190
|
-
// }).then(response => {
|
191
|
-
}, function(err, response, json){
|
192
|
-
if (err) {
|
193
|
-
winston.error("Error from webhook reply of getParsedMessage. Return standard reply", err);
|
194
|
-
|
195
|
-
return resolve(messageReply);
|
196
|
-
|
197
|
-
// return error
|
198
|
-
/*
|
199
|
-
var bot_answer = {};
|
200
|
-
bot_answer.text = err.toString();
|
201
|
-
if(response && response.text) {
|
202
|
-
bot_answer.text = bot_answer.text + ' '+response.text;
|
203
|
-
}
|
204
|
-
bot_answer.type = "text";
|
205
|
-
|
206
|
-
return resolve(bot_answer);
|
207
|
-
*/
|
208
|
-
}
|
209
|
-
if (response.statusCode >= 400) {
|
210
|
-
winston.verbose("The ChatBot webhook return error http status code. Return standard reply", response);
|
211
|
-
return resolve(messageReply);
|
212
|
-
}
|
213
|
-
|
214
|
-
if (!json) { //the webhook return empty body
|
215
|
-
winston.verbose("The ChatBot webhook return no json. Return standard reply", response);
|
216
|
-
return resolve(messageReply);
|
217
|
-
}
|
218
|
-
|
219
|
-
winston.debug("webhookurl repl_message ", response);
|
220
|
-
|
221
|
-
var text = undefined;
|
222
|
-
if(json && json.text===undefined) {
|
223
|
-
winston.verbose("webhookurl json is defined but text not. return standard reply",{json:json, response:response});
|
224
|
-
// text = 'Field text is not defined in the webhook respose of the faq with id: '+ faq._id+ ". Error: " + JSON.stringify(response);
|
225
|
-
return resolve(messageReply);
|
226
|
-
}else {
|
227
|
-
text = json.text;
|
228
|
-
}
|
229
|
-
winston.debug("webhookurl text: "+ text);
|
230
|
-
|
231
|
-
// // let cloned_message = Object.assign({}, messageReply);
|
232
|
-
// let cloned_message = message;
|
233
|
-
// winston.debug("cloned_message : ",cloned_message);
|
234
|
-
|
235
|
-
// if (json.attributes) {
|
236
|
-
// if (!cloned_message.attributes) {
|
237
|
-
// cloned_message.attributes = {}
|
238
|
-
// }
|
239
|
-
// winston.debug("ChatBot webhook json.attributes: ",json.attributes);
|
240
|
-
// for(const [key, value] of Object.entries(json.attributes)) {
|
241
|
-
// cloned_message.attributes[key] = value
|
242
|
-
// }
|
243
|
-
// }
|
244
|
-
|
245
|
-
// winston.debug("cloned_message after attributes: ",cloned_message);
|
246
|
-
|
247
|
-
that.parseMicrolanguage(text, message, bot, faq, true, json).then(function(bot_answer) {
|
248
|
-
return resolve(bot_answer);
|
249
|
-
});
|
250
|
-
});
|
251
|
-
}
|
252
|
-
|
253
|
-
return resolve(messageReply);
|
254
|
-
});
|
255
|
-
}
|
256
|
-
|
257
|
-
getParsedMessage(text, message, bot, faq) {
|
258
|
-
return this.parseMicrolanguage(text, message, bot, faq, false);
|
259
|
-
// return this.parseMicrolanguageOld(text, message, bot, faq);
|
260
|
-
}
|
261
|
-
|
262
|
-
// parseMicrolanguageOld(text, message, bot, faq) {
|
263
|
-
// var that = this;
|
264
|
-
// // text = "*"
|
265
|
-
// return new Promise(function(resolve, reject) {
|
266
|
-
// winston.debug("getParsedMessage ******",text);
|
267
|
-
// var repl_message = {};
|
268
|
-
|
269
|
-
// // cerca i bottoni eventualmente definiti
|
270
|
-
// var button_pattern = /^\*.*/mg; // buttons are defined as a line starting with an asterisk
|
271
|
-
// var text_buttons = text.match(button_pattern);
|
272
|
-
// if (text_buttons) {
|
273
|
-
// var text_with_removed_buttons = text.replace(button_pattern,"").trim();
|
274
|
-
// repl_message.text = text_with_removed_buttons
|
275
|
-
// var buttons = []
|
276
|
-
// text_buttons.forEach(element => {
|
277
|
-
// winston.debug("button ", element)
|
278
|
-
// var remove_extra_from_button = /^\*/mg;
|
279
|
-
// var button_text = element.replace(remove_extra_from_button, "").trim()
|
280
|
-
// var button = {}
|
281
|
-
// button["type"] = "text"
|
282
|
-
// button["value"] = button_text
|
283
|
-
// buttons.push(button)
|
284
|
-
// });
|
285
|
-
// repl_message.attributes =
|
286
|
-
// {
|
287
|
-
// attachment: {
|
288
|
-
// type:"template",
|
289
|
-
// buttons: buttons
|
290
|
-
// }
|
291
|
-
// }
|
292
|
-
// repl_message.type = MessageConstants.MESSAGE_TYPE.TEXT;
|
293
|
-
// } else {
|
294
|
-
// // no buttons
|
295
|
-
// repl_message.text = text
|
296
|
-
// repl_message.type = MessageConstants.MESSAGE_TYPE.TEXT;
|
297
|
-
// }
|
298
|
-
|
299
|
-
// var image_pattern = /^\\image:.*/mg;
|
300
|
-
// var imagetext = text.match(image_pattern);
|
301
|
-
// if (imagetext && imagetext.length>0) {
|
302
|
-
// var imageurl = imagetext[0].replace("\\image:","").trim();
|
303
|
-
// winston.debug("imageurl ", imageurl)
|
304
|
-
// var text_with_removed_image = text.replace(image_pattern,"").trim();
|
305
|
-
// repl_message.text = text_with_removed_image + " " + imageurl
|
306
|
-
// repl_message.metadata = {src: imageurl, width:200, height:200};
|
307
|
-
// repl_message.type = MessageConstants.MESSAGE_TYPE.IMAGE;
|
308
|
-
// }
|
309
|
-
|
310
|
-
// var frame_pattern = /^\\frame:.*/mg;
|
311
|
-
// var frametext = text.match(frame_pattern);
|
312
|
-
// if (frametext && frametext.length>0) {
|
313
|
-
// var frameurl = frametext[0].replace("\\frame:","").trim();
|
314
|
-
// winston.debug("frameurl ", frameurl)
|
315
|
-
// // var text_with_removed_image = text.replace(frame_pattern,"").trim();
|
316
|
-
// // repl_message.text = text_with_removed_image + " " + imageurl
|
317
|
-
// repl_message.metadata = {src: frameurl};
|
318
|
-
// repl_message.type = MessageConstants.MESSAGE_TYPE.FRAME;
|
319
|
-
// }
|
320
|
-
|
321
|
-
|
322
|
-
// var webhook_pattern = /^\\webhook:.*/mg;
|
323
|
-
// var webhooktext = text.match(webhook_pattern);
|
324
|
-
// if (webhooktext && webhooktext.length>0) {
|
325
|
-
// var webhookurl = webhooktext[0].replace("\\webhook:","").trim();
|
326
|
-
// winston.debug("webhookurl ", webhookurl)
|
327
|
-
|
328
|
-
// return request({
|
329
|
-
// uri : webhookurl,
|
330
|
-
// headers: {
|
331
|
-
// 'Content-Type': 'application/json'
|
332
|
-
// },
|
333
|
-
// method: 'POST',
|
334
|
-
// json: true,
|
335
|
-
// body: {payload:{text: text, bot: bot, message: message, faq: faq}},
|
336
|
-
// // }).then(response => {
|
337
|
-
// }, function(err, response, json){
|
338
|
-
// if (err) {
|
339
|
-
// bot_answer.text = err +' '+ response.text;
|
340
|
-
// bot_answer.type = MessageConstants.MESSAGE_TYPE.TEXT;
|
341
|
-
// winston.error("Error from webhook reply of getParsedMessage", err);
|
342
|
-
// return resolve(bot_answer);
|
343
|
-
// }
|
344
|
-
// // if (response.statusCode >= 400) {
|
345
|
-
// // return reject(`HTTP Error: ${response.statusCode}`);
|
346
|
-
// // }
|
347
|
-
// winston.debug("webhookurl repl_message ", response);
|
348
|
-
|
349
|
-
// var text = undefined;
|
350
|
-
// if(json && json.text===undefined) {
|
351
|
-
// text = 'Field text is not defined in the webhook respose of the faq with id: '+ faq._id+ ". Error: " + JSON.stringify(response);
|
352
|
-
// }else {
|
353
|
-
// text = json.text;
|
354
|
-
// }
|
355
|
-
|
356
|
-
|
357
|
-
// that.getParsedMessage(text,message, bot, faq).then(function(bot_answer) {
|
358
|
-
// return resolve(bot_answer);
|
359
|
-
// });
|
360
|
-
// });
|
361
|
-
|
362
|
-
// }else {
|
363
|
-
// winston.debug("repl_message ", repl_message)
|
364
|
-
// return resolve(repl_message);
|
365
|
-
// }
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
// });
|
370
|
-
// }
|
371
|
-
|
372
|
-
|
373
|
-
getBotMessage(botAnswer, projectid, bot, message, threshold) {
|
374
|
-
var that = this;
|
375
|
-
return new Promise(function(resolve, reject) {
|
376
|
-
|
377
|
-
winston.debug('botAnswer', botAnswer);
|
378
|
-
// var found = false;
|
379
|
-
var bot_answer={};
|
380
|
-
|
381
|
-
if (!botAnswer ) {
|
382
|
-
|
383
|
-
var query = { "id_project": projectid, "id_faq_kb": bot._id, "question": "defaultFallback"};
|
384
|
-
winston.debug('query', query);
|
385
|
-
|
386
|
-
|
387
|
-
Faq.find(query)
|
388
|
-
.lean(). //fai cache
|
389
|
-
exec(function (err, faqs) {
|
390
|
-
if (err) {
|
391
|
-
return res.status(500).send({ success: false, msg: 'Error getting object.' });
|
392
|
-
}
|
393
|
-
|
394
|
-
winston.debug("faqs", faqs);
|
395
|
-
|
396
|
-
if (faqs && faqs.length>0) {
|
397
|
-
winston.debug("faqs exact", faqs);
|
398
|
-
|
399
|
-
bot_answer.text=faqs[0].answer;
|
400
|
-
|
401
|
-
winston.debug("bot_answer exact", bot_answer);
|
402
|
-
// found = true;
|
403
|
-
// return resolve(bot_answer);
|
404
|
-
|
405
|
-
if (message.channel.name == "chat21") { //why this contition on chat21 channel? bacause only chat21 support parsed replies?
|
406
|
-
winston.debug("faqBotSupport message.channel.name is chat21",message);
|
407
|
-
that.getParsedMessage(bot_answer.text,message, bot, faqs[0]).then(function(bot_answerres) {
|
408
|
-
|
409
|
-
bot_answerres.defaultFallback=true;
|
410
|
-
|
411
|
-
return resolve(bot_answerres);
|
412
|
-
});
|
413
|
-
|
414
|
-
} else {
|
415
|
-
winston.debug("faqBotSupport message.channel.name is not chat21 returning default",message);
|
416
|
-
return resolve(bot_answer);
|
417
|
-
}
|
418
|
-
|
419
|
-
} else {
|
420
|
-
var message_key = "DEFAULT_NOTFOUND_NOBOT_SENTENCE_REPLY_MESSAGE";
|
421
|
-
bot_answer.text = that.getMessage(message_key, message.language, faqBotSupport.LABELS);
|
422
|
-
bot_answer.defaultFallback = true;
|
423
|
-
// console.log("bot_answer ", bot_answer)
|
424
|
-
return resolve(bot_answer);
|
425
|
-
}
|
426
|
-
});
|
427
|
-
}
|
428
|
-
|
429
|
-
|
430
|
-
});
|
431
|
-
|
432
|
-
}
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
}
|
437
|
-
|
438
|
-
|
439
|
-
var faqBotSupport = new FaqBotSupport();
|
440
|
-
|
441
|
-
faqBotSupport.LABELS = {
|
442
|
-
EN : {
|
443
|
-
DEFAULT_NOTFOUND_NOBOT_SENTENCE_REPLY_MESSAGE: "I did not find an answer in the knowledge base. \n Please reformulate your question?"
|
444
|
-
},
|
445
|
-
IT : {
|
446
|
-
DEFAULT_NOTFOUND_NOBOT_SENTENCE_REPLY_MESSAGE: "Non sono in grado di fornirti una risposta adeguata. \n Prego riformula la domanda."
|
447
|
-
},
|
448
|
-
"IT-IT" : {
|
449
|
-
DEFAULT_NOTFOUND_NOBOT_SENTENCE_REPLY_MESSAGE: "Non sono in grado di fornirti una risposta adeguata. \n Prego riformula la domanda."
|
450
|
-
}
|
451
|
-
}
|
452
|
-
|
453
|
-
module.exports = faqBotSupport;
|