@tiledesk/tiledesk-server 2.9.26 → 2.9.28
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +9 -0
- package/package.json +2 -2
- package/pubmodules/pubModulesManager.js +41 -41
- package/pubmodules/routing-queue/listenerQueued.js +72 -27
- package/routes/faq_kb.js +1 -1
- package/routes/kb.js +2 -1
- package/routes/message.js +55 -50
- package/routes/request.js +581 -47
- package/routes/users.js +4 -7
- package/services/QuoteManager.js +104 -16
- package/services/emailService.js +11 -2
- package/services/operatingHoursService.js +1 -0
- package/services/projectService.js +21 -0
- package/services/requestService.js +344 -9
- package/template/email/redirectToDesktopEmail.html +2 -2
- package/test/mock/projectMock.js +29 -1
- package/test/projectRoute.js +86 -3
- package/test/quoteManager.js +77 -5
- package/test/requestRoute.js +42 -0
- package/websocket/webSocketServer.js +1 -1
package/CHANGELOG.md
CHANGED
@@ -5,6 +5,15 @@
|
|
5
5
|
🚀 IN PRODUCTION 🚀
|
6
6
|
(https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
|
7
7
|
|
8
|
+
# 2.9.28
|
9
|
+
- Updated number_assigned_request count logic (removed incr/decr)
|
10
|
+
|
11
|
+
# 2.9.27
|
12
|
+
- Updated tybot-connector to 0.2.107
|
13
|
+
- Improved quotas slots
|
14
|
+
- Improved requests quota count (temporary conversation will no longer counted)
|
15
|
+
- Fixed bug: savedFaq is not defined in /importjson
|
16
|
+
|
8
17
|
# 2.9.26
|
9
18
|
- Updated tybot-connector to 0.2.105
|
10
19
|
- Added route for faqs csv file uploading on /kb
|
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.28",
|
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.107",
|
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",
|
@@ -33,11 +33,11 @@ class PubModulesManager {
|
|
33
33
|
this.telegram = undefined;
|
34
34
|
this.telegramRoute = undefined;
|
35
35
|
|
36
|
-
this.sms = undefined;
|
37
|
-
this.smsRoute = undefined;
|
36
|
+
// this.sms = undefined;
|
37
|
+
// this.smsRoute = undefined;
|
38
38
|
|
39
|
-
this.voice = undefined;
|
40
|
-
this.voiceRoute = undefined;
|
39
|
+
// this.voice = undefined;
|
40
|
+
// this.voiceRoute = undefined;
|
41
41
|
|
42
42
|
this.mqttTest = undefined;
|
43
43
|
this.mqttTestRoute = undefined;
|
@@ -97,14 +97,14 @@ class PubModulesManager {
|
|
97
97
|
app.use('/modules/telegram', this.telegramRoute);
|
98
98
|
winston.info("PubModulesManager telegramRoute controller loaded");
|
99
99
|
}
|
100
|
-
if (this.smsRoute) {
|
101
|
-
|
102
|
-
|
103
|
-
}
|
104
|
-
if (this.voiceRoute) {
|
105
|
-
|
106
|
-
|
107
|
-
}
|
100
|
+
// if (this.smsRoute) {
|
101
|
+
// app.use('/modules/sms', this.smsRoute);
|
102
|
+
// winston.info("PubModulesManager smsRoute controller loaded");
|
103
|
+
// }
|
104
|
+
// if (this.voiceRoute) {
|
105
|
+
// app.use('/modules/voice', this.voiceRoute);
|
106
|
+
// winston.info("PubModulesManager voiceRoute controller loaded");
|
107
|
+
// }
|
108
108
|
if (this.mqttTestRoute) {
|
109
109
|
app.use('/modules/mqttTest', this.mqttTestRoute);
|
110
110
|
winston.info("PubModulesManager mqttTestRoute controller loaded");
|
@@ -345,40 +345,40 @@ class PubModulesManager {
|
|
345
345
|
}
|
346
346
|
}
|
347
347
|
|
348
|
-
if (process.env.VOICE_TOKEN === process.env.VOICE_SECRET) {
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
348
|
+
// if (process.env.VOICE_TOKEN === process.env.VOICE_SECRET) {
|
349
|
+
// try {
|
350
|
+
// this.voice = require('./voice');
|
351
|
+
// winston.info("this.voice: " + this.voice);
|
352
|
+
// this.voice.listener.listen(config);
|
353
353
|
|
354
|
-
|
354
|
+
// this.voiceRoute = this.voice.voiceRoute;
|
355
355
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
}
|
356
|
+
// winston.info("PubModulesManager initialized apps (voice).")
|
357
|
+
// } catch(err) {
|
358
|
+
// console.log("\n Unable to start voice connector: ", err);
|
359
|
+
// if (err.code == 'MODULE_NOT_FOUND') {
|
360
|
+
// winston.info("PubModulesManager init apps module not found ");
|
361
|
+
// } else {
|
362
|
+
// winston.info("PubModulesManager error initializing init apps module", err);
|
363
|
+
// }
|
364
|
+
// }
|
365
|
+
// }
|
366
366
|
|
367
|
-
try {
|
368
|
-
|
369
|
-
|
370
|
-
|
367
|
+
// try {
|
368
|
+
// this.sms = require('./sms');
|
369
|
+
// winston.info("this.sms: " + this.sms);
|
370
|
+
// this.sms.listener.listen(config);
|
371
371
|
|
372
|
-
|
372
|
+
// this.smsRoute = this.sms.smsRoute;
|
373
373
|
|
374
|
-
|
375
|
-
} catch(err) {
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
}
|
374
|
+
// winston.info("PubModulesManager initialized apps (sms).")
|
375
|
+
// } catch(err) {
|
376
|
+
// if (err.code == 'MODULE_NOT_FOUND') {
|
377
|
+
// winston.info("PubModulesManager init apps module not found ");
|
378
|
+
// } else {
|
379
|
+
// winston.info("PubModulesManager error initializing init apps module", err);
|
380
|
+
// }
|
381
|
+
// }
|
382
382
|
|
383
383
|
try {
|
384
384
|
this.mqttTest = require('./mqttTest');
|
@@ -2,6 +2,7 @@ const authEvent = require('../../event/authEvent');
|
|
2
2
|
const requestEvent = require('../../event/requestEvent');
|
3
3
|
var Project = require('../../models/project');
|
4
4
|
var Project_user = require('../../models/project_user');
|
5
|
+
var Request = require('../../models/request')
|
5
6
|
var winston = require('../../config/winston');
|
6
7
|
|
7
8
|
var ProjectUserUtil = require("../../utils/project_userUtil");
|
@@ -34,44 +35,88 @@ class Listener {
|
|
34
35
|
this.enabled = false;
|
35
36
|
}
|
36
37
|
winston.debug("Listener this.enabled: "+ this.enabled);
|
37
|
-
}
|
38
|
+
}
|
38
39
|
|
39
40
|
|
40
|
-
|
41
|
+
// db.getCollection('project_users').find({"number_assigned_requests" : {"$lt":0}}).count()
|
42
|
+
|
43
|
+
// New version of updateProjectUser() method.
|
44
|
+
// This will not increment or decrement the number_assigned_requests field but search the exact number of assigned conversation to the project user
|
45
|
+
updateProjectUser(id_user, id_project, operation) {
|
46
|
+
winston.debug("Route queue updateProjectUser start operation: " + operation + "id_user " + id_user + " id_project " + id_project);
|
47
|
+
|
48
|
+
return Request.countDocuments({ id_project: id_project, participantsAgents: id_user, status: { $lt: 1000 } }, (err, requestsCount) => {
|
49
|
+
console.log("requestsCount for id_user: ", id_user, "and project: ", id_project, "-->", requestsCount);
|
50
|
+
if (err) {
|
51
|
+
return winston.error(err);
|
52
|
+
}
|
53
|
+
|
54
|
+
return Project_user
|
55
|
+
.findOneAndUpdate({ id_user: id_user, id_project: id_project }, { number_assigned_requests: requestsCount }, { new: true, upsert: false }, function (err, updatedPU) {
|
56
|
+
if (err) {
|
57
|
+
return winston.error(err);
|
58
|
+
}
|
59
|
+
// winston.debug("Route queue number_assigned_requests +1 :" + updatedPU.id);
|
60
|
+
// winston.debug("Route queue number_assigned_requests +1 :" + updatedPU.id);
|
61
|
+
winston.debug("Route queue number_assigned_requests updated to " + requestsCount + "for project user " + updatedPU.id);
|
62
|
+
|
63
|
+
updatedPU.populate({ path: 'id_user', select: { 'firstname': 1, 'lastname': 1 } }, function (err, updatedProject_userPopulated) {
|
64
|
+
|
65
|
+
var pu = updatedProject_userPopulated.toJSON();
|
66
|
+
|
67
|
+
return Project.findById(id_project).exec(function (err, project) {
|
68
|
+
pu.isBusy = ProjectUserUtil.isBusy(updatedProject_userPopulated, project.settings && project.settings.max_agent_assigned_chat);
|
69
|
+
winston.debug("Route queue pu.isBusy: " + pu.isBusy);
|
70
|
+
|
71
|
+
authEvent.emit('project_user.update', { updatedProject_userPopulated: pu, req: undefined, skipArchive: true }); //if queued with jobs -> websocket notification on project_user.update doesn't work??? forse si in quanto viene convertito in .pub.queue e poi rifunziiona
|
72
|
+
|
73
|
+
|
74
|
+
// project_user.update triggers activityArchiver(tested), cache invalidation(tested), subscriptionNotifierQueued and websocket(tested works from queue i trigger ws)
|
75
|
+
if (requestEvent.queueEnabled) { //force to .queue to be catched into the queue (activity archiver, subscriptionNotifierQueued )
|
76
|
+
authEvent.emit('project_user.update.queue', { updatedProject_userPopulated: pu, req: undefined, skipArchive: true });
|
77
|
+
}
|
78
|
+
|
79
|
+
})
|
80
|
+
|
81
|
+
});
|
82
|
+
|
83
|
+
});
|
84
|
+
})
|
41
85
|
|
86
|
+
}
|
42
87
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
88
|
+
_updateProjectUser(id_user, id_project, operation) {
|
89
|
+
winston.debug("Route queue updateProjectUser start operation: " + operation + "id_user " + id_user + " id_project " + id_project);
|
90
|
+
return Project_user
|
91
|
+
.findOneAndUpdate({ id_user: id_user, id_project: id_project }, { $inc: { 'number_assigned_requests': operation } }, { new: true, upsert: false }, function (err, updatedPU) {
|
92
|
+
if (err) {
|
93
|
+
return winston.error(err);
|
94
|
+
}
|
95
|
+
winston.debug("Route queue number_assigned_requests +1 :" + updatedPU.id);
|
96
|
+
winston.debug("Route queue number_assigned_requests +1 :" + updatedPU.id);
|
52
97
|
|
53
|
-
|
98
|
+
updatedPU.populate({ path: 'id_user', select: { 'firstname': 1, 'lastname': 1 } }, function (err, updatedProject_userPopulated) {
|
54
99
|
|
55
|
-
|
100
|
+
var pu = updatedProject_userPopulated.toJSON();
|
56
101
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
authEvent.emit('project_user.update', {updatedProject_userPopulated:pu, req: undefined, skipArchive: true}); //if queued with jobs -> websocket notification on project_user.update doesn't work??? forse si in quanto viene convertito in .pub.queue e poi rifunziiona
|
102
|
+
return Project.findById(id_project).exec(function (err, project) {
|
103
|
+
pu.isBusy = ProjectUserUtil.isBusy(updatedProject_userPopulated, project.settings && project.settings.max_agent_assigned_chat);
|
104
|
+
winston.debug("Route queue pu.isBusy: " + pu.isBusy);
|
62
105
|
|
106
|
+
authEvent.emit('project_user.update', { updatedProject_userPopulated: pu, req: undefined, skipArchive: true }); //if queued with jobs -> websocket notification on project_user.update doesn't work??? forse si in quanto viene convertito in .pub.queue e poi rifunziiona
|
63
107
|
|
64
|
-
// project_user.update triggers activityArchiver(tested), cache invalidation(tested), subscriptionNotifierQueued and websocket(tested works from queue i trigger ws)
|
65
|
-
if (requestEvent.queueEnabled) { //force to .queue to be catched into the queue (activity archiver, subscriptionNotifierQueued )
|
66
|
-
authEvent.emit('project_user.update.queue', {updatedProject_userPopulated:pu, req: undefined, skipArchive: true});
|
67
|
-
}
|
68
108
|
|
69
|
-
|
70
|
-
|
71
|
-
|
109
|
+
// project_user.update triggers activityArchiver(tested), cache invalidation(tested), subscriptionNotifierQueued and websocket(tested works from queue i trigger ws)
|
110
|
+
if (requestEvent.queueEnabled) { //force to .queue to be catched into the queue (activity archiver, subscriptionNotifierQueued )
|
111
|
+
authEvent.emit('project_user.update.queue', { updatedProject_userPopulated: pu, req: undefined, skipArchive: true });
|
112
|
+
}
|
72
113
|
|
73
|
-
|
74
|
-
|
114
|
+
})
|
115
|
+
|
116
|
+
});
|
117
|
+
|
118
|
+
});
|
119
|
+
}
|
75
120
|
|
76
121
|
updateParticipatingProjectUsers(request, operation) {
|
77
122
|
winston.debug("Route queue request.participatingAgents", request.participatingAgents);
|
package/routes/faq_kb.js
CHANGED
package/routes/kb.js
CHANGED
@@ -466,7 +466,7 @@ router.get('/namespace/:id/chatbots', async (req, res) => {
|
|
466
466
|
|
467
467
|
let project_id = req.projectid;
|
468
468
|
let namespace_id = req.params.id;
|
469
|
-
|
469
|
+
|
470
470
|
let chatbotsArray = [];
|
471
471
|
|
472
472
|
let namespaces = await Namespace.find({ id_project: project_id }).catch((err) => {
|
@@ -492,6 +492,7 @@ router.get('/namespace/:id/chatbots', async (req, res) => {
|
|
492
492
|
let chatbots = intents.map(i => i.id_faq_kb);
|
493
493
|
let uniqueChatbots = [...new Set(chatbots)];
|
494
494
|
|
495
|
+
|
495
496
|
let chatbotPromises = uniqueChatbots.map(async (c_id) => {
|
496
497
|
try {
|
497
498
|
let chatbot = await faq_kb.findOne({ _id: c_id, trashed: false });
|
package/routes/message.js
CHANGED
@@ -181,77 +181,82 @@ async (req, res) => {
|
|
181
181
|
requester: project_user,
|
182
182
|
priority: req.body.priority,
|
183
183
|
followers: req.body.followers,
|
184
|
+
proactive: true
|
184
185
|
};
|
185
186
|
|
186
187
|
return requestService.create(new_request).then(function (savedRequest) {
|
187
188
|
|
189
|
+
|
190
|
+
if (!savedRequest) {
|
191
|
+
return res.status(403).send({ success: false, message: "Requests quota exceeded"})
|
192
|
+
}
|
188
193
|
winston.debug("returning savedRequest to", savedRequest.toJSON());
|
189
194
|
|
190
195
|
// createWithIdAndRequester(request_id, project_user_id, lead_id, id_project, first_text, departmentid, sourcePage, language, userAgent, status,
|
191
196
|
// createdBy, attributes, subject, preflight, channel, location) {
|
192
|
-
|
193
|
-
// return requestService.createWithIdAndRequester(req.params.request_id, req.projectuser._id, createdLead._id, req.projectid,
|
194
|
-
// req.body.text, req.body.departmentid, req.body.sourcePage,
|
195
|
-
// req.body.language, req.body.userAgent, null, req.user._id, req.body.attributes, req.body.subject, undefined, req.body.channel, req.body.location ).then(function (savedRequest) {
|
196
197
|
|
198
|
+
// return requestService.createWithIdAndRequester(req.params.request_id, req.projectuser._id, createdLead._id, req.projectid,
|
199
|
+
// req.body.text, req.body.departmentid, req.body.sourcePage,
|
200
|
+
// req.body.language, req.body.userAgent, null, req.user._id, req.body.attributes, req.body.subject, undefined, req.body.channel, req.body.location ).then(function (savedRequest) {
|
197
201
|
|
198
|
-
|
199
|
-
|
200
|
-
// create(sender, senderFullname, recipient, text, id_project, createdBy, status, attributes, type, metadata, language, channel_type, channel) {
|
201
|
-
return messageService.create(sender || req.user._id, fullname, req.params.request_id, req.body.text,
|
202
|
-
req.projectid, req.user._id, messageStatus, req.body.attributes, req.body.type, req.body.metadata, req.body.language, undefined, req.body.channel).then(function(savedMessage){
|
203
|
-
|
204
|
-
// return requestService.incrementMessagesCountByRequestId(savedRequest.request_id, savedRequest.id_project).then(function(savedRequestWithIncrement) {
|
205
202
|
|
206
|
-
let message = savedMessage.toJSON();
|
207
203
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
.populate({path:'requester',populate:{path:'id_user'}})
|
221
|
-
// .exec(function (err, savedRequestPopulated){
|
222
|
-
.execPopulate(function (err, savedRequestPopulated){ //bug with execPopulate request.attributes are invalid (NOT real data). but this bug is related to chat21 listener changes by reference. i think populate suffer from this problem bacause it it the same obect passed by reference
|
223
|
-
|
224
|
-
if (err) {
|
225
|
-
return winston.error("Error gettting savedRequestPopulated for send Message", err);
|
226
|
-
}
|
227
|
-
|
228
|
-
winston.debug("returning savedRequest221 to", savedRequest.toJSON());
|
204
|
+
|
205
|
+
// create(sender, senderFullname, recipient, text, id_project, createdBy, status, attributes, type, metadata, language, channel_type, channel) {
|
206
|
+
return messageService.create(sender || req.user._id, fullname, req.params.request_id, req.body.text,
|
207
|
+
req.projectid, req.user._id, messageStatus, req.body.attributes, req.body.type, req.body.metadata, req.body.language, undefined, req.body.channel).then(function (savedMessage) {
|
208
|
+
|
209
|
+
// return requestService.incrementMessagesCountByRequestId(savedRequest.request_id, savedRequest.id_project).then(function(savedRequestWithIncrement) {
|
210
|
+
|
211
|
+
let message = savedMessage.toJSON();
|
212
|
+
|
213
|
+
winston.debug("returning message to", message);
|
214
|
+
|
215
|
+
winston.debug("returning savedRequest2210 to", savedRequest.toJSON());
|
229
216
|
|
230
217
|
|
231
|
-
|
218
|
+
savedRequest //bug
|
219
|
+
// Request.findById(savedRequest.id)
|
220
|
+
.populate('lead')
|
221
|
+
.populate('department')
|
222
|
+
.populate('participatingBots')
|
223
|
+
.populate('participatingAgents')
|
224
|
+
// .populate('followers')
|
225
|
+
.populate({ path: 'requester', populate: { path: 'id_user' } })
|
226
|
+
// .exec(function (err, savedRequestPopulated){
|
227
|
+
.execPopulate(function (err, savedRequestPopulated) { //bug with execPopulate request.attributes are invalid (NOT real data). but this bug is related to chat21 listener changes by reference. i think populate suffer from this problem bacause it it the same obect passed by reference
|
232
228
|
|
233
|
-
|
229
|
+
if (err) {
|
230
|
+
return winston.error("Error gettting savedRequestPopulated for send Message", err);
|
231
|
+
}
|
234
232
|
|
233
|
+
winston.debug("returning savedRequest221 to", savedRequest.toJSON());
|
235
234
|
|
236
|
-
message.request = savedRequestPopulated;
|
237
|
-
winston.debug("returning2 message to", message);
|
238
235
|
|
236
|
+
winston.debug("savedRequestPopulated", savedRequestPopulated.toJSON());
|
239
237
|
|
240
|
-
|
241
|
-
|
238
|
+
winston.debug("returning savedRequest22 to", savedRequest.toJSON());
|
239
|
+
|
240
|
+
|
241
|
+
message.request = savedRequestPopulated;
|
242
|
+
winston.debug("returning2 message to", message);
|
243
|
+
|
244
|
+
|
245
|
+
return res.json(message);
|
242
246
|
});
|
243
|
-
})
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
// winston.error("Error creating message", err);
|
251
|
-
return res.status(500).send({success: false, msg: 'Error creating request', err:err });
|
252
|
-
});
|
253
|
-
|
247
|
+
});
|
248
|
+
}).catch(function (err) { //pubblica questo
|
249
|
+
winston.error('Error creating request: ' + JSON.stringify(err));
|
250
|
+
winston.log({
|
251
|
+
level: 'error',
|
252
|
+
message: 'Error creating request: ' + JSON.stringify(err) + " " + JSON.stringify(req.body),
|
253
|
+
label: req.projectid
|
254
254
|
});
|
255
|
+
// winston.error("Error creating message", err);
|
256
|
+
return res.status(500).send({ success: false, msg: 'Error creating request', err: err });
|
257
|
+
});
|
258
|
+
|
259
|
+
});
|
255
260
|
|
256
261
|
|
257
262
|
|