@tiledesk/tiledesk-server 2.10.100 → 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 +7 -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/unanswered.js +256 -0
- 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,13 @@
|
|
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
|
+
|
8
15
|
# 2.10.100
|
9
16
|
- Update: removed verbose logs
|
10
17
|
|
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) => {
|
@@ -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;
|
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);
|