@tiledesk/tiledesk-server 2.7.1 → 2.7.3

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 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 }