@tiledesk/tiledesk-server 2.3.6 → 2.3.7-1.2

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.
Files changed (126) hide show
  1. package/.github/workflows/docker-community-worker-push-latest.yml +23 -0
  2. package/.github/workflows/docker-image-tag-worker-community-tag-push.yml +22 -0
  3. package/CHANGELOG.md +361 -3
  4. package/Dockerfile-jobs +31 -0
  5. package/app.js +62 -69
  6. package/channels/chat21/chat21Handler.js +37 -6
  7. package/channels/chat21/chat21WebHook.js +62 -34
  8. package/channels/chat21/package-lock.json +663 -706
  9. package/channels/chat21/package.json +2 -2
  10. package/config/labels/widget.json +337 -136
  11. package/deploy.sh +2 -0
  12. package/event/messageEvent.js +110 -9
  13. package/jobs.js +80 -0
  14. package/jobsManager.js +47 -0
  15. package/middleware/has-role.js +10 -3
  16. package/middleware/ipFilter.js +220 -0
  17. package/middleware/passport.js +8 -2
  18. package/models/department.js +1 -1
  19. package/models/faq.js +77 -25
  20. package/models/faq_kb.js +19 -0
  21. package/models/message.js +10 -8
  22. package/models/project.js +10 -0
  23. package/models/project_user.js +10 -0
  24. package/models/request.js +12 -1
  25. package/package.json +12 -11
  26. package/pubmodules/activities/activityArchiver.js +216 -90
  27. package/pubmodules/activities/routes/activity.js +1 -1
  28. package/pubmodules/apps/index.js +8 -0
  29. package/pubmodules/apps/listener.js +27 -0
  30. package/pubmodules/cache/index.js +2 -0
  31. package/pubmodules/cache/mongoose-cachegoose-fn.js +630 -0
  32. package/pubmodules/canned/cannedResponse.js +4 -0
  33. package/pubmodules/canned/cannedResponseRoute.js +10 -5
  34. package/pubmodules/dialogflow/index.js +10 -0
  35. package/pubmodules/dialogflow/listener.js +66 -0
  36. package/pubmodules/emailNotification/requestNotification.js +58 -28
  37. package/pubmodules/events/eventRoute.js +49 -24
  38. package/pubmodules/messageTransformer/messageHandlebarsTransformerInterceptor.js +6 -1
  39. package/pubmodules/messageTransformer/messageTransformerInterceptor.js +10 -4
  40. package/pubmodules/pubModulesManager.js +173 -7
  41. package/pubmodules/queue/index.js +4 -0
  42. package/pubmodules/queue/reconnect.js +331 -0
  43. package/pubmodules/queue/reconnectFanout.js +256 -0
  44. package/pubmodules/rasa/listener.js +5 -5
  45. package/pubmodules/routing-queue/index.js +3 -0
  46. package/pubmodules/routing-queue/listener.js +328 -0
  47. package/pubmodules/rules/conciergeBot.js +2 -2
  48. package/pubmodules/scheduler/tasks/closeAgentUnresponsiveRequestTask.js +6 -1
  49. package/pubmodules/scheduler/tasks/closeBotUnresponsiveRequestTask.js +7 -1
  50. package/pubmodules/tilebot/index.js +11 -0
  51. package/pubmodules/tilebot/listener.js +85 -0
  52. package/pubmodules/trigger/rulesTrigger.js +137 -14
  53. package/pubmodules/trigger/start.js +5 -1
  54. package/pubmodules/whatsapp/index.js +7 -0
  55. package/pubmodules/whatsapp/listener.js +32 -0
  56. package/routes/auth.js +7 -2
  57. package/routes/campaigns.js +3 -3
  58. package/routes/department.js +3 -2
  59. package/routes/email.js +32 -2
  60. package/routes/faq.js +37 -2
  61. package/routes/faq_kb.js +496 -133
  62. package/routes/faqpub.js +5 -0
  63. package/routes/lead.js +56 -0
  64. package/routes/message.js +196 -14
  65. package/routes/messagesRoot.js +39 -0
  66. package/routes/project.js +76 -4
  67. package/routes/project_user.js +11 -1
  68. package/routes/project_user_test.js +19 -0
  69. package/routes/request.js +134 -30
  70. package/routes/troubleshooting.js +12 -0
  71. package/routes/users-util.js +39 -0
  72. package/routes/users.js +1 -1
  73. package/routes/widget.js +64 -2
  74. package/services/BotSubscriptionNotifier.js +5 -0
  75. package/services/banUserNotifier.js +86 -0
  76. package/services/cacheEnabler.js +56 -0
  77. package/services/chatbotService.js +101 -0
  78. package/services/departmentService.js +25 -3
  79. package/services/emailService.js +170 -28
  80. package/services/faqBotHandler.js +2 -3
  81. package/services/faqService.js +28 -3
  82. package/services/geoService.js +36 -6
  83. package/services/labelService.js +1 -1
  84. package/services/leadService.js +3 -2
  85. package/services/messageService.js +4 -2
  86. package/services/modulesManager.js +23 -76
  87. package/services/operatingHoursService.js +9 -4
  88. package/services/requestService.js +75 -39
  89. package/services/subscriptionNotifier.js +9 -4
  90. package/services/trainingService.js +106 -0
  91. package/template/email/assignedEmailMessage.html +21 -11
  92. package/template/email/assignedRequest.html +21 -11
  93. package/template/email/beenInvitedExistingUser.html +16 -6
  94. package/template/email/beenInvitedNewUser.html +16 -6
  95. package/template/email/emailDirect.html +130 -0
  96. package/template/email/newMessage.html +18 -8
  97. package/template/email/newMessageFollower.html +22 -12
  98. package/template/email/passwordChanged.html +15 -5
  99. package/template/email/pooledEmailMessage.html +21 -11
  100. package/template/email/pooledRequest.html +20 -10
  101. package/template/email/resetPassword.html +15 -5
  102. package/template/email/sendTranscript.html +7 -4
  103. package/template/email/ticket.html +17 -7
  104. package/template/email/verify.html +15 -5
  105. package/test/cannedRoute.js +157 -0
  106. package/test/chatbot-mock.js +127 -0
  107. package/test/example-json-intents.txt +1 -0
  108. package/test/example-json.txt +1 -0
  109. package/test/example.json +1 -0
  110. package/test/faqRoute.js +353 -208
  111. package/test/faqkbRoute.js +669 -64
  112. package/test/imageRoute.js +1 -1
  113. package/test/messageRoute.js +387 -5
  114. package/test/requestRoute.js +6 -6
  115. package/test/requestService.js +55 -4
  116. package/test-int/cache-project.js +90 -0
  117. package/test-int/cache-project_user.js +88 -0
  118. package/utils/UIDGenerator.js +20 -0
  119. package/utils/cacheUtil.js +2 -2
  120. package/utils/orgUtil.js +3 -3
  121. package/utils/promiseUtil.js +31 -0
  122. package/utils/recipientEmailUtil.js +66 -0
  123. package/utils/sendEmailUtil.js +34 -0
  124. package/utils/sendMessageUtil.js +1 -1
  125. package/utils/stringUtil.js +12 -0
  126. package/websocket/webSocketServer.js +33 -10
@@ -24,6 +24,7 @@ var licenseKey = process.env.LICENSE_KEY;
24
24
  if (licenseKey) {
25
25
  var maskedLicenseKey = MaskData.maskPhone(licenseKey, maskOptions);
26
26
  winston.info("LicenseKey: " + maskedLicenseKey);
27
+ // winston.info("LicenseKey: " + licenseKey);
27
28
  }
28
29
 
29
30
  class ModulesManager {
@@ -35,12 +36,8 @@ class ModulesManager {
35
36
  this.facebookRoute = undefined;
36
37
  this.jwthistoryArchiver = undefined;
37
38
  this.jwthistoryRoute = undefined;
38
- this.dialogflowListener = undefined;
39
39
  this.requestHistoryArchiver = undefined;
40
- this.requestHistoryRoute = undefined;
41
- this.routingQueue = undefined;
42
- this.queue = undefined;
43
- this.cache = undefined;
40
+ this.requestHistoryRoute = undefined;
44
41
  this.visitorCounterRoute = undefined;
45
42
  this.visitorCounterMiddleware = undefined;
46
43
  this.widgetsRoute = undefined;
@@ -201,62 +198,19 @@ class ModulesManager {
201
198
 
202
199
 
203
200
 
204
- try {
205
- this.dialogflowListener = require('@tiledesk-ent/tiledesk-server-dialogflow').listener;
206
- // this.dialogflowListener.listen();
207
- winston.debug("this.dialogflowListener:"+ this.dialogflowListener);
208
-
209
- winston.info("ModulesManager dialogflow initialized");
210
- } catch(err) {
211
- if (err.code == 'MODULE_NOT_FOUND') {
212
- winston.info("ModulesManager init dialogflow module not found");
213
- }else {
214
- winston.error("ModulesManager error initializing init dialogflow module", err);
215
- }
216
- }
217
-
218
-
219
- try {
220
- this.routingQueue = require('@tiledesk-ent/tiledesk-server-routing-queue').listener;
221
- // this.routingQueue.listen();
222
- winston.debug("this.routingQueue:"+ this.routingQueue);
223
-
224
- winston.info("ModulesManager routing queue initialized");
225
- } catch(err) {
226
- if (err.code == 'MODULE_NOT_FOUND') {
227
- winston.info("ModulesManager init routing queue module not found");
228
- }else {
229
- winston.error("ModulesManager error initializing init routing queue module", err);
230
- }
231
- }
232
-
233
-
234
-
235
- try {
236
- this.queue = require('@tiledesk-ent/tiledesk-server-queue');
237
- winston.debug("this.queue:"+ this.queue);
238
-
239
- winston.info("ModulesManager queue initialized");
240
- } catch(err) {
241
- if (err.code == 'MODULE_NOT_FOUND') {
242
- winston.info("ModulesManager init queue module not found");
243
- }else {
244
- winston.error("ModulesManager error initializing init queue module", err);
245
- }
246
- }
247
-
201
+ // try {
202
+ // this.dialogflowListener = require('@tiledesk-ent/tiledesk-server-dialogflow').listener;
203
+ // // this.dialogflowListener.listen();
204
+ // winston.debug("this.dialogflowListener:"+ this.dialogflowListener);
248
205
 
249
- try {
250
- this.cache = require('@tiledesk-ent/tiledesk-server-cache').cachegoose(config.mongoose);
251
- winston.debug("this.cache:"+ this.cache);
252
- winston.info("ModulesManager cache initialized");
253
- } catch(err) {
254
- if (err.code == 'MODULE_NOT_FOUND') {
255
- winston.info("ModulesManager init cache module not found");
256
- }else {
257
- winston.error("ModulesManager error initializing init cache module", err);
258
- }
259
- }
206
+ // winston.info("ModulesManager dialogflow initialized");
207
+ // } catch(err) {
208
+ // if (err.code == 'MODULE_NOT_FOUND') {
209
+ // winston.info("ModulesManager init dialogflow module not found");
210
+ // }else {
211
+ // winston.error("ModulesManager error initializing init dialogflow module", err);
212
+ // }
213
+ // }
260
214
 
261
215
 
262
216
 
@@ -329,22 +283,15 @@ class ModulesManager {
329
283
  winston.info("ModulesManager error starting requestHistoryArchiver module", err);
330
284
  }
331
285
  }
332
- if (this.routingQueue) {
333
- try {
334
- this.routingQueue.listen();
335
- winston.info("ModulesManager routingQueue started");
336
- } catch(err) {
337
- winston.info("ModulesManager error starting routingQueue module", err);
338
- }
339
- }
340
- if (this.dialogflowListener) {
341
- try {
342
- this.dialogflowListener.listen();
343
- winston.info("ModulesManager dialogflowListener started");
344
- } catch(err) {
345
- winston.info("ModulesManager error starting dialogflowListener module", err);
346
- }
347
- }
286
+
287
+ // if (this.dialogflowListener) {
288
+ // try {
289
+ // this.dialogflowListener.listen();
290
+ // winston.info("ModulesManager dialogflowListener started");
291
+ // } catch(err) {
292
+ // winston.info("ModulesManager error starting dialogflowListener module", err);
293
+ // }
294
+ // }
348
295
 
349
296
 
350
297
 
@@ -4,16 +4,19 @@ var Project = require("../models/project");
4
4
  var moment_tz = require('moment-timezone');
5
5
  var winston = require('../config/winston');
6
6
  var cacheUtil = require('../utils/cacheUtil');
7
-
7
+ var cacheEnabler = require("../services/cacheEnabler");
8
8
 
9
9
  class OperatingHoursService {
10
10
 
11
11
  projectIsOpenNow(projectId, callback) {
12
12
 
13
13
  // winston.debug('O ---> [ OHS ] -> PROJECT ID ', projectId)
14
- Project.findOne({_id: projectId, status: 100})
15
- //@DISABLED_CACHE .cache(cacheUtil.defaultTTL, "projects:id:"+projectId)
16
- .exec(function (err, project) {
14
+ let q = Project.findOne({_id: projectId, status: 100});
15
+ if (cacheEnabler.project) {
16
+ q.cache(cacheUtil.longTTL, "projects:id:"+projectId) //project_cache
17
+ winston.debug('project cache enabled');
18
+ }
19
+ q.exec(function (err, project) {
17
20
  // winston.debug("XXXXXXXX project", project);
18
21
  if (err) {
19
22
  winston.error("O ---> [ OHS ] -> ERROR GETTING PROJECT ", err);
@@ -36,6 +39,8 @@ class OperatingHoursService {
36
39
 
37
40
  // IF THE TRIAL IS EXPIRED OR IF THE SUBSCIPTION IS NOT ACTIVE THE PROJECT IS ALWAYS OPEN EVEN IF activeOperatingHours IS SETTED TO true AND, FOR EXAMPLE,
38
41
  // THE USER HAS SETTED ALL DAYS TO CLOSED
42
+
43
+ //secondo me qui manca un parentesi tonda per gli or
39
44
  if (project.profile && (project.profile.type === 'free' && project.trialExpired === true) || (project.profile.type === 'payment' && project.isActiveSubscription === false)) {
40
45
  winston.debug('O ---> [ OHS ] -> trial Expired OR Subscription NOT Active - PROJECT ALWAYS OPEN')
41
46
  callback(true, null) ;
@@ -7,11 +7,12 @@ var messageService = require('../services/messageService');
7
7
  const requestEvent = require('../event/requestEvent');
8
8
  const leadEvent = require('../event/leadEvent');
9
9
  var winston = require('../config/winston');
10
- const uuidv4 = require('uuid/v4');
11
10
  var RequestConstants = require("../models/requestConstants");
12
11
  var requestUtil = require("../utils/requestUtil");
13
12
  var cacheUtil = require("../utils/cacheUtil");
14
13
  var arrayUtil = require("../utils/arrayUtil");
14
+ var cacheEnabler = require("../services/cacheEnabler");
15
+ var UIDGenerator = require("../utils/UIDGenerator");
15
16
 
16
17
  class RequestService {
17
18
 
@@ -62,7 +63,8 @@ class RequestService {
62
63
 
63
64
 
64
65
  sendMessageUpdateLead() {
65
- leadEvent.on('lead.fullname.update', function(lead) {
66
+ leadEvent.on('lead.fullname.email.update', function(lead) {
67
+ winston.debug("lead.fullname.email.update ");
66
68
  // leadEvent.on('lead.update', function(lead) {
67
69
 
68
70
  setImmediate(() => {
@@ -226,16 +228,21 @@ class RequestService {
226
228
  winston.debug("id_project:" + id_project);
227
229
  winston.debug("nobot:"+ nobot);
228
230
 
229
- return Request
230
- .findOne({request_id: request_id, id_project: id_project})
231
- //@DISABLED_CACHE .cache(cacheUtil.defaultTTL, id_project+":requests:request_id:"+request_id)
232
- .exec( function(err, request) {
231
+ let q= Request
232
+ .findOne({request_id: request_id, id_project: id_project});
233
+
234
+ // if (cacheEnabler.request) { //(node:60837) UnhandledPromiseRejectionWarning: VersionError: No matching document found for id "633efe246a6cc0eda5732684" version 0 modifiedPaths "status, participants, participantsAgents, department, assigned_at, snapshot, snapshot.department, snapshot.department.updatedAt, snapshot.agents"
235
+ // q.cache(cacheUtil.defaultTTL, id_project+":requests:request_id:"+request_id+":simple") //request_cache
236
+ // winston.debug('request cache enabled');
237
+ // }
238
+ return q.exec( function(err, request) {
233
239
 
234
240
  if (err) {
235
241
  winston.error(err);
236
242
  return reject(err);
237
243
  }
238
244
 
245
+ winston.debug('request return',request);
239
246
 
240
247
  // cambia var in let
241
248
 
@@ -378,10 +385,15 @@ class RequestService {
378
385
  // winston.debug("request_id", request_id);
379
386
  // winston.debug("newstatus", newstatus);
380
387
 
381
- return Request
382
- .findOne({request_id: request_id, id_project: id_project})
383
- //@DISABLED_CACHE .cache(cacheUtil.defaultTTL, id_project+":requests:request_id:"+request_id)
384
- .exec( function(err, request) {
388
+ let q = Request
389
+ .findOne({request_id: request_id, id_project: id_project});
390
+
391
+ if (cacheEnabler.request) {
392
+ q.cache(cacheUtil.defaultTTL, id_project+":requests:request_id:"+request_id+":simple") //request_cache
393
+ winston.debug('request cache enabled');
394
+ }
395
+
396
+ return q.exec( function(err, request) {
385
397
 
386
398
  if (err) {
387
399
  winston.error(err);
@@ -407,7 +419,7 @@ class RequestService {
407
419
 
408
420
  createWithRequester(project_user_id, lead_id, id_project, first_text, departmentid, sourcePage, language, userAgent, status, createdBy, attributes, subject, preflight) {
409
421
 
410
- var request_id = 'support-group-'+ id_project + "-" + uuidv4();
422
+ var request_id = 'support-group-'+ id_project + "-" + UIDGenerator.generate();
411
423
  winston.debug("request_id: "+request_id);
412
424
 
413
425
  return this.createWithIdAndRequester(request_id, project_user_id, lead_id, id_project, first_text, departmentid, sourcePage, language, userAgent, status, createdBy, attributes, subject, preflight);
@@ -502,6 +514,8 @@ class RequestService {
502
514
  try {
503
515
  // getOperators(departmentid, projectid, nobot, disableWebHookCall, context) {
504
516
  var result = await departmentService.getOperators(departmentid, id_project, false, undefined, context);
517
+ // console.log("************* after get operator: "+new Date().toISOString());
518
+
505
519
  winston.debug("getOperators", result);
506
520
  } catch(err) {
507
521
  return reject(err);
@@ -809,6 +823,7 @@ class RequestService {
809
823
 
810
824
 
811
825
  return new Promise(function (resolve, reject) {
826
+ winston.debug("changeFirstTextAndPreflightByRequestId", request_id);
812
827
  // winston.debug("request_id", request_id);
813
828
  // winston.debug("newstatus", newstatus);
814
829
 
@@ -933,41 +948,53 @@ class RequestService {
933
948
 
934
949
  }
935
950
 
936
- // unused
937
- incrementMessagesCountByRequestId(request_id, id_project) {
938
951
 
939
- return new Promise(function (resolve, reject) {
940
- // winston.debug("request_id", request_id);
941
- // winston.debug("newstatus", newstatus);
942
952
 
943
- return Request
944
- .findOneAndUpdate({request_id: request_id, id_project: id_project}, {$inc : {'messages_count' : 1}}, {new: true, upsert:false}, function(err, updatedRequest) {
945
- if (err) {
946
- winston.error(err);
947
- return reject(err);
948
- }
949
- winston.debug("Message count +1");
950
- return resolve(updatedRequest);
951
- });
952
- });
953
+ // unused
954
+ incrementMessagesCountByRequestId(request_id, id_project) {
953
955
 
954
- }
956
+ return new Promise(function (resolve, reject) {
957
+ // winston.debug("request_id", request_id);
958
+ // winston.debug("newstatus", newstatus);
959
+
960
+ return Request
961
+ .findOneAndUpdate({request_id: request_id, id_project: id_project}, {$inc : {'messages.messages_count' : 1}}, {new: true, upsert:false}, function(err, updatedRequest) {
962
+ if (err) {
963
+ winston.error(err);
964
+ return reject(err);
965
+ }
966
+ winston.debug("Message count +1");
967
+ return resolve(updatedRequest);
968
+ });
969
+ });
970
+
971
+ }
955
972
 
956
- updateWaitingTimeByRequestId(request_id, id_project) {
973
+ updateWaitingTimeByRequestId(request_id, id_project, enable_populate) {
957
974
 
958
975
  return new Promise(function (resolve, reject) {
959
976
  // winston.debug("request_id", request_id);
960
977
  // winston.debug("newstatus", newstatus);
961
978
 
962
- return Request
963
- .findOne({request_id: request_id, id_project: id_project})
964
- .populate('lead')
965
- .populate('department')
966
- .populate('participatingBots')
967
- .populate('participatingAgents')
968
- .populate({path:'requester',populate:{path:'id_user'}})
969
- //@DISABLED_CACHE .cache(cacheUtil.defaultTTL, id_project+":requests:request_id:"+request_id)
970
- .exec(function(err, request) {
979
+ let q = Request
980
+ .findOne({request_id: request_id, id_project: id_project});
981
+
982
+ if (enable_populate==true) {
983
+ winston.debug("updateWaitingTimeByRequestId enable_populate");
984
+
985
+ q.populate('lead')
986
+ .populate('department')
987
+ .populate('participatingBots')
988
+ .populate('participatingAgents')
989
+ .populate({path:'requester',populate:{path:'id_user'}});
990
+ }
991
+
992
+
993
+ // if (cacheEnabler.request) { //attention this cache is not usable bacause cacheoose don't support populate without .lean.. so if cached populated field is not returned with cacheoose, updateWaitingTime is only used in chat21webhook but i thik it is important for messages route
994
+ // q.cache(cacheUtil.defaultTTL, id_project+":requests:request_id:"+request_id) //request_cache
995
+ // winston.debug('request cache enabled');
996
+ // }
997
+ q.exec(function(err, request) {
971
998
  if (err) {
972
999
  winston.error(err);
973
1000
  return reject(err);
@@ -999,12 +1026,19 @@ class RequestService {
999
1026
  }
1000
1027
 
1001
1028
 
1002
- closeRequestByRequestId(request_id, id_project, skipStatsUpdate, notify, closed_by) {
1029
+ closeRequestByRequestId(request_id, id_project, skipStatsUpdate, notify, closed_by, force) {
1003
1030
 
1004
1031
  var that = this;
1005
1032
  return new Promise(function (resolve, reject) {
1006
1033
  // winston.debug("request_id", request_id);
1007
1034
 
1035
+ if (force==undefined) {
1036
+ winston.debug("force is undefined ");
1037
+ force = false;
1038
+ }
1039
+ // else {
1040
+ // winston.info("force is: " + force);
1041
+ // }
1008
1042
 
1009
1043
  return Request
1010
1044
  .findOne({request_id: request_id, id_project: id_project})
@@ -1025,13 +1059,15 @@ class RequestService {
1025
1059
  winston.error("Request not found for request_id "+ request_id + " and id_project " + id_project);
1026
1060
  return reject({"success":false, msg:"Request not found for request_id "+ request_id + " and id_project " + id_project});
1027
1061
  }
1028
- if (request.status == RequestConstants.CLOSED) {
1062
+ if (force == false && request.status == RequestConstants.CLOSED) {
1029
1063
  // qui1000
1030
1064
  // if (request.statusObj.closed) {
1031
1065
  winston.debug("Request already closed for request_id "+ request_id + " and id_project " + id_project);
1032
1066
  return resolve(request);
1033
1067
  }
1034
1068
 
1069
+ winston.debug("sono qui");
1070
+
1035
1071
  // un utente può chiudere se appartiene a participatingAgents oppure meglio agents del progetto?
1036
1072
 
1037
1073
 
@@ -21,6 +21,7 @@ var jwt = require('jsonwebtoken');
21
21
  var config = require('../config/database'); // get db config file
22
22
  var cacheUtil = require("../utils/cacheUtil");
23
23
 
24
+ var cacheEnabler = require("../services/cacheEnabler");
24
25
 
25
26
  var webhook_origin = process.env.WEBHOOK_ORIGIN || "http://localhost:3000";
26
27
  winston.debug("webhook_origin: "+webhook_origin);
@@ -36,9 +37,13 @@ class SubscriptionNotifier {
36
37
 
37
38
  findSubscriber(event, id_project) {
38
39
  return new Promise(function (resolve, reject) {
39
- Subscription.find({event:event, $or:[{id_project: id_project}, {global: true}]})
40
- .cache(cacheUtil.longTTL, id_project+":subscriptions:event:"+event)
41
- .select("+secret +global")
40
+ let q = Subscription.find({event:event, $or:[{id_project: id_project}, {global: true}]});
41
+ if (cacheEnabler.subscription) {
42
+ q.cache(cacheUtil.longTTL, id_project+":subscriptions:event:"+event); //CACHE_SUBSCRIPTION
43
+ winston.debug('subscription cache enabled');
44
+ }
45
+
46
+ q.select("+secret +global")
42
47
  .exec(function (err, subscriptions) {
43
48
  // if (subscriptions && subscriptions.length>0) {
44
49
  // winston.debug("Subscription.notify", event, item , "length", subscriptions.length);
@@ -81,7 +86,7 @@ class SubscriptionNotifier {
81
86
 
82
87
  if (s.global==true){
83
88
  signOptions.audience = 'https://tiledesk.com';
84
- secret = config.secret;
89
+ secret = process.env.GLOBAL_SECRET || config.secret;
85
90
  }
86
91
 
87
92
  var token = jwt.sign(sJson, secret, signOptions);
@@ -0,0 +1,106 @@
1
+ const faqBotEvent = require('../event/faqBotEvent');
2
+ const Faq_kb = require('../models/faq_kb');
3
+ const Faq = require('../models/faq');
4
+ var winston = require('../config/winston');
5
+ const axios = require("axios").default;
6
+
7
+
8
+ let chatbot_training_api_url = "http://34.65.210.38/model/train"
9
+
10
+ class TrainingService {
11
+
12
+
13
+
14
+ train(eventName, faq) {
15
+
16
+ Faq_kb.findById(faq.id_faq_kb, (err, faq_kb) => {
17
+ winston.debug("faq_kb: ", faq_kb)
18
+
19
+ if (faq_kb.intentsEngine !== 'tiledesk-ai') {
20
+ winston.info("intentsEngine: off")
21
+ return null;
22
+ }
23
+
24
+ winston.info("intentsEngine: on")
25
+ Faq.find({ id_faq_kb: faq.id_faq_kb }, (err, faqs) => {
26
+
27
+ if (err) {
28
+ winston.error("[Training] find all error: ", err);
29
+ } else {
30
+
31
+ let json = {
32
+ "configuration": {
33
+ "language": faq_kb.language,
34
+ "pipeline": [""]
35
+ },
36
+ "model": faq_kb._id,
37
+ "nlu": []
38
+ }
39
+
40
+ faqs.forEach((f) => {
41
+ if (f.enabled == true) {
42
+ let intent = {
43
+ "intent": f.intent_display_name,
44
+ "examples": []
45
+ }
46
+ let questions = f.question.split("\n");
47
+ intent.examples = questions;
48
+ json.nlu.push(intent);
49
+ }
50
+ })
51
+
52
+ winston.debug("training json: \n" + JSON.stringify(json, null, 2));
53
+
54
+ axios({
55
+ url: chatbot_training_api_url,
56
+ headers: {
57
+ 'Content-Type': 'application/json'
58
+ },
59
+ data: json,
60
+ method: 'POST'
61
+ }).then((resbody) => {
62
+ winston.info("[Training] resbody: ", resbody.data);
63
+ return true;
64
+ }).catch((err) => {
65
+ winston.error("[Training] error: ", err.response.data);
66
+ })
67
+ }
68
+ })
69
+
70
+ })
71
+
72
+
73
+
74
+ }
75
+
76
+ start() {
77
+ winston.info('TrainingService start');
78
+
79
+ faqBotEvent.on('faq.create', (faq) => {
80
+ setImmediate(() => {
81
+ trainingService.train('faq.create', faq);
82
+ })
83
+ })
84
+
85
+ faqBotEvent.on('faq.update', (faq) => {
86
+ winston.debug("--> event faq: ", faq);
87
+ setImmediate(() => {
88
+ trainingService.train('faq.update', faq);
89
+ })
90
+ })
91
+
92
+ faqBotEvent.on('faq.delete', (faq) => {
93
+ console.log("--> event faq: ", faq);
94
+ setImmediate(() => {
95
+ trainingService.train('faq.delete', faq);
96
+ })
97
+ })
98
+
99
+
100
+ }
101
+
102
+ }
103
+
104
+ var trainingService = new TrainingService();
105
+
106
+ module.exports = trainingService;
@@ -11,9 +11,19 @@
11
11
  img {
12
12
  max-width: 100%;
13
13
  margin-left:16px;
14
- margin-bottom:16px;
15
14
  text-align:center !important;
16
15
  }
16
+ img.CToWUd {
17
+ margin-bottom: 16px;
18
+ max-width: 200px !important;
19
+ width: 200px !important;
20
+ min-width: 200px !important;
21
+ outline: none;
22
+ text-decoration: none;
23
+ border: none;
24
+ height: auto;
25
+ margin-left: 0px;
26
+ }
17
27
  body {
18
28
  -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em;
19
29
  }
@@ -82,7 +92,7 @@
82
92
 
83
93
  <div style="text-align:center">
84
94
  <a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
85
- <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:10%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
95
+ <img src="https://tiledesk.com/wp-content/uploads/2023/01/tiledesk_log_email_200.png" class="CToWUd">
86
96
  </a>
87
97
  </div>
88
98
  </tr>
@@ -102,7 +112,7 @@
102
112
  <table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
103
113
 
104
114
  <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
105
- <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
115
+ <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top">
106
116
  {{#ifEquals message.type "text"}}
107
117
  <div style="white-space: pre-wrap;">{{{msgText}}}</div>
108
118
  {{/ifEquals}}
@@ -120,26 +130,26 @@
120
130
 
121
131
 
122
132
  <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
123
- <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
133
+ <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top">
124
134
  Project name : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{project.name}}</strong>
125
135
  </td>
126
136
  </tr>
127
137
 
128
138
 
129
139
  <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
130
- <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
140
+ <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top">
131
141
  Department name : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{request.department.name}}</strong>
132
142
  </td>
133
143
  </tr>
134
144
 
135
145
  <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
136
- <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
146
+ <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top">
137
147
  From email : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{request.lead.email}}</strong>
138
148
  </td>
139
149
  </tr>
140
150
 
141
151
  <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
142
- <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
152
+ <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top">
143
153
  Contact name : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{request.lead.fullname}}</strong>
144
154
  </td>
145
155
  </tr>
@@ -151,7 +161,7 @@
151
161
  </tr> -->
152
162
 
153
163
  <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
154
- <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
164
+ <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top">
155
165
  Channel : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
156
166
  {{#ifEquals request.channel.name "chat21"}}
157
167
  Chat
@@ -163,7 +173,7 @@
163
173
  </tr>
164
174
 
165
175
  <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
166
- <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
176
+ <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top">
167
177
  <a href="{{baseScope.baseUrl}}/#/project/{{request.id_project}}/wsrequest/{{request.request_id}}/messages">Open the dashboard</a>.
168
178
 
169
179
  </td>
@@ -174,7 +184,7 @@
174
184
 
175
185
 
176
186
  <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
177
- <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
187
+ <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top">
178
188
  </td>
179
189
  </tr>
180
190
  </table>
@@ -184,7 +194,7 @@
184
194
  <div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;">
185
195
  <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
186
196
  <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
187
- <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">
197
+ <td class="aligncenter content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; vertical-align: top; color: #999; text-align: center; margin: 0;" align="center" valign="top">
188
198
  <span><a href="http://www.tiledesk.com" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;" > Tiledesk.com </a></span>
189
199
  <br><span><a href="%unsubscribe_url%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 12px; color: #999; text-decoration: underline; margin: 0;">Unsubscribe</a></span>
190
200
  </td>