@tiledesk/tiledesk-server 2.2.23 → 2.2.28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +6 -0
  3. package/app.js +73 -3
  4. package/bin/www +4 -1
  5. package/channels/chat21/chat21WebHook.js +1 -1
  6. package/config/email.js +1 -1
  7. package/config/global.js +2 -0
  8. package/config/labels/widget.json +781 -611
  9. package/event/messageEvent.js +4 -4
  10. package/middleware/has-role.js +1 -1
  11. package/middleware/passport.js +3 -3
  12. package/models/project.js +10 -0
  13. package/models/project_user.js +2 -0
  14. package/models/request.js +1 -1
  15. package/package.json +4 -3
  16. package/pubmodules/emailNotification/requestNotification.js +4 -4
  17. package/pubmodules/messageTransformer/messageHandlebarsTransformerInterceptor.js +3 -3
  18. package/pubmodules/messageTransformer/messageTransformerInterceptor.js +3 -3
  19. package/pubmodules/rules/conciergeBot.js +5 -2
  20. package/pubmodules/scheduler/tasks/closeBotUnresponsiveRequestTask.js +12 -3
  21. package/routes/department.js +1 -1
  22. package/routes/faq_kb.js +2 -3
  23. package/routes/labels.js +2 -0
  24. package/routes/message.js +1 -1
  25. package/routes/project.js +73 -1
  26. package/routes/project_user.js +11 -4
  27. package/routes/request.js +15 -0
  28. package/routes/user-request.js +15 -0
  29. package/routes/widget.js +1 -1
  30. package/services/departmentService.js +5 -4
  31. package/services/faqBotHandler.js +1 -1
  32. package/services/faqService.js +62 -29
  33. package/services/labelService-no-default.js +2 -2
  34. package/services/labelService.js +1 -1
  35. package/services/leadService.js +2 -2
  36. package/services/operatingHoursService.js +1 -1
  37. package/services/requestService.js +3 -3
  38. package/utils/orgUtil.js +74 -0
  39. package/utils/sendMessageUtil.js +2 -2
  40. package/websocket/webSocketServer.js +10 -10
  41. 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;