@tiledesk/tiledesk-server 2.2.39 → 2.3.1-8.2
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +121 -0
- package/LICENSE +14 -657
- package/README.md +17 -3
- package/app.js +21 -60
- package/channels/chat21/chat21Handler.js +18 -3
- package/channels/chat21/chat21WebHook.js +31 -15
- package/channels/chat21/package-lock.json +663 -706
- package/channels/chat21/package.json +2 -2
- package/deploy.sh +2 -0
- package/event/botEvent.js +1 -1
- package/event/subscriptionEvent.js +11 -0
- package/fonts/Roboto-Italic.ttf +0 -0
- package/fonts/Roboto-Medium.ttf +0 -0
- package/fonts/Roboto-MediumItalic.ttf +0 -0
- package/fonts/Roboto-Regular.ttf +0 -0
- package/middleware/ipFilter.js +220 -0
- package/middleware/passport.js +11 -2
- package/models/lead.js +2 -0
- package/models/project.js +10 -0
- package/models/project_user.js +4 -0
- package/models/request.js +50 -12
- package/models/subscriptionLog.js +34 -0
- package/models/tagLibrary.js +42 -0
- package/package.json +6 -12
- package/pubmodules/activities/activityArchiver.js +314 -0
- package/pubmodules/activities/index.js +3 -0
- package/pubmodules/activities/models/activity.js +88 -0
- package/pubmodules/activities/routes/activity.js +710 -0
- package/pubmodules/activities/test/activityRoute.js +85 -0
- package/pubmodules/analytics/analytics.js +1719 -0
- package/pubmodules/analytics/index.js +3 -0
- package/pubmodules/canned/cannedResponse.js +55 -0
- package/pubmodules/canned/cannedResponseRoute.js +163 -0
- package/pubmodules/canned/index.js +3 -0
- package/pubmodules/emailNotification/requestNotification.js +215 -28
- package/pubmodules/events/eventRoute.js +37 -7
- package/pubmodules/messageActions/messageActionsInterceptor.js +4 -2
- package/pubmodules/pubModulesManager.js +129 -5
- package/pubmodules/rasa/listener.js +5 -5
- package/pubmodules/rules/conciergeBot.js +4 -4
- package/pubmodules/scheduler/tasks/closeAgentUnresponsiveRequestTask.js +3 -1
- package/pubmodules/scheduler/tasks/closeBotUnresponsiveRequestTask.js +3 -1
- package/pubmodules/tilebot/index.js +11 -0
- package/pubmodules/tilebot/listener.js +69 -0
- package/pubmodules/trigger/default.js +271 -0
- package/pubmodules/trigger/event/actionEventEmitter.js +10 -0
- package/pubmodules/trigger/event/flowEventEmitter.js +10 -0
- package/pubmodules/trigger/event/triggerEventEmitter.js +10 -0
- package/pubmodules/trigger/index.js +3 -0
- package/pubmodules/trigger/models/trigger.js +149 -0
- package/pubmodules/trigger/rulesTrigger.js +1181 -0
- package/pubmodules/trigger/start.js +118 -0
- package/pubmodules/trigger/triggerRoute.js +150 -0
- package/routes/auth.js +7 -2
- package/routes/department.js +51 -0
- package/routes/faq.js +7 -0
- package/routes/faq_kb.js +1 -1
- package/routes/group.js +140 -0
- package/routes/lead.js +24 -1
- package/routes/message.js +6 -3
- package/routes/project.js +118 -0
- package/routes/project_user.js +9 -0
- package/routes/public-request.js +280 -2
- package/routes/request.js +122 -16
- package/routes/subscription.js +140 -0
- package/routes/tag.js +138 -0
- package/routes/user-request.js +3 -2
- package/routes/users.js +1 -1
- package/routes/widget.js +80 -3
- package/routes/widgetLoader.js +31 -0
- package/services/banUserNotifier.js +86 -0
- package/services/emailService.js +189 -11
- package/services/faqService.js +2 -2
- package/services/geoService.js +30 -4
- package/services/leadService.js +2 -0
- package/services/modulesManager.js +7 -188
- package/services/requestService.js +364 -6
- package/services/subscriptionNotifier.js +485 -0
- package/template/email/assignedEmailMessage.html +1 -1
- package/template/email/assignedRequest.html +1 -1
- package/template/email/newMessage.html +1 -1
- package/template/email/newMessageFollower.html +236 -0
- package/template/email/passwordChanged.html +1 -1
- package/template/email/pooledEmailMessage.html +1 -1
- package/template/email/pooledRequest.html +1 -1
- package/template/email/resetPassword.html +2 -2
- package/template/email/ticket.html +1 -1
- package/test/cannedRoute.js +166 -0
- package/test/messageRoute.js +69 -0
- package/test/requestService.js +3 -1
- package/utils/orgUtil.js +3 -3
- package/views/messages.jade +2 -2
- package/websocket/webSocketServer.js +23 -5
package/README.md
CHANGED
@@ -9,11 +9,23 @@
|
|
9
9
|
|
10
10
|
# Introduction
|
11
11
|
|
12
|
-
Tiledesk-server is the server engine of Tiledesk. Tiledesk is an Open Source Live Chat platform with integrated
|
12
|
+
Tiledesk-server is the server engine of Tiledesk. Tiledesk is an Open Source Live Chat platform with integrated Chatbots written in NodeJs and Express. Build your own customer support with a multi-channel platform for Web, Android and iOS.
|
13
13
|
|
14
|
-
|
14
|
+
Designed to be open source since the beginning, we actively worked on it to create a totally new, first class customer service platform based on instant messaging.
|
15
15
|
|
16
|
-
|
16
|
+
What is Tiledesk today? It became the open source “conversational app development” platform that everyone needs 😌
|
17
|
+
|
18
|
+
You can use Tiledesk to increase sales for your website or for post-sales customer service. Every conversation can be automated using our first class native chatbot technology.
|
19
|
+
You can also connect your own applications using our APIs or Webhooks.
|
20
|
+
Moreover you can deploy entire visual applications inside a conversation. And your applications can converse with your chatbots or your end-users! We know this is cool 😎
|
21
|
+
|
22
|
+
Tiledesk is multichannel in a totally new way. You can write your chatbot scripts with images, buttons and other cool elements that your channels support. But you will configureyour chatbot replies only once. They will run on every channel, auto-adapting the responses to the target channel whatever it is, Whatsapp, Facebook Messenger, Telegram etc.
|
23
|
+
|
24
|
+
More info on Tiledesk website: https://www.tiledesk.com.
|
25
|
+
|
26
|
+
You can find technical documentation here: https://developer.tiledesk.com
|
27
|
+
|
28
|
+
# Prerequisites for Installation
|
17
29
|
|
18
30
|
* [Nodejs](https://www.npmjs.com/) and npm installed. Suggested versions are NodeJS 12.20.2 and NPM 6.14.11
|
19
31
|
* [MongoDb](https://www.mongodb.com) installed
|
@@ -80,6 +92,8 @@ Deploy with button:
|
|
80
92
|
|
81
93
|
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/Tiledesk/tiledesk-server)
|
82
94
|
|
95
|
+
# Community? Questions? Support ?
|
96
|
+
If you need help or just want to hang out, come, say hi on our [<img width="15" alt="Tiledesk discord" src="https://seeklogo.com/images/D/discord-color-logo-E5E6DFEF80-seeklogo.com.png"> Discord](https://discord.gg/nERZEZ7SmG) server.
|
83
97
|
|
84
98
|
# REST API
|
85
99
|
|
package/app.js
CHANGED
@@ -87,6 +87,9 @@ var lead = require('./routes/lead');
|
|
87
87
|
var message = require('./routes/message');
|
88
88
|
var messagesRootRoute = require('./routes/messagesRoot');
|
89
89
|
var department = require('./routes/department');
|
90
|
+
var group = require('./routes/group');
|
91
|
+
var resthook = require('./routes/subscription');
|
92
|
+
var tag = require('./routes/tag');
|
90
93
|
var faq = require('./routes/faq');
|
91
94
|
var faq_kb = require('./routes/faq_kb');
|
92
95
|
var project = require('./routes/project');
|
@@ -124,6 +127,9 @@ var RouterLogger = require('./models/routerLogger');
|
|
124
127
|
|
125
128
|
require('./services/mongoose-cache-fn')(mongoose);
|
126
129
|
|
130
|
+
var subscriptionNotifier = require('./services/subscriptionNotifier');
|
131
|
+
subscriptionNotifier.start();
|
132
|
+
|
127
133
|
var botSubscriptionNotifier = require('./services/BotSubscriptionNotifier');
|
128
134
|
botSubscriptionNotifier.start();
|
129
135
|
|
@@ -140,10 +146,10 @@ pubModulesManager.init({express:express, mongoose:mongoose, passport:passport, d
|
|
140
146
|
var channelManager = require('./channels/channelManager');
|
141
147
|
channelManager.listen();
|
142
148
|
|
143
|
-
|
144
|
-
// const IpDeniedError = require('express-ipfilter').IpDeniedError;
|
145
|
-
|
149
|
+
var IPFilter = require('./middleware/ipFilter');
|
146
150
|
|
151
|
+
var BanUserNotifier = require('./services/banUserNotifier');
|
152
|
+
BanUserNotifier.listen();
|
147
153
|
|
148
154
|
var modulesManager = undefined;
|
149
155
|
try {
|
@@ -170,7 +176,6 @@ if (process.env.CREATE_INITIAL_DATA !== "false") {
|
|
170
176
|
|
171
177
|
|
172
178
|
|
173
|
-
|
174
179
|
var app = express();
|
175
180
|
|
176
181
|
|
@@ -331,57 +336,6 @@ var projectSetter = function (req, res, next) {
|
|
331
336
|
}
|
332
337
|
|
333
338
|
|
334
|
-
function customDetection (req) {
|
335
|
-
// const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
|
336
|
-
const ip = (req.headers['x-forwarded-for'] || '').split(',').pop().trim() || //https://stackoverflow.com/questions/8107856/how-to-determine-a-users-ip-address-in-node
|
337
|
-
req.socket.remoteAddress
|
338
|
-
|
339
|
-
winston.info("standard ip: "+ip); // ip address of the user
|
340
|
-
return ip;
|
341
|
-
}
|
342
|
-
|
343
|
-
|
344
|
-
var projectIpFilter = function (req, res, next) {
|
345
|
-
// var projectIpFilter = function (err, req, res, next) {
|
346
|
-
|
347
|
-
// var ip = require('ip');
|
348
|
-
// winston.info("projectIpFilter ip2: " + ip.address() );
|
349
|
-
|
350
|
-
|
351
|
-
const nextIp = function(err) {
|
352
|
-
winston.info("projectIpFilter next",err);
|
353
|
-
|
354
|
-
if (err && err.name === "IpDeniedError") {
|
355
|
-
winston.info("IpDeniedError");
|
356
|
-
return res.status(401).json({ err: "error project ip filter" });
|
357
|
-
// next(err)
|
358
|
-
}
|
359
|
-
|
360
|
-
next();
|
361
|
-
|
362
|
-
}
|
363
|
-
|
364
|
-
|
365
|
-
if (!req.project) {
|
366
|
-
return next();
|
367
|
-
}
|
368
|
-
|
369
|
-
var projectIpFilterEnabled = req.project.ipFilterEnabled;
|
370
|
-
winston.debug("project projectIpFilterEnabled: " +projectIpFilterEnabled)
|
371
|
-
|
372
|
-
var projectIpFilter = req.project.ipFilter
|
373
|
-
winston.debug("project ipFilter: " + projectIpFilter)
|
374
|
-
|
375
|
-
if (projectIpFilterEnabled === true && projectIpFilter && projectIpFilter.length > 0) {
|
376
|
-
var ip = ipfilter(projectIpFilter, { detectIp: customDetection, mode: 'allow' })
|
377
|
-
// var ip = ipfilter(projectIpFilter, { mode: 'allow' })
|
378
|
-
ip(req, res, nextIp);
|
379
|
-
} else {
|
380
|
-
next();
|
381
|
-
}
|
382
|
-
|
383
|
-
}
|
384
|
-
|
385
339
|
|
386
340
|
|
387
341
|
// app.use('/admin', admin);
|
@@ -398,6 +352,8 @@ app.use('/auth', auth);
|
|
398
352
|
app.use('/testauth', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken], authtest);
|
399
353
|
|
400
354
|
app.use('/widgets', widgetsLoader);
|
355
|
+
app.use('/w', widgetsLoader);
|
356
|
+
|
401
357
|
app.use('/images', images);
|
402
358
|
app.use('/files', files);
|
403
359
|
app.use('/urls', urls);
|
@@ -425,8 +381,7 @@ if (modulesManager) {
|
|
425
381
|
modulesManager.use(app);
|
426
382
|
}
|
427
383
|
|
428
|
-
|
429
|
-
app.use('/:projectid/', [projectIdSetter, projectSetter, projectIpFilter]);
|
384
|
+
app.use('/:projectid/', [projectIdSetter, projectSetter, IPFilter.projectIpFilter, IPFilter.projectIpFilterDeny, IPFilter.decodeJwt, IPFilter.projectBanUserFilter]);
|
430
385
|
|
431
386
|
|
432
387
|
app.use('/:projectid/authtestWithRoleCheck', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken], authtestWithRoleCheck);
|
@@ -441,11 +396,17 @@ app.use('/:projectid/departments', department);
|
|
441
396
|
|
442
397
|
|
443
398
|
|
399
|
+
|
400
|
+
|
444
401
|
channelManager.useUnderProjects(app);
|
445
402
|
|
403
|
+
app.use('/:projectid/groups', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], group);
|
404
|
+
app.use('/:projectid/tags', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], tag);
|
405
|
+
app.use('/:projectid/subscriptions', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], resthook);
|
406
|
+
|
446
407
|
//deprecated
|
447
|
-
app.use('/:projectid/faq', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.
|
448
|
-
app.use('/:projectid/intents', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.
|
408
|
+
app.use('/:projectid/faq', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], faq);
|
409
|
+
app.use('/:projectid/intents', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], faq);
|
449
410
|
|
450
411
|
//Deprecated??
|
451
412
|
app.use('/:projectid/faqpub', faqpub);
|
@@ -528,7 +489,7 @@ app.use(function (err, req, res, next) {
|
|
528
489
|
// error handler
|
529
490
|
app.use((err, req, res, next) => {
|
530
491
|
|
531
|
-
winston.
|
492
|
+
winston.debug("err.name", err.name)
|
532
493
|
if (err.name === "IpDeniedError") {
|
533
494
|
winston.info("IpDeniedError");
|
534
495
|
return res.status(401).json({ err: "error ip filter" });
|
@@ -246,7 +246,18 @@ class Chat21Handler {
|
|
246
246
|
});
|
247
247
|
|
248
248
|
|
249
|
+
messageEvent.on('message.test', function(message) {
|
250
|
+
|
251
|
+
winston.info("Chat21Sender message.test");
|
252
|
+
|
253
|
+
chat21.auth.setAdminToken(adminToken);
|
249
254
|
|
255
|
+
return chat21.messages.sendToGroup(message.senderFullname, message.recipient,
|
256
|
+
message.recipient_fullname, message.text, message.sender, message.attributes, message.type, message.metadata, message.timestamp, message.group)
|
257
|
+
.then(function(data){
|
258
|
+
winston.info("Chat21Sender sendToGroup test: "+ JSON.stringify(data));
|
259
|
+
});
|
260
|
+
});
|
250
261
|
|
251
262
|
|
252
263
|
messageEvent.on('message.sending', function(message) {
|
@@ -299,7 +310,8 @@ class Chat21Handler {
|
|
299
310
|
}
|
300
311
|
|
301
312
|
var recipient_fullname = "Guest";
|
302
|
-
//
|
313
|
+
// guest_here
|
314
|
+
|
303
315
|
if (message.request && message.request.lead && message.request.lead.fullname) {
|
304
316
|
recipient_fullname = message.request.lead.fullname;
|
305
317
|
}
|
@@ -332,6 +344,7 @@ class Chat21Handler {
|
|
332
344
|
}
|
333
345
|
*/
|
334
346
|
|
347
|
+
|
335
348
|
return chat21.messages.sendToGroup(message.senderFullname, message.recipient,
|
336
349
|
recipient_fullname, message.text, message.sender, attributes, message.type, message.metadata, timestamp)
|
337
350
|
.then(function(data){
|
@@ -339,7 +352,7 @@ class Chat21Handler {
|
|
339
352
|
|
340
353
|
|
341
354
|
// chat21.conversations.stopTyping(message.recipient,message.sender);
|
342
|
-
|
355
|
+
|
343
356
|
chat21Event.emit('message.sent', data);
|
344
357
|
|
345
358
|
messageService.changeStatus(message._id, MessageConstants.CHAT_MESSAGE_STATUS.DELIVERED) .then(function(upMessage){
|
@@ -563,13 +576,15 @@ class Chat21Handler {
|
|
563
576
|
var groupId = request.request_id;
|
564
577
|
|
565
578
|
var group_name = "Guest";
|
566
|
-
|
579
|
+
// guest_here
|
580
|
+
|
567
581
|
if (request.lead && request.lead.fullname) {
|
568
582
|
group_name = request.lead.fullname;
|
569
583
|
}
|
570
584
|
if (request.subject) {
|
571
585
|
group_name = request.subject;
|
572
586
|
}
|
587
|
+
|
573
588
|
//TODO racecondition?
|
574
589
|
return chat21.groups.create(group_name, members, gAttributes, groupId).then(function(data) {
|
575
590
|
winston.verbose("Chat21 group created: " + JSON.stringify(data));
|
@@ -201,12 +201,16 @@ router.post('/', function (req, res) {
|
|
201
201
|
return winston.error("project_user not found with query: ", queryProjectUser);
|
202
202
|
}
|
203
203
|
|
204
|
+
|
205
|
+
|
206
|
+
|
204
207
|
|
205
208
|
var new_request = {
|
206
209
|
request_id: message.recipient, project_user_id:project_user_id, lead_id:createdLead._id, id_project:projectid, first_text:message.text,
|
207
210
|
departmentid:departmentid, sourcePage:sourcePage, language:language, userAgent:client, status:requestStatus, createdBy: undefined,
|
208
211
|
attributes:rAttributes, subject:undefined, preflight:false, channel:undefined, location:undefined,
|
209
212
|
lead:createdLead, requester:project_user
|
213
|
+
|
210
214
|
};
|
211
215
|
|
212
216
|
winston.debug("new_request", new_request);
|
@@ -226,10 +230,10 @@ router.post('/', function (req, res) {
|
|
226
230
|
// upsert(id, sender, senderFullname, recipient, text, id_project, createdBy, status, attributes, type, metadata, language)
|
227
231
|
return messageService.upsert(messageId, message.sender, message.sender_fullname, message.recipient, message.text,
|
228
232
|
projectid, null, MessageConstants.CHAT_MESSAGE_STATUS.RECEIVED, message.attributes, message.type, message.metadata, language).then(function(savedMessage){
|
229
|
-
|
230
|
-
return requestService.incrementMessagesCountByRequestId(savedRequest.request_id, savedRequest.id_project).then(function(savedRequestWithIncrement) {
|
231
|
-
return res.json(savedRequestWithIncrement);
|
232
|
-
});
|
233
|
+
return res.json(savedRequest);
|
234
|
+
// return requestService.incrementMessagesCountByRequestId(savedRequest.request_id, savedRequest.id_project).then(function(savedRequestWithIncrement) {
|
235
|
+
// return res.json(savedRequestWithIncrement);
|
236
|
+
// });
|
233
237
|
|
234
238
|
|
235
239
|
}).catch(function (err) {
|
@@ -286,23 +290,25 @@ router.post('/', function (req, res) {
|
|
286
290
|
|
287
291
|
// TOOD update also request attributes and sourcePage
|
288
292
|
|
289
|
-
return requestService.incrementMessagesCountByRequestId(request.request_id, request.id_project).then(function(savedRequest) {
|
293
|
+
// return requestService.incrementMessagesCountByRequestId(request.request_id, request.id_project).then(function(savedRequest) {
|
290
294
|
// winston.debug("savedRequest.participants.indexOf(message.sender)", savedRequest.participants.indexOf(message.sender));
|
291
295
|
|
292
296
|
// TODO it doesn't work for internal requests bacause participanets == message.sender⁄
|
293
|
-
if (
|
297
|
+
if (request.participants && request.participants.indexOf(message.sender) > -1) { //update waiitng time if write an agent (member of participants)
|
294
298
|
winston.debug("updateWaitingTimeByRequestId");
|
299
|
+
|
295
300
|
return requestService.updateWaitingTimeByRequestId(request.request_id, request.id_project).then(function(upRequest) {
|
296
301
|
return res.json(upRequest);
|
297
302
|
});
|
298
303
|
}else {
|
299
|
-
|
304
|
+
|
305
|
+
return res.json(savedMessage);
|
300
306
|
}
|
301
|
-
});
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
307
|
+
// });
|
308
|
+
}).catch(function(err){
|
309
|
+
winston.error("Error creating chat21 webhook message: "+ JSON.stringify({err: err, message: message}));
|
310
|
+
return res.status(500).send({success: false, msg: 'Error creating message', err:err });
|
311
|
+
});
|
306
312
|
|
307
313
|
|
308
314
|
|
@@ -398,7 +404,9 @@ router.post('/', function (req, res) {
|
|
398
404
|
// winston.debug('updatedParticipantsRequest', updatedParticipantsRequest);
|
399
405
|
// manca id
|
400
406
|
|
401
|
-
|
407
|
+
// closeRequestByRequestId(request_id, id_project, skipStatsUpdate, notify, closed_by)
|
408
|
+
const closed_by = user_id;
|
409
|
+
return requestService.closeRequestByRequestId(recipient_id, projectId, false, true,closed_by ).then(function(updatedStatusRequest) {
|
402
410
|
|
403
411
|
winston.debug('updatedStatusRequest', updatedStatusRequest.toObject());
|
404
412
|
return res.json(updatedStatusRequest);
|
@@ -532,7 +540,7 @@ router.post('/', function (req, res) {
|
|
532
540
|
});
|
533
541
|
}
|
534
542
|
|
535
|
-
else if (req.body.event_type == "deleted-archivedconversation") {
|
543
|
+
else if (req.body.event_type == "deleted-archivedconversation" || req.body.event_type == "conversation-unarchived") {
|
536
544
|
|
537
545
|
winston.debug("event_type","deleted-archivedconversation");
|
538
546
|
|
@@ -544,7 +552,7 @@ router.post('/', function (req, res) {
|
|
544
552
|
}
|
545
553
|
|
546
554
|
|
547
|
-
var conversation = req.body.data;
|
555
|
+
var conversation = req.body.data;
|
548
556
|
// winston.debug("conversation",conversation);
|
549
557
|
|
550
558
|
var user_id = req.body.user_id;
|
@@ -561,16 +569,24 @@ router.post('/', function (req, res) {
|
|
561
569
|
return res.status(400).send({success: false, msg: "not a support conversation" });
|
562
570
|
}
|
563
571
|
|
572
|
+
|
573
|
+
|
564
574
|
if (user_id!="system"){
|
565
575
|
winston.debug("not a system conversation");
|
566
576
|
return res.status(400).send({success: false, msg: "not a system conversation" });
|
567
577
|
}
|
568
578
|
|
569
579
|
|
580
|
+
|
581
|
+
// scrivo... nuova viene popolato projectid in attributes poi chiudo ed in archived c'è projectid
|
582
|
+
// quando scrivo viene cancellato archived e nuovo messaggio crea conv ma senza project id... lineare che è cosi
|
583
|
+
// si verifica solo se admin (da ionic ) archivia di nuovo senza che widget abbia scritto nulla (widget risetta projectid in properties)
|
584
|
+
|
570
585
|
var id_project;
|
571
586
|
if (conversation && conversation.attributes) {
|
572
587
|
id_project = conversation.attributes.projectId;
|
573
588
|
}else {
|
589
|
+
winston.debug( "not a support deleting archived conversation" );
|
574
590
|
return res.status(400).send({success: false, msg: "not a support deleting archived conversation" });
|
575
591
|
}
|
576
592
|
winston.debug("id_project", id_project);
|