@tiledesk/tiledesk-server 2.4.100 → 2.4.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 +4 -0
- package/app.js +45 -9
- package/event/emailEvent.js +13 -0
- package/event/integrationEvent.js +13 -0
- package/models/integrations.js +23 -0
- package/package.json +1 -1
- 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/kbsettings.js +8 -76
- package/routes/openai.js +52 -14
- 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 +12 -12
- package/services/requestService.js +1764 -1421
- package/services/trainingService.js +6 -2
- 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;
|