@tiledesk/tiledesk-server 2.3.5 → 2.3.7-1.1
Sign up to get free protection for your applications and to get access to all the features.
- package/.github/workflows/docker-community-worker-push-latest.yml +23 -0
- package/.github/workflows/docker-image-tag-worker-community-tag-push.yml +22 -0
- package/CHANGELOG.md +361 -3
- package/Dockerfile-jobs +31 -0
- package/app.js +62 -69
- package/channels/chat21/chat21Handler.js +37 -6
- package/channels/chat21/chat21WebHook.js +52 -29
- package/channels/chat21/package-lock.json +663 -706
- package/channels/chat21/package.json +2 -2
- package/config/labels/widget.json +337 -136
- package/deploy.sh +2 -0
- package/event/messageEvent.js +110 -9
- package/jobs.js +80 -0
- package/jobsManager.js +47 -0
- package/middleware/has-role.js +10 -3
- package/middleware/ipFilter.js +220 -0
- package/middleware/passport.js +8 -2
- package/models/department.js +1 -1
- package/models/faq.js +77 -25
- package/models/faq_kb.js +19 -0
- package/models/message.js +10 -8
- package/models/project.js +10 -0
- package/models/project_user.js +10 -0
- package/models/request.js +12 -1
- package/package.json +12 -11
- package/pubmodules/activities/activityArchiver.js +216 -90
- package/pubmodules/activities/routes/activity.js +1 -1
- package/pubmodules/apps/index.js +8 -0
- package/pubmodules/apps/listener.js +27 -0
- package/pubmodules/cache/index.js +2 -0
- package/pubmodules/cache/mongoose-cachegoose-fn.js +630 -0
- package/pubmodules/canned/cannedResponse.js +4 -0
- package/pubmodules/canned/cannedResponseRoute.js +10 -5
- package/pubmodules/dialogflow/index.js +10 -0
- package/pubmodules/dialogflow/listener.js +66 -0
- package/pubmodules/emailNotification/requestNotification.js +58 -28
- package/pubmodules/events/eventRoute.js +49 -24
- package/pubmodules/messageTransformer/messageHandlebarsTransformerInterceptor.js +6 -1
- package/pubmodules/messageTransformer/messageTransformerInterceptor.js +10 -4
- package/pubmodules/pubModulesManager.js +173 -7
- package/pubmodules/queue/index.js +4 -0
- package/pubmodules/queue/reconnect.js +331 -0
- package/pubmodules/queue/reconnectFanout.js +256 -0
- package/pubmodules/rasa/listener.js +5 -5
- package/pubmodules/routing-queue/index.js +3 -0
- package/pubmodules/routing-queue/listener.js +328 -0
- package/pubmodules/rules/conciergeBot.js +4 -4
- package/pubmodules/scheduler/tasks/closeAgentUnresponsiveRequestTask.js +6 -1
- package/pubmodules/scheduler/tasks/closeBotUnresponsiveRequestTask.js +7 -1
- package/pubmodules/tilebot/index.js +11 -0
- package/pubmodules/tilebot/listener.js +85 -0
- package/pubmodules/trigger/rulesTrigger.js +137 -14
- package/pubmodules/trigger/start.js +5 -1
- package/pubmodules/whatsapp/index.js +7 -0
- package/pubmodules/whatsapp/listener.js +32 -0
- package/routes/auth.js +7 -2
- package/routes/campaigns.js +3 -3
- package/routes/department.js +3 -2
- package/routes/email.js +32 -2
- package/routes/faq.js +37 -2
- package/routes/faq_kb.js +496 -133
- package/routes/faqpub.js +5 -0
- package/routes/lead.js +56 -0
- package/routes/message.js +196 -14
- package/routes/messagesRoot.js +39 -0
- package/routes/project.js +76 -4
- package/routes/project_user.js +11 -1
- package/routes/project_user_test.js +19 -0
- package/routes/request.js +134 -30
- package/routes/troubleshooting.js +12 -0
- package/routes/users-util.js +39 -0
- package/routes/users.js +1 -1
- package/routes/widget.js +64 -2
- package/services/BotSubscriptionNotifier.js +5 -0
- package/services/banUserNotifier.js +86 -0
- package/services/cacheEnabler.js +56 -0
- package/services/chatbotService.js +101 -0
- package/services/departmentService.js +25 -3
- package/services/emailService.js +170 -28
- package/services/faqBotHandler.js +2 -3
- package/services/faqService.js +28 -3
- package/services/geoService.js +36 -6
- package/services/labelService.js +1 -1
- package/services/leadService.js +3 -2
- package/services/messageService.js +4 -2
- package/services/modulesManager.js +23 -76
- package/services/operatingHoursService.js +9 -4
- package/services/requestService.js +75 -39
- package/services/subscriptionNotifier.js +9 -4
- package/services/trainingService.js +106 -0
- package/template/email/assignedEmailMessage.html +21 -11
- package/template/email/assignedRequest.html +21 -11
- package/template/email/beenInvitedExistingUser.html +16 -6
- package/template/email/beenInvitedNewUser.html +16 -6
- package/template/email/emailDirect.html +130 -0
- package/template/email/newMessage.html +18 -8
- package/template/email/newMessageFollower.html +22 -12
- package/template/email/passwordChanged.html +15 -5
- package/template/email/pooledEmailMessage.html +21 -11
- package/template/email/pooledRequest.html +20 -10
- package/template/email/resetPassword.html +15 -5
- package/template/email/sendTranscript.html +7 -4
- package/template/email/ticket.html +17 -7
- package/template/email/verify.html +15 -5
- package/test/cannedRoute.js +157 -0
- package/test/chatbot-mock.js +127 -0
- package/test/example-json-intents.txt +1 -0
- package/test/example-json.txt +1 -0
- package/test/example.json +1 -0
- package/test/faqRoute.js +353 -208
- package/test/faqkbRoute.js +669 -64
- package/test/imageRoute.js +1 -1
- package/test/messageRoute.js +387 -5
- package/test/requestRoute.js +6 -6
- package/test/requestService.js +55 -4
- package/test-int/cache-project.js +90 -0
- package/test-int/cache-project_user.js +88 -0
- package/utils/UIDGenerator.js +20 -0
- package/utils/cacheUtil.js +2 -2
- package/utils/orgUtil.js +3 -3
- package/utils/promiseUtil.js +31 -0
- package/utils/recipientEmailUtil.js +66 -0
- package/utils/sendEmailUtil.js +34 -0
- package/utils/sendMessageUtil.js +1 -1
- package/utils/stringUtil.js +12 -0
- package/websocket/webSocketServer.js +33 -10
package/routes/faq_kb.js
CHANGED
@@ -1,21 +1,27 @@
|
|
1
1
|
var express = require('express');
|
2
2
|
var router = express.Router();
|
3
3
|
var Faq_kb = require("../models/faq_kb");
|
4
|
-
var Faq= require("../models/faq");
|
4
|
+
var Faq = require("../models/faq");
|
5
5
|
var Department = require("../models/department");
|
6
6
|
var faqService = require("../services/faqService");
|
7
7
|
const botEvent = require('../event/botEvent');
|
8
|
+
const faqBotEvent = require('../event/faqBotEvent');
|
8
9
|
var winston = require('../config/winston');
|
9
10
|
var httpUtil = require("../utils/httpUtil");
|
11
|
+
const { forEach } = require('lodash');
|
12
|
+
var multer = require('multer')
|
13
|
+
var upload = multer()
|
14
|
+
var configGlobal = require('../config/global');
|
15
|
+
|
16
|
+
var chatbot_templates_api_url = "https://chatbot-templates.herokuapp.com/chatbots/public/templates"
|
10
17
|
|
11
18
|
router.post('/', function (req, res) {
|
12
19
|
winston.info('create BOT ', req.body);
|
13
|
-
|
14
|
-
|
20
|
+
//create(name, url, projectid, user_id, type, description, webhook_url, webhook_enabled, language, template)
|
21
|
+
faqService.create(req.body.name, req.body.url, req.projectid, req.user.id, req.body.type, req.body.description, undefined, undefined, req.body.language, req.body.template, req.body.mainCategory, req.body.intentsEngine).then(function (savedFaq_kb) {
|
15
22
|
res.json(savedFaq_kb);
|
16
23
|
});
|
17
24
|
|
18
|
-
|
19
25
|
});
|
20
26
|
|
21
27
|
|
@@ -23,7 +29,7 @@ router.post('/train', function (req, res) {
|
|
23
29
|
|
24
30
|
winston.info('train BOT ', req.body);
|
25
31
|
|
26
|
-
Faq_kb.findById(req.body.id_faq_kb).exec(function(err, faq_kb) {
|
32
|
+
Faq_kb.findById(req.body.id_faq_kb).exec(function (err, faq_kb) {
|
27
33
|
if (err) {
|
28
34
|
return res.status(500).send({ success: false, msg: 'Error getting object.' });
|
29
35
|
}
|
@@ -32,59 +38,59 @@ router.post('/train', function (req, res) {
|
|
32
38
|
}
|
33
39
|
winston.debug('faq_kb ', faq_kb.toJSON());
|
34
40
|
|
35
|
-
winston.debug('faq_kb.type :'+ faq_kb.type);
|
36
|
-
if (faq_kb.type =="internal" && faq_kb.url) {
|
41
|
+
winston.debug('faq_kb.type :' + faq_kb.type);
|
42
|
+
if (faq_kb.type == "internal" && faq_kb.url) {
|
37
43
|
|
38
44
|
|
39
45
|
|
40
|
-
var train =
|
41
|
-
language:faq_kb.language,
|
42
|
-
nlu:[]
|
46
|
+
var train = {
|
47
|
+
language: faq_kb.language,
|
48
|
+
nlu: []
|
43
49
|
};
|
44
|
-
winston.info("train", train);
|
45
|
-
|
46
|
-
|
47
|
-
var query = { "id_project": req.projectid, "id_faq_kb": req.body.id_faq_kb};
|
48
|
-
|
49
|
-
Faq.find(query)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
}
|
56
|
-
if (faqs && faqs.length>0) {
|
57
|
-
winston.info("faqs exact", faqs);
|
58
|
-
|
59
|
-
faqs.forEach(function(f) {
|
60
|
-
var intent = {
|
61
|
-
intent:f.intent_display_name,
|
62
|
-
examples:[]
|
63
|
-
}
|
64
|
-
var questions = f.question.split("\n");
|
65
|
-
winston.info("questions", questions);
|
66
|
-
|
67
|
-
questions.forEach(function(q) {
|
68
|
-
winston.info("q", q);
|
69
|
-
intent.examples.push(q);
|
70
|
-
});
|
71
|
-
winston.info("intent", intent);
|
72
|
-
train.nlu.push(intent);
|
73
|
-
});
|
74
|
-
winston.info("train", train);
|
75
|
-
|
76
|
-
try {
|
77
|
-
var trainHttp = await httpUtil.call(faq_kb.url+"/trainandload", undefined, train, "POST");
|
78
|
-
}catch(e) {
|
79
|
-
winston.error("error training", e);
|
50
|
+
winston.info("train", train);
|
51
|
+
|
52
|
+
|
53
|
+
var query = { "id_project": req.projectid, "id_faq_kb": req.body.id_faq_kb };
|
54
|
+
|
55
|
+
Faq.find(query)
|
56
|
+
.limit(10000)
|
57
|
+
.lean().
|
58
|
+
exec(async (err, faqs) => {
|
59
|
+
if (err) {
|
60
|
+
return res.status(500).send({ success: false, msg: 'Error getting object.' });
|
80
61
|
}
|
81
|
-
|
62
|
+
if (faqs && faqs.length > 0) {
|
63
|
+
winston.info("faqs exact", faqs);
|
64
|
+
|
65
|
+
faqs.forEach(function (f) {
|
66
|
+
var intent = {
|
67
|
+
intent: f.intent_display_name,
|
68
|
+
examples: []
|
69
|
+
}
|
70
|
+
var questions = f.question.split("\n");
|
71
|
+
winston.info("questions", questions);
|
72
|
+
|
73
|
+
questions.forEach(function (q) {
|
74
|
+
winston.info("q", q);
|
75
|
+
intent.examples.push(q);
|
76
|
+
});
|
77
|
+
winston.info("intent", intent);
|
78
|
+
train.nlu.push(intent);
|
79
|
+
});
|
80
|
+
winston.info("train", train);
|
82
81
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
82
|
+
try {
|
83
|
+
var trainHttp = await httpUtil.call(faq_kb.url + "/trainandload", undefined, train, "POST");
|
84
|
+
} catch (e) {
|
85
|
+
winston.error("error training", e);
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
return res.json({ train: train, httpResponse: trainHttp });
|
90
|
+
// return res.json(trainHttp);
|
91
|
+
} else {
|
92
|
+
return res.status(400).send({ success: false, msg: 'no faq to train on external bot.' });
|
93
|
+
}
|
88
94
|
});
|
89
95
|
} else {
|
90
96
|
winston.debug('external query: ');
|
@@ -93,28 +99,28 @@ router.post('/train', function (req, res) {
|
|
93
99
|
|
94
100
|
});
|
95
101
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
102
|
+
/*
|
103
|
+
{
|
104
|
+
"language":"it",
|
105
|
+
"nlu":[
|
106
|
+
{
|
107
|
+
"intent":"eta",
|
108
|
+
"examples":[
|
109
|
+
"quanti anni hai",
|
110
|
+
"dimmi la tua età",
|
111
|
+
"quanto sei grande",
|
112
|
+
"parlami della tua età"
|
113
|
+
]
|
114
|
+
},
|
115
|
+
{
|
116
|
+
"intent":"brutteparole",
|
117
|
+
"examples":[
|
118
|
+
"non dire parolacce",
|
119
|
+
"le brutte parole non dovrebbero dirsi"
|
120
|
+
]
|
121
|
+
}
|
122
|
+
]
|
123
|
+
}
|
118
124
|
*/
|
119
125
|
|
120
126
|
});
|
@@ -124,7 +130,7 @@ router.post('/askbot', function (req, res) {
|
|
124
130
|
|
125
131
|
winston.debug('ASK BOT ', req.body);
|
126
132
|
|
127
|
-
Faq_kb.findById(req.body.id_faq_kb).exec(function(err, faq_kb) {
|
133
|
+
Faq_kb.findById(req.body.id_faq_kb).exec(function (err, faq_kb) {
|
128
134
|
if (err) {
|
129
135
|
return res.status(500).send({ success: false, msg: 'Error getting object.' });
|
130
136
|
}
|
@@ -132,73 +138,73 @@ router.post('/askbot', function (req, res) {
|
|
132
138
|
return res.status(404).send({ success: false, msg: 'Object not found.' });
|
133
139
|
}
|
134
140
|
winston.debug('faq_kb ', faq_kb.toJSON());
|
135
|
-
winston.debug('faq_kb.type :'+ faq_kb.type);
|
136
|
-
if (faq_kb.type =="internal") {
|
141
|
+
winston.debug('faq_kb.type :' + faq_kb.type);
|
142
|
+
if (faq_kb.type == "internal" || faq_kb.type == "tilebot") {
|
137
143
|
|
138
144
|
|
139
145
|
|
140
|
-
|
141
146
|
|
142
|
-
var query = { "id_project": req.projectid, "id_faq_kb": req.body.id_faq_kb, "question": req.body.question};
|
143
147
|
|
144
|
-
|
145
|
-
.lean().
|
146
|
-
exec(function (err, faqs) {
|
147
|
-
if (err) {
|
148
|
-
return res.status(500).send({ success: false, msg: 'Error getting object.' });
|
149
|
-
}
|
150
|
-
if (faqs && faqs.length>0) {
|
151
|
-
winston.debug("faqs exact", faqs);
|
148
|
+
var query = { "id_project": req.projectid, "id_faq_kb": req.body.id_faq_kb, "question": req.body.question };
|
152
149
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
150
|
+
Faq.find(query)
|
151
|
+
.lean().
|
152
|
+
exec(function (err, faqs) {
|
153
|
+
if (err) {
|
154
|
+
return res.status(500).send({ success: false, msg: 'Error getting object.' });
|
155
|
+
}
|
156
|
+
if (faqs && faqs.length > 0) {
|
157
|
+
winston.debug("faqs exact", faqs);
|
158
|
+
|
159
|
+
faqs.forEach(f => {
|
160
|
+
f.score = 100;
|
161
|
+
});
|
162
|
+
var result = { hits: faqs };
|
157
163
|
|
158
164
|
|
159
|
-
|
160
|
-
|
161
|
-
|
165
|
+
res.json(result);
|
166
|
+
} else {
|
167
|
+
query = { "id_project": req.projectid, "id_faq_kb": req.body.id_faq_kb };
|
162
168
|
|
163
|
-
|
169
|
+
var search_obj = { "$search": req.body.question };
|
164
170
|
|
165
|
-
|
171
|
+
if (faq_kb.language) {
|
166
172
|
search_obj["$language"] = faq_kb.language;
|
167
|
-
|
168
|
-
|
169
|
-
|
173
|
+
}
|
174
|
+
query.$text = search_obj;
|
175
|
+
winston.debug("fulltext search query", query);
|
170
176
|
|
171
177
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
178
|
+
winston.debug('internal ft query: ' + query);
|
179
|
+
|
180
|
+
Faq.find(query, { score: { $meta: "textScore" } })
|
181
|
+
.sort({ score: { $meta: "textScore" } }) //https://docs.mongodb.com/manual/reference/operator/query/text/#sort-by-text-search-score
|
182
|
+
.lean().
|
183
|
+
exec(function (err, faqs) {
|
184
|
+
if (err) {
|
185
|
+
winston.error('Error getting object.', err);
|
186
|
+
return res.status(500).send({ success: false, msg: 'Error getting fulltext object.' });
|
187
|
+
}
|
188
|
+
|
189
|
+
winston.debug("faqs", faqs);
|
190
|
+
|
191
|
+
var result = { hits: faqs };
|
192
|
+
res.json(result);
|
193
|
+
});
|
194
|
+
|
195
|
+
|
196
|
+
}
|
188
197
|
|
189
|
-
|
190
|
-
}
|
191
198
|
|
192
|
-
|
193
|
-
|
199
|
+
});
|
200
|
+
|
194
201
|
|
195
|
-
|
196
|
-
}else {
|
202
|
+
} else {
|
197
203
|
winston.debug('external query: ');
|
198
204
|
return res.status(400).send({ success: false, msg: 'askbot on external bot.' });
|
199
205
|
}
|
200
|
-
|
201
|
-
|
206
|
+
|
207
|
+
|
202
208
|
});
|
203
209
|
|
204
210
|
});
|
@@ -210,28 +216,39 @@ router.put('/:faq_kbid', function (req, res) {
|
|
210
216
|
winston.debug(req.body);
|
211
217
|
|
212
218
|
var update = {};
|
213
|
-
if (req.body.name!=undefined) {
|
219
|
+
if (req.body.name != undefined) {
|
214
220
|
update.name = req.body.name;
|
215
221
|
}
|
216
|
-
if (req.body.description!=undefined) {
|
222
|
+
if (req.body.description != undefined) {
|
217
223
|
update.description = req.body.description;
|
218
224
|
}
|
219
|
-
if (req.body.url!=undefined) {
|
225
|
+
if (req.body.url != undefined) {
|
220
226
|
update.url = req.body.url;
|
221
227
|
}
|
222
|
-
if (req.body.webhook_url!=undefined) {
|
228
|
+
if (req.body.webhook_url != undefined) {
|
223
229
|
update.webhook_url = req.body.webhook_url;
|
224
230
|
}
|
225
|
-
if (req.body.webhook_enabled!=undefined) {
|
231
|
+
if (req.body.webhook_enabled != undefined) {
|
226
232
|
update.webhook_enabled = req.body.webhook_enabled;
|
227
233
|
}
|
228
|
-
|
229
|
-
if (req.body.type!=undefined) {
|
234
|
+
if (req.body.type != undefined) {
|
230
235
|
update.type = req.body.type;
|
231
236
|
}
|
232
|
-
if (req.body.trashed!=undefined) {
|
237
|
+
if (req.body.trashed != undefined) {
|
233
238
|
update.trashed = req.body.trashed;
|
234
239
|
}
|
240
|
+
if (req.body.public != undefined) {
|
241
|
+
update.public = req.body.public;
|
242
|
+
}
|
243
|
+
if (req.body.certified != undefined) {
|
244
|
+
update.certified = req.body.certified;
|
245
|
+
}
|
246
|
+
if (req.body.mainCategory != undefined) {
|
247
|
+
update.mainCategory = req.body.mainCategory;
|
248
|
+
}
|
249
|
+
if (req.body.intentsEngine != undefined) {
|
250
|
+
update.intentsEngine = req.body.intentsEngine;
|
251
|
+
}
|
235
252
|
|
236
253
|
Faq_kb.findByIdAndUpdate(req.params.faq_kbid, update, { new: true, upsert: true }, function (err, updatedFaq_kb) {
|
237
254
|
if (err) {
|
@@ -317,10 +334,10 @@ router.get('/', function (req, res) {
|
|
317
334
|
*/
|
318
335
|
var query = { "id_project": req.projectid, "trashed": { $in: [null, false] } };
|
319
336
|
|
320
|
-
if (req.query.all!="true") {
|
337
|
+
if (req.query.all != "true") {
|
321
338
|
query.type = { $ne: "identity" }
|
322
339
|
}
|
323
|
-
|
340
|
+
|
324
341
|
winston.debug("query", query);
|
325
342
|
|
326
343
|
Faq_kb.find(query, function (err, faq_kb) {
|
@@ -335,4 +352,350 @@ router.get('/', function (req, res) {
|
|
335
352
|
|
336
353
|
});
|
337
354
|
|
355
|
+
router.post('/fork/:id_faq_kb', async (req, res) => {
|
356
|
+
|
357
|
+
let id_faq_kb = req.params.id_faq_kb;
|
358
|
+
winston.info('id_faq_kb: ' + id_faq_kb);
|
359
|
+
|
360
|
+
const api_url = process.env.API_URL || configGlobal.apiUrl;
|
361
|
+
winston.info("fork --> base_url: " + api_url); // check if correct
|
362
|
+
|
363
|
+
let current_project_id = req.projectid;
|
364
|
+
winston.info("current project id: " + current_project_id);
|
365
|
+
|
366
|
+
let landing_project_id = req.query.projectid;
|
367
|
+
winston.info("landing project id " + landing_project_id)
|
368
|
+
|
369
|
+
let public = req.query.public;
|
370
|
+
winston.info("public " + public);
|
371
|
+
|
372
|
+
let token = req.headers.authorization;
|
373
|
+
|
374
|
+
let cs = req.app.get('chatbot_service')
|
375
|
+
|
376
|
+
let chatbot = await cs.getBotById(id_faq_kb, public, api_url, chatbot_templates_api_url, token, current_project_id);
|
377
|
+
winston.debug("chatbot: ", chatbot)
|
378
|
+
|
379
|
+
if (!chatbot) {
|
380
|
+
return res.status(500).send({ success: false, message: "Unable to get chatbot" });
|
381
|
+
}
|
382
|
+
|
383
|
+
let savedChatbot = await cs.createBot(api_url, token, chatbot, landing_project_id);
|
384
|
+
winston.info("savedChatbot: ", savedChatbot)
|
385
|
+
|
386
|
+
if (!savedChatbot) {
|
387
|
+
return res.status(500).send({ success: false, message: "Unable to create new chatbot" });
|
388
|
+
}
|
389
|
+
|
390
|
+
let import_result = await cs.importFaqs(api_url, savedChatbot._id, token, chatbot, landing_project_id);
|
391
|
+
winston.info("imported: ", import_result);
|
392
|
+
|
393
|
+
if (import_result.success == "false") {
|
394
|
+
return res.status(500).send({ success: false, message: "Unable to import intents in the new chatbot" });
|
395
|
+
}
|
396
|
+
|
397
|
+
return res.status(200).send({ message: "Chatbot forked successfully", bot_id: savedChatbot._id });
|
398
|
+
|
399
|
+
})
|
400
|
+
|
401
|
+
|
402
|
+
router.post('/importjson/:id_faq_kb', upload.single('uploadFile'), (req, res) => {
|
403
|
+
|
404
|
+
let id_faq_kb = req.params.id_faq_kb;
|
405
|
+
winston.info('import on id_faq_kb: ', id_faq_kb);
|
406
|
+
|
407
|
+
let json_string;
|
408
|
+
let json;
|
409
|
+
if (req.file) {
|
410
|
+
json_string = req.file.buffer.toString('utf-8');
|
411
|
+
json = JSON.parse(json_string);
|
412
|
+
} else {
|
413
|
+
json = req.body;
|
414
|
+
}
|
415
|
+
|
416
|
+
winston.info("json source " + json_string)
|
417
|
+
|
418
|
+
if (req.query.intentsOnly && req.query.intentsOnly == "true") {
|
419
|
+
|
420
|
+
winston.info("intents only")
|
421
|
+
|
422
|
+
json.intents.forEach((intent) => {
|
423
|
+
|
424
|
+
let new_faq = {
|
425
|
+
id_faq_kb: id_faq_kb,
|
426
|
+
id_project: req.projectid,
|
427
|
+
createdBy: req.user.id,
|
428
|
+
intent_display_name: intent.intent_display_name,
|
429
|
+
question: intent.question,
|
430
|
+
answer: intent.answer,
|
431
|
+
reply: intent.reply,
|
432
|
+
form: intent.form,
|
433
|
+
enabled: intent.enabled,
|
434
|
+
webhook_enabled: intent.webhook_enabled,
|
435
|
+
language: intent.language,
|
436
|
+
actions: intent.actions
|
437
|
+
}
|
438
|
+
|
439
|
+
// overwrite duplicated intents
|
440
|
+
if (req.query.overwrite == "true") {
|
441
|
+
Faq.findOneAndUpdate({ id_faq_kb: id_faq_kb, intent_display_name: intent.intent_display_name }, new_faq, { new: true, upsert: true, rawResult: true }, (err, savingResult) => {
|
442
|
+
if (err) {
|
443
|
+
winston.error("findOneAndUpdate (upsert) FAQ ERROR ", err);
|
444
|
+
} else {
|
445
|
+
if (savingResult.lastErrorObject.updatedExisting == true) {
|
446
|
+
winston.info("updated existing intent")
|
447
|
+
faqBotEvent.emit('faq.update', savingResult.value);
|
448
|
+
} else {
|
449
|
+
winston.info("new intent crated")
|
450
|
+
faqBotEvent.emit('faq.create', savingResult.value);
|
451
|
+
}
|
452
|
+
}
|
453
|
+
})
|
454
|
+
|
455
|
+
// don't overwrite duplicated intents
|
456
|
+
} else {
|
457
|
+
Faq.create(new_faq, (err, savedFaq) => {
|
458
|
+
if (err) {
|
459
|
+
winston.debug("create new FAQ ERROR ", err);
|
460
|
+
if (err.code == 11000) {
|
461
|
+
winston.error("Duplicate intent_display_name.");
|
462
|
+
winston.info("Skip duplicated intent_display_name");
|
463
|
+
} else {
|
464
|
+
winston.info("new intent crated")
|
465
|
+
faqBotEvent.emit('faq.create', savedFaq);
|
466
|
+
}
|
467
|
+
}
|
468
|
+
})
|
469
|
+
}
|
470
|
+
|
471
|
+
})
|
472
|
+
|
473
|
+
return res.status(200).send({ success: true, msg: "Intents imported successfully" })
|
474
|
+
|
475
|
+
} else {
|
476
|
+
|
477
|
+
if (req.query.create && req.query.create == 'true') {
|
478
|
+
faqService.create(json.name, undefined, req.projectid, req.user.id, "tilebot", json.description, json.webhook_url, json.webhook_enabled, json.language, undefined, undefined, undefined).then((savedFaq_kb) => {
|
479
|
+
winston.debug("saved (and imported) faq kb: ", savedFaq_kb);
|
480
|
+
botEvent.emit('faqbot.create', savedFaq_kb);
|
481
|
+
|
482
|
+
json.intents.forEach((intent) => {
|
483
|
+
|
484
|
+
let new_faq = {
|
485
|
+
id_faq_kb: savedFaq_kb._id,
|
486
|
+
id_project: req.projectid,
|
487
|
+
createdBy: req.user.id,
|
488
|
+
intent_display_name: intent.intent_display_name,
|
489
|
+
question: intent.question,
|
490
|
+
answer: intent.answer,
|
491
|
+
reply: intent.reply,
|
492
|
+
form: intent.form,
|
493
|
+
enabled: intent.enabled,
|
494
|
+
webhook_enabled: intent.webhook_enabled,
|
495
|
+
language: intent.language,
|
496
|
+
actions: intent.actions
|
497
|
+
}
|
498
|
+
|
499
|
+
// TO DELETE: no used when req.query.create = 'true'
|
500
|
+
if (req.query.overwrite == "true") {
|
501
|
+
Faq.findOneAndUpdate({ id_faq_kb: id_faq_kb, intent_display_name: intent.intent_display_name }, new_faq, { new: true, upsert: true, rawResult: true }, (err, savingResult) => {
|
502
|
+
if (err) {
|
503
|
+
winston.error("findOneAndUpdate (upsert) FAQ ERROR ", err);
|
504
|
+
} else {
|
505
|
+
|
506
|
+
if (savingResult.lastErrorObject.updatedExisting == true) {
|
507
|
+
winston.info("updated existing intent")
|
508
|
+
faqBotEvent.emit('faq.update', savingResult.value);
|
509
|
+
} else {
|
510
|
+
winston.info("new intent crated")
|
511
|
+
faqBotEvent.emit('faq.create', savingResult.value);
|
512
|
+
}
|
513
|
+
|
514
|
+
}
|
515
|
+
|
516
|
+
})
|
517
|
+
|
518
|
+
// don't overwrite duplicated intents
|
519
|
+
} else {
|
520
|
+
Faq.create(new_faq, (err, savedFaq) => {
|
521
|
+
if (err) {
|
522
|
+
winston.debug("create new FAQ ERROR ", err);
|
523
|
+
if (err.code == 11000) {
|
524
|
+
winston.error("Duplicate intent_display_name.");
|
525
|
+
winston.info("Skip duplicated intent_display_name");
|
526
|
+
} else {
|
527
|
+
winston.info("new intent crated")
|
528
|
+
faqBotEvent.emit('faq.create', savedFaq);
|
529
|
+
}
|
530
|
+
}
|
531
|
+
})
|
532
|
+
}
|
533
|
+
|
534
|
+
})
|
535
|
+
return res.status(200).send(savedFaq_kb);
|
536
|
+
|
537
|
+
}).catch((err) => {
|
538
|
+
winston.error("error saving faq_kb: ", err);
|
539
|
+
return res.status(500).send(err);
|
540
|
+
})
|
541
|
+
|
542
|
+
} else {
|
543
|
+
|
544
|
+
Faq_kb.findById(id_faq_kb, (err, faq_kb) => {
|
545
|
+
if (err) {
|
546
|
+
winston.error("GET FAQ-KB ERROR", err);
|
547
|
+
return res.status(500).send({ success: false, msg: "Error getting bot." });
|
548
|
+
}
|
549
|
+
if (!faq_kb) {
|
550
|
+
return res.status(404).send({ success: false, msg: 'Bot not found.' });
|
551
|
+
}
|
552
|
+
|
553
|
+
// should be wrong
|
554
|
+
//const json = JSON.parse(json_string);
|
555
|
+
|
556
|
+
if (json.webhook_enabled) {
|
557
|
+
faq_kb.webhook_enabled = json.webhook_enabled;
|
558
|
+
}
|
559
|
+
if (json.webhook_url) {
|
560
|
+
faq_kb.webhook_url = json.webhook_url;
|
561
|
+
}
|
562
|
+
if (json.language) {
|
563
|
+
faq_kb.language = json.language;
|
564
|
+
}
|
565
|
+
if (json.name) {
|
566
|
+
faq_kb.name = json.name;
|
567
|
+
}
|
568
|
+
if (json.description) {
|
569
|
+
faq_kb.description = json.description;
|
570
|
+
}
|
571
|
+
|
572
|
+
Faq_kb.findByIdAndUpdate(id_faq_kb, faq_kb, { new: true }, (err, updatedFaq_kb) => {
|
573
|
+
if (err) {
|
574
|
+
return res.status(500).send({ success: false, msg: "Error updating bot." });
|
575
|
+
}
|
576
|
+
|
577
|
+
botEvent.emit('faqbot.update', updatedFaq_kb);
|
578
|
+
|
579
|
+
json.intents.forEach((intent) => {
|
580
|
+
|
581
|
+
let new_faq = {
|
582
|
+
id_faq_kb: updatedFaq_kb._id,
|
583
|
+
id_project: req.projectid,
|
584
|
+
createdBy: req.user.id,
|
585
|
+
intent_display_name: intent.intent_display_name,
|
586
|
+
question: intent.question,
|
587
|
+
answer: intent.answer,
|
588
|
+
reply: intent.reply,
|
589
|
+
form: intent.form,
|
590
|
+
enabled: intent.enabled,
|
591
|
+
webhook_enabled: intent.webhook_enabled,
|
592
|
+
language: intent.language,
|
593
|
+
actions: intent.actions
|
594
|
+
}
|
595
|
+
|
596
|
+
// overwrite duplicated intents
|
597
|
+
if (req.query.overwrite == "true") {
|
598
|
+
Faq.findOneAndUpdate({ id_faq_kb: id_faq_kb, intent_display_name: intent.intent_display_name }, new_faq, { new: true, upsert: true, rawResult: true }, (err, savingResult) => {
|
599
|
+
if (err) {
|
600
|
+
winston.error("findOneAndUpdate (upsert) FAQ ERROR ", err);
|
601
|
+
} else {
|
602
|
+
|
603
|
+
if (savingResult.lastErrorObject.updatedExisting == true) {
|
604
|
+
winston.info("updated existing intent")
|
605
|
+
faqBotEvent.emit('faq.update', savingResult.value);
|
606
|
+
} else {
|
607
|
+
winston.info("new intent crated")
|
608
|
+
faqBotEvent.emit('faq.create', savingResult.value);
|
609
|
+
}
|
610
|
+
|
611
|
+
}
|
612
|
+
|
613
|
+
})
|
614
|
+
|
615
|
+
// don't overwrite duplicated intents
|
616
|
+
} else {
|
617
|
+
Faq.create(new_faq, (err, savedFaq) => {
|
618
|
+
if (err) {
|
619
|
+
winston.debug("create new FAQ ERROR ", err);
|
620
|
+
if (err.code == 11000) {
|
621
|
+
winston.error("Duplicate intent_display_name.");
|
622
|
+
winston.info("Skip duplicated intent_display_name");
|
623
|
+
} else {
|
624
|
+
winston.info("new intent crated")
|
625
|
+
faqBotEvent.emit('faq.create', savedFaq);
|
626
|
+
}
|
627
|
+
}
|
628
|
+
})
|
629
|
+
}
|
630
|
+
|
631
|
+
})
|
632
|
+
|
633
|
+
return res.send(updatedFaq_kb);
|
634
|
+
|
635
|
+
})
|
636
|
+
|
637
|
+
})
|
638
|
+
}
|
639
|
+
|
640
|
+
}
|
641
|
+
|
642
|
+
})
|
643
|
+
|
644
|
+
router.get('/exportjson/:id_faq_kb', (req, res) => {
|
645
|
+
|
646
|
+
winston.info("exporting bot...")
|
647
|
+
|
648
|
+
|
649
|
+
let id_faq_kb = req.params.id_faq_kb;
|
650
|
+
|
651
|
+
Faq_kb.findById(id_faq_kb, (err, faq_kb) => {
|
652
|
+
if (err) {
|
653
|
+
winston.error('GET FAQ-KB ERROR ', err)
|
654
|
+
return res.status(500).send({ success: false, msg: 'Error getting bot.' });
|
655
|
+
} else {
|
656
|
+
winston.debug('FAQ-KB: ', faq_kb)
|
657
|
+
|
658
|
+
|
659
|
+
faqService.getAll(id_faq_kb).then((faqs) => {
|
660
|
+
|
661
|
+
const intents = faqs.map(({ _id, id_project, topic, status, id_faq_kb, createdBy, intent_id, createdAt, updatedAt, __v, ...keepAttrs }) => keepAttrs)
|
662
|
+
|
663
|
+
let json = {
|
664
|
+
webhook_enabled: faq_kb.webhook_enabled,
|
665
|
+
webhook_url: faq_kb.webhook_url,
|
666
|
+
language: faq_kb.language,
|
667
|
+
name: faq_kb.name,
|
668
|
+
description: faq_kb.description,
|
669
|
+
intents: intents
|
670
|
+
}
|
671
|
+
|
672
|
+
if (req.query.intentsOnly == 'true') {
|
673
|
+
let intents_obj = {
|
674
|
+
intents: intents
|
675
|
+
}
|
676
|
+
let intents_string = JSON.stringify(intents_obj);
|
677
|
+
res.set({ "Content-Disposition": "attachment; filename=\"intents.json\"" });
|
678
|
+
return res.send(intents_string);
|
679
|
+
|
680
|
+
} else {
|
681
|
+
|
682
|
+
// if (req.query.file == "false") {
|
683
|
+
// return res.status(200).send(json);
|
684
|
+
// }
|
685
|
+
let json_string = JSON.stringify(json);
|
686
|
+
res.set({ "Content-Disposition": "attachment; filename=\"bot.json\"" });
|
687
|
+
return res.send(json_string);
|
688
|
+
}
|
689
|
+
|
690
|
+
|
691
|
+
}).catch((err) => {
|
692
|
+
winston.error('GET FAQ ERROR: ', err)
|
693
|
+
return res.status(500).send({ success: false, msg: 'Error getting faqs.' });
|
694
|
+
})
|
695
|
+
}
|
696
|
+
})
|
697
|
+
|
698
|
+
})
|
699
|
+
|
700
|
+
|
338
701
|
module.exports = router;
|