@tiledesk/tiledesk-server 2.7.1 → 2.7.3

Sign up to get free protection for your applications and to get access to all the features.
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.7.3
9
+ - Updated project profile call
10
+ - Updated tybot-connector to 0.2.59
11
+
12
+ # 2.7.2
13
+ - Improved QuoteManager with kbs and chatbots (disabled)
14
+ - Improved QuoteManager with AI multipliers
15
+
8
16
  # 2.7.1
9
17
  - Updated widget.json translation file
10
18
  - Improved widget White Label
@@ -184,8 +184,22 @@ class RoleChecker {
184
184
  }
185
185
  } else {
186
186
 
187
+ /**
188
+ * Updated by Johnny - 29mar2024 - START
189
+ */
190
+ // console.log("req.user: ", req.user);
191
+ if (req.user.email === process.env.ADMIN_EMAIL) {
192
+ req.user.attributes = { isSuperadmin: true };
193
+ next();
194
+ } else {
195
+ res.status(403).send({success: false, msg: 'you dont belong to the project.'});
196
+ }
197
+ /**
198
+ * Updated by Johnny - 29mar2024 - END
199
+ */
200
+
187
201
  // if (req.user) equals super admin next()
188
- res.status(403).send({success: false, msg: 'you dont belong to the project.'});
202
+ //res.status(403).send({success: false, msg: 'you dont belong to the project.'});
189
203
  }
190
204
 
191
205
  });
package/models/profile.js CHANGED
@@ -20,6 +20,9 @@ var ProfileSchema = new Schema({
20
20
  type: String,
21
21
  default: 'free',
22
22
  },
23
+ quotes: {
24
+ type: Object
25
+ },
23
26
  subStart: {
24
27
  type: Date,
25
28
  },
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.7.1",
4
+ "version": "2.7.3",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -48,7 +48,7 @@
48
48
  "@tiledesk/tiledesk-rasa-connector": "^1.0.10",
49
49
  "@tiledesk/tiledesk-telegram-connector": "^0.1.10",
50
50
  "@tiledesk/tiledesk-train-jobworker": "^0.0.7",
51
- "@tiledesk/tiledesk-tybot-connector": "^0.2.57",
51
+ "@tiledesk/tiledesk-tybot-connector": "^0.2.59",
52
52
  "@tiledesk/tiledesk-whatsapp-connector": "^0.1.64",
53
53
  "@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.7",
54
54
  "amqplib": "^0.5.5",
@@ -711,7 +711,8 @@ class RulesTrigger {
711
711
 
712
712
 
713
713
 
714
- var startText = "\\start";
714
+ var startText = "\start";
715
+ // var startText = "\\start";
715
716
  if (action.parameters && action.parameters.text) {
716
717
  startText = action.parameters.text;
717
718
  }
@@ -787,7 +788,7 @@ class RulesTrigger {
787
788
  'system',
788
789
  'Bot',
789
790
  request_id,
790
- '\\start', // / start
791
+ '\\start', // TODO CHANGE TO / start
791
792
  id_project,
792
793
  null,
793
794
  {subtype:'info', updateconversation : false}
@@ -1037,6 +1038,7 @@ class RulesTrigger {
1037
1038
  if (eventAttributes.participants && eventAttributes.participants.length>0) {
1038
1039
  participants = eventAttributes.participants;
1039
1040
  if (participants[0].indexOf("bot_")>-1) {
1041
+ // TODO CHANGE TO /start
1040
1042
  text = "\\start"; //if participants is passed than the bot reply to the first message "welcome" so I changed "welcome" with "\start"
1041
1043
  }
1042
1044
  // status = RequestConstants.ASSIGNED;
package/routes/auth.js CHANGED
@@ -72,14 +72,29 @@ router.post('/signup',
72
72
  } else {
73
73
  return userService.signup(req.body.email, req.body.password, req.body.firstname, req.body.lastname, false)
74
74
  .then(function (savedUser) {
75
-
76
-
75
+
77
76
  winston.debug('-- >> -- >> savedUser ', savedUser.toObject());
78
77
 
78
+ // let skipVerificationEmail = false;
79
+ // if (req.headers.authorization) {
80
+
81
+ // let token = req.headers.authorization.split(" ")[1];
82
+ // let decode = jwt.verify(token, configSecret)
83
+ // if (decode && (decode.email === process.env.ADMIN_EMAIL)) {
84
+ // skipVerificationEmail = true;
85
+ // winston.verbose("skip sending verification email")
86
+ // }
87
+ // }
88
+
89
+ // if (!req.body.disableEmail){
90
+ // if (!skipVerificationEmail) {
91
+ // emailService.sendVerifyEmailAddress(savedUser.email, savedUser);
92
+ // }
93
+ // }
94
+
79
95
  if (!req.body.disableEmail){
80
- emailService.sendVerifyEmailAddress(savedUser.email, savedUser);
96
+ emailService.sendVerifyEmailAddress(savedUser.email, savedUser);
81
97
  }
82
-
83
98
 
84
99
 
85
100
  /*
package/routes/faq_kb.js CHANGED
@@ -19,10 +19,23 @@ const trainingService = require('../services/trainingService');
19
19
 
20
20
  let chatbot_templates_api_url = process.env.CHATBOT_TEMPLATES_API_URL
21
21
 
22
- router.post('/', function (req, res) {
22
+ router.post('/', async function (req, res) {
23
23
  winston.debug('create BOT ', req.body);
24
24
  //create(name, url, projectid, user_id, type, description, webhook_url, webhook_enabled, language, template)
25
25
  //faqService.create(req.body.name, req.body.url, req.projectid, req.user.id, req.body.type, req.body.description, undefined, undefined, req.body.language, req.body.template, req.body.mainCategory, req.body.intentsEngine).then(function (savedFaq_kb) {
26
+ let quoteManager = req.app.get('quote_manager');
27
+ let limits = await quoteManager.getPlanLimits(req.project);
28
+ let chatbots_limit = limits.chatbots;
29
+ winston.debug("chatbots_limit for project " + req.projectid + ": " + chatbots_limit);
30
+
31
+ let chatbots_count = await Faq_kb.countDocuments({ id_project: req.projectid, type: { $ne: "identity" } }).exec();
32
+ winston.debug("chatbots_count for project " + req.projectid + ": " + chatbots_count);
33
+
34
+ if (chatbots_count >= chatbots_limit) {
35
+ //return res.status(403).send({ success: false, error: "Maximum number of chatbots reached for the current plan", plan_limit: chatbots_limit })
36
+ winston.info("Chatbots limit reached for project " + req.projectid + ". Block currently disabled.");
37
+ }
38
+
26
39
  faqService.create(req.body.name, req.body.url, req.projectid, req.user.id, req.body.type, req.body.description, req.body.webhook_url, req.body.webhook_enabled, req.body.language, req.body.template, req.body.mainCategory, req.body.intentsEngine, req.body.attributes).then(function (savedFaq_kb) {
27
40
  res.json(savedFaq_kb);
28
41
  });
package/routes/openai.js CHANGED
@@ -4,6 +4,7 @@ var { KBSettings } = require('../models/kb_setting');
4
4
  var openaiService = require('../services/openaiService');
5
5
  var winston = require('../config/winston');
6
6
  const { QuoteManager } = require('../services/QuoteManager');
7
+ const { MODEL_MULTIPLIER } = require('../utils/aiUtils');
7
8
 
8
9
  router.post('/', async (req, res) => {
9
10
 
@@ -60,8 +61,14 @@ router.post('/', async (req, res) => {
60
61
  json.messages.unshift(message);
61
62
  }
62
63
 
64
+ let multiplier = MODEL_MULTIPLIER[json.model];
65
+ if (!multiplier) {
66
+ multiplier = 1;
67
+ winston.info("No multiplier found for AI model")
68
+ }
69
+
63
70
  openaiService.completions(json, gptkey).then(async (response) => {
64
- let data = { createdAt: new Date(), tokens: response.data.usage.total_tokens }
71
+ let data = { createdAt: new Date(), tokens: response.data.usage.total_tokens, multiplier: multiplier }
65
72
  if (usePublicKey === true) {
66
73
  let incremented_key = await quoteManager.incrementTokenCount(req.project, data);
67
74
  winston.verbose("Tokens quota incremented for key " + incremented_key);
package/routes/project.js CHANGED
@@ -11,6 +11,7 @@ var operatingHoursService = require("../services/operatingHoursService");
11
11
  var winston = require('../config/winston');
12
12
  var roleChecker = require('../middleware/has-role');
13
13
 
14
+
14
15
  // THE THREE FOLLOWS IMPORTS ARE USED FOR AUTHENTICATION IN THE ROUTE
15
16
  var passport = require('passport');
16
17
  require('../middleware/passport')(passport);
@@ -20,6 +21,21 @@ var cacheUtil = require('../utils/cacheUtil');
20
21
  var orgUtil = require("../utils/orgUtil");
21
22
  var cacheEnabler = require("../services/cacheEnabler");
22
23
 
24
+ /**
25
+ * NEW
26
+ */
27
+ var jwt = require('jsonwebtoken');
28
+ var config = require('../config/database');
29
+
30
+ let configSecret = process.env.GLOBAL_SECRET || config.secret;
31
+ var pKey = process.env.GLOBAL_SECRET_OR_PUB_KEY;
32
+ if (pKey) {
33
+ configSecret = pKey.replace(/\\n/g, '\n');
34
+ }
35
+ /**
36
+ * End NEW
37
+ */
38
+
23
39
  router.post('/', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken], async (req, res) => {
24
40
 
25
41
  // create(name, createdBy, settings)
@@ -71,10 +87,219 @@ router.delete('/:projectid', [passport.authenticate(['basic', 'jwt'], { session:
71
87
  });
72
88
  });
73
89
 
90
+ // router.put('/:projectid/update', function (req, res) {
91
+ // // router.put('/:projectid/profile', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken], function (req, res) {
92
+
93
+ // // Get token from header authorization
94
+ // let token = req.headers.authorization;
95
+ // token = token.split(" ")[1];
96
+
97
+ // try {
98
+ // let decoded = jwt.verify(token, configSecret)
99
+ // winston.debug("user decode: ", decoded);
100
+
101
+ // if (!process.env.ADMIN_EMAIL) {
102
+ // winston.warn("Missing admin email parameter in environment");
103
+ // return res.status(401).send({ success: false, error: "Missing admin email parameter"});
104
+ // }
105
+
106
+ // if (decoded.email !== process.env.ADMIN_EMAIL) {
107
+ // winston.warn("Profile modification: permission denied.");
108
+ // return res.status(403).send({ success: false, error: "You don't have the permission required to modify the project profile"});
109
+ // }
110
+
111
+ // /**
112
+ // * modify the project profile here
113
+ // */
114
+ // var update = {};
115
+
116
+ // if (req.body.name!=undefined) {
117
+ // update.name = req.body.name;
118
+ // }
119
+
120
+ // if (req.body.activeOperatingHours!=undefined) {
121
+ // update.activeOperatingHours = req.body.activeOperatingHours;
122
+ // }
123
+
124
+ // if (req.body.operatingHours!=undefined) {
125
+ // update.operatingHours = req.body.operatingHours;
126
+ // }
127
+
128
+ // if (req.body.settings!=undefined) {
129
+ // update.settings = req.body.settings;
130
+ // }
131
+
132
+ // if (req.body["settings.email.autoSendTranscriptToRequester"]!=undefined) {
133
+ // update["settings.email.autoSendTranscriptToRequester"] = req.body["settings.email.autoSendTranscriptToRequester"];
134
+ // }
135
+ // if (req.body["settings.email.notification.conversation.assigned"]!=undefined) {
136
+ // update["settings.email.notification.conversation.assigned"] = req.body["settings.email.notification.conversation.assigned"];
137
+ // }
138
+ // if (req.body["settings.email.notification.conversation.pooled"]!=undefined) {
139
+ // update["settings.email.notification.conversation.pooled"] = req.body["settings.email.notification.conversation.pooled"];
140
+ // }
141
+ // if (req.body["settings.email.templates.assignedRequest"]!=undefined) {
142
+ // update["settings.email.templates.assignedRequest"] = req.body["settings.email.templates.assignedRequest"];
143
+ // }
144
+ // if (req.body["settings.email.templates.assignedEmailMessage"]!=undefined) {
145
+ // update["settings.email.templates.assignedEmailMessage"] = req.body["settings.email.templates.assignedEmailMessage"];
146
+ // }
147
+ // if (req.body["settings.email.templates.pooledRequest"]!=undefined) {
148
+ // update["settings.email.templates.pooledRequest"] = req.body["settings.email.templates.pooledRequest"];
149
+ // }
150
+ // if (req.body["settings.email.templates.pooledEmailMessage"]!=undefined) {
151
+ // update["settings.email.templates.pooledEmailMessage"] = req.body["settings.email.templates.pooledEmailMessage"];
152
+ // }
153
+ // if (req.body["settings.email.templates.newMessage"]!=undefined) {
154
+ // update["settings.email.templates.newMessage"] = req.body["settings.email.templates.newMessage"];
155
+ // }
156
+ // if (req.body["settings.email.templates.newMessageFollower"]!=undefined) {
157
+ // update["settings.email.templates.newMessageFollower"] = req.body["settings.email.templates.newMessageFollower"];
158
+ // }
159
+ // if (req.body["settings.email.templates.ticket"]!=undefined) {
160
+ // update["settings.email.templates.ticket"] = req.body["settings.email.templates.ticket"];
161
+ // }
162
+ // if (req.body["settings.email.templates.sendTranscript"]!=undefined) {
163
+ // update["settings.email.templates.sendTranscript"] = req.body["settings.email.templates.sendTranscript"];
164
+ // }
165
+ // if (req.body["settings.email.templates.emailDirect"]!=undefined) {
166
+ // update["settings.email.templates.emailDirect"] = req.body["settings.email.templates.emailDirect"];
167
+ // }
168
+ // if (req.body["settings.email.from"]!=undefined) {
169
+ // update["settings.email.from"] = req.body["settings.email.from"];
170
+ // }
171
+ // if (req.body["settings.email.config.host"]!=undefined) {
172
+ // update["settings.email.config.host"] = req.body["settings.email.config.host"];
173
+ // }
174
+ // if (req.body["settings.email.config.port"]!=undefined) {
175
+ // update["settings.email.config.port"] = req.body["settings.email.config.port"];
176
+ // }
177
+ // if (req.body["settings.email.config.secure"]!=undefined) {
178
+ // update["settings.email.config.secure"] = req.body["settings.email.config.secure"];
179
+ // }
180
+ // if (req.body["settings.email.config.user"]!=undefined) {
181
+ // update["settings.email.config.user"] = req.body["settings.email.config.user"];
182
+ // }
183
+ // if (req.body["settings.email.config.pass"]!=undefined) {
184
+ // update["settings.email.config.pass"] = req.body["settings.email.config.pass"];
185
+ // }
186
+ // if (req.body["settings.chat_limit_on"]!=undefined) {
187
+ // update["settings.chat_limit_on"] = req.body["settings.chat_limit_on"];
188
+ // }
189
+ // if (req.body["settings.max_agent_assigned_chat"]!=undefined) {
190
+ // update["settings.max_agent_assigned_chat"] = req.body["settings.max_agent_assigned_chat"];
191
+ // }
192
+ // if (req.body["settings.reassignment_on"]!=undefined) {
193
+ // update["settings.reassignment_on"] = req.body["settings.reassignment_on"];
194
+ // }
195
+ // if (req.body["settings.reassignment_delay"]!=undefined) {
196
+ // update["settings.reassignment_delay"] = req.body["settings.reassignment_delay"];
197
+ // }
198
+ // if (req.body["settings.automatic_unavailable_status_on"]!=undefined) {
199
+ // update["settings.automatic_unavailable_status_on"] = req.body["settings.automatic_unavailable_status_on"];
200
+ // }
201
+ // if (req.body["settings.automatic_idle_chats"]!=undefined) {
202
+ // update["settings.automatic_idle_chats"] = req.body["settings.automatic_idle_chats"];
203
+ // }
204
+
205
+ // if (req.body.widget!=undefined) {
206
+ // update.widget = req.body.widget;
207
+ // }
208
+ // if (req.body.versions!=undefined) {
209
+ // update.versions = req.body.versions;
210
+ // }
211
+ // if (req.body.channels!=undefined) {
212
+ // update.channels = req.body.channels;
213
+ // }
214
+ // if (req.body.ipFilterEnabled!=undefined) {
215
+ // update.ipFilterEnabled = req.body.ipFilterEnabled;
216
+ // }
217
+ // if (req.body.ipFilter!=undefined) {
218
+ // update.ipFilter = req.body.ipFilter;
219
+ // }
220
+ // if (req.body.ipFilterDenyEnabled!=undefined) {
221
+ // update.ipFilterDenyEnabled = req.body.ipFilterDenyEnabled;
222
+ // }
223
+ // if (req.body.ipFilterDeny!=undefined) {
224
+ // update.ipFilterDeny = req.body.ipFilterDeny;
225
+ // }
226
+ // if (req.body.bannedUsers!=undefined) {
227
+ // update.bannedUsers = req.body.bannedUsers;
228
+ // }
229
+ // if (req.body.profile!=undefined) {
230
+ // update.profile = req.body.profile;
231
+ // }
232
+
233
+ // winston.debug('UPDATE PROJECT REQ BODY ', update);
234
+
235
+ // Project.findByIdAndUpdate(req.params.projectid, update, { new: true, upsert: true }, function (err, updatedProject) {
236
+ // if (err) {
237
+ // winston.error('Error putting project ', err);
238
+ // return res.status(500).send({ success: false, msg: 'Error updating object.' });
239
+ // }
240
+ // projectEvent.emit('project.update', updatedProject );
241
+ // res.json(updatedProject);
242
+ // });
243
+
244
+ // } catch (err) {
245
+ // winston.warn("Profile modification: permission denied.");
246
+ // res.status(403).send({ success: false, error: "You don't have the permission required to modify the project profile"});
247
+ // }
248
+
249
+ // })
250
+
74
251
  router.put('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], function (req, res) {
252
+
75
253
  winston.debug('UPDATE PROJECT REQ BODY ', req.body);
76
254
 
77
255
  var update = {};
256
+
257
+ console.log("ADMIN EMAIL: ", process.env.ADMIN_EMAIL)
258
+ if (req.body.profile) {
259
+
260
+ if (req.user &&
261
+ req.user.attributes &&
262
+ req.user.attributes.isSuperadmin === true) {
263
+
264
+ winston.debug("Superadmin can modify the project profile")
265
+ update.profile = req.body.profile;
266
+
267
+ delete req.user.attributes.isSuperadmin;
268
+ }
269
+
270
+ else {
271
+ winston.verbose("Project profile can't be modified by the current user " + req.user._id);
272
+ return res.status(403).send({ success: false, error: "You don't have the permission required to modify the project profile"});
273
+ }
274
+
275
+ // check if super admin
276
+ // let token = req.headers.authorization
277
+ // token = token.split(" ")[1];
278
+
279
+ // let decoded = jwt.verify(token, configSecret);
280
+ // winston.debug("user decoded: ", decoded);
281
+ // console.log("user decoded: ", decoded);
282
+
283
+ // if (!process.env.ADMIN_EMAIL) {
284
+ // winston.warn("Missing admin email parameter in environment");
285
+ // return res.status(401).send({ success: false, error: "Missing admin email parameter"});
286
+ // }
287
+
288
+ // if (!decoded) {
289
+ // winston.warn("Profile modification: permission denied.");
290
+ // return res.status(403).send({ success: false, error: "You don't have the permission required to modify the project profile. Can't decode user."});
291
+ // }
292
+
293
+ // if (decoded.email !== process.env.ADMIN_EMAIL) {
294
+ // winston.warn("Profile modification: permission denied.");
295
+ // return res.status(403).send({ success: false, error: "You don't have the permission required to modify the project profile"});
296
+ // }
297
+
298
+ // console.log("You can modify the project profile");
299
+
300
+ // winston.info("Illegal field profile detected. Deny project profile update.");
301
+ // return res.status(403).send({ success: false, error: "You cannot edit the project profile."});
302
+ }
78
303
 
79
304
  //like patch
80
305
  if (req.body.name!=undefined) {
@@ -232,10 +457,6 @@ router.put('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: fa
232
457
  if (req.body.bannedUsers!=undefined) {
233
458
  update.bannedUsers = req.body.bannedUsers;
234
459
  }
235
-
236
- if (req.body.profile != undefined) {
237
- update.profile = req.body.profile;
238
- }
239
460
 
240
461
  // if (req.body.defaultLanguage!=undefined) {
241
462
  // update.defaultLanguage = req.body.defaultLanguage;
@@ -243,7 +464,6 @@ router.put('/:projectid', [passport.authenticate(['basic', 'jwt'], { session: fa
243
464
 
244
465
 
245
466
  winston.debug('UPDATE PROJECT REQ BODY ', update);
246
-
247
467
  // console.log("update",JSON.stringify(update));
248
468
 
249
469
  Project.findByIdAndUpdate(req.params.projectid, update, { new: true, upsert: true }, function (err, updatedProject) {
@@ -5,14 +5,14 @@ const messageEvent = require('../event/messageEvent');
5
5
  const emailEvent = require('../event/emailEvent');
6
6
 
7
7
  const PLANS_LIST = {
8
- FREE_TRIAL: { requests: 3000, messages: 0, tokens: 250000, email: 200, kbs: 50 }, // same as PREMIUM
9
- SANDBOX: { requests: 200, messages: 0, tokens: 10000, email: 200, kbs: 50 },
10
- BASIC: { requests: 800, messages: 0, tokens: 50000, email: 200, kbs: 150},
11
- PREMIUM: { requests: 3000, messages: 0, tokens: 250000, email: 200, kbs: 300},
12
- CUSTOM: { requests: 3000, messages: 0, tokens: 250000, email: 200, kbs: 300}
8
+ FREE_TRIAL: { requests: 3000, messages: 0, tokens: 250000, email: 200, chatbots: 20, kbs: 50 }, // same as PREMIUM
9
+ SANDBOX: { requests: 200, messages: 0, tokens: 10000, email: 200, chatbots: 2, kbs: 50 },
10
+ BASIC: { requests: 800, messages: 0, tokens: 50000, email: 200, chatbots: 5, kbs: 150},
11
+ PREMIUM: { requests: 3000, messages: 0, tokens: 250000, email: 200, chatbots: 20, kbs: 300},
12
+ CUSTOM: { requests: 3000, messages: 0, tokens: 250000, email: 200, chatbots: 20, kbs: 1000}
13
13
  }
14
14
 
15
- const typesList = ['requests', 'messages', 'email', 'tokens']
15
+ const typesList = ['requests', 'messages', 'email', 'tokens', 'chatbots', 'kbs']
16
16
 
17
17
  let quotes_enabled = true;
18
18
 
@@ -74,8 +74,11 @@ class QuoteManager {
74
74
  winston.debug("QUOTES DISABLED - incrementTokenCount")
75
75
  return key;
76
76
  }
77
-
78
- await this.tdCache.incrby(key, data.tokens);
77
+
78
+ let tokens = data.tokens * data.multiplier;
79
+ await this.tdCache.incrbyfloat(key, tokens);
80
+ // await this.tdCache.incrby(key, tokens);
81
+
79
82
  return key;
80
83
  }
81
84
  // INCREMENT KEY SECTION - END
@@ -156,6 +159,7 @@ class QuoteManager {
156
159
  this.project = project;
157
160
  let limits = await this.getPlanLimits();
158
161
  winston.verbose("limits for current plan: ", limits)
162
+
159
163
  let quote = await this.getCurrentQuote(project, object, type);
160
164
  winston.verbose("getCurrentQuote resp: ", quote)
161
165
 
@@ -194,16 +198,13 @@ class QuoteManager {
194
198
  case 'Custom':
195
199
  limits = PLANS_LIST.CUSTOM;
196
200
  break;
197
- case 'Sandbox':
198
- limits = PLANS_LIST.SANDBOX;
199
- break;
200
- case 'Growth':
201
+ case 'Growth': // OLD PLAN
201
202
  limits = PLANS_LIST.BASIC
202
203
  break;
203
- case 'Scale':
204
+ case 'Scale': // OLD PLAN
204
205
  limits = PLANS_LIST.PREMIUM
205
206
  break;
206
- case 'Plus':
207
+ case 'Plus': // OLD PLAN
207
208
  limits = PLANS_LIST.CUSTOM
208
209
  break;
209
210
  default:
@@ -212,7 +213,14 @@ class QuoteManager {
212
213
  } else {
213
214
  limits = PLANS_LIST.FREE_TRIAL;
214
215
  }
215
- return limits;
216
+
217
+ if (this.project?.profile?.quotes) {
218
+ let profile_quotes = this.project?.profile?.quotes;
219
+ const merged_quotes = Object.assign({}, limits, profile_quotes);
220
+ return merged_quotes;
221
+ } else {
222
+ return limits;
223
+ }
216
224
  }
217
225
 
218
226
 
@@ -226,7 +234,7 @@ class QuoteManager {
226
234
  }
227
235
  }
228
236
 
229
- winston.info("QUOTES ENABLED ? ", quotes_enabled);
237
+ winston.info("QUOTES ENABLED: " + quotes_enabled);
230
238
 
231
239
  // TODO - Try to generalize to avoid repetition
232
240
  let incrementEventHandler = (object) => { }
@@ -1,6 +1,6 @@
1
1
  //During the test the env variable is set to test
2
2
  process.env.NODE_ENV = 'test';
3
-
3
+ process.env.ADMIN_EMAIL = "admin@tiledesk.com";
4
4
  //var User = require('../models/user');
5
5
  var projectService = require('../services/projectService');
6
6
  var requestService = require('../services/requestService');
@@ -201,6 +201,33 @@ describe('/signup', () => {
201
201
 
202
202
  });
203
203
 
204
+ // it('signUpAdminNoVerificationEmail', (done) => {
205
+
206
+ // var email = "test-signup-" + Date.now() + "@email.com";
207
+ // var pwd = "pwd";
208
+
209
+ // chai.request(server)
210
+ // .post("/auth/signin")
211
+ // .send({ email: "admin@tiledesk.com", password: "adminadmin" })
212
+ // .end((err, res) => {
213
+
214
+ // // console.log("login with superadmin res.body: ", res.body)
215
+ // let superadmin_token = res.body.token;
216
+
217
+ // chai.request(server)
218
+ // .post("/auth/signup")
219
+ // .set('Authorization', superadmin_token)
220
+ // .send({ email: email, password: pwd, lastname: "lastname", firstname: "firstname", disableEmail: true })
221
+ // .end((err, res) => {
222
+
223
+ // // console.log("res.body: ", res.body);
224
+ // done();
225
+ // })
226
+ // })
227
+
228
+
229
+ // })
230
+
204
231
  // mocha test/authentication.js --grep 'signupUpperCaseEmail'
205
232
 
206
233
 
@@ -73,6 +73,74 @@ describe('FaqKBRoute', () => {
73
73
 
74
74
  }).timeout(20000);
75
75
 
76
+ /**
77
+ * This test will be no longer available after merge with master because
78
+ * the profile section can no longer be modified via api.
79
+ */
80
+ // it('createMaximumNumberExceeded', (done) => {
81
+
82
+ // var email = "test-signup-" + Date.now() + "@email.com";
83
+ // var pwd = "pwd";
84
+
85
+ // userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) {
86
+ // projectService.create("test-faqkb-create", savedUser._id).then(function (savedProject) {
87
+
88
+ // chai.request(server)
89
+ // .put('/projects/' + savedProject._id)
90
+ // .auth(email, pwd)
91
+ // .send({ profile: { quotes: { chatbots: 2 } } })
92
+ // .end((err, res) => {
93
+
94
+ // if (log) { console.log("res.body", res.body); }
95
+
96
+ // chai.request(server)
97
+ // .post('/' + savedProject._id + '/faq_kb')
98
+ // .auth(email, pwd)
99
+ // .send({ "name": "testbot1", type: "external", language: 'en' })
100
+ // .end((err, res) => {
101
+ // if (log) { console.log("res.body", res.body); }
102
+ // res.should.have.status(200);
103
+ // res.body.should.be.a('object');
104
+ // expect(res.body.name).to.equal("testbot1");
105
+ // expect(res.body.language).to.equal("en");
106
+
107
+ // chai.request(server)
108
+ // .post('/' + savedProject._id + '/faq_kb')
109
+ // .auth(email, pwd)
110
+ // .send({ "name": "testbot2", type: "external", language: 'en' })
111
+ // .end((err, res) => {
112
+ // if (log) { console.log("res.body", res.body); }
113
+ // res.should.have.status(200);
114
+ // res.body.should.be.a('object');
115
+ // expect(res.body.name).to.equal("testbot2");
116
+ // expect(res.body.language).to.equal("en");
117
+
118
+ // chai.request(server)
119
+ // .post('/' + savedProject._id + '/faq_kb')
120
+ // .auth(email, pwd)
121
+ // .send({ "name": "testbot3", type: "external", language: 'en' })
122
+ // .end((err, res) => {
123
+
124
+ // if (log) { console.log("res.body", res.body); }
125
+
126
+ // res.should.have.status(403);
127
+ // res.body.should.be.a('object');
128
+ // expect(res.body.success).to.equal(false);
129
+ // expect(res.body.error).to.equal("Maximum number of chatbots reached for the current plan");
130
+ // expect(res.body.plan_limit).to.equal(2);
131
+
132
+ // done()
133
+
134
+ // });
135
+ // });
136
+ // });
137
+ // })
138
+ // });
139
+ // });
140
+
141
+ // }).timeout(20000);
142
+
143
+
76
144
  // it('train with tiledesk-ai', (done) => {
77
145
  // var email = "test-signup-" + Date.now() + "@email.com";
78
146
  // var pwd = "pwd";
@@ -69,9 +69,8 @@ describe('messageService', function () {
69
69
  let obj = { createdAt: new Date() }
70
70
 
71
71
  let quotes = await qm.getAllQuotes(savedProject, obj);
72
- console.log("quotes: ", quotes);
73
- quotes.messages.quote.should.be.a('string');
74
- expect(quotes.messages.quote).to.equal('1');
72
+ quotes.messages.quote.should.be.a('number');
73
+ expect(quotes.messages.quote).to.equal(1);
75
74
 
76
75
  done();
77
76
 
@@ -84,7 +83,7 @@ describe('messageService', function () {
84
83
  });
85
84
 
86
85
  });
87
- });
86
+ }).timeout(10000);
88
87
 
89
88
  it('createMessage', function (done) {
90
89
  // this.timeout(10000);
@@ -1,5 +1,6 @@
1
1
  //During the test the env variable is set to test
2
2
  process.env.NODE_ENV = 'test';
3
+ // process.env.GPTKEY = 'customgptkey';
3
4
 
4
5
  let log = false;
5
6
  var projectService = require('../services/projectService');
@@ -67,7 +68,43 @@ describe('OpenaiRoute', () => {
67
68
  // })
68
69
  // }).timeout(20000)
69
70
 
70
- it('completions missing gptkey', (done) => {
71
+ // it('completions missing gptkey', (done) => {
72
+
73
+ // var email = "test-signup-" + Date.now() + "@email.com";
74
+ // var pwd = "pwd";
75
+
76
+ // userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
77
+ // projectService.create("test-openai-create", savedUser._id).then((savedProject) => {
78
+
79
+ // chai.request(server)
80
+ // .post('/' + savedProject._id + '/kbsettings')
81
+ // .auth(email, pwd)
82
+ // .send({}) // can be empty
83
+ // .end((err, res) => {
84
+ // if (log) { console.log("create kbsettings res.body: ", res.body); }
85
+ // res.should.have.status(200);
86
+ // res.body.should.be.a('object');
87
+
88
+ // chai.request(server)
89
+ // .post('/' + savedProject._id + '/openai')
90
+ // .auth(email, pwd)
91
+ // .send({ question: "Provide 3 names for a dog", context: "you are an awesome assistant", max_tokens: 100, temperature: 0, model: "gpt-3.5-turbo" })
92
+ // .end((err, res) => {
93
+ // if (log) { console.log("res.body: ", res.body); }
94
+ // console.log("res.body: ", res.body)
95
+ // // res.should.have.status(400);
96
+ // // res.body.should.be.a('object');
97
+ // // expect(res.body.success).to.equal(false);
98
+ // // expect(res.body.message).to.equal("Missing gptkey parameter");
99
+
100
+ // done();
101
+ // })
102
+ // })
103
+ // })
104
+ // })
105
+ // }).timeout(20000)
106
+
107
+ it('newCompletionsMissingGptkey', (done) => {
71
108
 
72
109
  var email = "test-signup-" + Date.now() + "@email.com";
73
110
  var pwd = "pwd";
@@ -76,32 +113,61 @@ describe('OpenaiRoute', () => {
76
113
  projectService.create("test-openai-create", savedUser._id).then((savedProject) => {
77
114
 
78
115
  chai.request(server)
79
- .post('/' + savedProject._id + '/kbsettings')
116
+ .post('/' + savedProject._id + '/openai')
80
117
  .auth(email, pwd)
81
- .send({}) // can be empty
118
+ .send({ question: "Provide 3 names for a dog", context: "you are an awesome assistant", max_tokens: 100, temperature: 0, model: "gpt-3.5-turbo" })
82
119
  .end((err, res) => {
83
- if (log) { console.log("create kbsettings res.body: ", res.body); }
84
- res.should.have.status(200);
120
+ if (log) { console.log("res.body: ", res.body); }
121
+ res.should.have.status(400);
85
122
  res.body.should.be.a('object');
123
+ expect(res.body.success).to.equal(false);
124
+ expect(res.body.message).to.equal("Missing gptkey parameter");
86
125
 
87
- chai.request(server)
88
- .post('/' + savedProject._id + '/openai')
89
- .auth(email, pwd)
90
- .send({ question: "Provide 3 names for a dog", context: "you are an awesome assistant", max_tokens: 100, temperature: 0, model: "gpt-3.5-turbo" })
91
- .end((err, res) => {
92
- if (log) {console.log("res.body: ", res.body);}
93
- res.should.have.status(400);
94
- res.body.should.be.a('object');
95
- expect(res.body.success).to.equal(false);
96
- expect(res.body.message).to.equal("Missing gptkey parameter");
97
-
98
- done();
99
- })
126
+ done();
100
127
  })
128
+
129
+
101
130
  })
102
131
  })
103
- }).timeout(20000)
132
+ }).timeout(10000)
133
+
134
+
135
+ /**
136
+ * This test will be no longer available after merge with master because
137
+ * the profile section can no longer be modified via api.
138
+ */
139
+ // it('completionsWithProfileModified', (done) => {
140
+
141
+ // var email = "test-signup-" + Date.now() + "@email.com";
142
+ // var pwd = "pwd";
143
+
144
+ // userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
145
+ // projectService.create("test-openai-create", savedUser._id).then((savedProject) => {
146
+
147
+ // chai.request(server)
148
+ // .put('/projects/' + savedProject._id)
149
+ // .auth(email, pwd)
150
+ // .send({ profile: { quotes: { tokens: 400000, kbs: 100 } } })
151
+ // .end((err, res) => {
152
+ // if (log) { console.log("res.body: ", res.body); };
153
+ // console.log("res.body: ", res.body)
154
+
155
+ // chai.request(server)
156
+ // .post('/' + savedProject._id + '/openai')
157
+ // .auth(email, pwd)
158
+ // .send({ question: "Provide 3 names for a dog", context: "you are an awesome assistant", max_tokens: 100, temperature: 0, model: "gpt-3.5-turbo" })
159
+ // .end((err, res) => {
160
+
161
+ // if (log) { console.log("res.body: ", res.body); }
162
+ // done();
104
163
 
164
+ // })
165
+
166
+
167
+ // })
168
+ // })
169
+ // })
170
+ // }).timeout(10000)
105
171
 
106
172
  });
107
173
 
@@ -0,0 +1,97 @@
1
+ //During the test the env variable is set to test
2
+ process.env.NODE_ENV = 'test';
3
+ process.env.ADMIN_EMAIL = "admin@tiledesk.com";
4
+
5
+ let log = false;
6
+ var projectService = require('../services/projectService');
7
+ var userService = require('../services/userService');
8
+
9
+ //Require the dev-dependencies
10
+ let chai = require('chai');
11
+ let chaiHttp = require('chai-http');
12
+ let server = require('../app');
13
+ let should = chai.should();
14
+ var fs = require('fs');
15
+ const path = require('path');
16
+
17
+ // chai.config.includeStack = true;
18
+
19
+ var expect = chai.expect;
20
+ var assert = chai.assert;
21
+
22
+ chai.use(chaiHttp);
23
+
24
+ describe('ProjectRoute', () => {
25
+
26
+ describe('/create', () => {
27
+
28
+ it('updateProjectProfileWithSuperAdminCredential', (done) => {
29
+
30
+ var email = "test-signup-" + Date.now() + "@email.com";
31
+ var pwd = "pwd";
32
+
33
+ userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
34
+ projectService.create("test-project-create", savedUser._id).then((savedProject) => {
35
+
36
+ chai.request(server)
37
+ .post('/auth/signin')
38
+ .send({ email: "admin@tiledesk.com", password: "adminadmin" })
39
+ .end((err, res) => {
40
+
41
+ if (log) { console.log("login with superadmin res.body: ", res.body) };
42
+ res.should.have.status(200);
43
+ res.body.should.be.a('object');
44
+ expect(res.body.success).to.equal(true);
45
+ expect(res.body.token).not.equal(null);
46
+
47
+ let superadmin_token = res.body.token;
48
+
49
+ chai.request(server)
50
+ // .put('/projects/' + savedProject._id + "/update")
51
+ .put('/projects/' + savedProject._id)
52
+ .set('Authorization', superadmin_token)
53
+ .send({ profile: { name: "Custom", quotes: { kbs: 1000} } })
54
+ .end((err, res) => {
55
+
56
+ if (log) { console.log("update project profile res.body: ", res.body) };
57
+ res.should.have.status(200);
58
+ res.body.should.be.a('object');
59
+ expect(res.body.profile.name).to.equal("Custom");
60
+ // expect(res.body.profile.quotes.kbs).to.equal(1000);
61
+
62
+ done();
63
+ })
64
+ })
65
+ })
66
+ })
67
+ }).timeout(10000)
68
+
69
+ it('denyUpdateProjectProfile', (done) => {
70
+
71
+ var email = "test-signup-" + Date.now() + "@email.com";
72
+ var pwd = "pwd";
73
+
74
+ userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => {
75
+ projectService.create("test-project-create", savedUser._id).then((savedProject) => {
76
+
77
+ chai.request(server)
78
+ .put('/projects/' + savedProject._id)
79
+ // .put('/projects/' + savedProject._id + "/update")
80
+ .auth(email, pwd)
81
+ .send({ profile: { name: "Custom", quotes: { kbs: 1000} } })
82
+ .end((err, res) => {
83
+
84
+ if (log) { console.log("update project profile res.body: ", res.body) };
85
+ res.should.have.status(403);
86
+ expect(res.body.success).to.equal(false);
87
+ expect(res.body.error).to.equal("You don't have the permission required to modify the project profile");
88
+ done();
89
+ })
90
+ })
91
+ })
92
+ }).timeout(10000)
93
+ });
94
+
95
+ });
96
+
97
+
@@ -1,3 +1,6 @@
1
+ process.env.NODE_ENV = 'test';
2
+ process.env.QUOTES_ENABLED = 'true';
3
+
1
4
  const { QuoteManager } = require('../services/QuoteManager');
2
5
  const pubModulesManager = require('../pubmodules/pubModulesManager'); // on constructor init is undefined beacusae pub module is loaded after
3
6
  var projectService = require('../services/projectService');
@@ -198,7 +201,7 @@ describe('QuoteManager', function () {
198
201
  chai.request(server)
199
202
  .post('/' + savedProject._id + "/openai/quotes")
200
203
  .auth(email, pwd)
201
- .send({ createdAt: createdAt , tokens: 128 })
204
+ .send({ createdAt: createdAt , tokens: 128, multiplier: 25 })
202
205
  .end((err, res) => {
203
206
  if (log) { console.log("res.body", res.body )};
204
207
  res.should.have.status(200);
@@ -210,7 +213,8 @@ describe('QuoteManager', function () {
210
213
  let message_resp = "value incremented for key " + key;
211
214
  expect(res.body.message).to.equal(message_resp);
212
215
  expect(res.body.key).to.equal(key);
213
- expect(res.body.currentQuote).to.equal(128);
216
+ let expected_quote = 128 * 25;
217
+ expect(res.body.currentQuote).to.equal(expected_quote);
214
218
 
215
219
 
216
220
  done();
package/utils/TdCache.js CHANGED
@@ -103,6 +103,20 @@ class TdCache {
103
103
  })
104
104
  }
105
105
 
106
+ async incrbyfloat(key, increment) {
107
+ return new Promise( async (resolve, reject) => {
108
+ try {
109
+ await this.client.incrbyfloat(key, increment);
110
+ }
111
+
112
+ catch(error) {
113
+ console.error("Error on incrby: ", error);
114
+ reject(error);
115
+ }
116
+ return resolve();
117
+ })
118
+ }
119
+
106
120
  async hset(dict_key, key, value, options) {
107
121
  //console.log("hsetting dict_key key value", dict_key, key, value)
108
122
  return new Promise( async (resolve, reject) => {
@@ -0,0 +1,7 @@
1
+ MODEL_MULTIPLIER = {
2
+ "gpt-3.5-turbo": 0.6,
3
+ "gpt-4": 25,
4
+ "gpt-4-turbo-preview": 12
5
+ }
6
+
7
+ module.exports = { MODEL_MULTIPLIER }