@tiledesk/tiledesk-server 2.2.38 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +14 -657
  3. package/README.md +36 -21
  4. package/app.js +29 -5
  5. package/channels/chat21/chat21WebHook.js +12 -1
  6. package/config/labels/widget.json +320 -0
  7. package/event/botEvent.js +1 -1
  8. package/event/subscriptionEvent.js +11 -0
  9. package/fonts/Roboto-Italic.ttf +0 -0
  10. package/fonts/Roboto-Medium.ttf +0 -0
  11. package/fonts/Roboto-MediumItalic.ttf +0 -0
  12. package/fonts/Roboto-Regular.ttf +0 -0
  13. package/middleware/passport.js +4 -1
  14. package/models/lead.js +2 -0
  15. package/models/request.js +38 -11
  16. package/models/subscriptionLog.js +34 -0
  17. package/models/tagLibrary.js +42 -0
  18. package/package.json +4 -10
  19. package/pubmodules/activities/activityArchiver.js +295 -0
  20. package/pubmodules/activities/index.js +3 -0
  21. package/pubmodules/activities/models/activity.js +88 -0
  22. package/pubmodules/activities/routes/activity.js +710 -0
  23. package/pubmodules/activities/test/activityRoute.js +85 -0
  24. package/pubmodules/analytics/analytics.js +1719 -0
  25. package/pubmodules/analytics/index.js +3 -0
  26. package/pubmodules/canned/cannedResponse.js +51 -0
  27. package/pubmodules/canned/cannedResponseRoute.js +157 -0
  28. package/pubmodules/canned/index.js +3 -0
  29. package/pubmodules/messageActions/messageActionsInterceptor.js +4 -2
  30. package/pubmodules/pubModulesManager.js +115 -7
  31. package/pubmodules/rasa/index.js +8 -1
  32. package/pubmodules/rasa/listener.js +28 -7
  33. package/pubmodules/scheduler/tasks/closeAgentUnresponsiveRequestTask.js +3 -1
  34. package/pubmodules/scheduler/tasks/closeBotUnresponsiveRequestTask.js +5 -3
  35. package/pubmodules/trigger/default.js +271 -0
  36. package/pubmodules/trigger/event/actionEventEmitter.js +10 -0
  37. package/pubmodules/trigger/event/flowEventEmitter.js +10 -0
  38. package/pubmodules/trigger/event/triggerEventEmitter.js +10 -0
  39. package/pubmodules/trigger/index.js +3 -0
  40. package/pubmodules/trigger/models/trigger.js +149 -0
  41. package/pubmodules/trigger/rulesTrigger.js +1181 -0
  42. package/pubmodules/trigger/start.js +114 -0
  43. package/pubmodules/trigger/triggerRoute.js +150 -0
  44. package/routes/department.js +51 -0
  45. package/routes/group.js +140 -0
  46. package/routes/lead.js +24 -1
  47. package/routes/message.js +6 -3
  48. package/routes/project.js +52 -0
  49. package/routes/public-request.js +265 -2
  50. package/routes/request.js +86 -13
  51. package/routes/subscription.js +140 -0
  52. package/routes/tag.js +138 -0
  53. package/routes/user-request.js +3 -2
  54. package/routes/widget.js +16 -1
  55. package/routes/widgetLoader.js +31 -0
  56. package/services/faqBotHandler.js +2 -2
  57. package/services/faqBotSupport.js +0 -1
  58. package/services/faqService.js +1 -1
  59. package/services/modulesManager.js +16 -182
  60. package/services/requestService.js +364 -6
  61. package/services/subscriptionNotifier.js +485 -0
  62. package/template/email/assignedEmailMessage.html +1 -1
  63. package/template/email/assignedRequest.html +1 -1
  64. package/template/email/newMessage.html +1 -1
  65. package/template/email/passwordChanged.html +1 -1
  66. package/template/email/pooledEmailMessage.html +1 -1
  67. package/template/email/pooledRequest.html +1 -1
  68. package/template/email/resetPassword.html +2 -2
  69. package/template/email/ticket.html +1 -1
  70. package/test/messageRoute.js +69 -0
  71. package/test/requestService.js +3 -1
  72. package/views/messages.jade +1 -1
@@ -0,0 +1,3 @@
1
+ const analyticsRoute = require("./analytics");
2
+
3
+ module.exports = {analyticsRoute:analyticsRoute};
@@ -0,0 +1,51 @@
1
+ var mongoose = require('mongoose');
2
+ var Schema = mongoose.Schema;
3
+ var winston = require('../../config/winston');
4
+
5
+
6
+ var CannedResponseSchema = new Schema({
7
+
8
+ title: {
9
+ type: String,
10
+ required: false,
11
+ index: true
12
+ },
13
+ text: {
14
+ type: String,
15
+ required: true,
16
+ },
17
+ attributes: {
18
+ type: Object,
19
+ },
20
+ id_project: {
21
+ type: String,
22
+ required: true,
23
+ index: true
24
+ },
25
+ createdBy: {
26
+ type: String,
27
+ required: true
28
+ },
29
+ status: {
30
+ type: Number,
31
+ required: false,
32
+ default: 100,
33
+ index: true
34
+ },
35
+ },{
36
+ timestamps: true
37
+ }
38
+ );
39
+
40
+
41
+ // CannedResponseSchema.index({text: 'text'},
42
+ // {"name":"cannedresponse_fulltext","default_language": "italian","language_override": "dummy"}); // schema level
43
+
44
+ var CannedResponse = mongoose.model('cannedResponse', CannedResponseSchema);
45
+
46
+ if (process.env.MONGOOSE_SYNCINDEX) {
47
+ CannedResponse.syncIndexes();
48
+ winston.info("CannedResponse syncIndexes")
49
+ }
50
+
51
+ module.exports = CannedResponse;
@@ -0,0 +1,157 @@
1
+ var express = require('express');
2
+ var router = express.Router();
3
+ var CannedResponse = require("./cannedResponse");
4
+ var winston = require('../../config/winston');
5
+ // const CannedResponseEvent = require('../event/CannedResponseEvent');
6
+
7
+
8
+ router.post('/', function (req, res) {
9
+
10
+ winston.debug(req.body);
11
+ winston.debug("req.user", req.user);
12
+
13
+ var newCannedResponse = new CannedResponse({
14
+ title: req.body.title,
15
+ text: req.body.text,
16
+ id_project: req.projectid,
17
+ createdBy: req.user.id,
18
+ updatedBy: req.user.id
19
+ });
20
+
21
+ newCannedResponse.save(function (err, savedCannedResponse) {
22
+ if (err) {
23
+ winston.error('--- > ERROR ', err)
24
+
25
+ return res.status(500).send({ success: false, msg: 'Error saving object.' });
26
+ }
27
+
28
+ res.json(savedCannedResponse);
29
+ });
30
+ });
31
+
32
+ router.put('/:cannedResponseid', function (req, res) {
33
+ winston.debug(req.body);
34
+ var update = {};
35
+
36
+ if (req.body.title!=undefined) {
37
+ update.title = req.body.title;
38
+ }
39
+ if (req.body.text!=undefined) {
40
+ update.text = req.body.text;
41
+ }
42
+ if (req.body.attributes!=undefined) {
43
+ update.attributes = req.body.attributes;
44
+ }
45
+
46
+
47
+ CannedResponse.findByIdAndUpdate(req.params.cannedResponseid, update, { new: true, upsert: true }, function (err, updatedCannedResponse) {
48
+ if (err) {
49
+ winston.error('--- > ERROR ', err);
50
+ return res.status(500).send({ success: false, msg: 'Error updating object.' });
51
+ }
52
+
53
+
54
+
55
+ // CannedResponseEvent.emit('CannedResponse.update', updatedCannedResponse);
56
+ res.json(updatedCannedResponse);
57
+ });
58
+ });
59
+
60
+ router.delete('/:cannedResponseid', function (req, res) {
61
+ winston.debug(req.body);
62
+
63
+ CannedResponse.findByIdAndUpdate(req.params.cannedResponseid, {status: 1000}, { new: true, upsert: true }, function (err, updatedCannedResponse) {
64
+ if (err) {
65
+ winston.error('--- > ERROR ', err);
66
+ return res.status(500).send({ success: false, msg: 'Error updating object.' });
67
+ }
68
+
69
+
70
+
71
+ // CannedResponseEvent.emit('CannedResponse.delete', updatedCannedResponse);
72
+ res.json(updatedCannedResponse);
73
+ });
74
+ });
75
+
76
+ router.delete('/:cannedResponseid/physical', function (req, res) {
77
+ winston.debug(req.body);
78
+
79
+ CannedResponse.remove({ _id: req.params.cannedResponseid }, function (err, cannedResponse) {
80
+ if (err) {
81
+ winston.error('--- > ERROR ', err);
82
+ return res.status(500).send({ success: false, msg: 'Error deleting object.' });
83
+ }
84
+
85
+
86
+ // CannedResponseEvent.emit('CannedResponse.delete', CannedResponse);
87
+
88
+ res.json(cannedResponse);
89
+ });
90
+ });
91
+
92
+ router.get('/:cannedResponseid', function (req, res) {
93
+ winston.debug(req.body);
94
+
95
+ CannedResponse.findById(req.params.cannedResponseid, function (err, cannedResponse) {
96
+ if (err) {
97
+ return res.status(500).send({ success: false, msg: 'Error getting object.' });
98
+ }
99
+ if (!cannedResponse) {
100
+ return res.status(404).send({ success: false, msg: 'Object not found.' });
101
+ }
102
+ res.json(cannedResponse);
103
+ });
104
+ });
105
+
106
+ router.get('/', function (req, res) {
107
+ var limit = 40; // Number of CannedResponses per page
108
+ var page = 0;
109
+
110
+ if (req.query.page) {
111
+ page = req.query.page;
112
+ }
113
+
114
+ var skip = page * limit;
115
+ winston.debug('CannedResponse ROUTE - SKIP PAGE ', skip);
116
+
117
+
118
+ var query = { "id_project": req.projectid, "status": {$lt:1000}};
119
+
120
+ if (req.query.full_text) {
121
+ winston.debug('CannedResponse ROUTE req.query.fulltext', req.query.full_text);
122
+ query.$text = { "$search": req.query.full_text };
123
+ }
124
+
125
+
126
+ var direction = -1; //-1 descending , 1 ascending
127
+ if (req.query.direction) {
128
+ direction = req.query.direction;
129
+ }
130
+
131
+ var sortField = "createdAt";
132
+ if (req.query.sort) {
133
+ sortField = req.query.sort;
134
+ }
135
+
136
+ var sortQuery = {};
137
+ sortQuery[sortField] = direction;
138
+
139
+ winston.debug("sort query", sortQuery);
140
+
141
+ return CannedResponse.find(query).
142
+ skip(skip).limit(limit).
143
+ sort(sortQuery).
144
+ exec(function (err, cannedResponses) {
145
+ if (err) {
146
+ winston.error('CannedResponse ROUTE - REQUEST FIND ERR ', err)
147
+ return (err);
148
+ }
149
+
150
+ return res.json(cannedResponses);
151
+ });
152
+ });
153
+
154
+
155
+
156
+
157
+ module.exports = router;
@@ -0,0 +1,3 @@
1
+ const cannedResponseRoute = require("./cannedResponseRoute");
2
+
3
+ module.exports = {cannedResponseRoute: cannedResponseRoute};
@@ -149,8 +149,10 @@ class MessageActionsInterceptor {
149
149
  if (request) {
150
150
  // setTimeout(function() {
151
151
  // winston.info("delayed")
152
- // closeRequestByRequestId(request_id, id_project, notify) {
153
- requestService.closeRequestByRequestId(request.request_id, request.id_project );
152
+
153
+ // closeRequestByRequestId(request_id, id_project, skipStatsUpdate, notify, closed_by)
154
+ const closed_by = message.sender;
155
+ requestService.closeRequestByRequestId(request.request_id, request.id_project, false, true, closed_by );
154
156
  // }, 1500);
155
157
 
156
158
 
@@ -1,10 +1,9 @@
1
1
 
2
2
  var winston = require('../config/winston');
3
- // var validtoken = require('../middleware/valid-token');
4
- // var roleChecker = require('../middleware/has-role');
5
- // var passport = require('passport');
6
- // require('../middleware/passport')(passport);
7
-
3
+ var validtoken = require('../middleware/valid-token');
4
+ var roleChecker = require('../middleware/has-role');
5
+ var passport = require('passport');
6
+ require('../middleware/passport')(passport);
8
7
 
9
8
  class PubModulesManager {
10
9
 
@@ -20,12 +19,29 @@ class PubModulesManager {
20
19
  this.scheduler = undefined;
21
20
 
22
21
  this.rasa = undefined;
22
+ this.rasaRoute = undefined;
23
+
24
+ this.activityArchiver = undefined;
25
+ this.activityRoute = undefined;
26
+
27
+ this.analyticsRoute = undefined;
28
+
29
+ this.cannedResponseRoute = undefined;
30
+
31
+ this.trigger = undefined;
32
+ this.triggerRoute = undefined;
33
+
23
34
  }
24
35
 
25
36
 
26
37
 
27
38
  use(app) {
28
39
 
40
+ if (this.rasaRoute) {
41
+ app.use('/modules/rasa', this.rasaRoute);
42
+ winston.info("ModulesManager rasaRoute controller loaded");
43
+ }
44
+
29
45
  }
30
46
  useUnderProjects(app) {
31
47
  var that = this;
@@ -39,10 +55,31 @@ class PubModulesManager {
39
55
  winston.info("ModulesManager eventsRoute controller loaded");
40
56
  }
41
57
 
58
+
59
+ if (this.activityRoute) {
60
+ app.use('/:projectid/activities', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], this.activityRoute);
61
+ winston.info("ModulesManager activities controller loaded");
62
+ }
63
+
64
+ if (this.analyticsRoute) {
65
+ app.use('/:projectid/analytics', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], this.analyticsRoute);
66
+ winston.info("ModulesManager analytics controller loaded");
67
+ }
68
+
69
+ if (this.cannedResponseRoute) {
70
+ app.use('/:projectid/canned', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], this.cannedResponseRoute);
71
+ winston.info("ModulesManager canned controller loaded");
72
+ }
73
+
74
+ if (this.triggerRoute) {
75
+ app.use('/:projectid/modules/triggers', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], this.triggerRoute);
76
+ winston.info("ModulesManager trigger controller loaded");
77
+ }
78
+
42
79
  }
43
80
 
44
81
 
45
- init() {
82
+ init(config) {
46
83
  winston.debug("PubModulesManager init");
47
84
 
48
85
  try {
@@ -145,7 +182,10 @@ class PubModulesManager {
145
182
  try {
146
183
  this.rasa = require('./rasa');
147
184
  winston.debug("this.rasa:"+ this.rasa);
148
- this.rasa.listener.listen();
185
+ this.rasa.listener.listen(config);
186
+
187
+ this.rasaRoute = this.rasa.rasaRoute;
188
+
149
189
  winston.info("PubModulesManager initialized rasa.");
150
190
  } catch(err) {
151
191
  if (err.code == 'MODULE_NOT_FOUND') {
@@ -157,7 +197,65 @@ class PubModulesManager {
157
197
 
158
198
 
159
199
 
200
+
201
+ try {
202
+ this.activityArchiver = require('./activities').activityArchiver;
203
+ // this.activityArchiver.listen();
204
+ winston.debug("this.activityArchiver:"+ this.activityArchiver);
205
+
206
+ this.activityRoute = require('./activities').activityRoute;
207
+ winston.debug("this.activityRoute:"+ this.activityRoute);
208
+
209
+ winston.info("ModulesManager activities initialized");
210
+ } catch(err) {
211
+ if (err.code == 'MODULE_NOT_FOUND') {
212
+ winston.info("ModulesManager init activities module not found");
213
+ }else {
214
+ winston.error("ModulesManager error initializing init activities module", err);
215
+ }
216
+ }
217
+
218
+
219
+ try {
220
+ this.analyticsRoute = require('./analytics').analyticsRoute;
221
+ winston.debug("this.analyticsRoute:"+ this.analyticsRoute);
222
+ winston.info("ModulesManager analyticsRoute initialized");
223
+ } catch(err) {
224
+ if (err.code == 'MODULE_NOT_FOUND') {
225
+ winston.info("ModulesManager init analytics module not found");
226
+ }else {
227
+ winston.error("ModulesManager error initializing init analytics module", err);
228
+ }
229
+ }
230
+
231
+
232
+
233
+ try {
234
+ this.cannedResponseRoute = require('./canned').cannedResponseRoute;
235
+ winston.debug("this.cannedResponseRoute:"+ this.cannedResponseRoute);
236
+ winston.info("ModulesManager cannedResponseRoute initialized");
237
+ } catch(err) {
238
+ if (err.code == 'MODULE_NOT_FOUND') {
239
+ winston.info("ModulesManager init canned module not found");
240
+ }else {
241
+ winston.error("ModulesManager error initializing init canned module", err);
242
+ }
243
+ }
244
+
160
245
 
246
+ try {
247
+ this.trigger = require('./trigger').start;
248
+ winston.debug("this.trigger:"+ this.trigger);
249
+ this.triggerRoute = require('./trigger').triggerRoute;
250
+ winston.debug("this.triggerRoute:"+ this.triggerRoute);
251
+ winston.info("ModulesManager trigger initialized");
252
+ } catch(err) {
253
+ if (err.code == 'MODULE_NOT_FOUND') {
254
+ winston.info("ModulesManager init trigger module not found");
255
+ }else {
256
+ winston.error("ModulesManager error initializing init trigger module", err);
257
+ }
258
+ }
161
259
 
162
260
  }
163
261
 
@@ -212,6 +310,16 @@ class PubModulesManager {
212
310
  }
213
311
 
214
312
 
313
+ if (this.activityArchiver) {
314
+ try {
315
+ this.activityArchiver.listen();
316
+ winston.info("ModulesManager activityArchiver started");
317
+ } catch(err) {
318
+ winston.info("ModulesManager error starting activityArchiver module", err);
319
+ }
320
+ }
321
+
322
+
215
323
  }
216
324
 
217
325
 
@@ -1,3 +1,10 @@
1
1
  const listener = require("./listener");
2
2
 
3
- module.exports = {listener:listener };
3
+ const rasa = require("@tiledesk/tiledesk-rasa-connector");
4
+ const rasaRoute = rasa.router;
5
+
6
+
7
+
8
+
9
+
10
+ module.exports = { listener: listener, rasaRoute: rasaRoute };
@@ -1,25 +1,46 @@
1
1
  const botEvent = require('../../event/botEvent');
2
2
  var Faq_kb = require("../../models/faq_kb");
3
3
  var winston = require('../../config/winston');
4
+ const rasa = require("@tiledesk/tiledesk-rasa-connector");
5
+ var configGlobal = require('../../config/global');
4
6
 
5
- const BOT_RASA_ENDPOINT = process.env.BOT_RASA_ENDPOINT;
7
+ var port = process.env.PORT || '3000';
8
+
9
+ const BOT_RASA_ENDPOINT = "http://localhost:" + port+ "/modules/rasa/rasabot" || process.env.BOT_RASA_ENDPOINT;
6
10
  winston.debug("BOT_RASA_ENDPOINT: " + BOT_RASA_ENDPOINT);
7
11
 
8
- if (BOT_RASA_ENDPOINT) {
12
+ // if (BOT_RASA_ENDPOINT) {
9
13
  winston.info("Rasa endpoint: " + BOT_RASA_ENDPOINT);
10
- } else {
11
- winston.info("Rasa endpoint not configured");
12
- }
14
+ // } else {
15
+ // winston.info("Rasa endpoint not configured");
16
+ // }
13
17
 
18
+ const apiUrl = process.env.API_URL || configGlobal.apiUrl;
19
+ winston.info('Rasa apiUrl: '+ apiUrl);
14
20
 
15
21
  class Listener {
16
22
 
17
- listen() {
23
+ listen(config) {
18
24
 
19
- winston.debug('rasa Listener listen');
25
+ winston.info('Rasa Listener listen');
26
+ winston.debug("config databaseUri: " + config.databaseUri);
27
+
20
28
 
21
29
  var that = this;
22
30
 
31
+
32
+ rasa.startRasa(
33
+ {
34
+ KVBASE_COLLECTION : process.env.KVBASE_COLLECTION,
35
+ MONGODB_URI: config.databaseUri,
36
+ API_ENDPOINT: apiUrl,
37
+ log: true
38
+ }, () => {
39
+ winston.info("RASA proxy server successfully started.");
40
+ });
41
+
42
+
43
+
23
44
  botEvent.on('faqbot.create', function(bot) {
24
45
  if (BOT_RASA_ENDPOINT) {
25
46
 
@@ -84,7 +84,9 @@ findUnresponsiveRequests() {
84
84
  requests.forEach(request => {
85
85
  winston.debug("********unresponsive request ", request);
86
86
 
87
- return requestService.closeRequestByRequestId(request.request_id, request.id_project, false, false).then(function(updatedStatusRequest) {
87
+ // closeRequestByRequestId(request_id, id_project, skipStatsUpdate, notify, closed_by)
88
+ const closed_by = "_bot_unresponsive";
89
+ return requestService.closeRequestByRequestId(request.request_id, request.id_project, false, false, closed_by).then(function(updatedStatusRequest) {
88
90
  winston.verbose("CloseAgentUnresponsiveRequestTask: Request closed with request_id: " + request.request_id);
89
91
  // winston.info("Request closed",updatedStatusRequest);
90
92
  }).catch(function(err) {
@@ -50,8 +50,8 @@ scheduleUnresponsiveRequests() {
50
50
  //https://crontab.guru/examples.html
51
51
  var s= schedule.scheduleJob(this.cronExp, function(fireDate){ //TODO aggiungi un bias random
52
52
 
53
- let timeInMs = Math.random() * (1000); // avoid cluster concurrent jobs in multiple nodes between 0 and 1sec
54
- winston.info('timeInMs => '+ timeInMs);
53
+ let timeInMs = Math.random() * (1000); // avoid cluster concurrent jobs in multiple nodes delay between 0 and 1sec
54
+ winston.debug('timeInMs => '+ timeInMs);
55
55
 
56
56
  setTimeout(function () {
57
57
  winston.debug('CloseBotUnresponsiveRequestTask scheduleUnresponsiveRequests job was supposed to run at ' + fireDate + ', but actually ran at ' + new Date());
@@ -95,7 +95,9 @@ findUnresponsiveRequests() {
95
95
 
96
96
  winston.debug("********unresponsive request ", request);
97
97
 
98
- return requestService.closeRequestByRequestId(request.request_id, request.id_project, false, false).then(function(updatedStatusRequest) {
98
+ // closeRequestByRequestId(request_id, id_project, skipStatsUpdate, notify, closed_by)
99
+ const closed_by = "_bot_unresponsive";
100
+ return requestService.closeRequestByRequestId(request.request_id, request.id_project, false, false, closed_by).then(function(updatedStatusRequest) {
99
101
  winston.info("CloseBotUnresponsiveRequestTask: Request closed with request_id: " + request.request_id);
100
102
  // winston.info("Request closed",updatedStatusRequest);
101
103
  }).catch(function(err) {