@tiledesk/tiledesk-server 2.3.2 → 2.3.5

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
@@ -1,5 +1,17 @@
1
1
 
2
2
 
3
+ # 2.3.2
4
+ - Dowload trascript as csv, pdf and txt endpoint
5
+ - Added closed_by field to the request model
6
+ - Added followers field to the request model
7
+ - Added lead index
8
+ - Added widget v5 code loader /widgets/v5/:project_id -> heroku blocca cache-control
9
+ - Bugfix Cannot read property 'profile' of null
10
+ - Added filter by channel offline and online
11
+ - Updated Rasa Connector to 1.0.7
12
+ - Send info message on lead.fullaname.update
13
+
14
+
3
15
  # 2.3.1
4
16
  - changed tiledesk logo for emails
5
17
  - open modules: analytics, activity log, multi tenancy, departments, groups, canned responses, tags, triggers, webhooks
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.3.2",
4
+ "version": "2.3.5",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -76,7 +76,7 @@ class ActivityArchiver {
76
76
 
77
77
  authEvent.on('project_user.update', function(event) {
78
78
  setImmediate(() => {
79
- console.log("project_user.update");
79
+ // console.log("project_user.update");
80
80
  /*
81
81
  2019-11-20T10:40:52.686991+00:00 app[web.1]: TypeError: Cannot read property '_id' of undefined
82
82
  */
@@ -47,7 +47,7 @@ listen() {
47
47
  messageEvent.on(messageCreateKey, function(message) {
48
48
 
49
49
  setImmediate(() => {
50
- winston.debug("sendUserEmail", message);
50
+ winston.debug("messageEvent.on(messageCreateKey", message);
51
51
 
52
52
  if (message.attributes && message.attributes.subtype==='info') {
53
53
  return winston.debug("not sending sendUserEmail for attributes.subtype info messages");
@@ -56,17 +56,18 @@ listen() {
56
56
 
57
57
  if (message.request && (message.request.channel.name===ChannelConstants.EMAIL || message.request.channel.name===ChannelConstants.FORM)) {
58
58
 
59
+ //messages sent from admins or agents to requester
59
60
  if (message.sender != message.request.lead.lead_id) {
60
61
  winston.verbose("sending sendToUserEmailChannelEmail for EMAIL or FORM channel");
61
-
62
- if (message.attributes && message.attributes.subtype==='private') {
63
- return winston.debug("not sending sendToUserEmailChannelEmail for attributes.subtype private messages");
64
- }
65
- return that.sendToUserEmailChannelEmail(message.id_project, message);
66
- } else {
62
+
63
+ //send email notification to requester (send also to followers)
64
+ return that.sendToUserEmailChannelEmail(message.id_project, message);
65
+ } else { //messages sent from requester to agents or admins
67
66
 
68
67
  if (message.text != message.request.first_text) {
69
68
  winston.verbose("sending sendToAgentEmailChannelEmail for EMAIL or FORM channel");
69
+
70
+ //send email notification to admins and agents(send also to followers)
70
71
  return that.sendToAgentEmailChannelEmail(message.id_project, message);
71
72
  } else {
72
73
  winston.debug("sending sendToAgentEmailChannelEmail for EMAIL or FORM channel disabled for first text message")
@@ -76,16 +77,23 @@ listen() {
76
77
 
77
78
  } else {
78
79
  winston.debug("sendUserEmail chat channel");
79
- // controlla se sta funzionando
80
- if (process.env.DISABLE_SEND_OFFLINE_EMAIL === "true" || process.env.DISABLE_SEND_OFFLINE_EMAIL === true ) {
81
- return winston.debug("DISABLE_SEND_OFFLINE_EMAIL disabled");
82
- }
83
- // mandare email se ultimo messaggio > X MINUTI configurato in Notification . potresti usare request.updated_at ?
80
+
81
+ //TODO mandare email se ultimo messaggio > X MINUTI configurato in Notification . potresti usare request.updated_at ?
82
+
83
+
84
+
85
+ //messages sent from admins or agents
86
+ //send email notification to requester
84
87
  if (message.request && message.request.lead && message.sender != message.request.lead.lead_id) {
88
+ winston.debug("sendUserEmail");
85
89
  winston.debug("sendUserEmail", message);
86
90
 
87
- // send an email only if offline and has an email
91
+ // send an email only if offline and has an email (send also to followers)
88
92
  return that.sendUserEmail(message.id_project, message);
93
+ } else { //send email to followers
94
+
95
+ that.sendToFollower(message.id_project, message);
96
+
89
97
  }
90
98
 
91
99
  }
@@ -139,7 +147,6 @@ listen() {
139
147
 
140
148
 
141
149
 
142
-
143
150
  // requestEvent.on("request.update.preflight", function(request) {
144
151
 
145
152
  // winston.info("requestEvent request.update.preflight");
@@ -227,15 +234,19 @@ listen() {
227
234
 
228
235
 
229
236
  sendToUserEmailChannelEmail(projectid, message) {
237
+ winston.debug("sendToUserEmailChannelEmail");
238
+ var that = this;
230
239
  try {
231
240
 
232
241
  if (!message.request) {
233
242
  return winston.debug("This is a direct message");
234
243
  }
235
244
 
236
- if (!message.request.lead || !message.request.lead.email) {
237
- return winston.debug("The lead object is undefined or has empty email");
238
- }
245
+
246
+
247
+
248
+
249
+
239
250
 
240
251
  Project.findOne({_id: projectid, status: 100}).select("+settings").exec(function(err, project){
241
252
  if (err) {
@@ -245,6 +256,7 @@ sendToUserEmailChannelEmail(projectid, message) {
245
256
  if (!project) {
246
257
  return winston.warn("Project not found", projectid);
247
258
  }
259
+
248
260
 
249
261
  // if (project.settings && project.settings.email && project.settings.email.notification && project.settings.email.notification.conversation && project.settings.email.notification.conversation.offline && project.settings.email.notification.conversation.offline.blocked == true ) {
250
262
  // return winston.info("RequestNotification offline email notification for the project with id : " + projectid + " for the conversations is blocked");
@@ -256,7 +268,7 @@ sendToUserEmailChannelEmail(projectid, message) {
256
268
  // }
257
269
 
258
270
  let lead = message.request.lead;
259
- winston.debug("sending channel emaol email to lead ", lead);
271
+ winston.debug("sending channel email to lead ", lead);
260
272
 
261
273
 
262
274
  winston.debug("sending user email to "+ lead.email);
@@ -307,8 +319,24 @@ sendToUserEmailChannelEmail(projectid, message) {
307
319
  }
308
320
  winston.debug("tokenQueryString: "+tokenQueryString);
309
321
 
322
+
323
+
324
+ // winston.info("savedRequest.followers", savedRequest.followers);
325
+ // winston.info("savedRequest.followers.length:"+ savedRequest.followers.length);
326
+ that.notifyFollowers(message.request, project, message);
327
+
328
+
329
+ if (message.attributes && message.attributes.subtype==='private') {
330
+ return winston.debug("not sending sendToUserEmailChannelEmail for attributes.subtype private messages");
331
+ }
332
+
333
+ // nn va bene qui
334
+ if (!message.request.lead || !message.request.lead.email) {
335
+ return winston.debug("The lead object is undefined or has empty email");
336
+ }
337
+
310
338
  emailService.sendEmailChannelNotification(message.request.lead.email, message, project, tokenQueryString, sourcePage);
311
-
339
+
312
340
 
313
341
  });
314
342
 
@@ -318,9 +346,105 @@ sendToUserEmailChannelEmail(projectid, message) {
318
346
  }
319
347
 
320
348
 
349
+ async notifyFollowers(savedRequest, project, message) {
350
+
351
+ if (message.attributes && message.attributes.subtype==='info/support') {
352
+ return winston.debug("not sending notifyFollowers for attributes.subtype info/support messages");
353
+ }
354
+
355
+ if (message.attributes && message.attributes.subtype==='info') {
356
+ return winston.debug("not sending notifyFollowers for attributes.subtype info messages");
357
+ }
358
+
359
+ var reqWithFollowers = await Request.findById(savedRequest._id).populate('followers').exec();
360
+ winston.debug("reqWithFollowers");
361
+ winston.debug("reqWithFollowers",reqWithFollowers);
362
+ // console.log("reqWithFollowers",reqWithFollowers);
363
+
364
+ if (reqWithFollowers.followers && reqWithFollowers.followers.length>0) {
321
365
 
366
+ winston.debug("reqWithFollowers.followers.length: "+reqWithFollowers.followers.length);
367
+
368
+ reqWithFollowers.followers.forEach(project_user => {
369
+ winston.debug("project_user", project_user);
370
+ //TODO skip participants from followers
371
+
372
+ var userid = project_user.id_user;
373
+
374
+ if (project_user.settings && project_user.settings.email && project_user.settings.email.notification && project_user.settings.email.notification.conversation && project_user.settings.email.notification.conversation.ticket && project_user.settings.email.notification.conversation.ticket.follower == false ) {
375
+ return winston.verbose("RequestNotification email notification for the user with id " + userid+ " the follower conversation ticket is disabled");
376
+ }
377
+
378
+ User.findOne({_id: userid , status: 100})
379
+ //@DISABLED_CACHE .cache(cacheUtil.defaultTTL, "users:id:"+userid)
380
+ .exec(function (err, user) {
381
+ if (err) {
382
+ // winston.debug(err);
383
+ }
384
+ if (!user) {
385
+ winston.warn("User not found", userid);
386
+ } else {
387
+ winston.info("Sending notifyFollowers to user with email: "+ user.email);
388
+ if (user.emailverified) {
389
+ emailService.sendFollowerNotification(user.email, message, project);
390
+ // emailService.sendEmailChannelNotification(user.email, message, project);
391
+
392
+ // emailService.sendNewAssignedAgentMessageEmailNotification(user.email, savedRequest, project, message);
393
+
394
+ }else {
395
+ winston.info("User email not verified", user.email);
396
+ }
397
+ }
398
+ });
399
+
400
+
401
+ });
402
+
403
+
404
+ }
405
+ }
406
+
407
+ sendToFollower(projectid, message) {
408
+ winston.debug("sendToFollower");
409
+ var that = this;
410
+ let savedRequest = message.request;
411
+ // send email
412
+ try {
413
+
414
+
415
+ Project.findOne({_id: projectid, status: 100}).select("+settings").exec(async function(err, project){
416
+ if (err) {
417
+ return winston.error(err);
418
+ }
419
+
420
+ if (!project) {
421
+ return winston.warn("Project not found", projectid);
422
+ } else {
423
+
424
+ winston.debug("project", project);
425
+
426
+ // if (project.settings && project.settings.email && project.settings.email.notification && project.settings.email.notification.conversation && project.settings.email.notification.conversation.blocked == true ) {
427
+ // return winston.verbose("RequestNotification email notification for the project with id : " + projectid + " for all the conversations is blocked");
428
+ // }
429
+
430
+ winston.debug("savedRequest", savedRequest);
431
+
432
+
433
+
434
+ // winston.info("savedRequest.followers", savedRequest.followers);
435
+ // winston.info("savedRequest.followers.length:"+ savedRequest.followers.length);
436
+ that.notifyFollowers(message.request, project, message);
437
+
438
+
439
+ }
440
+ })
441
+ } catch (e) {
442
+ winston.warn("Error sending email", {error:e, projectid:projectid, message: message, savedRequest:savedRequest}); //it's better to view error email at this stage
443
+ }
444
+ }
322
445
 
323
446
  sendToAgentEmailChannelEmail(projectid, message) {
447
+ var that = this;
324
448
  let savedRequest = message.request;
325
449
  // send email
326
450
  try {
@@ -343,9 +467,17 @@ sendToAgentEmailChannelEmail(projectid, message) {
343
467
 
344
468
  winston.debug("savedRequest", savedRequest);
345
469
 
346
-
347
470
 
348
471
 
472
+ // winston.info("savedRequest.followers", savedRequest.followers);
473
+ // winston.info("savedRequest.followers.length:"+ savedRequest.followers.length);
474
+ that.notifyFollowers(message.request, project, message);
475
+
476
+
477
+
478
+ // UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'status' of undefined
479
+ // at /Users/andrealeo/dev/chat21/ti
480
+
349
481
  // TODO fare il controllo anche sul dipartimento con modalità assigned o pooled
350
482
  if (savedRequest.status==RequestConstants.UNASSIGNED) { //POOLED
351
483
 
@@ -523,15 +655,19 @@ sendEmailChannelTakingNotification(projectid, request) {
523
655
 
524
656
 
525
657
  sendUserEmail(projectid, message) {
658
+ winston.debug("sendUserEmail");
659
+ var that = this;
660
+
661
+
526
662
  try {
527
663
 
528
664
  if (!message.request) {
529
665
  return winston.debug("This is a direct message");
530
666
  }
667
+
531
668
 
532
- if (!message.request.lead || !message.request.lead.email) {
533
- return winston.debug("The lead object is undefined or has empty email");
534
- }
669
+
670
+
535
671
 
536
672
  Project.findOne({_id: projectid, status: 100}).select("+settings").exec(function(err, project){
537
673
  if (err) {
@@ -542,6 +678,28 @@ sendUserEmail(projectid, message) {
542
678
  return winston.warn("Project not found", projectid);
543
679
  }
544
680
 
681
+ winston.debug("notifyFollowers");
682
+ that.notifyFollowers(message.request, project, message);
683
+
684
+
685
+
686
+ if (process.env.DISABLE_SEND_OFFLINE_EMAIL === "true" || process.env.DISABLE_SEND_OFFLINE_EMAIL === true ) {
687
+ return winston.info("DISABLE_SEND_OFFLINE_EMAIL disabled");
688
+ }
689
+ if (message.attributes && message.attributes.subtype==='info/support') {
690
+ return winston.debug("not sending sendUserEmail for attributes.subtype info/support messages");
691
+ }
692
+
693
+ if (message.attributes && message.attributes.subtype==='info') {
694
+ return winston.debug("not sending sendUserEmail for attributes.subtype info messages");
695
+ }
696
+
697
+
698
+
699
+ if (!message.request.lead || !message.request.lead.email) {
700
+ return winston.info("The lead object is undefined or has empty email");
701
+ }
702
+
545
703
  if (project.settings && project.settings.email && project.settings.email.notification && project.settings.email.notification.conversation && project.settings.email.notification.conversation.offline && project.settings.email.notification.conversation.offline.blocked == true ) {
546
704
  return winston.info("RequestNotification offline email notification for the project with id : " + projectid + " for the conversations is blocked");
547
705
  }
@@ -550,8 +708,8 @@ sendUserEmail(projectid, message) {
550
708
  if (project.settings && project.settings.email && project.settings.email.notification && project.settings.email.notification.conversation && project.settings.email.notification.conversation.offline && project.settings.email.notification.conversation.offline.enabled == false ) {
551
709
  return winston.info("RequestNotification offline email notification for the project with id : " + projectid + " for the offline conversation is disabled");
552
710
  }
553
-
554
-
711
+
712
+
555
713
 
556
714
  var recipient = message.request.lead.lead_id;
557
715
  winston.debug("recipient:"+ recipient);
@@ -678,7 +836,7 @@ sendAgentEmail(projectid, savedRequest) {
678
836
  }
679
837
 
680
838
 
681
-
839
+
682
840
  var snapshotAgents = savedRequest; //riassegno varibile cosi nn cambio righe successive
683
841
 
684
842
 
@@ -86,6 +86,9 @@ var printer = new PdfPrinter(fonts);
86
86
  delete element.attributes;
87
87
  });
88
88
 
89
+ res.setHeader('Content-Type', 'applictext/csv');
90
+ res.setHeader('Content-Disposition', 'attachment; filename=transcript.csv');
91
+
89
92
  return res.csv(messages, true);
90
93
  });
91
94
 
@@ -170,6 +173,11 @@ var printer = new PdfPrinter(fonts);
170
173
 
171
174
  var pdfDoc = printer.createPdfKitDocument(docDefinition);
172
175
  // pdfDoc.pipe(fs.createWriteStream('lists.pdf'));
176
+
177
+ res.setHeader('Content-Type', 'application/pdf');
178
+ res.setHeader('Content-Disposition', 'attachment; filename=transcript.pdf');
179
+
180
+
173
181
  pdfDoc.pipe(res);
174
182
  pdfDoc.end();
175
183
 
@@ -287,6 +295,10 @@ var printer = new PdfPrinter(fonts);
287
295
 
288
296
  var pdfDoc = printer.createPdfKitDocument(docDefinition);
289
297
  // pdfDoc.pipe(fs.createWriteStream('lists.pdf'));
298
+
299
+ res.setHeader('Content-Type', 'application/pdf');
300
+ res.setHeader('Content-Disposition', 'attachment; filename=transcript.pdf');
301
+
290
302
  pdfDoc.pipe(res);
291
303
  pdfDoc.end();
292
304
 
@@ -328,6 +340,9 @@ var printer = new PdfPrinter(fonts);
328
340
  });
329
341
 
330
342
 
343
+ res.setHeader('Content-Type', 'applictext/csv');
344
+ res.setHeader('Content-Disposition', 'attachment; filename=transcript.csv');
345
+
331
346
  return res.csv(messages, true);
332
347
  });
333
348
 
package/routes/request.js CHANGED
@@ -656,6 +656,8 @@ router.delete('/id/:id', function (req, res) {
656
656
 
657
657
  router.get('/', function (req, res, next) {
658
658
 
659
+ const startExecTime = new Date();
660
+
659
661
  winston.debug("req projectid", req.projectid);
660
662
  winston.debug("req.query.sort", req.query.sort);
661
663
  winston.debug('REQUEST ROUTE - QUERY ', req.query)
@@ -910,14 +912,17 @@ router.get('/', function (req, res, next) {
910
912
 
911
913
  winston.debug("sort query", sortQuery);
912
914
 
913
- winston.verbose('REQUEST ROUTE - REQUEST FIND ', query);
915
+ winston.debug('REQUEST ROUTE - REQUEST FIND ', query);
914
916
 
915
917
  var projection = undefined;
916
918
 
917
919
  if (req.query.full_text) {
918
- winston.debug('fulltext projection');
919
920
 
920
- projection = {score: { $meta: "textScore" } };
921
+ if (req.query.no_textscore!= "true" && req.query.no_textscore!= true) {
922
+ winston.info('fulltext projection on');
923
+ projection = {score: { $meta: "textScore" } };
924
+ }
925
+
921
926
  }
922
927
  // requestcachefarequi populaterequired
923
928
  var q1 = Request.find(query, projection).
@@ -949,7 +954,9 @@ router.get('/', function (req, res, next) {
949
954
 
950
955
  if (req.query.full_text) {
951
956
  winston.debug('fulltext sort');
952
- q1.sort( { score: { $meta: "textScore" } } ) //https://docs.mongodb.com/manual/reference/operator/query/text/#sort-by-text-search-score
957
+ if (req.query.no_textscore!= "true" && req.query.no_textscore!= true) {
958
+ q1.sort( { score: { $meta: "textScore" } } ) //https://docs.mongodb.com/manual/reference/operator/query/text/#sort-by-text-search-score
959
+ }
953
960
  } else {
954
961
  q1.sort(sortQuery);
955
962
  }
@@ -965,6 +972,11 @@ router.get('/', function (req, res, next) {
965
972
 
966
973
  var q2 = Request.countDocuments(query).exec();
967
974
 
975
+ if (req.query.no_count && req.query.no_count =="true") {
976
+ winston.info('REQUEST ROUTE - no_count ');
977
+ q2 = 0;
978
+ }
979
+
968
980
  var promises = [
969
981
  q1,
970
982
  q2
@@ -978,6 +990,10 @@ router.get('/', function (req, res, next) {
978
990
  };
979
991
  winston.debug('REQUEST ROUTE - objectToReturn ');
980
992
  winston.debug('REQUEST ROUTE - objectToReturn ', objectToReturn);
993
+
994
+ const endExecTime = new Date();
995
+ winston.info('REQUEST ROUTE - exec time: ' + (endExecTime-startExecTime));
996
+
981
997
  return res.json(objectToReturn);
982
998
 
983
999
  }).catch(function(err){
@@ -191,20 +191,24 @@ class EmailService {
191
191
  user: configEmail.user,
192
192
  pass: configEmail.pass
193
193
  },
194
+ // secureConnection: false,
195
+ // tls:{
196
+ // ciphers:'SSLv3'
197
+ // },
194
198
 
195
- // openssl genrsa -out dkim_private.pem 2048
199
+ // openssl genrsa -out dkim_private.pem 2048
196
200
  // openssl rsa -in dkim_private.pem -pubout -outform der 2>/dev/null | openssl base64 -A
197
201
  // ->
198
202
  // v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunT2EopDAYnHwAOHd33KhlzjUXJfhmA+fK+cG85i9Pm33oyv1NoGrOynsni0PO6j7oRxxHqs6EMDOw4I/Q0C7aWn20oBomJZehTOkCV2xpuPKESiRktCe/MIZqbkRdypis4jSkFfFFkBHwgkAg5tb11E9elJap0ed/lN5/XlpGedqoypKxp+nEabgYO5mBMMNKRvbHx0eQttRYyIaNkTuMbAaqs4y3TkHOpGvZTJsvUonVMGAstSCfUmXnjF38aKpgyTausTSsxHbaxh3ieUB4ex+svnvsJ4Uh5Skklr+bxLVEHeJN55rxmV67ytLg5XCRWqdKIcJHFvSlm2YwJfcwIDAQABMacAL
199
203
  // testdkim._domainkey.tiledesk.com. 86400 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunT2EopDAYnHwAOHd33KhlzjUXJfhmA+fK+cG85i9Pm33oyv1NoGrOynsni0PO6j7oRxxHqs6EMDOw4I/Q0C7aWn20oBomJZehTOkCV2xpuPKESiRktCe/MIZqbkRdypis4jSkFfFFkBHwgkAg5tb11E9elJap0ed/lN5/XlpGedqoypKxp+nEabgYO5mBMMNKRvbHx0eQttRYyIaNkTuMbAaqs4y3TkHOpGvZTJsvUonVMGAstSCfUmXnjF38aKpgyTausTSsxHbaxh3ieUB4ex+svnvsJ4Uh5Skklr+bxLVEHeJN55rxmV67ytLg5XCRWqdKIcJHFvSlm2YwJfcwIDAQABMacAL"
200
204
 
201
- dkim: {
202
- domainName: "example.com",
203
- keySelector: "2017",
204
- privateKey: "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBg...",
205
- cacheDir: "/tmp",
206
- cacheTreshold: 100 * 1024
207
- }
205
+ // dkim: {
206
+ // domainName: "example.com",
207
+ // keySelector: "2017",
208
+ // privateKey: "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBg...",
209
+ // cacheDir: "/tmp",
210
+ // cacheTreshold: 100 * 1024
211
+ // }
208
212
  };
209
213
 
210
214
  winston.debug("getTransport transport: ",transport);
@@ -406,7 +410,9 @@ class EmailService {
406
410
  }
407
411
  }
408
412
 
409
-
413
+ // troncare nome utnete e nome progetto a max 10 caratteri
414
+ // cambiare in [Nicky:Dashboard Support] Assigned Chat
415
+ // serve per aggiornare native... fai aggiornamento
410
416
 
411
417
  let subject = `[Tiledesk ${project ? project.name : '-'}] New Assigned Chat`;
412
418
 
@@ -958,11 +964,12 @@ class EmailService {
958
964
 
959
965
  let inReplyTo;
960
966
  let references;
967
+ winston.debug("message.request.attributes", message.request.attributes);
961
968
  if (message.request.attributes) {
962
969
  if (message.request.attributes.email_messageId) {
963
970
  inReplyTo = message.request.attributes.email_messageId;
964
971
  }
965
- if (message.attributes.email_references) {
972
+ if (message.request.attributes.email_references) {
966
973
  references = message.request.attributes.email_references;
967
974
  }
968
975
  }
@@ -1176,6 +1183,177 @@ class EmailService {
1176
1183
  }
1177
1184
 
1178
1185
 
1186
+
1187
+
1188
+
1189
+
1190
+
1191
+
1192
+
1193
+
1194
+
1195
+ async sendFollowerNotification(to, message, project) {
1196
+
1197
+ var that = this;
1198
+
1199
+
1200
+ if (project.toJSON) {
1201
+ project = project.toJSON();
1202
+ }
1203
+
1204
+ var html = await this.readTemplate('newMessageFollower.html', project.settings);
1205
+
1206
+
1207
+ var envTemplate = process.env.EMAIL_FOLLOWER_HTML_TEMPLATE;
1208
+ winston.debug("envTemplate: " + envTemplate);
1209
+
1210
+ if (envTemplate) {
1211
+ html = envTemplate;
1212
+ }
1213
+
1214
+ winston.debug("html: " + html);
1215
+
1216
+ var template = handlebars.compile(html);
1217
+
1218
+ var baseScope = JSON.parse(JSON.stringify(that));
1219
+ delete baseScope.pass;
1220
+
1221
+
1222
+ let msgText = message.text;//.replace(/[\n\r]/g, '<br>');
1223
+ msgText = encode(msgText);
1224
+ if (this.markdown) {
1225
+ msgText = marked(msgText);
1226
+ }
1227
+
1228
+ winston.debug("msgText: " + msgText);
1229
+ winston.debug("baseScope: " + JSON.stringify(baseScope));
1230
+
1231
+
1232
+ var replacements = {
1233
+ message: message,
1234
+ project: project,
1235
+ msgText: msgText,
1236
+ baseScope: baseScope
1237
+ };
1238
+
1239
+ var html = template(replacements);
1240
+ winston.debug("html: " + html);
1241
+
1242
+ const fs = require('fs');
1243
+ fs.writeFileSync('tem1111.html', html);
1244
+
1245
+
1246
+
1247
+ let messageId = message._id + "@" + MESSAGE_ID_DOMAIN;
1248
+
1249
+ let replyTo;
1250
+ if (this.replyEnabled) {
1251
+ replyTo = message.request.request_id + this.inboundDomainDomainWithAt;
1252
+ }
1253
+
1254
+ let headers;
1255
+ if (message.request) {
1256
+
1257
+ messageId = message.request.request_id + "+" + messageId;
1258
+
1259
+ if (message.request.attributes && message.request.attributes.email_replyTo) {
1260
+ replyTo = message.request.attributes.email_replyTo;
1261
+ }
1262
+
1263
+ headers = {"X-TILEDESK-PROJECT-ID": project._id, "X-TILEDESK-REQUEST-ID": message.request.request_id, "X-TILEDESK-TICKET-ID":message.request.ticket_id };
1264
+
1265
+ winston.verbose("messageId: " + messageId);
1266
+ winston.verbose("replyTo: " + replyTo);
1267
+ winston.verbose("email headers", headers);
1268
+ }
1269
+
1270
+
1271
+ let inReplyTo;
1272
+ let references;
1273
+ let cc;
1274
+ let ccString;
1275
+
1276
+ if (message.request && message.request.attributes) {
1277
+ winston.debug("email message.request.attributes: ", message.request.attributes);
1278
+
1279
+ if (message.request.attributes.email_messageId) {
1280
+ inReplyTo = message.request.attributes.email_messageId;
1281
+ }
1282
+ if (message.request.attributes.email_references) {
1283
+ references = message.request.attributes.email_references;
1284
+ }
1285
+
1286
+ if (message.request.attributes.email_cc) {
1287
+ cc = message.request.attributes.email_cc;
1288
+ }
1289
+ winston.debug("email message.request.attributes.email_ccStr: "+ message.request.attributes.email_ccStr);
1290
+ if (message.request.attributes.email_ccStr!=undefined) {
1291
+ ccString = message.request.attributes.email_ccStr;
1292
+ winston.debug("email set ccString");
1293
+ }
1294
+ }
1295
+ winston.verbose("email inReplyTo: "+ inReplyTo);
1296
+ winston.verbose("email references: "+ references);
1297
+ winston.verbose("email cc: ", cc);
1298
+ winston.verbose("email ccString: "+ ccString);
1299
+
1300
+ let from;
1301
+ let configEmail;
1302
+ if (project && project.settings && project.settings.email) {
1303
+ if (project.settings.email.config) {
1304
+ configEmail = project.settings.email.config;
1305
+ winston.verbose("custom email configEmail setting found: ", configEmail);
1306
+ }
1307
+ if (project.settings.email.from) {
1308
+ from = project.settings.email.from;
1309
+ winston.verbose("custom from email setting found: "+ from);
1310
+ }
1311
+ }
1312
+
1313
+
1314
+
1315
+
1316
+ that.send({
1317
+ messageId: messageId,
1318
+ // sender: message.senderFullname, //must be an email
1319
+ from:from,
1320
+ to:to,
1321
+ cc: ccString,
1322
+ replyTo: replyTo,
1323
+ inReplyTo: inReplyTo,
1324
+ references: references,
1325
+ // subject:`${message.request ? message.request.subject : '-'}`,
1326
+ subject:`${message.request ? message.request.ticket_id : '-'}`, //gmail uses subject
1327
+ text:html,
1328
+ html:html,
1329
+ config:configEmail,
1330
+ headers:headers
1331
+ });
1332
+
1333
+ // // messageId = "notification" + messageId;
1334
+
1335
+ // // that.send({
1336
+ // // messageId: messageId,
1337
+ // // // sender: message.senderFullname, //must be an email
1338
+ // // to: that.bcc,
1339
+ // // replyTo: replyTo,
1340
+ // // inReplyTo: inReplyTo,
1341
+ // // references: references,
1342
+ // // // subject: `${message.request ? message.request.subject : '-'} - notification`,
1343
+ // // subject: `${message.request ? message.request.subject : '-'} - notification`,
1344
+ // // text:html,
1345
+ // // html:html,
1346
+ // // headers:headers
1347
+ // // });
1348
+
1349
+
1350
+ }
1351
+
1352
+
1353
+
1354
+
1355
+
1356
+
1179
1357
  /*
1180
1358
  sendEmailChannelTakingNotification(to, request, project, tokenQueryString) {
1181
1359
 
@@ -1505,6 +1683,6 @@ async sendRequestTranscript(to, messages, request, project) {
1505
1683
 
1506
1684
  var emailService = new EmailService();
1507
1685
 
1508
- // emailService.sendTest("al@f21.it");
1686
+ // emailService.sendTest("asd.");
1509
1687
 
1510
1688
  module.exports = emailService;
@@ -128,6 +128,8 @@ class LeadService {
128
128
 
129
129
 
130
130
  leadEvent.emit('lead.update', updatedLead);
131
+ leadEvent.emit('lead.email.update', updatedLead);
132
+ leadEvent.emit('lead.fullname.update', updatedLead);
131
133
  return resolve(updatedLead);
132
134
  });
133
135
  });
@@ -0,0 +1,236 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html lang="en" xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
3
+
4
+ <head>
5
+ <meta name="viewport" content="width=device-width" />
6
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
7
+ <title>New Ticket from TileDesk</title>
8
+
9
+ <style type="text/css">
10
+ img {
11
+ max-width: 100%;
12
+ margin-left:16px;
13
+ margin-bottom:16px;
14
+ text-align:center !important;
15
+ }
16
+ body {
17
+ -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em;
18
+ }
19
+ body {
20
+ background-color: #f6f6f6;
21
+ }
22
+
23
+ @media only screen and (max-width: 640px) {
24
+ body {
25
+ padding: 0 !important;
26
+ }
27
+ h1 {
28
+ font-weight: 800 !important; margin: 20px 0 5px !important;
29
+ text-align:center !important;
30
+ }
31
+ h2 {
32
+ font-weight: 800 !important; margin: 20px 0 5px !important;
33
+ }
34
+ h3 {
35
+ font-weight: 800 !important; margin: 20px 0 5px !important;
36
+ }
37
+ h4 {
38
+ font-weight: 800 !important; margin: 20px 0 5px !important;
39
+ }
40
+ h1 {
41
+ font-size: 22px !important;
42
+ }
43
+ h2 {
44
+ font-size: 18px !important;
45
+ }
46
+ h3 {
47
+ font-size: 16px !important;
48
+ }
49
+ .container {
50
+ padding: 0 !important; width: 100% !important;
51
+ }
52
+ .content {
53
+ padding: 0 !important;
54
+ }
55
+ .content-wrap {
56
+ padding: 10px !important;
57
+ }
58
+ .invoice {
59
+ width: 100% !important;
60
+ }
61
+ }
62
+ </style>
63
+ </head>
64
+
65
+ <body itemscope itemtype="http://schema.org/EmailMessage" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em; background-color: #f6f6f6; margin: 0;" bgcolor="#f6f6f6">
66
+
67
+ {{#if baseScope.replyEnabled}}
68
+ <div>\# Please type your reply above this line \#</div>
69
+ {{/if}}
70
+
71
+ <table class="main" width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; border-radius: 3px; background-color: #fff; margin: 0; border: 1px solid #e9e9e9;" bgcolor="#fff">
72
+
73
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
74
+ <td class="alert alert-warning" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 16px; vertical-align: top; font-weight: 500; text-align: center; border-radius: 3px 3px 0 0; margin: 0;" align="center" valign="top">
75
+
76
+ <div style="text-align:center">
77
+ <a href="http://www.tiledesk.com" style="color:#2daae1;font-weight:bold;text-decoration:none;word-break:break-word" target="_blank">
78
+ <img src="https://tiledesk.com/wp-content/uploads/2022/07/tiledesk_v2.png" style="width:20%;outline:none;text-decoration:none;border:none;min-height:36px" class="CToWUd">
79
+ </a>
80
+ </div>
81
+ </td>
82
+ </tr>
83
+
84
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
85
+
86
+ <td class="alert alert-warning" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 16px; vertical-align: top; font-weight: 500; text-align: center; border-radius: 3px 3px 0 0; margin: 0;" align="center" valign="top">
87
+ <div>
88
+ <h2>You are a follower of the ticket number: #{{message.request.ticket_id}}</h2>
89
+ </div>
90
+
91
+ </td>
92
+ </tr>
93
+
94
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
95
+ <td class="content-wrap" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 20px;" valign="top">
96
+ <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;">
97
+
98
+
99
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
100
+ <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">
101
+ Sender: <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{message.senderFullname}}</strong>
102
+ </td>
103
+ </tr>
104
+
105
+
106
+
107
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
108
+ <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">
109
+ {{#ifEquals message.type "text"}}
110
+ <div style="white-space: pre-wrap;">{{{msgText}}}</div>
111
+ {{/ifEquals}}
112
+ {{#ifEquals message.type "image"}}
113
+ <img src="{{message.metadata.src}}"/>
114
+ {{#if msgText}}
115
+ <div style="white-space: pre-wrap;">{{{msgText}}}</div>
116
+ {{/if}}
117
+ {{/ifEquals}}
118
+ {{#ifEquals message.type "file"}}
119
+ <a href="{{message.metadata.src}}">{{message.metadata.name}}</a>
120
+ {{/ifEquals}}
121
+ {{#ifEquals message.type "frame"}}
122
+ <a href="{{message.metadata.src}}">{{message.metadata.name}}</a>
123
+ {{#if msgText}}
124
+ <div style="white-space: pre-wrap;">{{{msgText}}}</div>
125
+ {{/if}}
126
+ {{/ifEquals}}
127
+
128
+ {{#if message.attributes}}
129
+ {{#if message.attributes.attachment}}
130
+ {{#if message.attributes.attachment.buttons}}
131
+ {{#each message.attributes.attachment.buttons}}
132
+ {{#ifEquals this.type "url"}}
133
+ <li><a href="{{this.link}}" class="dynamic_button">{{this.value}}</a></li>
134
+ {{else}}
135
+ <li><a href="mailto:{{../message.request.request_id}}@{{../baseScope.inboundDomain}}?subject=Re:%20{{../message.request.subject}}&body={{this.value}}" class="dynamic_button">{{this.value}}</a></li>
136
+ {{/ifEquals}}
137
+ {{/each}}
138
+
139
+
140
+ {{/if}}
141
+ {{/if}}
142
+ {{/if}}
143
+
144
+ <!-- {{#if message.attributes.intent_info}}
145
+ {{#if message.attributes.intent_info.others}}
146
+ Others:
147
+ {{#each message.attributes.intent_info.others}}
148
+ <li><span>{{this.answer}}</span></li>
149
+ {{/each}}
150
+ {{/if}}
151
+ {{/if}} -->
152
+
153
+
154
+
155
+
156
+
157
+ </td>
158
+ </tr>
159
+
160
+
161
+
162
+
163
+
164
+
165
+ <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">
167
+ Project name : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{project.name}}</strong>
168
+ </td>
169
+ </tr>
170
+
171
+
172
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
173
+ <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">
174
+ Department name : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{message.request.department.name}}</strong>
175
+ </td>
176
+ </tr>
177
+
178
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
179
+ <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">
180
+ Source page : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{message.request.sourcePage}}</strong>
181
+ </td>
182
+ </tr>
183
+
184
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
185
+ <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">
186
+ Contact name : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{message.request.lead.fullname}}</strong>
187
+ </td>
188
+ </tr>
189
+
190
+
191
+
192
+
193
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
194
+ <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">
195
+ Channel : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
196
+
197
+ {{#ifEquals message.request.channel.name "chat21"}}
198
+ Chat
199
+ {{else}}
200
+ {{message.request.channel.name}}
201
+ {{/ifEquals}}
202
+
203
+
204
+ </strong>
205
+ </td>
206
+ </tr>
207
+
208
+
209
+
210
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
211
+ <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">
212
+ Priority : <strong style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">{{message.request.priority}}</strong>
213
+ </td>
214
+ </tr>
215
+
216
+
217
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
218
+ <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">
219
+ </td>
220
+ </tr>
221
+ </table>
222
+ </td>
223
+ </tr>
224
+ </table>
225
+ <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;">
226
+ <table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
227
+ <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
228
+ <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">
229
+ <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>
230
+ <!-- <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> -->
231
+ </td>
232
+ </tr>
233
+ </table>
234
+
235
+ </body>
236
+ </html>
@@ -10,7 +10,7 @@ block content
10
10
 
11
11
  each message in messages
12
12
  p(class="transcript-p")
13
- span(class="transcript-chat-date") [#{message.createdAt.toLocaleString('it', { timeZone: 'UTC' })}]
13
+ span(class="transcript-chat-date") [#{message.createdAt.toLocaleString('en', { timeZone: 'UTC' })}]
14
14
  span(class="transcript-chat-sender") #{message.senderFullname}:
15
15
  span(class="transcript-chat-msg") #{message.text}
16
16