@tiledesk/tiledesk-server 2.1.40 → 2.2.3
Sign up to get free protection for your applications and to get access to all the features.
- package/.circleci/config.yml +54 -0
- package/.env.sample +1 -1
- package/.github/workflows/docker-community-push-latest.yml +22 -0
- package/.github/workflows/{docker-image-push.yml → docker-image-en-tag-push.yml} +1 -1
- package/.github/workflows/docker-image-tag-community-tag-push.yml +21 -0
- package/.github/workflows/{docker-push-latest.yml → docker-push-en-push-latest.yml} +1 -1
- package/CHANGELOG.md +195 -1
- package/Dockerfile +1 -1
- package/Dockerfile-en +1 -1
- package/README.md +5 -7
- package/app.js +12 -1
- package/channels/channelManager.js +1 -1
- package/channels/chat21/chat21Contact.js +34 -8
- package/channels/chat21/chat21Handler.js +48 -5
- package/channels/chat21/chat21WebHook.js +34 -9
- package/channels/chat21/nativeauth.js +2 -2
- package/channels/chat21/package-lock.json +3013 -0
- package/config/email.js +2 -0
- package/config/global.js +3 -0
- package/config/labels/widget.json +170 -16
- package/event/messageEvent.js +18 -1
- package/middleware/passport.js +10 -4
- package/migrations/1619185894304-request-remove-duplicated-request-by-request_id--autosync.js +67 -0
- package/models/actionsConstants.js +7 -0
- package/models/department.js +3 -0
- package/models/faq.js +8 -2
- package/models/faq_kb.js +6 -0
- package/models/message.js +10 -4
- package/models/messageConstants.js +9 -3
- package/models/request.js +33 -3
- package/package.json +31 -28
- package/pubmodules/emailNotification/requestNotification.js +483 -56
- package/pubmodules/messageActions/messageActionsInterceptor.js +20 -7
- package/pubmodules/messageTransformer/index.js +5 -1
- package/pubmodules/messageTransformer/messageTransformerInterceptor.js +4 -2
- package/pubmodules/messageTransformer/microLanguageAttributesTransformerInterceptor.js +67 -0
- package/pubmodules/messageTransformer/microLanguageTransformerInterceptor.js +67 -0
- package/pubmodules/pubModulesManager.js +66 -13
- package/pubmodules/rules/conciergeBot.js +81 -49
- package/routes/auth.js +46 -11
- package/routes/campaigns.js +117 -25
- package/routes/department.js +2 -2
- package/routes/faq.js +19 -0
- package/routes/faq_kb.js +13 -4
- package/routes/faqpub.js +1 -1
- package/routes/files.js +17 -2
- package/routes/images.js +1 -1
- package/routes/jwt.js +0 -1
- package/routes/logs.js +26 -0
- package/routes/message.js +7 -2
- package/routes/messagesRoot.js +73 -16
- package/routes/project_user.js +36 -1
- package/routes/request.js +88 -12
- package/routes/requestUtilRoot.js +30 -0
- package/routes/urls.js +12 -0
- package/routes/users.js +5 -1
- package/services/BotSubscriptionNotifier.js +1 -0
- package/services/departmentService.js +29 -5
- package/services/emailService.js +1170 -239
- package/services/faqBotHandler.js +176 -61
- package/services/faqBotSupport.js +182 -117
- package/services/faqService.js +18 -14
- package/services/messageService.js +57 -9
- package/services/modulesManager.js +86 -23
- package/services/requestService.js +58 -17
- package/template/email/assignedEmailMessage.html +205 -0
- package/template/email/assignedRequest.html +44 -14
- package/template/email/beenInvitedExistingUser.html +2 -2
- package/template/email/beenInvitedNewUser.html +1 -1
- package/template/email/newMessage.html +31 -12
- package/template/email/passwordChanged.html +2 -3
- package/template/email/pooledEmailMessage.html +208 -0
- package/template/email/pooledRequest.html +41 -14
- package/template/email/resetPassword.html +2 -3
- package/template/email/sendTranscript.html +1 -1
- package/template/email/test.html +1 -1
- package/template/email/ticket.html +191 -0
- package/template/email/ticket.txt +11 -0
- package/template/email/verify.html +1 -1
- package/test/authentication.js +76 -4
- package/test/authenticationJwt.js +76 -2
- package/test/campaignsRoute.js +226 -0
- package/test/faqService.js +3 -3
- package/test/faqkbRoute.js +3 -2
- package/test/messageRootRoute.js +193 -0
- package/test/messageRoute.js +75 -0
- package/test/messageService.js +39 -2
- package/test/requestRoute.js +27 -9
- package/test/requestService.js +472 -11
- package/test-int/bot.js +673 -8
- package/websocket/webSocketServer.js +7 -4
@@ -10,9 +10,60 @@ var BotFromParticipant = require("../utils/botFromParticipant");
|
|
10
10
|
var cacheUtil = require('../utils/cacheUtil');
|
11
11
|
var eventService = require('../pubmodules/events/eventService');
|
12
12
|
var mongoose = require('mongoose');
|
13
|
+
const { TiledeskChatbotUtil } = require('@tiledesk/tiledesk-chatbot-util');
|
14
|
+
const ActionsConstants = require('../models/actionsConstants');
|
13
15
|
|
14
16
|
class FaqBotHandler {
|
15
17
|
|
18
|
+
static is_command(text) {
|
19
|
+
// console.log("msg:", msg);
|
20
|
+
if (!text) {
|
21
|
+
return {
|
22
|
+
'command': null,
|
23
|
+
'text': null
|
24
|
+
}
|
25
|
+
}
|
26
|
+
// const text = msg.text;
|
27
|
+
// console.log("msg.text:", msg.text);
|
28
|
+
// console.log("TiledeskChatbotUtil.AGENT_COMMAND:", TiledeskChatbotUtil.AGENT_COMMAND.replace(/\\\\/g, '\\'));
|
29
|
+
//const agent_pattern = new RegExp('^(' + TiledeskChatbotUtil.AGENT_COMMAND.replace(/\\/g, '\\\\') + ')$', 'm');
|
30
|
+
// console.log("agent_pattern:", agent_pattern);
|
31
|
+
//const match_agent = text.match(agent_pattern);
|
32
|
+
//console.log("match_agent: ", match_agent);
|
33
|
+
const match_agent = text.indexOf(ActionsConstants.CHAT_ACTION_MESSAGE.AGENT);
|
34
|
+
const match_close = text.indexOf(ActionsConstants.CHAT_ACTION_MESSAGE.CLOSE);
|
35
|
+
//console.log("match_agent: ", match_agent);
|
36
|
+
// const agent_handoff = null;
|
37
|
+
//if (match_agent && match_agent.length >=2) {
|
38
|
+
if (match_close >-1) {
|
39
|
+
// console.log("match!");
|
40
|
+
// let parts = text.split('\\agent');
|
41
|
+
// console.log(parts)
|
42
|
+
const new_msg_text = text.replace(ActionsConstants.CHAT_ACTION_MESSAGE.CLOSE,"");
|
43
|
+
// const new_msg_text = parts[0].trim()
|
44
|
+
// console.log(new_msg_text)
|
45
|
+
return {
|
46
|
+
'command': ActionsConstants.CHAT_ACTION_MESSAGE.CLOSE,
|
47
|
+
'text': new_msg_text
|
48
|
+
}
|
49
|
+
}
|
50
|
+
if (match_agent >-1) {
|
51
|
+
// console.log("match!");
|
52
|
+
// let parts = text.split('\\agent');
|
53
|
+
// console.log(parts)
|
54
|
+
const new_msg_text = text.replace(ActionsConstants.CHAT_ACTION_MESSAGE.AGENT,"");
|
55
|
+
// const new_msg_text = parts[0].trim()
|
56
|
+
// console.log(new_msg_text)
|
57
|
+
return {
|
58
|
+
'command': ActionsConstants.CHAT_ACTION_MESSAGE.AGENT,
|
59
|
+
'text': new_msg_text
|
60
|
+
}
|
61
|
+
}
|
62
|
+
return {
|
63
|
+
'command': null,
|
64
|
+
'text': text
|
65
|
+
}
|
66
|
+
}
|
16
67
|
|
17
68
|
|
18
69
|
listen() {
|
@@ -51,8 +102,14 @@ class FaqBotHandler {
|
|
51
102
|
var query = { "id_project": message.id_project, "id_faq_kb": faq_kb._id, "question": message.text};
|
52
103
|
|
53
104
|
if (message.attributes && message.attributes.action) {
|
105
|
+
|
54
106
|
var action = message.attributes.action;
|
55
|
-
|
107
|
+
var action_parameters_index = action.indexOf("?");
|
108
|
+
if (action_parameters_index > -1) {
|
109
|
+
action = action.substring(0,action_parameters_index);
|
110
|
+
}
|
111
|
+
winston.debug("action: " + action);
|
112
|
+
|
56
113
|
var isObjectId = mongoose.Types.ObjectId.isValid(action);
|
57
114
|
winston.debug("isObjectId:"+ isObjectId);
|
58
115
|
|
@@ -66,7 +123,18 @@ class FaqBotHandler {
|
|
66
123
|
winston.debug("query message.attributes.action ", query);
|
67
124
|
}
|
68
125
|
|
69
|
-
|
126
|
+
|
127
|
+
if (message.request && message.request.attributes && message.request.attributes.blocked_intent) {
|
128
|
+
query = { "id_project": message.id_project, "id_faq_kb": faq_kb._id, $or:[{"intent_id": message.request.attributes.blocked_intent}, {"intent_display_name": message.request.attributes.blocked_intent}]};
|
129
|
+
// TODO skip if type reset (better create a resetIntent action /reset reset the attributes) -> TODO DELETE message.request.attributes.blocked_intent for next call
|
130
|
+
winston.debug("query message.attributes.blocked_intent ", query);
|
131
|
+
// res.send({text:"ripeti la mail", action: id_intent}); fai un test che forse già funziona
|
132
|
+
}
|
133
|
+
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
|
70
138
|
Faq.find(query)
|
71
139
|
.lean().
|
72
140
|
exec(function (err, faqs) {
|
@@ -91,31 +159,6 @@ class FaqBotHandler {
|
|
91
159
|
answerObj.score = 100; //exact search not set score
|
92
160
|
winston.debug("answerObj.score", answerObj.score);
|
93
161
|
|
94
|
-
|
95
|
-
|
96
|
-
// === TEMPORARY: search for handoff to agent command (\agent)
|
97
|
-
/*
|
98
|
-
const handoff_parsed = TiledeskChatbotUtil.is_agent_handoff_command(message);
|
99
|
-
winston.debug('handoff_parsed?', handoff_parsed);
|
100
|
-
|
101
|
-
if (handoff_parsed.agent_handoff) {
|
102
|
-
console.log("agent_handoff command found");
|
103
|
-
|
104
|
-
messageService.send(sender, botName, message.recipient, handoff_parsed.agent_handoff,
|
105
|
-
message.id_project, sender, {subtype: "info"}, 'text', undefined).then(function(savedMessage){
|
106
|
-
winston.info("faqbot agent sent ", savedMessage.toObject());
|
107
|
-
});
|
108
|
-
|
109
|
-
// PATCH: Chat clients (i.e. web widget) remove messages with text = null
|
110
|
-
// handoff_parsed.text contains the eventual text before the \agent command
|
111
|
-
// or 'all the message text' if \agent was not found
|
112
|
-
message.text = handoff_parsed.text? handoff_parsed.text : '';
|
113
|
-
}
|
114
|
-
*/
|
115
|
-
// === TEMPORARY: search for handoff to agent command (\agent)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
162
|
// qui
|
120
163
|
faqBotSupport.getParsedMessage(answerObj.answer, message, faq_kb, answerObj).then(function(bot_answer) {
|
121
164
|
// send(sender, senderFullname, recipient, text, id_project, createdBy, attributes, type) {
|
@@ -128,66 +171,90 @@ class FaqBotHandler {
|
|
128
171
|
// attr._answer = that.getCircularReplacer(answerObj);
|
129
172
|
if (answerObj && answerObj._id) {
|
130
173
|
attr._answerid = answerObj._id.toString();
|
131
|
-
}
|
132
|
-
|
174
|
+
}
|
133
175
|
|
134
176
|
let question_payload = Object.assign({}, message);
|
135
177
|
delete question_payload.request;
|
136
178
|
|
137
179
|
winston.debug("question_payload", question_payload);
|
138
180
|
|
181
|
+
let clonedfaqs = faqs.slice();
|
182
|
+
if (clonedfaqs && clonedfaqs.length>0) {
|
183
|
+
clonedfaqs = clonedfaqs.shift()
|
184
|
+
}
|
185
|
+
winston.verbose("clonedfaqs", clonedfaqs);
|
186
|
+
|
139
187
|
const intent_info = {
|
140
188
|
intent_name: answerObj.intent_display_name,
|
141
189
|
is_fallback: false,
|
142
190
|
confidence: answerObj.score,
|
143
|
-
question_payload: question_payload
|
191
|
+
question_payload: question_payload,
|
192
|
+
others: clonedfaqs
|
144
193
|
}
|
145
194
|
winston.debug("intent_info", intent_info);
|
146
195
|
attr.intent_info = intent_info;
|
147
196
|
|
148
197
|
winston.debug("answerObj", answerObj);
|
149
198
|
// winston.info("that.getCircularReplacer(answerObj)", that.getCircularReplacer(answerObj));
|
150
|
-
winston.debug("attr", attr);
|
199
|
+
winston.debug("attr", attr);
|
151
200
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
201
|
+
|
202
|
+
|
203
|
+
const command_parsed = FaqBotHandler.is_command(bot_answer.text);
|
204
|
+
winston.debug('command_parsed?', command_parsed);
|
205
|
+
|
206
|
+
if (command_parsed.command) {
|
207
|
+
winston.debug("agent_handoff faqs command found");
|
208
|
+
|
209
|
+
messageService.send(sender, botName, message.recipient, command_parsed.command,
|
210
|
+
message.id_project, sender, {subtype: "info"}, 'text', undefined).then(function(savedMessage){
|
211
|
+
winston.debug("agent_handoff faqs agent sent ", savedMessage.toObject());
|
212
|
+
});
|
213
|
+
// PATCH: Chat clients (i.e. web widget) remove messages with text = null
|
214
|
+
// command_parsed.text contains the eventual text before the \agent command
|
215
|
+
// or 'all the message text' if \agent was not found
|
216
|
+
bot_answer.text = command_parsed.text? command_parsed.text : undefined;
|
217
|
+
winston.debug("bot_answer.text1 "+ bot_answer.text );
|
218
|
+
}
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
winston.debug("bot_answer.text2 "+ bot_answer.text );
|
223
|
+
// if (bot_answer.text) { //can be undefined id /agent only
|
224
|
+
messageService.send(sender, botName, message.recipient, bot_answer.text,
|
225
|
+
message.id_project, sender, attr, bot_answer.type, bot_answer.metadata, bot_answer.language).then(function(savedMessage){
|
226
|
+
winston.debug("faqbot message botAns ", savedMessage.toObject());
|
227
|
+
});
|
228
|
+
// }
|
229
|
+
|
230
|
+
|
231
|
+
|
161
232
|
});
|
162
233
|
|
163
234
|
|
164
235
|
}
|
165
236
|
|
166
|
-
|
167
|
-
// getBotMessageNew(botAnswer, projectid, bot, language, threshold)
|
168
|
-
// faqBotSupport.getBotMessageNew(answerObj, message.id_project, faq_kb, message, 1.2).then(function(botAns){
|
169
|
-
// // faqBotSupport.getBotMessage(answerObj, message.id_project, message.request.department._id, message.language, 1.2).then(function(botAns){
|
170
|
-
// winston.debug("faqbot message botAns ", botAns);
|
171
|
-
|
172
|
-
// if (botAns) {
|
173
|
-
// // let attributes = {bot_reponse_template: botAns.template};
|
174
|
-
// messageService.send(sender, botName, message.recipient, botAns.text,
|
175
|
-
// message.id_project, sender, botAns.attributes, botAns.type, botAns.metadata).then(function(savedMessage){
|
176
|
-
// winston.info("faqbot message bot answer " ,savedMessage.toObject());
|
177
|
-
// });
|
178
|
-
// }
|
179
|
-
// });
|
180
|
-
|
237
|
+
|
181
238
|
|
182
239
|
} else {
|
183
240
|
|
184
241
|
query = { "id_project": message.id_project, "id_faq_kb": faq_kb._id};
|
185
|
-
|
186
|
-
|
242
|
+
|
243
|
+
var search_obj = {"$search": message.text};
|
244
|
+
|
245
|
+
if (faq_kb.language) {
|
246
|
+
search_obj["$language"] = faq_kb.language;
|
247
|
+
}
|
248
|
+
query.$text = search_obj;
|
249
|
+
winston.debug("fulltext search query", query);
|
250
|
+
|
187
251
|
Faq.find(query, {score: { $meta: "textScore" } })
|
188
252
|
.sort( { score: { $meta: "textScore" } } ) //https://docs.mongodb.com/manual/reference/operator/query/text/#sort-by-text-search-score
|
189
253
|
.lean().
|
190
254
|
exec(function (err, faqs) {
|
255
|
+
if (err) {
|
256
|
+
return winston.error('Error getting fulltext objects.', err);
|
257
|
+
}
|
191
258
|
winston.debug("faqs", faqs);
|
192
259
|
|
193
260
|
// botprefix
|
@@ -218,11 +285,18 @@ class FaqBotHandler {
|
|
218
285
|
|
219
286
|
winston.debug("question_payload", question_payload);
|
220
287
|
|
288
|
+
let clonedfaqs = faqs.slice();
|
289
|
+
if (clonedfaqs && clonedfaqs.length>0) {
|
290
|
+
clonedfaqs = clonedfaqs.shift()
|
291
|
+
}
|
292
|
+
winston.verbose("clonedfaqs", clonedfaqs);
|
293
|
+
|
221
294
|
const intent_info = {
|
222
295
|
intent_name: answerObj.intent_display_name,
|
223
296
|
is_fallback: false,
|
224
297
|
confidence: answerObj.score,
|
225
|
-
question_payload: question_payload
|
298
|
+
question_payload: question_payload,
|
299
|
+
others: clonedfaqs
|
226
300
|
}
|
227
301
|
winston.debug("intent_info", intent_info);
|
228
302
|
attr.intent_info = intent_info;
|
@@ -230,9 +304,30 @@ class FaqBotHandler {
|
|
230
304
|
|
231
305
|
|
232
306
|
winston.debug("attr", attr);
|
307
|
+
|
308
|
+
|
309
|
+
const command_parsed = FaqBotHandler.is_command(bot_answer.text);
|
310
|
+
winston.debug('command_parsed?', command_parsed);
|
311
|
+
|
312
|
+
if (command_parsed.command) {
|
313
|
+
winston.debug("agent_handoff faqs command found");
|
314
|
+
|
315
|
+
messageService.send(sender, botName, message.recipient, command_parsed.command,
|
316
|
+
message.id_project, sender, {subtype: "info"}, 'text', undefined).then(function(savedMessage){
|
317
|
+
winston.debug("agent_handoff faqs agent sent ", savedMessage.toObject());
|
318
|
+
});
|
319
|
+
// PATCH: Chat clients (i.e. web widget) remove messages with text = null
|
320
|
+
// command_parsed.text contains the eventual text before the \agent command
|
321
|
+
// or 'all the message text' if \agent was not found
|
322
|
+
bot_answer.text = command_parsed.text? command_parsed.text : undefined;
|
323
|
+
winston.debug("bot_answer.text1 "+ bot_answer.text );
|
324
|
+
}
|
325
|
+
|
326
|
+
|
327
|
+
|
233
328
|
// send(sender, senderFullname, recipient, text, id_project, createdBy, attributes) {
|
234
329
|
messageService.send(sender, botName, message.recipient, bot_answer.text,
|
235
|
-
message.id_project, sender, attr, bot_answer.type, bot_answer.metadata).then(function(savedMessage){
|
330
|
+
message.id_project, sender, attr, bot_answer.type, bot_answer.metadata, bot_answer.language).then(function(savedMessage){
|
236
331
|
|
237
332
|
winston.debug("faqbot message sending ", savedMessage.toObject());
|
238
333
|
});
|
@@ -244,7 +339,6 @@ class FaqBotHandler {
|
|
244
339
|
var threshold = 1.2;
|
245
340
|
|
246
341
|
faqBotSupport.getBotMessage(answerObj, message.id_project, faq_kb, message, threshold).then(function(botAns){
|
247
|
-
// faqBotSupport.getBotMessage(answerObj, message.id_project, message.request.department._id, message.language, 1.2).then(function(botAns){
|
248
342
|
winston.debug("faqbot message botAns ", botAns);
|
249
343
|
|
250
344
|
if (botAns) {
|
@@ -304,9 +398,30 @@ class FaqBotHandler {
|
|
304
398
|
winston.debug("attr", attr);
|
305
399
|
|
306
400
|
|
401
|
+
|
402
|
+
const command_parsed = FaqBotHandler.is_command(botAns.text);
|
403
|
+
winston.debug('command_parsed?', command_parsed);
|
404
|
+
|
405
|
+
if (command_parsed.command) {
|
406
|
+
winston.debug("agent_handoff faqs command found");
|
407
|
+
|
408
|
+
messageService.send(sender, botName, message.recipient, command_parsed.command,
|
409
|
+
message.id_project, sender, {subtype: "info"}, 'text', undefined).then(function(savedMessage){
|
410
|
+
winston.debug("agent_handoff faqs agent sent ", savedMessage.toObject());
|
411
|
+
});
|
412
|
+
// PATCH: Chat clients (i.e. web widget) remove messages with text = null
|
413
|
+
// command_parsed.text contains the eventual text before the \agent command
|
414
|
+
// or 'all the message text' if \agent was not found
|
415
|
+
botAns.text = command_parsed.text? command_parsed.text : undefined;
|
416
|
+
winston.debug("bot_answer.text1 "+ botAns.text );
|
417
|
+
}
|
418
|
+
|
419
|
+
|
420
|
+
|
421
|
+
|
307
422
|
// send(sender, senderFullname, recipient, text, id_project, createdBy, attributes, type, metadata)
|
308
423
|
messageService.send(sender, botName, message.recipient, botAns.text,
|
309
|
-
message.id_project, sender, attr, botAns.type, botAns.metadata).then(function(savedMessage){
|
424
|
+
message.id_project, sender, attr, botAns.type, botAns.metadata, botAns.language).then(function(savedMessage){
|
310
425
|
winston.debug("faqbot message botAns " ,savedMessage.toObject());
|
311
426
|
});
|
312
427
|
}
|