@tiledesk/tiledesk-server 2.19.15 → 2.20.0
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 +8 -0
- package/jobs.js +12 -2
- package/package.json +2 -2
- package/pubmodules/activities/models/activity.js +48 -1
- package/pubmodules/activities/routes/activity.js +1 -1
- package/pubmodules/pubModulesManager.js +3 -0
- package/pubmodules/routing-queue/listenerQueued.js +190 -133
- package/routes/kb.js +5 -9
- package/routes/request.js +8 -3
- package/services/requestService.js +20 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
🚀 IN PRODUCTION 🚀
|
|
6
6
|
(https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
|
|
7
7
|
|
|
8
|
+
# 2.20.0
|
|
9
|
+
- Updated tybot-connector to 2.1.8
|
|
10
|
+
- Improved flow attributes management
|
|
11
|
+
|
|
12
|
+
# 2.19.16
|
|
13
|
+
- Queued /kb/scrape/single via scheduleScrape instead of sync startScrape
|
|
14
|
+
- Improved guest closure event handling in activity monitoring
|
|
15
|
+
|
|
8
16
|
# 2.19.15
|
|
9
17
|
- Fixed bug on updating cells in a table row
|
|
10
18
|
|
package/jobs.js
CHANGED
|
@@ -84,7 +84,14 @@ async function main()
|
|
|
84
84
|
//************* LOAD CHAT21 ************ //
|
|
85
85
|
channelManager.listen(); // chat21Handler is loaded with stadard events like request.create and NOT request.create.queue because it is used internally by the worker when the request is closed by ChatUnhandledRequestScheduler
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
// Same Redis client as app.js — required by routing-queue (flow attributes cache delete)
|
|
88
|
+
const { TdCache } = require('./utils/TdCache');
|
|
89
|
+
let tdCache = new TdCache({
|
|
90
|
+
host: process.env.CACHE_REDIS_HOST,
|
|
91
|
+
port: process.env.CACHE_REDIS_PORT,
|
|
92
|
+
password: process.env.CACHE_REDIS_PASSWORD
|
|
93
|
+
});
|
|
94
|
+
tdCache.connect();
|
|
88
95
|
|
|
89
96
|
|
|
90
97
|
let jobsManager = new JobsManager(undefined, geoService, botEvent, subscriptionNotifierQueued, botSubscriptionNotifier, updateLeadQueued, updateRequestSnapshotQueued);
|
|
@@ -102,7 +109,10 @@ async function main()
|
|
|
102
109
|
|
|
103
110
|
|
|
104
111
|
let routingQueueQueued = require('./pubmodules/routing-queue').listenerQueued;
|
|
105
|
-
winston.debug("routingQueueQueued");
|
|
112
|
+
winston.debug("routingQueueQueued");
|
|
113
|
+
if (tdCache) {
|
|
114
|
+
routingQueueQueued.setTdCache(tdCache);
|
|
115
|
+
}
|
|
106
116
|
jobsManager.listenRoutingQueue(routingQueueQueued);
|
|
107
117
|
|
|
108
118
|
let whatsappQueue = require('@tiledesk/tiledesk-whatsapp-jobworker');
|
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.
|
|
4
|
+
"version": "2.20.0",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"start": "node ./bin/www",
|
|
7
7
|
"pretest": "mongodb-runner start",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@tiledesk/tiledesk-rasa-connector": "^1.0.10",
|
|
50
50
|
"@tiledesk/tiledesk-sms-connector": "^0.1.13",
|
|
51
51
|
"@tiledesk/tiledesk-telegram-connector": "^0.1.14",
|
|
52
|
-
"@tiledesk/tiledesk-tybot-connector": "^2.1.
|
|
52
|
+
"@tiledesk/tiledesk-tybot-connector": "^2.1.8",
|
|
53
53
|
"@tiledesk/tiledesk-voice-twilio-connector": "^0.3.2",
|
|
54
54
|
"@tiledesk/tiledesk-vxml-connector": "^0.1.91",
|
|
55
55
|
"@tiledesk/tiledesk-whatsapp-connector": "1.0.26",
|
|
@@ -103,6 +103,49 @@ function userIdFromEntity(entity) {
|
|
|
103
103
|
return null;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
// Human agents assigned to a request target (e.g. REQUEST_CLOSE when a guest closes).
|
|
107
|
+
// Without this, involvedUserIds would only contain closed_by / actor and miss the assignee,
|
|
108
|
+
// so ?agent_id= filters would not return the activity for the assigned operator.
|
|
109
|
+
function agentIdsFromRequestTarget(target) {
|
|
110
|
+
if (!target || !target.object) {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
var ids = [];
|
|
114
|
+
var seen = {};
|
|
115
|
+
function addId(raw) {
|
|
116
|
+
if (raw == null) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
var id = String(raw);
|
|
120
|
+
if (!id || id.indexOf('bot_') === 0 || seen[id]) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
seen[id] = true;
|
|
124
|
+
ids.push(id);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
var participantsAgents = target.object.participantsAgents;
|
|
128
|
+
if (Array.isArray(participantsAgents)) {
|
|
129
|
+
for (var i = 0; i < participantsAgents.length; i++) {
|
|
130
|
+
addId(participantsAgents[i]);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Fallback when only the populated virtual is present on the serialized request
|
|
135
|
+
var participatingAgents = target.object.participatingAgents;
|
|
136
|
+
if (Array.isArray(participatingAgents)) {
|
|
137
|
+
for (var j = 0; j < participatingAgents.length; j++) {
|
|
138
|
+
var agent = participatingAgents[j];
|
|
139
|
+
if (!agent) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
addId(agent._id || agent.id || agent);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return ids;
|
|
147
|
+
}
|
|
148
|
+
|
|
106
149
|
function computeInvolvedUserIds(doc) {
|
|
107
150
|
var ids = new Set();
|
|
108
151
|
if (doc.actor && doc.actor.type === 'user' && doc.actor.id) {
|
|
@@ -116,6 +159,9 @@ function computeInvolvedUserIds(doc) {
|
|
|
116
159
|
if (relatedUserId) {
|
|
117
160
|
ids.add(relatedUserId);
|
|
118
161
|
}
|
|
162
|
+
agentIdsFromRequestTarget(doc.target).forEach(function (id) {
|
|
163
|
+
ids.add(id);
|
|
164
|
+
});
|
|
119
165
|
return Array.from(ids);
|
|
120
166
|
}
|
|
121
167
|
|
|
@@ -147,7 +193,8 @@ var ActivitySchema = new Schema({
|
|
|
147
193
|
type: RelatedActivitySchema,
|
|
148
194
|
required: false
|
|
149
195
|
},
|
|
150
|
-
// Denormalized list of user ids involved in the activity
|
|
196
|
+
// Denormalized list of user ids involved in the activity
|
|
197
|
+
// (actor, target user, related user, and request participantsAgents when target is a request).
|
|
151
198
|
// Auto-filled by the pre-save hook below. Indexed for efficient "activities of a user" queries.
|
|
152
199
|
involvedUserIds: {
|
|
153
200
|
type: [String],
|
|
@@ -86,7 +86,7 @@ router.get('/', async (req, res) => {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
if (req.query.agent_id) {
|
|
89
|
-
// involvedUserIds covers actor, target user
|
|
89
|
+
// involvedUserIds covers actor, target user, related user and request participantsAgents.
|
|
90
90
|
// The other two clauses keep backward compatibility with legacy records.
|
|
91
91
|
query["$or"] = [
|
|
92
92
|
{ "involvedUserIds": req.query.agent_id },
|
|
@@ -689,6 +689,9 @@ class PubModulesManager {
|
|
|
689
689
|
}
|
|
690
690
|
if (this.routingQueueQueued) {
|
|
691
691
|
try {
|
|
692
|
+
if (this.tdCache) {
|
|
693
|
+
this.routingQueueQueued.setTdCache(this.tdCache);
|
|
694
|
+
}
|
|
692
695
|
// this.routingQueueQueued.listen();
|
|
693
696
|
this.jobsManager.listenRoutingQueue(this.routingQueueQueued);
|
|
694
697
|
winston.info("PubModulesManager routingQueue queued started");
|
|
@@ -6,6 +6,7 @@ var Request = require('../../models/request')
|
|
|
6
6
|
var winston = require('../../config/winston');
|
|
7
7
|
|
|
8
8
|
var ProjectUserUtil = require("../../utils/project_userUtil");
|
|
9
|
+
const requestService = require('../../services/requestService');
|
|
9
10
|
|
|
10
11
|
// var request = require('retry-request', {
|
|
11
12
|
// request: require('request')
|
|
@@ -28,23 +29,36 @@ var ProjectUserUtil = require("../../utils/project_userUtil");
|
|
|
28
29
|
// TODO web socket is not supported with queue
|
|
29
30
|
class Listener {
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
|
|
32
33
|
constructor() {
|
|
33
34
|
this.enabled = true;
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
this.tdCache = null;
|
|
36
|
+
if (process.env.ROUTE_QUEUE_ENABLED == "false" || process.env.ROUTE_QUEUE_ENABLED == false) {
|
|
37
|
+
this.enabled = false;
|
|
36
38
|
}
|
|
37
|
-
winston.debug("Listener this.enabled: "+ this.enabled);
|
|
39
|
+
winston.debug("Listener this.enabled: " + this.enabled);
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Reuse app's TdCache instance instead of opening a new Redis connection.
|
|
44
|
+
* Injected by PubModulesManager.
|
|
45
|
+
* @param {TdCache} tdCache - shared Redis cache from app.get('redis_client')
|
|
46
|
+
*/
|
|
47
|
+
setTdCache(tdCache) {
|
|
48
|
+
if (tdCache && typeof tdCache.del === 'function') {
|
|
49
|
+
this.tdCache = tdCache;
|
|
50
|
+
winston.debug("Route queue Listener using shared TdCache for flow attributes");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
41
55
|
// db.getCollection('project_users').find({"number_assigned_requests" : {"$lt":0}}).count()
|
|
42
56
|
|
|
43
57
|
// New version of updateProjectUser() method.
|
|
44
58
|
// This will not increment or decrement the number_assigned_requests field but search the exact number of assigned conversation to the project user
|
|
45
59
|
updateProjectUser(id_user, id_project, operation) {
|
|
46
60
|
// winston.debug("Route queue updateProjectUser start operation: " + operation + "id_user " + id_user + " id_project " + id_project);
|
|
47
|
-
|
|
61
|
+
|
|
48
62
|
// escludi id_user che iniziano con bot_
|
|
49
63
|
if (id_user.startsWith('bot_')) {
|
|
50
64
|
return winston.warn("Chatbot is not a project_user. Skip update.")
|
|
@@ -64,27 +78,27 @@ class Listener {
|
|
|
64
78
|
// winston.debug("Route queue number_assigned_requests +1 :" + updatedPU.id);
|
|
65
79
|
// winston.debug("Route queue number_assigned_requests +1 :" + updatedPU.id);
|
|
66
80
|
winston.debug("Route queue number_assigned_requests updated to " + requestsCount + "for project user " + updatedPU.id);
|
|
67
|
-
|
|
81
|
+
|
|
68
82
|
updatedPU.populate({ path: 'id_user', select: { 'firstname': 1, 'lastname': 1 } }, function (err, updatedProject_userPopulated) {
|
|
69
|
-
|
|
83
|
+
|
|
70
84
|
var pu = updatedProject_userPopulated.toJSON();
|
|
71
|
-
|
|
85
|
+
|
|
72
86
|
return Project.findById(id_project).exec(function (err, project) {
|
|
73
87
|
pu.isBusy = ProjectUserUtil.isBusy(updatedProject_userPopulated, project.settings && project.settings.max_agent_assigned_chat);
|
|
74
88
|
winston.debug("Route queue pu.isBusy: " + pu.isBusy);
|
|
75
|
-
|
|
89
|
+
|
|
76
90
|
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
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
|
|
92
|
+
|
|
79
93
|
// project_user.update triggers activityArchiver(tested), cache invalidation(tested), subscriptionNotifierQueued and websocket(tested works from queue i trigger ws)
|
|
80
94
|
if (requestEvent.queueEnabled) { //force to .queue to be catched into the queue (activity archiver, subscriptionNotifierQueued )
|
|
81
95
|
authEvent.emit('project_user.update.queue', { updatedProject_userPopulated: pu, req: undefined, skipArchive: true });
|
|
82
96
|
}
|
|
83
|
-
|
|
97
|
+
|
|
84
98
|
})
|
|
85
|
-
|
|
99
|
+
|
|
86
100
|
});
|
|
87
|
-
|
|
101
|
+
|
|
88
102
|
});
|
|
89
103
|
})
|
|
90
104
|
|
|
@@ -123,141 +137,184 @@ class Listener {
|
|
|
123
137
|
});
|
|
124
138
|
}
|
|
125
139
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (
|
|
142
|
-
winston.
|
|
143
|
-
}
|
|
144
|
-
|
|
140
|
+
updateParticipatingProjectUsers(request, operation) {
|
|
141
|
+
winston.debug("Route queue request.participatingAgents", request.participatingAgents);
|
|
142
|
+
if (request.participatingAgents.length > 0) {
|
|
143
|
+
request.participatingAgents.forEach(user => {
|
|
144
|
+
winston.debug("request.participatingAgents user", user); //it is a user and not a project_user
|
|
145
|
+
var userid = user.id || user._id;
|
|
146
|
+
winston.debug("updateParticipatingProjectUsers userid: " + userid);
|
|
147
|
+
|
|
148
|
+
this.updateProjectUser(userid, request.id_project, operation);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async saveFlowAttributes(request) {
|
|
154
|
+
try {
|
|
155
|
+
if (!request || !request.request_id) {
|
|
156
|
+
return winston.warn("saveFlowAttributes: missing request_id");
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* The parameters are taken from the chatbot, which already contains the logic to filter out system parameters.
|
|
160
|
+
* For deletion, you can act directly on Redis.
|
|
161
|
+
*/
|
|
162
|
+
let parameters = await requestService.getRequestParametersFromChatbot(request.request_id);
|
|
163
|
+
if (!parameters || Object.keys(parameters).length === 0) {
|
|
164
|
+
return;
|
|
145
165
|
}
|
|
166
|
+
await Request.updateOne(
|
|
167
|
+
{ request_id: request.request_id, id_project: request.id_project },
|
|
168
|
+
{ $set: { 'attributes.flowAttributes': parameters } }
|
|
169
|
+
);
|
|
170
|
+
winston.debug("Flow attributes saved for request: " + request.request_id);
|
|
146
171
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// TODO fai versione che passa anche project
|
|
150
|
-
var requestCreateKey = 'request.create';
|
|
151
|
-
if (requestEvent.queueEnabled) {
|
|
152
|
-
requestCreateKey = 'request.create.queue';
|
|
153
|
-
}
|
|
154
|
-
winston.debug('Route queue requestCreateKey: ' + requestCreateKey);
|
|
155
|
-
|
|
156
|
-
requestEvent.on(requestCreateKey, async (request) => {
|
|
157
|
-
setImmediate(() => {
|
|
158
|
-
winston.debug('Route queue requestCreate');
|
|
159
|
-
this.updateParticipatingProjectUsers(request, +1);
|
|
160
|
-
});
|
|
161
|
-
});
|
|
172
|
+
await this.deleteFlowAttributesFromCache(request);
|
|
162
173
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
winston.debug('Route queue requestCloseKey: ' + requestCloseKey);
|
|
174
|
+
} catch (err) {
|
|
175
|
+
winston.error("Error saving flow attributes: ", err);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
169
178
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
179
|
+
async deleteFlowAttributesFromCache(request) {
|
|
180
|
+
if (!this.tdCache) {
|
|
181
|
+
return winston.warn("deleteFlowAttributesFromCache: tdCache not set");
|
|
182
|
+
}
|
|
183
|
+
if (!request || !request.request_id) {
|
|
184
|
+
return winston.warn("deleteFlowAttributesFromCache: missing request_id");
|
|
185
|
+
}
|
|
186
|
+
const key = `tilebot:requests:${request.request_id}:parameters`;
|
|
187
|
+
try {
|
|
188
|
+
await this.tdCache.del(key);
|
|
189
|
+
winston.debug("Flow attributes cache deleted: " + key);
|
|
190
|
+
} catch (err) {
|
|
191
|
+
winston.error("Error deleting flow attributes from cache: ", err);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
177
194
|
|
|
195
|
+
listen() {
|
|
178
196
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
requestEvent.on(requestParticipantsJoinKey, async (data) => {
|
|
186
|
-
winston.debug('Route queue ParticipantsJoin');
|
|
187
|
-
|
|
188
|
-
var request = data.request;
|
|
189
|
-
var member = data.member;
|
|
190
|
-
setImmediate(() => {
|
|
191
|
-
this.updateProjectUser(member, request.id_project, 1);
|
|
192
|
-
});
|
|
193
|
-
});
|
|
197
|
+
if (this.enabled == true) {
|
|
198
|
+
winston.info("Route queue with queue Listener listen");
|
|
199
|
+
} else {
|
|
200
|
+
return winston.info("Route queue with queue Listener disabled");
|
|
201
|
+
}
|
|
194
202
|
|
|
195
|
-
|
|
196
|
-
if (requestEvent.queueEnabled) {
|
|
197
|
-
requestParticipantsLeaveKey = 'request.participants.leave.queue';
|
|
198
|
-
}
|
|
199
|
-
winston.debug('Route queue requestParticipantsLeaveKey: ' + requestParticipantsLeaveKey);
|
|
200
|
-
|
|
201
|
-
requestEvent.on(requestParticipantsLeaveKey, async (data) => {
|
|
202
|
-
winston.debug('Route queue ParticipantsLeave');
|
|
203
|
-
|
|
204
|
-
var request = data.request;
|
|
205
|
-
var member = data.member;
|
|
206
|
-
setImmediate(() => {
|
|
207
|
-
this.updateProjectUser(member, request.id_project, -1);
|
|
208
|
-
});
|
|
209
|
-
});
|
|
203
|
+
var that = this;
|
|
210
204
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
requestEvent.on(requestParticipantsUpdateKey, async (data) => {
|
|
218
|
-
winston.debug('Route queue Participants Update');
|
|
205
|
+
// TODO fai versione che passa anche project
|
|
206
|
+
var requestCreateKey = 'request.create';
|
|
207
|
+
if (requestEvent.queueEnabled) {
|
|
208
|
+
requestCreateKey = 'request.create.queue';
|
|
209
|
+
}
|
|
210
|
+
winston.debug('Route queue requestCreateKey: ' + requestCreateKey);
|
|
219
211
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
212
|
+
requestEvent.on(requestCreateKey, async (request) => {
|
|
213
|
+
setImmediate(() => {
|
|
214
|
+
winston.debug('Route queue requestCreate');
|
|
215
|
+
this.updateParticipatingProjectUsers(request, +1);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
223
218
|
|
|
224
|
-
|
|
219
|
+
// TODO usa versione complete con project per evitare query??
|
|
220
|
+
var requestCloseKey = 'request.close'; //request.close event here queued under job
|
|
221
|
+
if (requestEvent.queueEnabled) {
|
|
222
|
+
requestCloseKey = 'request.close.queue';
|
|
223
|
+
}
|
|
224
|
+
winston.debug('Route queue requestCloseKey: ' + requestCloseKey);
|
|
225
|
+
|
|
226
|
+
requestEvent.on(requestCloseKey, async (request) => { //request.close event here noqueued
|
|
227
|
+
winston.debug("request.close event here 4")
|
|
228
|
+
setImmediate(() => {
|
|
229
|
+
winston.debug('Route queue requestClose');
|
|
230
|
+
this.updateParticipatingProjectUsers(request, -1);
|
|
231
|
+
this.saveFlowAttributes(request);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
225
234
|
|
|
226
|
-
addedParticipants.forEach(participant => {
|
|
227
|
-
winston.debug('addedParticipants participant', participant);
|
|
228
|
-
this.updateProjectUser(participant, request.id_project, 1);
|
|
229
|
-
});
|
|
230
235
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
236
|
+
var requestParticipantsJoinKey = 'request.participants.join';
|
|
237
|
+
if (requestEvent.queueEnabled) {
|
|
238
|
+
requestParticipantsJoinKey = 'request.participants.join.queue';
|
|
239
|
+
}
|
|
240
|
+
winston.debug('Route queue requestParticipantsJoinKey: ' + requestParticipantsJoinKey);
|
|
235
241
|
|
|
236
|
-
|
|
242
|
+
requestEvent.on(requestParticipantsJoinKey, async (data) => {
|
|
243
|
+
winston.debug('Route queue ParticipantsJoin');
|
|
244
|
+
|
|
245
|
+
var request = data.request;
|
|
246
|
+
var member = data.member;
|
|
247
|
+
setImmediate(() => {
|
|
248
|
+
this.updateProjectUser(member, request.id_project, 1);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
var requestParticipantsLeaveKey = 'request.participants.leave';
|
|
253
|
+
if (requestEvent.queueEnabled) {
|
|
254
|
+
requestParticipantsLeaveKey = 'request.participants.leave.queue';
|
|
255
|
+
}
|
|
256
|
+
winston.debug('Route queue requestParticipantsLeaveKey: ' + requestParticipantsLeaveKey);
|
|
257
|
+
|
|
258
|
+
requestEvent.on(requestParticipantsLeaveKey, async (data) => {
|
|
259
|
+
winston.debug('Route queue ParticipantsLeave');
|
|
260
|
+
|
|
261
|
+
var request = data.request;
|
|
262
|
+
var member = data.member;
|
|
263
|
+
setImmediate(() => {
|
|
264
|
+
this.updateProjectUser(member, request.id_project, -1);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
var requestParticipantsUpdateKey = 'request.participants.update';
|
|
269
|
+
if (requestEvent.queueEnabled) {
|
|
270
|
+
requestParticipantsUpdateKey = 'request.participants.update.queue';
|
|
271
|
+
}
|
|
272
|
+
winston.debug('Route queue requestParticipantsUpdateKey: ' + requestParticipantsUpdateKey);
|
|
273
|
+
|
|
274
|
+
requestEvent.on(requestParticipantsUpdateKey, async (data) => {
|
|
275
|
+
winston.debug('Route queue Participants Update');
|
|
276
|
+
|
|
277
|
+
var request = data.request;
|
|
278
|
+
var removedParticipants = data.removedParticipants;
|
|
279
|
+
var addedParticipants = data.addedParticipants;
|
|
280
|
+
|
|
281
|
+
setImmediate(() => {
|
|
282
|
+
|
|
283
|
+
addedParticipants.forEach(participant => {
|
|
284
|
+
winston.debug('addedParticipants participant', participant);
|
|
285
|
+
this.updateProjectUser(participant, request.id_project, 1);
|
|
237
286
|
});
|
|
238
287
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
winston.debug('Route queue requestWorkingStatusUpdateKey: ' + requestWorkingStatusUpdateKey);
|
|
244
|
-
|
|
245
|
-
requestEvent.on(requestWorkingStatusUpdateKey, async (data) => {
|
|
246
|
-
winston.debug('Route queue WorkingStatus Update');
|
|
247
|
-
|
|
248
|
-
var request = data.request;
|
|
249
|
-
var participantIds = (request.participantsAgents && request.participantsAgents.length)
|
|
250
|
-
? request.participantsAgents
|
|
251
|
-
: (request.participatingAgents || []).map(u => u._id || u.id);
|
|
252
|
-
setImmediate(() => {
|
|
253
|
-
participantIds.forEach(id_user => {
|
|
254
|
-
if (id_user && !String(id_user).startsWith('bot_')) {
|
|
255
|
-
this.updateProjectUser(id_user, request.id_project, 0);
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
});
|
|
288
|
+
removedParticipants.forEach(participant => {
|
|
289
|
+
winston.debug('removedParticipants participant', participant);
|
|
290
|
+
this.updateProjectUser(participant, request.id_project, -1);
|
|
259
291
|
});
|
|
292
|
+
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
var requestWorkingStatusUpdateKey = 'request.workingStatus.update';
|
|
297
|
+
if (requestEvent.queueEnabled) {
|
|
298
|
+
requestWorkingStatusUpdateKey = 'request.workingStatus.update.queue';
|
|
260
299
|
}
|
|
300
|
+
winston.debug('Route queue requestWorkingStatusUpdateKey: ' + requestWorkingStatusUpdateKey);
|
|
301
|
+
|
|
302
|
+
requestEvent.on(requestWorkingStatusUpdateKey, async (data) => {
|
|
303
|
+
winston.debug('Route queue WorkingStatus Update');
|
|
304
|
+
|
|
305
|
+
var request = data.request;
|
|
306
|
+
var participantIds = (request.participantsAgents && request.participantsAgents.length)
|
|
307
|
+
? request.participantsAgents
|
|
308
|
+
: (request.participatingAgents || []).map(u => u._id || u.id);
|
|
309
|
+
setImmediate(() => {
|
|
310
|
+
participantIds.forEach(id_user => {
|
|
311
|
+
if (id_user && !String(id_user).startsWith('bot_')) {
|
|
312
|
+
this.updateProjectUser(id_user, request.id_project, 0);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
}
|
|
261
318
|
|
|
262
319
|
}
|
|
263
320
|
|
package/routes/kb.js
CHANGED
|
@@ -240,7 +240,7 @@ router.post('/scrape/single', async (req, res) => {
|
|
|
240
240
|
json.content = kb.content;
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
if (kb.scrape_type) {
|
|
243
|
+
if (kb.scrape_type !== null) {
|
|
244
244
|
json.scrape_type = kb.scrape_type
|
|
245
245
|
}
|
|
246
246
|
|
|
@@ -270,18 +270,14 @@ router.post('/scrape/single', async (req, res) => {
|
|
|
270
270
|
winston.verbose("/scrape/single json: ", json);
|
|
271
271
|
|
|
272
272
|
json.id_project = project_id;
|
|
273
|
+
json.webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
|
|
273
274
|
|
|
274
275
|
if (process.env.NODE_ENV === "test") {
|
|
275
|
-
res.status(200).send({ success: true, message: "Skip indexing in test environment", data: json })
|
|
276
|
+
return res.status(200).send({ success: true, message: "Skip indexing in test environment", data: json })
|
|
276
277
|
}
|
|
277
278
|
|
|
278
|
-
aiManager.
|
|
279
|
-
|
|
280
|
-
res.status(200).send(response);
|
|
281
|
-
}).catch((err) => {
|
|
282
|
-
winston.error("startScrape err: ", err);
|
|
283
|
-
res.status(500).send({ success: false, error: err });
|
|
284
|
-
})
|
|
279
|
+
aiManager.scheduleScrape([json], namespace.hybrid);
|
|
280
|
+
return res.status(200).send({ success: true, message: "Content queued for reindexing" });
|
|
285
281
|
|
|
286
282
|
}
|
|
287
283
|
})
|
package/routes/request.js
CHANGED
|
@@ -2479,12 +2479,17 @@ router.get('/:requestid/chatbot/parameters', async (req, res) => {
|
|
|
2479
2479
|
return res.status(401).send({ success: false, message: "Request does not belong to the project"})
|
|
2480
2480
|
}
|
|
2481
2481
|
|
|
2482
|
-
requestService.
|
|
2482
|
+
requestService.getRequestParameters(request_id).then((parameters) => {
|
|
2483
2483
|
res.status(200).send(parameters);
|
|
2484
2484
|
|
|
2485
2485
|
}).catch((err) => {
|
|
2486
|
-
|
|
2487
|
-
|
|
2486
|
+
if (err.message) {
|
|
2487
|
+
winston.error("Error getting request flow attributes: ", err.message);
|
|
2488
|
+
res.status(400).send({ success: false, message: err.message });
|
|
2489
|
+
} else {
|
|
2490
|
+
winston.error("err: ", err);
|
|
2491
|
+
res.status(400).send({ success: false, message: "Error getting request flow attributes" });
|
|
2492
|
+
}
|
|
2488
2493
|
})
|
|
2489
2494
|
|
|
2490
2495
|
})
|
|
@@ -2478,7 +2478,27 @@ class RequestService {
|
|
|
2478
2478
|
});
|
|
2479
2479
|
}
|
|
2480
2480
|
|
|
2481
|
+
async getRequestParameters(request_id) {
|
|
2482
|
+
try {
|
|
2483
|
+
let parameters = await this.getRequestParametersFromChatbot(request_id);
|
|
2484
|
+
if (parameters && Object.keys(parameters).length > 0) {
|
|
2485
|
+
return parameters;
|
|
2486
|
+
}
|
|
2487
|
+
} catch (err) {
|
|
2488
|
+
winston.warn("Error getting request parameters from chatbot, falling back to DB: ", err.message || err);
|
|
2489
|
+
}
|
|
2490
|
+
return await this.getRequestParametersFromDB(request_id);
|
|
2491
|
+
}
|
|
2481
2492
|
|
|
2493
|
+
async getRequestParametersFromDB(request_id) {
|
|
2494
|
+
try {
|
|
2495
|
+
let request = await Request.findOne({ request_id: request_id }).select('attributes.flowAttributes').exec();
|
|
2496
|
+
return request?.attributes?.flowAttributes || {};
|
|
2497
|
+
} catch (err) {
|
|
2498
|
+
winston.error("Error getting request parameters from DB: ", err);
|
|
2499
|
+
throw new Error("Error getting request flow attributes");
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2482
2502
|
|
|
2483
2503
|
async getRequestParametersFromChatbot(request_id) {
|
|
2484
2504
|
|