@tiledesk/tiledesk-server 2.10.99 โ 2.10.101
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/CHANGELOG.md +13 -0
- package/app.js +2 -0
- package/middleware/has-role.js +1 -0
- package/models/flowLogs.js +15 -0
- package/models/kb_setting.js +32 -5
- package/package.json +3 -3
- package/routes/kb.js +1 -1
- package/routes/logs.js +15 -14
- package/routes/request.js +6 -3
- package/routes/unanswered.js +256 -0
- package/services/departmentService.js +4 -2
- package/services/logsService.js +24 -6
- package/services/webhookService.js +3 -0
- package/test/kbRoute.js +286 -522
package/CHANGELOG.md
CHANGED
@@ -5,6 +5,19 @@
|
|
5
5
|
๐ IN PRODUCTION ๐
|
6
6
|
(https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
|
7
7
|
|
8
|
+
# 2.10.101
|
9
|
+
- Update: messenger-connector to 0.1.27
|
10
|
+
- Update: multi-worker to 0.3.3
|
11
|
+
- Added: endpoints for unanswered questions
|
12
|
+
- Update: endppoints to static logs
|
13
|
+
- Improved knowledge base import/export
|
14
|
+
|
15
|
+
# 2.10.100
|
16
|
+
- Update: removed verbose logs
|
17
|
+
|
18
|
+
# 2.10.99
|
19
|
+
- Update: messenger-connector to 0.1.24
|
20
|
+
|
8
21
|
# 2.10.98
|
9
22
|
- Update: whatsapp-connector to 0.1.84
|
10
23
|
|
package/app.js
CHANGED
@@ -127,6 +127,7 @@ var quotes = require('./routes/quotes');
|
|
127
127
|
var integration = require('./routes/integration')
|
128
128
|
var kbsettings = require('./routes/kbsettings');
|
129
129
|
var kb = require('./routes/kb');
|
130
|
+
var unanswered = require('./routes/unanswered');
|
130
131
|
|
131
132
|
// var admin = require('./routes/admin');
|
132
133
|
var faqpub = require('./routes/faqpub');
|
@@ -614,6 +615,7 @@ app.use('/:projectid/quotes', [passport.authenticate(['basic', 'jwt'], { session
|
|
614
615
|
app.use('/:projectid/integration', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('admin', ['bot','subscription'])], integration )
|
615
616
|
|
616
617
|
app.use('/:projectid/kbsettings', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], kbsettings);
|
618
|
+
app.use('/:projectid/kb/unanswered', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('admin', ['bot','subscription'])], unanswered);
|
617
619
|
app.use('/:projectid/kb', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('admin', ['bot','subscription'])], kb);
|
618
620
|
|
619
621
|
app.use('/:projectid/logs', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], logs);
|
package/middleware/has-role.js
CHANGED
package/models/flowLogs.js
CHANGED
@@ -29,6 +29,18 @@ const FlowLogsSchema = new Schema(
|
|
29
29
|
type: String,
|
30
30
|
required: false,
|
31
31
|
},
|
32
|
+
webhook_id: {
|
33
|
+
type: String,
|
34
|
+
required: false,
|
35
|
+
},
|
36
|
+
shortExp: {
|
37
|
+
type: Date,
|
38
|
+
required: false
|
39
|
+
},
|
40
|
+
longExp: {
|
41
|
+
type: Date,
|
42
|
+
required: false
|
43
|
+
},
|
32
44
|
level: {
|
33
45
|
type: String,
|
34
46
|
required: true,
|
@@ -43,6 +55,9 @@ const FlowLogsSchema = new Schema(
|
|
43
55
|
);
|
44
56
|
|
45
57
|
FlowLogsSchema.index({ request_id: 1 }, { unique: true });
|
58
|
+
FlowLogsSchema.index({ webhook_id: 1 });
|
59
|
+
FlowLogsSchema.index({ shortExp: 1 }, { expireAfterSeconds: 300 }); // 5 minutes
|
60
|
+
FlowLogsSchema.index({ longExp: 1 }, { expireAfterSeconds: 1800 }); // 30 minutes
|
46
61
|
|
47
62
|
// FlowLogsSchema.pre('findOneAndUpdate', async function (next) {
|
48
63
|
// const update = this.getUpdate();
|
package/models/kb_setting.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
var mongoose = require('mongoose');
|
2
2
|
var Schema = mongoose.Schema;
|
3
3
|
var winston = require('../config/winston');
|
4
|
+
let expireAfterSeconds = process.env.UNANSWERED_QUESTION_EXPIRATION_TIME || 7 * 24 * 60 * 60; // 7 days
|
4
5
|
|
5
6
|
var EngineSchema = new Schema({
|
6
7
|
name: {
|
@@ -122,7 +123,35 @@ var KBSchema = new Schema({
|
|
122
123
|
timestamps: true
|
123
124
|
})
|
124
125
|
|
126
|
+
const UnansweredQuestionSchema = new Schema({
|
127
|
+
id_project: {
|
128
|
+
type: String,
|
129
|
+
required: true,
|
130
|
+
index: true
|
131
|
+
},
|
132
|
+
namespace: {
|
133
|
+
type: String,
|
134
|
+
required: true,
|
135
|
+
index: true
|
136
|
+
},
|
137
|
+
question: {
|
138
|
+
type: String,
|
139
|
+
required: true
|
140
|
+
},
|
141
|
+
created_at: {
|
142
|
+
type: Date,
|
143
|
+
default: Date.now
|
144
|
+
},
|
145
|
+
updated_at: {
|
146
|
+
type: Date,
|
147
|
+
default: Date.now
|
148
|
+
}
|
149
|
+
},{
|
150
|
+
timestamps: true
|
151
|
+
});
|
125
152
|
|
153
|
+
// Add TTL index to automatically delete documents after 30 days
|
154
|
+
UnansweredQuestionSchema.index({ created_at: 1 }, { expireAfterSeconds: expireAfterSeconds }); // 30 days
|
126
155
|
|
127
156
|
// DEPRECATED !! - Start
|
128
157
|
var KBSettingSchema = new Schema({
|
@@ -158,15 +187,13 @@ const KBSettings = mongoose.model('KBSettings', KBSettingSchema);
|
|
158
187
|
const Engine = mongoose.model('Engine', EngineSchema)
|
159
188
|
const Namespace = mongoose.model('Namespace', NamespaceSchema)
|
160
189
|
const KB = mongoose.model('KB', KBSchema)
|
190
|
+
const UnansweredQuestion = mongoose.model('UnansweredQuestion', UnansweredQuestionSchema)
|
161
191
|
|
162
|
-
// module.exports = {
|
163
|
-
// KBSettings: KBSettings,
|
164
|
-
// KB: KB
|
165
|
-
// }
|
166
192
|
|
167
193
|
module.exports = {
|
168
194
|
KBSettings: KBSettings,
|
169
195
|
Namespace: Namespace,
|
170
196
|
Engine: Engine,
|
171
|
-
KB: KB
|
197
|
+
KB: KB,
|
198
|
+
UnansweredQuestion: UnansweredQuestion
|
172
199
|
}
|
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.10.
|
4
|
+
"version": "2.10.101",
|
5
5
|
"scripts": {
|
6
6
|
"start": "node ./bin/www",
|
7
7
|
"pretest": "mongodb-runner start",
|
@@ -44,7 +44,7 @@
|
|
44
44
|
"@tiledesk/tiledesk-dialogflow-connector": "^1.8.4",
|
45
45
|
"@tiledesk/tiledesk-json-rules-engine": "^4.0.3",
|
46
46
|
"@tiledesk/tiledesk-kaleyra-proxy": "^0.1.7",
|
47
|
-
"@tiledesk/tiledesk-messenger-connector": "^0.1.
|
47
|
+
"@tiledesk/tiledesk-messenger-connector": "^0.1.27",
|
48
48
|
"@tiledesk/tiledesk-rasa-connector": "^1.0.10",
|
49
49
|
"@tiledesk/tiledesk-telegram-connector": "^0.1.14",
|
50
50
|
"@tiledesk/tiledesk-tybot-connector": "^2.0.19",
|
@@ -53,7 +53,7 @@
|
|
53
53
|
"@tiledesk/tiledesk-sms-connector": "^0.1.11",
|
54
54
|
"@tiledesk/tiledesk-vxml-connector": "^0.1.76",
|
55
55
|
"@tiledesk/tiledesk-voice-twilio-connector": "^0.1.22",
|
56
|
-
"@tiledesk/tiledesk-multi-worker": "^0.3.
|
56
|
+
"@tiledesk/tiledesk-multi-worker": "^0.3.3",
|
57
57
|
"passport-oauth2": "^1.8.0",
|
58
58
|
"amqplib": "^0.5.5",
|
59
59
|
"app-root-path": "^3.0.0",
|
package/routes/kb.js
CHANGED
@@ -790,7 +790,7 @@ router.post('/namespace/import/:id', upload.single('uploadFile'), async (req, re
|
|
790
790
|
});
|
791
791
|
}
|
792
792
|
|
793
|
-
let deleteResponse = await KB.deleteMany({ id_project: id_project, namespace: namespace_id }).catch((err) => {
|
793
|
+
let deleteResponse = await KB.deleteMany({ id_project: id_project, namespace: namespace_id, type: { $in: ['url', 'text', 'faq'] } }).catch((err) => {
|
794
794
|
winston.error("deleteMany error: ", err);
|
795
795
|
return res.status(500).send({ success: false, error: err });
|
796
796
|
})
|
package/routes/logs.js
CHANGED
@@ -87,35 +87,36 @@ router.post('/whatsapp', async (req, res) => {
|
|
87
87
|
})
|
88
88
|
|
89
89
|
|
90
|
-
router.get('/flows/:
|
90
|
+
router.get('/flows/:id', async (req, res) => {
|
91
|
+
const id = req.params.id;
|
92
|
+
const { timestamp, direction, logLevel, type } = req.query;
|
91
93
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
if (!request_id) {
|
96
|
-
return res.status(400).send({ success: false, error: "Missing required parameter 'request_id'." });
|
94
|
+
if (!id) {
|
95
|
+
return res.status(400).send({ success: false, error: "Missing required parameter 'id'." });
|
97
96
|
}
|
98
97
|
|
98
|
+
// Determine if we're searching by request_id or webhook_id
|
99
|
+
const isWebhook = type === 'webhook';
|
100
|
+
const queryField = isWebhook ? 'webhook_id' : 'request_id';
|
101
|
+
|
99
102
|
let method;
|
100
103
|
|
101
104
|
if (!timestamp) {
|
102
|
-
method = logsService.getLastRows(
|
105
|
+
method = logsService.getLastRows(id, 20, logLevel, queryField);
|
103
106
|
} else if (direction === 'prev') {
|
104
|
-
logsService.
|
105
|
-
method = logsService.getOlderRows(request_id, 10, logLevel, new Date(timestamp));
|
107
|
+
method = logsService.getOlderRows(id, 10, logLevel, new Date(timestamp), queryField);
|
106
108
|
} else if (direction === 'next') {
|
107
|
-
method = logsService.getNewerRows(
|
109
|
+
method = logsService.getNewerRows(id, 10, logLevel, new Date(timestamp), queryField);
|
108
110
|
} else {
|
109
|
-
return res.status(400).send({ success: false, error: "Missing or invalid 'direction' parameter. Use 'prev' or 'next'."})
|
111
|
+
return res.status(400).send({ success: false, error: "Missing or invalid 'direction' parameter. Use 'prev' or 'next'."});
|
110
112
|
}
|
111
113
|
|
112
114
|
method.then((logs) => {
|
113
115
|
res.status(200).send(logs);
|
114
116
|
}).catch((err) => {
|
115
117
|
res.status(500).send({ success: false, error: "Error fetching logs: " + err.message });
|
116
|
-
})
|
117
|
-
|
118
|
-
})
|
118
|
+
});
|
119
|
+
});
|
119
120
|
|
120
121
|
|
121
122
|
router.get('/flows/auth/:request_id', async (req, res) => {
|
package/routes/request.js
CHANGED
@@ -569,7 +569,8 @@ router.put('/:requestid/assign', function (req, res) {
|
|
569
569
|
|
570
570
|
return res.json(updatedRequest);
|
571
571
|
}).catch(function (error) {
|
572
|
-
|
572
|
+
// TODO: error log removed due to attempt to reduces logs when no department is found
|
573
|
+
winston.verbose('Error changing the department.', error)
|
573
574
|
return res.status(500).send({ success: false, msg: 'Error changing the department.' });
|
574
575
|
})
|
575
576
|
});
|
@@ -585,7 +586,8 @@ router.put('/:requestid/departments', function (req, res) {
|
|
585
586
|
|
586
587
|
return res.json(updatedRequest);
|
587
588
|
}).catch(function (error) {
|
588
|
-
|
589
|
+
// TODO: error log removed due to attempt to reduces logs when no department is found
|
590
|
+
winston.verbose('Error changing the department.', error)
|
589
591
|
return res.status(500).send({ success: false, msg: 'Error changing the department.' });
|
590
592
|
})
|
591
593
|
});
|
@@ -619,7 +621,8 @@ router.put('/:requestid/agent', async (req, res) => {
|
|
619
621
|
|
620
622
|
return res.json(updatedRequest);
|
621
623
|
}).catch(function (error) {
|
622
|
-
|
624
|
+
// TODO: error log removed due to attempt to reduces logs when no department is found
|
625
|
+
winston.verbose('Error changing the department.', error)
|
623
626
|
return res.status(500).send({ success: false, msg: 'Error changing the department.' });
|
624
627
|
})
|
625
628
|
|
@@ -0,0 +1,256 @@
|
|
1
|
+
const express = require('express');
|
2
|
+
const router = express.Router();
|
3
|
+
const { Namespace, UnansweredQuestion } = require('../models/kb_setting');
|
4
|
+
var winston = require('../config/winston');
|
5
|
+
|
6
|
+
// Add a new unanswered question
|
7
|
+
router.post('/', async (req, res) => {
|
8
|
+
try {
|
9
|
+
const { namespace, question } = req.body;
|
10
|
+
const id_project = req.projectid;
|
11
|
+
|
12
|
+
if (!namespace || !question) {
|
13
|
+
return res.status(400).json({
|
14
|
+
success: false,
|
15
|
+
error: "Missing required parameters: namespace and question"
|
16
|
+
});
|
17
|
+
}
|
18
|
+
|
19
|
+
// Check if namespace belongs to project
|
20
|
+
const isValidNamespace = await validateNamespace(id_project, namespace);
|
21
|
+
if (!isValidNamespace) {
|
22
|
+
return res.status(403).json({
|
23
|
+
success: false,
|
24
|
+
error: "Not allowed. The namespace does not belong to the current project."
|
25
|
+
});
|
26
|
+
}
|
27
|
+
|
28
|
+
const unansweredQuestion = new UnansweredQuestion({
|
29
|
+
id_project,
|
30
|
+
namespace,
|
31
|
+
question
|
32
|
+
});
|
33
|
+
|
34
|
+
const savedQuestion = await unansweredQuestion.save();
|
35
|
+
res.status(200).json(savedQuestion);
|
36
|
+
|
37
|
+
} catch (error) {
|
38
|
+
winston.error('Error adding unanswered question:', error);
|
39
|
+
res.status(500).json({
|
40
|
+
success: false,
|
41
|
+
error: "Error adding unanswered question"
|
42
|
+
});
|
43
|
+
}
|
44
|
+
});
|
45
|
+
|
46
|
+
// Get all unanswered questions for a namespace
|
47
|
+
router.get('/:namespace', async (req, res) => {
|
48
|
+
try {
|
49
|
+
const { namespace } = req.params;
|
50
|
+
const id_project = req.projectid;
|
51
|
+
|
52
|
+
if (!namespace) {
|
53
|
+
return res.status(400).json({
|
54
|
+
success: false,
|
55
|
+
error: "Missing required parameter: namespace"
|
56
|
+
});
|
57
|
+
}
|
58
|
+
|
59
|
+
// Check if namespace belongs to project
|
60
|
+
const isValidNamespace = await validateNamespace(id_project, namespace);
|
61
|
+
if (!isValidNamespace) {
|
62
|
+
return res.status(403).json({
|
63
|
+
success: false,
|
64
|
+
error: "Not allowed. The namespace does not belong to the current project."
|
65
|
+
});
|
66
|
+
}
|
67
|
+
|
68
|
+
const page = parseInt(req.query.page) || 0;
|
69
|
+
const limit = parseInt(req.query.limit) || 20;
|
70
|
+
const sortField = req.query.sortField || 'created_at';
|
71
|
+
const direction = parseInt(req.query.direction) || -1;
|
72
|
+
|
73
|
+
const questions = await UnansweredQuestion.find({
|
74
|
+
id_project,
|
75
|
+
namespace
|
76
|
+
})
|
77
|
+
.sort({ [sortField]: direction })
|
78
|
+
.skip(page * limit)
|
79
|
+
.limit(limit);
|
80
|
+
|
81
|
+
const count = await UnansweredQuestion.countDocuments({
|
82
|
+
id_project,
|
83
|
+
namespace
|
84
|
+
});
|
85
|
+
|
86
|
+
res.status(200).json({
|
87
|
+
count,
|
88
|
+
questions,
|
89
|
+
query: {
|
90
|
+
page,
|
91
|
+
limit,
|
92
|
+
sortField,
|
93
|
+
direction
|
94
|
+
}
|
95
|
+
});
|
96
|
+
|
97
|
+
} catch (error) {
|
98
|
+
winston.error('Error getting unanswered questions:', error);
|
99
|
+
res.status(500).json({
|
100
|
+
success: false,
|
101
|
+
error: "Error getting unanswered questions"
|
102
|
+
});
|
103
|
+
}
|
104
|
+
});
|
105
|
+
|
106
|
+
// Delete a specific unanswered question
|
107
|
+
router.delete('/:id', async (req, res) => {
|
108
|
+
try {
|
109
|
+
const { id } = req.params;
|
110
|
+
const id_project = req.projectid;
|
111
|
+
|
112
|
+
const question = await UnansweredQuestion.findOne({ _id: id, id_project });
|
113
|
+
if (!question) {
|
114
|
+
return res.status(404).json({
|
115
|
+
success: false,
|
116
|
+
error: "Question not found"
|
117
|
+
});
|
118
|
+
}
|
119
|
+
|
120
|
+
await UnansweredQuestion.deleteOne({ _id: id });
|
121
|
+
res.status(200).json({
|
122
|
+
success: true,
|
123
|
+
message: "Question deleted successfully"
|
124
|
+
});
|
125
|
+
|
126
|
+
} catch (error) {
|
127
|
+
winston.error('Error deleting unanswered question:', error);
|
128
|
+
res.status(500).json({
|
129
|
+
success: false,
|
130
|
+
error: "Error deleting unanswered question"
|
131
|
+
});
|
132
|
+
}
|
133
|
+
});
|
134
|
+
|
135
|
+
// Delete all unanswered questions for a namespace
|
136
|
+
router.delete('/namespace/:namespace', async (req, res) => {
|
137
|
+
try {
|
138
|
+
const { namespace } = req.params;
|
139
|
+
const id_project = req.projectid;
|
140
|
+
|
141
|
+
// Check if namespace belongs to project
|
142
|
+
const isValidNamespace = await validateNamespace(id_project, namespace);
|
143
|
+
if (!isValidNamespace) {
|
144
|
+
return res.status(403).json({
|
145
|
+
success: false,
|
146
|
+
error: "Not allowed. The namespace does not belong to the current project."
|
147
|
+
});
|
148
|
+
}
|
149
|
+
|
150
|
+
const result = await UnansweredQuestion.deleteMany({ id_project, namespace });
|
151
|
+
res.status(200).json({
|
152
|
+
success: true,
|
153
|
+
count: result.deletedCount,
|
154
|
+
message: "All questions deleted successfully"
|
155
|
+
});
|
156
|
+
|
157
|
+
} catch (error) {
|
158
|
+
winston.error('Error deleting unanswered questions:', error);
|
159
|
+
res.status(500).json({
|
160
|
+
success: false,
|
161
|
+
error: "Error deleting unanswered questions"
|
162
|
+
});
|
163
|
+
}
|
164
|
+
});
|
165
|
+
|
166
|
+
// Update an unanswered question
|
167
|
+
router.put('/:id', async (req, res) => {
|
168
|
+
try {
|
169
|
+
const { id } = req.params;
|
170
|
+
const { question } = req.body;
|
171
|
+
const id_project = req.projectid;
|
172
|
+
|
173
|
+
if (!question) {
|
174
|
+
return res.status(400).json({
|
175
|
+
success: false,
|
176
|
+
error: "Missing required parameter: question"
|
177
|
+
});
|
178
|
+
}
|
179
|
+
|
180
|
+
const updatedQuestion = await UnansweredQuestion.findOneAndUpdate(
|
181
|
+
{ _id: id, id_project },
|
182
|
+
{ question },
|
183
|
+
{ new: true }
|
184
|
+
);
|
185
|
+
|
186
|
+
if (!updatedQuestion) {
|
187
|
+
return res.status(404).json({
|
188
|
+
success: false,
|
189
|
+
error: "Question not found"
|
190
|
+
});
|
191
|
+
}
|
192
|
+
|
193
|
+
res.status(200).json(updatedQuestion);
|
194
|
+
|
195
|
+
} catch (error) {
|
196
|
+
winston.error('Error updating unanswered question:', error);
|
197
|
+
res.status(500).json({
|
198
|
+
success: false,
|
199
|
+
error: "Error updating unanswered question"
|
200
|
+
});
|
201
|
+
}
|
202
|
+
});
|
203
|
+
|
204
|
+
// Count unanswered questions for a namespace
|
205
|
+
router.get('/count/:namespace', async (req, res) => {
|
206
|
+
try {
|
207
|
+
const { namespace } = req.params;
|
208
|
+
const id_project = req.projectid;
|
209
|
+
|
210
|
+
if (!namespace) {
|
211
|
+
return res.status(400).json({
|
212
|
+
success: false,
|
213
|
+
error: "Missing required parameter: namespace"
|
214
|
+
});
|
215
|
+
}
|
216
|
+
|
217
|
+
// Check if namespace belongs to project
|
218
|
+
const isValidNamespace = await validateNamespace(id_project, namespace);
|
219
|
+
if (!isValidNamespace) {
|
220
|
+
return res.status(403).json({
|
221
|
+
success: false,
|
222
|
+
error: "Not allowed. The namespace does not belong to the current project."
|
223
|
+
});
|
224
|
+
}
|
225
|
+
|
226
|
+
const count = await UnansweredQuestion.countDocuments({
|
227
|
+
id_project,
|
228
|
+
namespace
|
229
|
+
});
|
230
|
+
|
231
|
+
res.status(200).json({ count });
|
232
|
+
|
233
|
+
} catch (error) {
|
234
|
+
winston.error('Error counting unanswered questions:', error);
|
235
|
+
res.status(500).json({
|
236
|
+
success: false,
|
237
|
+
error: "Error counting unanswered questions"
|
238
|
+
});
|
239
|
+
}
|
240
|
+
});
|
241
|
+
|
242
|
+
// Helper function to validate namespace
|
243
|
+
async function validateNamespace(id_project, namespace_id) {
|
244
|
+
try {
|
245
|
+
const namespace = await Namespace.findOne({
|
246
|
+
id_project: id_project,
|
247
|
+
namespace: namespace_id
|
248
|
+
});
|
249
|
+
return !!namespace; // return true if namespace exists, false otherwise
|
250
|
+
} catch (err) {
|
251
|
+
winston.error("validate namespace error: ", err);
|
252
|
+
throw err;
|
253
|
+
}
|
254
|
+
}
|
255
|
+
|
256
|
+
module.exports = router;
|
@@ -240,7 +240,8 @@ getOperators(departmentid, projectid, nobot, disableWebHookCall, context) {
|
|
240
240
|
}
|
241
241
|
// console.log("department", department);
|
242
242
|
if (!department) {
|
243
|
-
|
243
|
+
// TODO: error log removed due to attempt to reduces logs when no department is found
|
244
|
+
winston.verbose("Department not found for projectid: "+ projectid +" for query: ", query, context);
|
244
245
|
return reject({ success: false, msg: 'Department not found for projectid: '+ projectid +' for query: ' + JSON.stringify(query) });
|
245
246
|
}
|
246
247
|
// console.log('OPERATORS - ยปยปยป DETECTED ROUTING ', department.routing)
|
@@ -562,7 +563,8 @@ getDefaultDepartment(projectid) {
|
|
562
563
|
}
|
563
564
|
// console.log("department", department);
|
564
565
|
if (!department) {
|
565
|
-
|
566
|
+
// TODO: error log removed due to attempt to reduces logs when no department is found
|
567
|
+
winston.verbose("Department not found for projectid: "+ projectid +" for query: ", query, context);
|
566
568
|
return reject({ success: false, msg: 'Department not found for projectid: '+ projectid +' for query: ' + JSON.stringify(query) });
|
567
569
|
}
|
568
570
|
winston.debug('department ', department);
|
package/services/logsService.js
CHANGED
@@ -7,14 +7,20 @@ const levels = { error: 0, warn: 1, info: 2, debug: 3, native: 4 };
|
|
7
7
|
|
8
8
|
class LogsService {
|
9
9
|
|
10
|
-
async getLastRows(
|
10
|
+
async getLastRows(id, limit, logLevel, queryField = 'request_id') {
|
11
11
|
let level = logLevel || default_log_level;
|
12
12
|
if (level === 'default') {
|
13
13
|
level = default_log_level
|
14
14
|
}
|
15
15
|
let nlevel = levels[level];
|
16
|
+
|
17
|
+
// Build match condition based on queryField
|
18
|
+
const matchCondition = queryField === 'webhook_id'
|
19
|
+
? { [queryField]: id, longExp: { $exists: true } }
|
20
|
+
: { [queryField]: id };
|
21
|
+
|
16
22
|
return FlowLogs.aggregate([
|
17
|
-
{ $match:
|
23
|
+
{ $match: matchCondition },
|
18
24
|
{ $unwind: "$rows" },
|
19
25
|
{ $match: { "rows.nlevel": { $lte: nlevel } } },
|
20
26
|
{ $sort: { "rows.timestamp": -1, "rows._id": -1 } },
|
@@ -22,14 +28,20 @@ class LogsService {
|
|
22
28
|
]).then(rows => rows.reverse())
|
23
29
|
}
|
24
30
|
|
25
|
-
async getOlderRows(
|
31
|
+
async getOlderRows(id, limit, logLevel, timestamp, queryField = 'request_id') {
|
26
32
|
let level = logLevel || default_log_level;
|
27
33
|
if (level === 'default') {
|
28
34
|
level = default_log_level
|
29
35
|
}
|
30
36
|
let nlevel = levels[level];
|
37
|
+
|
38
|
+
// Build match condition based on queryField
|
39
|
+
const matchCondition = queryField === 'webhook_id'
|
40
|
+
? { [queryField]: id, longExp: { $exists: true } }
|
41
|
+
: { [queryField]: id };
|
42
|
+
|
31
43
|
return FlowLogs.aggregate([
|
32
|
-
{ $match:
|
44
|
+
{ $match: matchCondition },
|
33
45
|
{ $unwind: "$rows" },
|
34
46
|
{ $match: { "rows.nlevel": { $lte: nlevel }, "rows.timestamp": { $lt: timestamp } } },
|
35
47
|
{ $sort: { "rows.timestamp": -1, "rows._id": -1 } },
|
@@ -37,14 +49,20 @@ class LogsService {
|
|
37
49
|
]).then(rows => rows.reverse())
|
38
50
|
}
|
39
51
|
|
40
|
-
async getNewerRows(
|
52
|
+
async getNewerRows(id, limit, logLevel, timestamp, queryField = 'request_id') {
|
41
53
|
let level = logLevel || default_log_level;
|
42
54
|
if (level === 'default') {
|
43
55
|
level = default_log_level
|
44
56
|
}
|
45
57
|
let nlevel = levels[level];
|
58
|
+
|
59
|
+
// Build match condition based on queryField
|
60
|
+
const matchCondition = queryField === 'webhook_id'
|
61
|
+
? { [queryField]: id, longExp: { $exists: true } }
|
62
|
+
: { [queryField]: id };
|
63
|
+
|
46
64
|
return FlowLogs.aggregate([
|
47
|
-
{ $match:
|
65
|
+
{ $match: matchCondition },
|
48
66
|
{ $unwind: "$rows" },
|
49
67
|
{ $match: { "rows.nlevel": { $lte: nlevel }, "rows.timestamp": { $gt: timestamp } } },
|
50
68
|
{ $sort: { "rows.timestamp": 1, "rows._id": 1 } },
|
@@ -4,6 +4,7 @@ const uuidv4 = require('uuid/v4');
|
|
4
4
|
var jwt = require('jsonwebtoken');
|
5
5
|
var winston = require('../config/winston');
|
6
6
|
const errorCodes = require("../errorCodes");
|
7
|
+
var ObjectId = require('mongoose').Types.ObjectId;
|
7
8
|
|
8
9
|
const port = process.env.PORT || '3000';
|
9
10
|
let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/";;
|
@@ -45,6 +46,8 @@ class WebhookService {
|
|
45
46
|
let json_value = JSON.parse(value);
|
46
47
|
payload.preloaded_request_id = json_value.request_id;
|
47
48
|
payload.draft = true;
|
49
|
+
} else {
|
50
|
+
payload.preloaded_request_id = "automation-request-" + webhook.id_project + "-" + new ObjectId() + "-" + webhook.webhook_id;
|
48
51
|
}
|
49
52
|
|
50
53
|
let token = await this.generateChatbotToken(chatbot);
|