@tiledesk/tiledesk-server 2.3.6 → 2.3.7-1.2
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/.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 +62 -34
- 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 +2 -2
- 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;
|