@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.
Files changed (126) hide show
  1. package/.github/workflows/docker-community-worker-push-latest.yml +23 -0
  2. package/.github/workflows/docker-image-tag-worker-community-tag-push.yml +22 -0
  3. package/CHANGELOG.md +361 -3
  4. package/Dockerfile-jobs +31 -0
  5. package/app.js +62 -69
  6. package/channels/chat21/chat21Handler.js +37 -6
  7. package/channels/chat21/chat21WebHook.js +62 -34
  8. package/channels/chat21/package-lock.json +663 -706
  9. package/channels/chat21/package.json +2 -2
  10. package/config/labels/widget.json +337 -136
  11. package/deploy.sh +2 -0
  12. package/event/messageEvent.js +110 -9
  13. package/jobs.js +80 -0
  14. package/jobsManager.js +47 -0
  15. package/middleware/has-role.js +10 -3
  16. package/middleware/ipFilter.js +220 -0
  17. package/middleware/passport.js +8 -2
  18. package/models/department.js +1 -1
  19. package/models/faq.js +77 -25
  20. package/models/faq_kb.js +19 -0
  21. package/models/message.js +10 -8
  22. package/models/project.js +10 -0
  23. package/models/project_user.js +10 -0
  24. package/models/request.js +12 -1
  25. package/package.json +12 -11
  26. package/pubmodules/activities/activityArchiver.js +216 -90
  27. package/pubmodules/activities/routes/activity.js +1 -1
  28. package/pubmodules/apps/index.js +8 -0
  29. package/pubmodules/apps/listener.js +27 -0
  30. package/pubmodules/cache/index.js +2 -0
  31. package/pubmodules/cache/mongoose-cachegoose-fn.js +630 -0
  32. package/pubmodules/canned/cannedResponse.js +4 -0
  33. package/pubmodules/canned/cannedResponseRoute.js +10 -5
  34. package/pubmodules/dialogflow/index.js +10 -0
  35. package/pubmodules/dialogflow/listener.js +66 -0
  36. package/pubmodules/emailNotification/requestNotification.js +58 -28
  37. package/pubmodules/events/eventRoute.js +49 -24
  38. package/pubmodules/messageTransformer/messageHandlebarsTransformerInterceptor.js +6 -1
  39. package/pubmodules/messageTransformer/messageTransformerInterceptor.js +10 -4
  40. package/pubmodules/pubModulesManager.js +173 -7
  41. package/pubmodules/queue/index.js +4 -0
  42. package/pubmodules/queue/reconnect.js +331 -0
  43. package/pubmodules/queue/reconnectFanout.js +256 -0
  44. package/pubmodules/rasa/listener.js +5 -5
  45. package/pubmodules/routing-queue/index.js +3 -0
  46. package/pubmodules/routing-queue/listener.js +328 -0
  47. package/pubmodules/rules/conciergeBot.js +2 -2
  48. package/pubmodules/scheduler/tasks/closeAgentUnresponsiveRequestTask.js +6 -1
  49. package/pubmodules/scheduler/tasks/closeBotUnresponsiveRequestTask.js +7 -1
  50. package/pubmodules/tilebot/index.js +11 -0
  51. package/pubmodules/tilebot/listener.js +85 -0
  52. package/pubmodules/trigger/rulesTrigger.js +137 -14
  53. package/pubmodules/trigger/start.js +5 -1
  54. package/pubmodules/whatsapp/index.js +7 -0
  55. package/pubmodules/whatsapp/listener.js +32 -0
  56. package/routes/auth.js +7 -2
  57. package/routes/campaigns.js +3 -3
  58. package/routes/department.js +3 -2
  59. package/routes/email.js +32 -2
  60. package/routes/faq.js +37 -2
  61. package/routes/faq_kb.js +496 -133
  62. package/routes/faqpub.js +5 -0
  63. package/routes/lead.js +56 -0
  64. package/routes/message.js +196 -14
  65. package/routes/messagesRoot.js +39 -0
  66. package/routes/project.js +76 -4
  67. package/routes/project_user.js +11 -1
  68. package/routes/project_user_test.js +19 -0
  69. package/routes/request.js +134 -30
  70. package/routes/troubleshooting.js +12 -0
  71. package/routes/users-util.js +39 -0
  72. package/routes/users.js +1 -1
  73. package/routes/widget.js +64 -2
  74. package/services/BotSubscriptionNotifier.js +5 -0
  75. package/services/banUserNotifier.js +86 -0
  76. package/services/cacheEnabler.js +56 -0
  77. package/services/chatbotService.js +101 -0
  78. package/services/departmentService.js +25 -3
  79. package/services/emailService.js +170 -28
  80. package/services/faqBotHandler.js +2 -3
  81. package/services/faqService.js +28 -3
  82. package/services/geoService.js +36 -6
  83. package/services/labelService.js +1 -1
  84. package/services/leadService.js +3 -2
  85. package/services/messageService.js +4 -2
  86. package/services/modulesManager.js +23 -76
  87. package/services/operatingHoursService.js +9 -4
  88. package/services/requestService.js +75 -39
  89. package/services/subscriptionNotifier.js +9 -4
  90. package/services/trainingService.js +106 -0
  91. package/template/email/assignedEmailMessage.html +21 -11
  92. package/template/email/assignedRequest.html +21 -11
  93. package/template/email/beenInvitedExistingUser.html +16 -6
  94. package/template/email/beenInvitedNewUser.html +16 -6
  95. package/template/email/emailDirect.html +130 -0
  96. package/template/email/newMessage.html +18 -8
  97. package/template/email/newMessageFollower.html +22 -12
  98. package/template/email/passwordChanged.html +15 -5
  99. package/template/email/pooledEmailMessage.html +21 -11
  100. package/template/email/pooledRequest.html +20 -10
  101. package/template/email/resetPassword.html +15 -5
  102. package/template/email/sendTranscript.html +7 -4
  103. package/template/email/ticket.html +17 -7
  104. package/template/email/verify.html +15 -5
  105. package/test/cannedRoute.js +157 -0
  106. package/test/chatbot-mock.js +127 -0
  107. package/test/example-json-intents.txt +1 -0
  108. package/test/example-json.txt +1 -0
  109. package/test/example.json +1 -0
  110. package/test/faqRoute.js +353 -208
  111. package/test/faqkbRoute.js +669 -64
  112. package/test/imageRoute.js +1 -1
  113. package/test/messageRoute.js +387 -5
  114. package/test/requestRoute.js +6 -6
  115. package/test/requestService.js +55 -4
  116. package/test-int/cache-project.js +90 -0
  117. package/test-int/cache-project_user.js +88 -0
  118. package/utils/UIDGenerator.js +20 -0
  119. package/utils/cacheUtil.js +2 -2
  120. package/utils/orgUtil.js +3 -3
  121. package/utils/promiseUtil.js +31 -0
  122. package/utils/recipientEmailUtil.js +66 -0
  123. package/utils/sendEmailUtil.js +34 -0
  124. package/utils/sendMessageUtil.js +1 -1
  125. package/utils/stringUtil.js +12 -0
  126. 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
- // create(name, url, projectid, user_id, type, description, webhook_url, webhook_enabled, language, template)
14
- 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).then(function(savedFaq_kb) {
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
- .limit(10000)
51
- .lean().
52
- exec(async (err, faqs) => {
53
- if (err) {
54
- return res.status(500).send({ success: false, msg: 'Error getting object.' });
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
- return res.json({train:train, httpResponse:trainHttp});
84
- // return res.json(trainHttp);
85
- }else {
86
- return res.status(400).send({ success: false, msg: 'no faq to train on external bot.' });
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
- "language":"it",
99
- "nlu":[
100
- {
101
- "intent":"eta",
102
- "examples":[
103
- "quanti anni hai",
104
- "dimmi la tua età",
105
- "quanto sei grande",
106
- "parlami della tua età"
107
- ]
108
- },
109
- {
110
- "intent":"brutteparole",
111
- "examples":[
112
- "non dire parolacce",
113
- "le brutte parole non dovrebbero dirsi"
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
- Faq.find(query)
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
- faqs.forEach(f => {
154
- f.score = 100;
155
- });
156
- var result = {hits:faqs};
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
- res.json(result);
160
- }else {
161
- query = { "id_project": req.projectid, "id_faq_kb": req.body.id_faq_kb};
165
+ res.json(result);
166
+ } else {
167
+ query = { "id_project": req.projectid, "id_faq_kb": req.body.id_faq_kb };
162
168
 
163
- var search_obj = {"$search": req.body.question};
169
+ var search_obj = { "$search": req.body.question };
164
170
 
165
- if (faq_kb.language) {
171
+ if (faq_kb.language) {
166
172
  search_obj["$language"] = faq_kb.language;
167
- }
168
- query.$text = search_obj;
169
- winston.debug("fulltext search query", query);
173
+ }
174
+ query.$text = search_obj;
175
+ winston.debug("fulltext search query", query);
170
176
 
171
177
 
172
- winston.debug('internal ft query: '+ query);
173
-
174
- Faq.find(query, {score: { $meta: "textScore" } })
175
- .sort( { score: { $meta: "textScore" } } ) //https://docs.mongodb.com/manual/reference/operator/query/text/#sort-by-text-search-score
176
- .lean().
177
- exec(function (err, faqs) {
178
- if (err) {
179
- winston.error('Error getting object.', err);
180
- return res.status(500).send({ success: false, msg: 'Error getting fulltext object.' });
181
- }
182
-
183
- winston.debug("faqs", faqs);
184
-
185
- var result = {hits:faqs};
186
- res.json(result);
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;