@tiledesk/tiledesk-server 2.9.25 → 2.9.26
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +4 -0
- package/package.json +2 -2
- package/routes/kb.js +112 -0
- package/test/example-kb-faqs.csv +2 -0
- package/test/kbRoute.js +45 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@tiledesk/tiledesk-server",
|
3
3
|
"description": "The Tiledesk server module",
|
4
|
-
"version": "2.9.
|
4
|
+
"version": "2.9.26",
|
5
5
|
"scripts": {
|
6
6
|
"start": "node ./bin/www",
|
7
7
|
"pretest": "mongodb-runner start",
|
@@ -48,7 +48,7 @@
|
|
48
48
|
"@tiledesk/tiledesk-rasa-connector": "^1.0.10",
|
49
49
|
"@tiledesk/tiledesk-telegram-connector": "^0.1.14",
|
50
50
|
"@tiledesk/tiledesk-train-jobworker": "^0.0.11",
|
51
|
-
"@tiledesk/tiledesk-tybot-connector": "^0.2.
|
51
|
+
"@tiledesk/tiledesk-tybot-connector": "^0.2.105",
|
52
52
|
"@tiledesk/tiledesk-whatsapp-connector": "^0.1.73",
|
53
53
|
"@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.8",
|
54
54
|
"@tiledesk/tiledesk-sms-connector": "^0.1.10",
|
package/routes/kb.js
CHANGED
@@ -14,6 +14,7 @@ var mongoose = require('mongoose');
|
|
14
14
|
const faq = require('../models/faq');
|
15
15
|
const faq_kb = require('../models/faq_kb');
|
16
16
|
let Integration = require('../models/integrations');
|
17
|
+
var parsecsv = require("fast-csv");
|
17
18
|
|
18
19
|
const { MODELS_MULTIPLIER } = require('../utils/aiUtils');
|
19
20
|
|
@@ -994,6 +995,117 @@ router.post('/multi', upload.single('uploadFile'), async (req, res) => {
|
|
994
995
|
|
995
996
|
})
|
996
997
|
|
998
|
+
router.post('/csv', upload.single('uploadFile'), async (req, res) => {
|
999
|
+
|
1000
|
+
let project_id = req.projectid;
|
1001
|
+
|
1002
|
+
let csv = req.file.buffer.toString('utf8');
|
1003
|
+
winston.debug("csv: ", csv);
|
1004
|
+
|
1005
|
+
let delimiter = req.body.delimiter || ";";
|
1006
|
+
winston.debug("delimiter: ", delimiter);
|
1007
|
+
|
1008
|
+
let namespace_id = req.query.namespace;
|
1009
|
+
if (!namespace_id) {
|
1010
|
+
return res.status(400).send({ success: false, error: "queryParam 'namespace' is not defined" })
|
1011
|
+
}
|
1012
|
+
|
1013
|
+
let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
|
1014
|
+
winston.error("find namespaces error: ", err)
|
1015
|
+
res.status(500).send({ success: false, error: err })
|
1016
|
+
})
|
1017
|
+
|
1018
|
+
if (!namespaces || namespaces.length == 0) {
|
1019
|
+
let alert = "No namespace found for the selected project " + project_id + ". Cannot add content to a non-existent namespace."
|
1020
|
+
winston.warn(alert);
|
1021
|
+
res.status(403).send({ success: false, error: alert });
|
1022
|
+
}
|
1023
|
+
|
1024
|
+
let namespaceIds = namespaces.map(namespace => namespace.id);
|
1025
|
+
|
1026
|
+
if (!namespaceIds.includes(namespace_id)) {
|
1027
|
+
return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project." })
|
1028
|
+
}
|
1029
|
+
|
1030
|
+
let quoteManager = req.app.get('quote_manager');
|
1031
|
+
let limits = await quoteManager.getPlanLimits(req.project);
|
1032
|
+
let kbs_limit = limits.kbs;
|
1033
|
+
winston.verbose("Limit of kbs for current plan: " + kbs_limit);
|
1034
|
+
|
1035
|
+
let kbs_count = await KB.countDocuments({ id_project: project_id }).exec();
|
1036
|
+
winston.verbose("Kbs count: " + kbs_count);
|
1037
|
+
|
1038
|
+
if (kbs_count >= kbs_limit) {
|
1039
|
+
return res.status(403).send({ success: false, error: "Maximum number of resources reached for the current plan", plan_limit: kbs_limit })
|
1040
|
+
}
|
1041
|
+
|
1042
|
+
let webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
|
1043
|
+
|
1044
|
+
let kbs = [];
|
1045
|
+
|
1046
|
+
parsecsv.parseString(csv, { headers: false, delimiter: delimiter })
|
1047
|
+
.on("data", (data) => {
|
1048
|
+
|
1049
|
+
let question = data[0];
|
1050
|
+
let answer = data[1];
|
1051
|
+
|
1052
|
+
console.log("data. ", data)
|
1053
|
+
kbs.push({
|
1054
|
+
id_project: project_id,
|
1055
|
+
name: question,
|
1056
|
+
source: question,
|
1057
|
+
type: 'faq',
|
1058
|
+
content: question + "\n" + answer,
|
1059
|
+
namespace: namespace_id,
|
1060
|
+
status: -1
|
1061
|
+
})
|
1062
|
+
})
|
1063
|
+
.on("end", () => {
|
1064
|
+
winston.debug("kbs after CSV parsing: ", kbs);
|
1065
|
+
|
1066
|
+
let total_count = kbs_count + kbs.length;
|
1067
|
+
if (total_count >= kbs_limit) {
|
1068
|
+
return res.status(403).send({ success: false, error: "Cannot exceed the number of resources in the current plan", plan_limit: kbs_limit })
|
1069
|
+
}
|
1070
|
+
|
1071
|
+
if (kbs.length > 300) {
|
1072
|
+
return res.status(403).send({ success: false, error: "Too many faqs. Can't index more than 300 urls at a time." })
|
1073
|
+
}
|
1074
|
+
|
1075
|
+
let operations = kbs.map(doc => {
|
1076
|
+
return {
|
1077
|
+
updateOne: {
|
1078
|
+
filter: { id_project: doc.id_project, type: 'faq', source: doc.source },
|
1079
|
+
update: doc,
|
1080
|
+
upsert: true,
|
1081
|
+
returnOriginal: false
|
1082
|
+
}
|
1083
|
+
}
|
1084
|
+
})
|
1085
|
+
|
1086
|
+
saveBulk(operations, kbs, project_id).then((result) => {
|
1087
|
+
let resources = result.map(({ name, status, __v, createdAt, updatedAt, id_project, ...keepAttrs }) => keepAttrs)
|
1088
|
+
resources = resources.map(({ _id, ...rest}) => {
|
1089
|
+
return { id: _id, webhooh: webhook, ...rest };
|
1090
|
+
})
|
1091
|
+
winston.verbose("resources to be sent to worker: ", resources);
|
1092
|
+
if (!process.env.NODE_ENV) {
|
1093
|
+
scheduleScrape(resources);
|
1094
|
+
}
|
1095
|
+
res.status(200).send(result);
|
1096
|
+
}).catch((err) => {
|
1097
|
+
winston.error("Unabled to saved kbs in bulk " + err);
|
1098
|
+
res.status(500).send(err);
|
1099
|
+
})
|
1100
|
+
|
1101
|
+
})
|
1102
|
+
.on("error", (err) => {
|
1103
|
+
winston.error("CSV parsing error: ", err);
|
1104
|
+
res.status(400).send({ success: false, error: err });
|
1105
|
+
})
|
1106
|
+
|
1107
|
+
})
|
1108
|
+
|
997
1109
|
router.post('/sitemap', async (req, res) => {
|
998
1110
|
|
999
1111
|
let sitemap_url = req.body.sitemap;
|
package/test/kbRoute.js
CHANGED
@@ -277,6 +277,51 @@ describe('KbRoute', () => {
|
|
277
277
|
})
|
278
278
|
}).timeout(20000)
|
279
279
|
|
280
|
+
it('add-multiple-faqs-with-csv', (done) => {
|
281
|
+
|
282
|
+
var email = "test-signup-" + Date.now() + "@email.com";
|
283
|
+
var pwd = "pwd";
|
284
|
+
|
285
|
+
userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) {
|
286
|
+
projectService.create("test-faqkb-create", savedUser._id).then(function (savedProject) {
|
287
|
+
|
288
|
+
chai.request(server)
|
289
|
+
.get('/' + savedProject._id + '/kb/namespace/all')
|
290
|
+
.auth(email, pwd)
|
291
|
+
.end((err, res) => {
|
292
|
+
|
293
|
+
if (err) { console.error("err: ", err); }
|
294
|
+
if (log) { console.log("res.body: ", res.body) }
|
295
|
+
|
296
|
+
res.should.have.status(200)
|
297
|
+
expect(res.body.length).to.equal(1);
|
298
|
+
|
299
|
+
let namespace_id = res.body[0].id;
|
300
|
+
|
301
|
+
chai.request(server)
|
302
|
+
.post('/' + savedProject._id + '/kb/csv?namespace=' + namespace_id)
|
303
|
+
.auth(email, pwd)
|
304
|
+
.set('Content-Type', 'text/csv')
|
305
|
+
.attach('uploadFile', fs.readFileSync(path.resolve(__dirname, './example-kb-faqs.csv')), 'example-kb-faqs.csv')
|
306
|
+
.field('delimiter', ';')
|
307
|
+
.end((err, res) => {
|
308
|
+
|
309
|
+
if (err) { console.error("err: ", err); }
|
310
|
+
if (log) { console.log("res.body: ", res.body) }
|
311
|
+
console.log("res.body: ", res.body)
|
312
|
+
|
313
|
+
res.should.have.status(200);
|
314
|
+
|
315
|
+
done();
|
316
|
+
|
317
|
+
})
|
318
|
+
})
|
319
|
+
});
|
320
|
+
});
|
321
|
+
|
322
|
+
}).timeout(10000)
|
323
|
+
|
324
|
+
|
280
325
|
/**
|
281
326
|
* If you try to add content to a project that has no namespace, it returns 403 forbidden.
|
282
327
|
*/
|