@tiledesk/tiledesk-server 2.4.99 → 2.4.101
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +8 -0
- package/app.js +47 -9
- package/event/emailEvent.js +13 -0
- package/event/integrationEvent.js +13 -0
- package/models/integrations.js +23 -0
- package/models/kb_setting.js +34 -3
- package/package.json +2 -2
- package/pubmodules/cache/mongoose-cachegoose-fn.js +12 -0
- package/pubmodules/emailNotification/requestNotification.js +1 -0
- package/routes/auth.js +14 -5
- package/routes/email.js +4 -2
- package/routes/faq.js +1 -0
- package/routes/integration.js +199 -0
- package/routes/kb.js +353 -0
- package/routes/kbsettings.js +6 -4
- package/routes/openai.js +53 -15
- package/routes/project.js +3 -4
- package/routes/quotes.js +52 -0
- package/routes/request.js +515 -499
- package/routes/users.js +5 -1
- package/services/QuoteManager.js +317 -0
- package/services/cacheEnabler.js +5 -0
- package/services/emailService.js +610 -586
- package/services/messageService.js +283 -202
- package/services/openaiService.js +198 -92
- package/services/requestService.js +1764 -1421
- package/services/trainingService.js +6 -2
- package/test/kbRoute.js +134 -0
- package/test/kbsettingsRoute.js +14 -12
- package/test/messageService.js +154 -92
- package/test/mock/MockTdCache.js +46 -0
- package/test/mock/emailMock.js +9 -0
- package/test/mock/messageMock.js +46 -0
- package/test/mock/projectMock.js +171 -0
- package/test/mock/requestMock.js +127 -0
- package/test/quoteManager.js +282 -0
- package/test/requestRoute.js +1 -1
- package/test/requestService.js +1196 -1079
- package/utils/TdCache.js +253 -0
package/routes/users.js
CHANGED
@@ -195,7 +195,11 @@ router.post('/loginemail', function (req, res) {
|
|
195
195
|
let chatbot_id = req.body.bot_id;
|
196
196
|
|
197
197
|
if (!project_id) {
|
198
|
-
res.status(500).send({ success: false, error: "missing 'id_project' field" })
|
198
|
+
res.status(500).send({ success: false, error: "missing 'id_project' field" });
|
199
|
+
}
|
200
|
+
|
201
|
+
if (!chatbot_id) {
|
202
|
+
res.status(500).send({ success: false, error: "missing 'bot_id' field" });
|
199
203
|
}
|
200
204
|
|
201
205
|
if (!chatbot_id) {
|
@@ -0,0 +1,317 @@
|
|
1
|
+
const { ceil, floor } = require('lodash');
|
2
|
+
let winston = require('../config/winston');
|
3
|
+
const requestEvent = require('../event/requestEvent');
|
4
|
+
const messageEvent = require('../event/messageEvent');
|
5
|
+
const emailEvent = require('../event/emailEvent');
|
6
|
+
|
7
|
+
// const PLANS_LIST = {
|
8
|
+
// FREE_TRIAL: { users: 2, requests: 3000, chatbots: 20, kbs: 3, kb_pages: 500, tokens: 250000 }, // same as PREMIUM
|
9
|
+
// SANDBOX: { users: 1, requests: 200, chatbots: 2, kbs: 1, kb_pages: 50, tokens: 10000 },
|
10
|
+
// BASIC: { users: 1, requests: 810, chatbots: 5, kbs: 2, kb_pages: 250, tokens: 50000 },
|
11
|
+
// PREMIUM: { users: 2, requests: 3000, chatbots: 20, kbs: 3, kb_pages: 500, tokens: 250000 },
|
12
|
+
// CUSTOM: { users: 100, conversations: 10000, chatbots: 100, kbs: 100, kb_pages: 1000, tokens: 100000 } // manage it --> get limit directly from project info
|
13
|
+
// }
|
14
|
+
|
15
|
+
// const PLANS_LIST = {
|
16
|
+
// FREE_TRIAL: { users: 2, requests: 3000, chatbots: 20, kbs: 3, kb_pages: 500, tokens: 250000 }, // same as PREMIUM
|
17
|
+
// SANDBOX: { users: 1, requests: 200, chatbots: 2, kbs: 1, kb_pages: 50, tokens: 10000 },
|
18
|
+
// BASIC: { users: 1, requests: 800, chatbots: 5, kbs: 2, kb_pages: 250, tokens: 50000 },
|
19
|
+
// PREMIUM: { users: 2, requests: 3000, chatbots: 20, kbs: 3, kb_pages: 500, tokens: 250000 },
|
20
|
+
// CUSTOM: { users: 2, requests: 3000, chatbots: 20, kbs: 3, kb_pages: 5000, tokens: 1000000 }
|
21
|
+
// }
|
22
|
+
|
23
|
+
const PLANS_LIST = {
|
24
|
+
FREE_TRIAL: { requests: 3000, messages: 0, tokens: 250000, email: 200 }, // same as PREMIUM
|
25
|
+
SANDBOX: { requests: 200, messages: 0, tokens: 10000, email: 200 },
|
26
|
+
BASIC: { requests: 800, messages: 0, tokens: 50000, email: 200 },
|
27
|
+
PREMIUM: { requests: 3000, messages: 0, tokens: 250000, email: 200 },
|
28
|
+
CUSTOM: { requests: 3000, messages: 0, tokens: 250000, email: 200 }
|
29
|
+
}
|
30
|
+
|
31
|
+
const typesList = ['requests', 'messages', 'email', 'tokens']
|
32
|
+
|
33
|
+
let quotes_enabled = true;
|
34
|
+
|
35
|
+
class QuoteManager {
|
36
|
+
|
37
|
+
constructor(config) {
|
38
|
+
|
39
|
+
if (!config) {
|
40
|
+
throw new Error('config is mandatory')
|
41
|
+
}
|
42
|
+
|
43
|
+
if (!config.tdCache) {
|
44
|
+
throw new Error('config.tdCache is mandatory')
|
45
|
+
}
|
46
|
+
|
47
|
+
this.tdCache = config.tdCache;
|
48
|
+
this.project;
|
49
|
+
|
50
|
+
}
|
51
|
+
|
52
|
+
// INCREMENT KEY SECTION - START
|
53
|
+
async incrementRequestsCount(project, request) {
|
54
|
+
|
55
|
+
this.project = project;
|
56
|
+
let key = await this.generateKey(request, 'requests');
|
57
|
+
winston.verbose("[QuoteManager] incrementRequestsCount key: " + key);
|
58
|
+
|
59
|
+
await this.tdCache.incr(key)
|
60
|
+
return key;
|
61
|
+
}
|
62
|
+
|
63
|
+
async incrementMessagesCount(project, message) {
|
64
|
+
|
65
|
+
this.project = project;
|
66
|
+
let key = await this.generateKey(message, 'messages');
|
67
|
+
winston.verbose("[QuoteManager] incrementMessagesCount key: " + key);
|
68
|
+
|
69
|
+
await this.tdCache.incr(key)
|
70
|
+
return key;
|
71
|
+
}
|
72
|
+
|
73
|
+
async incrementEmailCount(project, email) {
|
74
|
+
|
75
|
+
this.project = project;
|
76
|
+
let key = await this.generateKey(email, 'email');
|
77
|
+
winston.info("[QuoteManager] incrementEmailCount key: " + key);
|
78
|
+
|
79
|
+
await this.tdCache.incr(key)
|
80
|
+
return key;
|
81
|
+
}
|
82
|
+
|
83
|
+
async incrementTokenCount(project, data) { // ?? cosa passo? il messaggio per vedere la data?
|
84
|
+
|
85
|
+
this.project = project;
|
86
|
+
let key = await this.generateKey(data, 'tokens');
|
87
|
+
winston.info("[QuoteManager] incrementTokenCount key: " + key);
|
88
|
+
|
89
|
+
if (quotes_enabled === false) {
|
90
|
+
winston.debug("QUOTES DISABLED - incrementTokenCount")
|
91
|
+
return key;
|
92
|
+
}
|
93
|
+
|
94
|
+
await this.tdCache.incrby(key, data.tokens);
|
95
|
+
return key;
|
96
|
+
}
|
97
|
+
// INCREMENT KEY SECTION - END
|
98
|
+
|
99
|
+
|
100
|
+
async generateKey(object, type) {
|
101
|
+
|
102
|
+
let subscriptionDate;
|
103
|
+
if (this.project.profile.subStart) {
|
104
|
+
subscriptionDate = this.project.profile.subStart;
|
105
|
+
} else {
|
106
|
+
subscriptionDate = this.project.createdAt;
|
107
|
+
}
|
108
|
+
let objectDate = object.createdAt;
|
109
|
+
|
110
|
+
// converts date in timestamps and transform from ms to s
|
111
|
+
const objectDateTimestamp = ceil(objectDate.getTime() / 1000);
|
112
|
+
const subscriptionDateTimestamp = ceil(subscriptionDate.getTime() / 1000);
|
113
|
+
|
114
|
+
let ndays = (objectDateTimestamp - subscriptionDateTimestamp) / 86400; // 86400 is the number of seconds in 1 day
|
115
|
+
let nmonths = floor(ndays / 30); // number of month to add to the initial subscription date;
|
116
|
+
|
117
|
+
let date = new Date(subscriptionDate);
|
118
|
+
date.setMonth(date.getMonth() + nmonths);
|
119
|
+
|
120
|
+
return "quotes:" + type + ":" + this.project._id + ":" + date.toLocaleDateString();
|
121
|
+
}
|
122
|
+
|
123
|
+
/**
|
124
|
+
* Get current quote for a single type (tokens or request or ...)
|
125
|
+
*/
|
126
|
+
async getCurrentQuote(project, object, type) {
|
127
|
+
|
128
|
+
this.project = project;
|
129
|
+
let key = await this.generateKey(object, type);
|
130
|
+
winston.verbose("[QuoteManager] getCurrentQuote key: " + key);
|
131
|
+
|
132
|
+
let quote = await this.tdCache.get(key);
|
133
|
+
return Number(quote);
|
134
|
+
}
|
135
|
+
|
136
|
+
/**
|
137
|
+
* Get quotes for a all types (tokens and request and ...)
|
138
|
+
*/
|
139
|
+
async getAllQuotes(project, obj) {
|
140
|
+
|
141
|
+
this.project = project;
|
142
|
+
|
143
|
+
let quotes = {}
|
144
|
+
for (let type of typesList) {
|
145
|
+
console.log("*** get all quotes --> search for type: ", type);
|
146
|
+
let key = await this.generateKey(obj, type);
|
147
|
+
console.log("*** get all quotes --> key generated: ", key);
|
148
|
+
let quote = await this.tdCache.get(key);
|
149
|
+
console.log("*** get all quotes --> quote retrieved: ", quote);
|
150
|
+
|
151
|
+
quotes[type] = {
|
152
|
+
quote: Number(quote)
|
153
|
+
};
|
154
|
+
}
|
155
|
+
return quotes;
|
156
|
+
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* Perform a check on a single type.
|
161
|
+
* Returns TRUE if the limit is not reached --> operation can be performed
|
162
|
+
* Returns FALSE if the limit is reached --> operation can't be performed
|
163
|
+
*/
|
164
|
+
async checkQuote(project, object, type) {
|
165
|
+
|
166
|
+
if (quotes_enabled === false) {
|
167
|
+
winston.debug("QUOTES DISABLED - checkQuote for type " + type);
|
168
|
+
return true;
|
169
|
+
}
|
170
|
+
|
171
|
+
this.project = project;
|
172
|
+
let limits = await this.getPlanLimits();
|
173
|
+
console.log("limits for current plan: ", limits)
|
174
|
+
let quote = await this.getCurrentQuote(project, object, type);
|
175
|
+
|
176
|
+
if (quote == null) {
|
177
|
+
return true;
|
178
|
+
}
|
179
|
+
|
180
|
+
if (quote < limits[type]) {
|
181
|
+
return true;
|
182
|
+
} else {
|
183
|
+
return false;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
|
188
|
+
async getPlanLimits() {
|
189
|
+
|
190
|
+
let limits;
|
191
|
+
if (this.project.profile.type === 'payment') {
|
192
|
+
|
193
|
+
const plan = this.project.profile.name;
|
194
|
+
switch (plan) {
|
195
|
+
case 'Sandbox':
|
196
|
+
limits = PLANS_LIST.SANDBOX;
|
197
|
+
break;
|
198
|
+
case 'Basic':
|
199
|
+
limits = PLANS_LIST.BASIC;
|
200
|
+
break;
|
201
|
+
case 'Premium':
|
202
|
+
limits = PLANS_LIST.PREMIUM;
|
203
|
+
break;
|
204
|
+
case 'Custom':
|
205
|
+
limits = PLANS_LIST.CUSTOM;
|
206
|
+
break;
|
207
|
+
case 'Sandbox':
|
208
|
+
limits = PLANS_LIST.SANDBOX;
|
209
|
+
break;
|
210
|
+
case 'Growth':
|
211
|
+
limits = PLANS_LIST.BASIC
|
212
|
+
break;
|
213
|
+
case 'Scale':
|
214
|
+
limits = PLANS_LIST.PREMIUM
|
215
|
+
break;
|
216
|
+
case 'Plus':
|
217
|
+
limits = PLANS_LIST.CUSTOM
|
218
|
+
break;
|
219
|
+
default:
|
220
|
+
limits = PLANS_LIST.FREE_TRIAL;
|
221
|
+
}
|
222
|
+
} else {
|
223
|
+
limits = PLANS_LIST.FREE_TRIAL;
|
224
|
+
}
|
225
|
+
return limits;
|
226
|
+
}
|
227
|
+
|
228
|
+
|
229
|
+
|
230
|
+
start() {
|
231
|
+
winston.verbose('QuoteManager start');
|
232
|
+
|
233
|
+
if (process.env.QUOTES_ENABLED !== undefined) {
|
234
|
+
if (process.env.QUOTES_ENABLED === false || process.env.QUOTES_ENABLED === 'false') {
|
235
|
+
quotes_enabled = false;
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
// TODO - Try to generalize to avoid repetition
|
240
|
+
let incrementEventHandler = (object) => { }
|
241
|
+
let checkEventHandler = (object) => { }
|
242
|
+
|
243
|
+
|
244
|
+
// REQUESTS EVENTS - START
|
245
|
+
// requestEvent.on('request.create.quote.before', async (payload) => {
|
246
|
+
// let result = await this.checkQuote(payload.project, payload.request, 'requests');
|
247
|
+
// if (result == true) {
|
248
|
+
// winston.info("Limit not reached - a request can be created")
|
249
|
+
// } else {
|
250
|
+
// winston.info("Requests limit reached for the current plan!")
|
251
|
+
// }
|
252
|
+
// return result;
|
253
|
+
// });
|
254
|
+
|
255
|
+
requestEvent.on('request.create.quote', async (payload) => {
|
256
|
+
if (quotes_enabled === true) {
|
257
|
+
winston.verbose("request.create.quote event catched");
|
258
|
+
let result = await this.incrementRequestsCount(payload.project, payload.request);
|
259
|
+
return result;
|
260
|
+
} else {
|
261
|
+
console.log("QUOTES DISABLED - request.create.quote event")
|
262
|
+
winston.debug("QUOTES DISABLED - request.create.quote event")
|
263
|
+
}
|
264
|
+
})
|
265
|
+
// REQUESTS EVENTS - END
|
266
|
+
|
267
|
+
|
268
|
+
// MESSAGES EVENTS - START
|
269
|
+
// messageEvent.on('message.create.quote.before', async (payload) => {
|
270
|
+
// let result = await this.checkQuote(payload.project, payload.message, 'messages');
|
271
|
+
// if (result == true) {
|
272
|
+
// winston.info("Limit not reached - a message can be created")
|
273
|
+
// } else {
|
274
|
+
// winston.info("Messages limit reached for the current plan!")
|
275
|
+
// }
|
276
|
+
// return result;
|
277
|
+
// })
|
278
|
+
|
279
|
+
messageEvent.on('message.create.quote', async (payload) => {
|
280
|
+
if (quotes_enabled === true) {
|
281
|
+
winston.verbose("message.create.quote event catched");
|
282
|
+
let result = await this.incrementMessagesCount(payload.project, payload.message);
|
283
|
+
return result;
|
284
|
+
} else {
|
285
|
+
winston.debug("QUOTES DISABLED - message.create.quote event")
|
286
|
+
}
|
287
|
+
})
|
288
|
+
// MESSAGES EVENTS - END
|
289
|
+
|
290
|
+
|
291
|
+
// EMAIL EVENTS - START - Warning! Can't be used for check quote
|
292
|
+
// emailEvent.on('email.send.before', async (payload) => {
|
293
|
+
// let result = await this.checkQuote(payload.project, payload.email, 'email');
|
294
|
+
// if (result == true) {
|
295
|
+
// winston.info("Limit not reached - a message can be created")
|
296
|
+
// } else {
|
297
|
+
// winston.info("Email limit reached for the current plan!")
|
298
|
+
// }
|
299
|
+
// return result;
|
300
|
+
// })
|
301
|
+
|
302
|
+
emailEvent.on('email.send.quote', async (payload) => {
|
303
|
+
if (quotes_enabled === true) {
|
304
|
+
winston.info("email.send event catched");
|
305
|
+
let result = await this.incrementEmailCount(payload.project, payload.email);
|
306
|
+
return result;
|
307
|
+
} else {
|
308
|
+
winston.debug("QUOTES DISABLED - email.send event")
|
309
|
+
}
|
310
|
+
})
|
311
|
+
// EMAIL EVENTS - END
|
312
|
+
}
|
313
|
+
|
314
|
+
|
315
|
+
}
|
316
|
+
|
317
|
+
module.exports = { QuoteManager };
|
package/services/cacheEnabler.js
CHANGED
@@ -42,6 +42,11 @@ class CacheEnabler {
|
|
42
42
|
this.widgets = false;
|
43
43
|
}
|
44
44
|
|
45
|
+
this.integrations = true;
|
46
|
+
if (process.env.CACHE_INTEGRATIONS_ENABLED=="false" || process.env.CACHE_INTEGRATIONS_ENABLED==false) {
|
47
|
+
this.integrations = false;
|
48
|
+
}
|
49
|
+
|
45
50
|
// this.user = true;
|
46
51
|
// if (process.env.CACHE_USER_ENABLED=="false" || process.env.CACHE_USER_ENABLED==false) {
|
47
52
|
// this.user = false;
|