@tiledesk/tiledesk-server
Version:
The Tiledesk server module
543 lines (387 loc) • 20.1 kB
JavaScript
var express = require('express');
// https://stackoverflow.com/questions/28977253/express-router-undefined-params-with-router-use-when-split-across-files
var router = express.Router({mergeParams: true});
var Message = require("../models/message");
var Request = require("../models/request");
var Lead = require("../models/lead");
var requestService = require('../services/requestService');
var messageService = require('../services/messageService');
var leadService = require('../services/leadService');
var winston = require('../config/winston');
var MessageConstants = require("../models/messageConstants");
var cacheUtil = require('../utils/cacheUtil');
var cacheEnabler = require("../services/cacheEnabler");
const { check, validationResult } = require('express-validator');
var Project_user = require("../models/project_user");
var mongoose = require('mongoose');
var PromiseUtil = require("../utils/promiseUtil");
csv = require('csv-express');
csv.separator = ';';
// var roleChecker = require('../middleware/has-role');
router.post('/',
// [
// check('text').custom(value => {
// console.log("value",value);
// console.log("req.body.type",this.type);
// if (this.type === "text" && (value == undefined || value == "" ) ) {
// // if (this.type === "text" && ( (!value) || (value === "") ) ) {
// console.log("sono qui ",value);
// return Promise.reject('Text field is required for text message');
// }else {
// console.log("sono qua ",value);
// return Promise.resolve();
// }
// })
// ],
async (req, res) => {
winston.debug('req.body post message', req.body);
winston.debug('req.params: ', req.params);
winston.debug('req.params.request_id: ' + req.params.request_id);
// const errors = validationResult(req);
// if (!errors.isEmpty()) {
// return res.status(422).json({ errors: errors.array() });
// }
// TODO se sei agent non puoi cambiare sender
// verificare validazione invio immagine senza caption
var project_user = req.projectuser;
var sender = req.body.sender;
var fullname = req.body.senderFullname || req.user.fullName;
var email = req.body.email || req.user.email;
let messageStatus = req.body.status || MessageConstants.CHAT_MESSAGE_STATUS.SENDING;
winston.debug('messageStatus: ' + messageStatus);
let q = Request.findOne({request_id: req.params.request_id, id_project: req.projectid});
if (cacheEnabler.request) {
q.cache(cacheUtil.defaultTTL, req.projectid+":requests:request_id:"+req.params.request_id+":simple") //request_cache
winston.debug('request cache enabled');
}
// cacherequest // requestcachefarequi nocachepopulatereqired
return q.exec(async(err, request) => {
// .populate('lead')
// .populate('department')
// .populate('participatingBots')
// .populate('participatingAgents')
// .populate({path:'requester',populate:{path:'id_user'}})
if (err) {
winston.log({
level: 'error',
message: 'Error getting the request: '+ JSON.stringify(err) + " " + JSON.stringify(req.body) ,
label: req.projectid
});
// winston.error('Error getting the request.', err);
return res.status(500).send({success: false, msg: 'Error getting the request.', err:err});
}
if (!request) { //the request doen't exists create it
winston.debug("request not exists", request);
if (project_user) {
winston.debug("project_user", project_user);
}
// sponz: 4/01/23 disable it
if (!req.body.text && (!req.body.type || req.body.type=="text") ) {
return res.status(422).json({ errors: ["text field is required"] });
}
if (sender) {
var isObjectId = mongoose.Types.ObjectId.isValid(sender);
winston.debug("isObjectId:"+ isObjectId);
var queryProjectUser = {id_project:req.projectid, status: "active" };
if (isObjectId) {
queryProjectUser.id_user = sender;
} else {
queryProjectUser.uuid_user = sender;
}
winston.debug("queryProjectUser", queryProjectUser);
project_user = await Project_user.findOne(queryProjectUser).populate({path:'id_user', select:{'firstname':1, 'lastname':1, 'email':1}})
winston.debug("project_user", project_user);
if (!project_user) {
return res.status(403).send({success: false, msg: 'Unauthorized. Project_user not found with user id : '+ sender });
}
if ( project_user.id_user) {
fullname = project_user.id_user.fullName;
winston.debug("pu fullname: "+ fullname);
email = project_user.id_user.email;
winston.debug("pu email: "+ email);
} else if (project_user.uuid_user) {
var lead = await Lead.findOne({lead_id: project_user.uuid_user, id_project: req.projectid});
winston.debug("lead: ",lead);
if (lead) {
fullname = lead.fullname;
winston.debug("lead fullname: "+ fullname);
email = lead.email;
winston.debug("lead email: "+ email);
}else {
winston.warn("lead not found: " + JSON.stringify({lead_id: project_user.uuid_user, id_project: req.projectid}));
}
} else {
winston.warn("pu fullname and email empty");
}
}
// prende fullname e email da quello loggato
// createIfNotExistsWithLeadId(lead_id, fullname, email, id_project, createdBy, attributes) {
return leadService.createIfNotExistsWithLeadId(sender || req.user._id, fullname, email, req.projectid, null, req.body.attributes || req.user.attributes, undefined, req.user.phone)
.then(function(createdLead) {
const contact = {
...(createdLead.phone && { phone: createdLead.phone }),
...(createdLead.email && { email: createdLead.email })
};
var new_request = {
request_id: req.params.request_id,
project_user_id: project_user._id,
lead_id: createdLead._id,
...(Object.keys(contact).length && { contact }),
id_project:req.projectid,
first_text: req.body.text,
departmentid: req.body.departmentid,
sourcePage:req.body.sourcePage,
language: req.body.language,
userAgent:req.body.userAgent,
status:req.body.request_status,
createdBy: req.user._id,
attributes: req.body.attributes,
subject: req.body.subject,
preflight:req.body.preflight,
channel: req.body.channel,
location: req.body.location,
participants: req.body.participants,
lead: createdLead,
requester: project_user,
priority: req.body.priority,
followers: req.body.followers,
proactive: true
};
return requestService.create(new_request).then(function (savedRequest) {
if (!savedRequest) {
return res.status(403).send({ success: false, message: "Requests quota exceeded"})
}
winston.debug("returning savedRequest to", savedRequest.toJSON());
// createWithIdAndRequester(request_id, project_user_id, lead_id, id_project, first_text, departmentid, sourcePage, language, userAgent, status,
// createdBy, attributes, subject, preflight, channel, location) {
// return requestService.createWithIdAndRequester(req.params.request_id, req.projectuser._id, createdLead._id, req.projectid,
// req.body.text, req.body.departmentid, req.body.sourcePage,
// req.body.language, req.body.userAgent, null, req.user._id, req.body.attributes, req.body.subject, undefined, req.body.channel, req.body.location ).then(function (savedRequest) {
// create(sender, senderFullname, recipient, text, id_project, createdBy, status, attributes, type, metadata, language, channel_type, channel) {
return messageService.create(sender || req.user._id, fullname, req.params.request_id, req.body.text,
req.projectid, req.user._id, messageStatus, req.body.attributes, req.body.type, req.body.metadata, req.body.language, undefined, req.body.channel).then(function (savedMessage) {
// return requestService.incrementMessagesCountByRequestId(savedRequest.request_id, savedRequest.id_project).then(function(savedRequestWithIncrement) {
let message = savedMessage.toJSON();
winston.debug("returning message to", message);
winston.debug("returning savedRequest2210 to", savedRequest.toJSON());
savedRequest //bug
// Request.findById(savedRequest.id)
.populate('lead')
.populate('department')
.populate('participatingBots')
.populate('participatingAgents')
// .populate('followers')
.populate({ path: 'requester', populate: { path: 'id_user' } })
// .exec(function (err, savedRequestPopulated){
.execPopulate(function (err, savedRequestPopulated) { //bug with execPopulate request.attributes are invalid (NOT real data). but this bug is related to chat21 listener changes by reference. i think populate suffer from this problem bacause it it the same obect passed by reference
if (err) {
return winston.error("Error gettting savedRequestPopulated for send Message", err);
}
winston.debug("returning savedRequest221 to", savedRequest.toJSON());
winston.debug("savedRequestPopulated", savedRequestPopulated.toJSON());
winston.debug("returning savedRequest22 to", savedRequest.toJSON());
message.request = savedRequestPopulated;
winston.debug("returning2 message to", message);
return res.json(message);
});
});
}).catch(function (err) { //pubblica questo
winston.error('Error creating request: ' + JSON.stringify(err));
return res.status(500).send({ success: false, msg: 'Error creating request', err: err });
});
});
} else {
winston.debug("request exists", request.toObject());
if (request.channel?.name === 'form') {
if (!sender && request.participantsAgents?.[0] !== req.user.id) {
return res.status(403).send({ success: false, message: "Error creating message", err: "You don't belong the conversation" });
}
}
return messageService.create(sender || req.user._id, fullname, req.params.request_id, req.body.text,
request.id_project, null, messageStatus, req.body.attributes, req.body.type, req.body.metadata,
req.body.language, undefined, req.body.channel).then(function(savedMessage){
// TOOD update also request attributes and sourcePage
// return requestService.incrementMessagesCountByRequestId(request.request_id, request.id_project).then(function(savedRequest) {
Request.findOneAndUpdate({request_id: request.request_id, id_project: request.id_project}, { "attributes.last_message": savedMessage}).catch((err) => {
winston.error("Create message - saved last message in request error: ", error);
})
if (request.participants && request.participants.indexOf(sender) > -1) { //update waiitng time if write an agent (member of participants)
winston.debug("updateWaitingTimeByRequestId");
return requestService.updateWaitingTimeByRequestId(request.request_id, request.id_project, true).then(function(upRequest) {
let message = savedMessage.toJSON();
message.request = upRequest;
return res.json(message);
});
} else {
let message = savedMessage.toJSON();
winston.debug("getting request for response");
let q = Request.findOne({request_id: request.request_id, id_project: request.id_project})
.populate('lead')
.populate('department')
.populate('participatingBots')
.populate('participatingAgents')
.populate({path:'requester',populate:{path:'id_user'}});
if (cacheEnabler.request) {
q.cache(cacheUtil.defaultTTL, request.id_project+":requests:request_id:"+request.request_id)
winston.debug('request cache enabled for messages');
}
q.exec(function (err, requestPopulated) {
if (err) {
return winston.error("Error gettting savedRequestPopulated for send Message", err);
}
message.request = requestPopulated;
return res.json(message);
});
}
}).catch(function(err) {
winston.log({
level: 'error',
message: 'Error creating message endpoint: '+ JSON.stringify(err) + " " + JSON.stringify(req.body) ,
label: req.projectid
});
winston.error("Error creating message", err);
return res.status(500).send({success: false, msg: 'Error creating message', err:err });
});
}
});
});
// router.post('/multi2', async (req, res, next) => {
// if ( !req.body instanceof Array ) {
// return res.status(422).json({ errors: ["request body is not array"] });
// }
// req.url = '/';
// winston.info('--- > req.url'+req.url);
// req.method = 'POST';
// let promises = [];
// req.body.forEach(function(message,index) {
// promises.push(router.handle(req, res, next));
// });
// winston.info('--- >promises', promises);
// Promise.all(promises).then((values) => {
// console.log("finito",values);
// return res.status(200).json({ "success": true });
// }).catch((err) => {
// console.log("errore",err);
// });
// });
router.post('/multi',
async (req, res) => {
winston.debug('req.body post message', req.body);
winston.debug('req.params: ', req.params);
winston.debug('req.params.request_id: ' + req.params.request_id);
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
var project_user = req.projectuser;
let q = Request.findOne({request_id: req.params.request_id, id_project: req.projectid});
// if (cacheEnabler.request) {
// q.cache(cacheUtil.defaultTTL, req.projectid+":requests:request_id:"+req.params.request_id+":simple") //request_cache
// winston.debug('request cache enabled');
// }
return q.exec(async(err, request) => {
if (err) {
winston.log({
level: 'error',
message: 'Error getting the request: '+ JSON.stringify(err) + " " + JSON.stringify(req.body) ,
label: req.projectid
});
// winston.error('Error getting the request.', err);
return res.status(500).send({success: false, msg: 'Error getting the request.', err:err});
}
if (!request) { //the request doen't exists create it
return res.status(404).send({success: false, msg: 'Request doesn\'t exist.', err:err});
} else {
winston.debug("request exists", request.toObject());
let promises = [];
let sender;
let fullname;
let email;
let text;
let attributes;
let type;
let metadata;
let language;
let channel;
let messageStatus;
req.body.forEach(function(message,index) {
sender = message.sender;
fullname = message.senderFullname || req.user.fullName;
email = message.email || req.user.email;
text = message.text;
attributes = message.attributes;
type = message.type;
metadata = message.metadata;
language = message.language;
channel = message.channel;
messageStatus = message.status || MessageConstants.CHAT_MESSAGE_STATUS.SENDING;
// create(sender, senderFullname, recipient, text, id_project, createdBy, status, attributes, type, metadata, language, channel_type, channel) {
let promise = messageService.create(sender || req.user._id, fullname, req.params.request_id, text,
request.id_project, null, messageStatus, attributes, type, metadata, language, undefined, channel);
promises.push(promise);
});
winston.debug('--- >promises', promises);
//Promise.all(promises).then((values) => {
PromiseUtil.doAllSequentually(promises).then((values) => {
winston.info('Inserted multiple messages with values: ', values);
return res.status(200).json(values);
}).catch((err) => {
winston.error('Error inserting multiple messages.', err);
return res.status(500).send({success: false, msg: 'Error inserting multiple messages.', err:err});
});
}
});
});
// router.patch('/:messageid', function(req, res) {
// winston.info(req.body);
// Message.findByIdAndUpdate(req.params.messageid, req.body, {new: true, upsert:true}, function(err, updatedMessage) {
// if (err) {
// return res.status(500).send({success: false, msg: 'Error updating object.'});
// }
// res.json(updatedMessage);
// });
// });
// router.put('/:messageid', function(req, res) {
// console.log(req.body);
// Message.findByIdAndUpdate(req.params.messageid, req.body, {new: true, upsert:true}, function(err, updatedMessage) {
// if (err) {
// return res.status(500).send({success: false, msg: 'Error updating object.'});
// }
// res.json(updatedMessage);
// });
// });
// router.delete('/:messageid', function(req, res) {
// console.log(req.body);
// Message.remove({_id:req.params.messageid}, function(err, Message) {
// if (err) {
// return res.status(500).send({success: false, msg: 'Error deleting object.'});
// }
// res.json(Message);
// });
// });
router.get('/csv', function(req, res) {
// console.log("csv");
return Message.find({"recipient": req.params.request_id, id_project: req.projectid}).sort({createdAt: 'asc'}).exec(function(err, messages) {
if (err) return next(err);
res.csv(messages, true);
});
});
router.get('/:messageid', function(req, res) {
// console.log(req.body);
Message.findById(req.params.messageid, function(err, message) {
if (err) {
return res.status(500).send({success: false, msg: 'Error getting object.'});
}
if(!message){
return res.status(404).send({success: false, msg: 'Object not found.'});
}
res.json(message);
});
});
router.get('/', function(req, res) {
return Message.find({"recipient": req.params.request_id, id_project: req.projectid}).sort({createdAt: 'asc'}).exec(function(err, messages) {
if (err) return next(err);
res.json(messages);
});
});
module.exports = router;