2023-12-07 12:04:19 +01:00
|
|
|
const glob = require("glob");
|
|
|
|
const path = require("path");
|
|
|
|
const fs = require("fs-extra");
|
|
|
|
const axios = require("axios");
|
2024-02-15 12:32:51 +01:00
|
|
|
const dayjs = require("dayjs");
|
|
|
|
const Checkjson = require(`./Checkjson.js`);
|
2023-12-07 12:04:19 +01:00
|
|
|
//const smtp = require("smtp-client");
|
|
|
|
const nodemailer = require("nodemailer");
|
2024-03-20 11:24:03 +01:00
|
|
|
const conf = require(`../../../conf.json`);
|
2024-02-15 12:32:51 +01:00
|
|
|
const currentmod = "Notifications";
|
|
|
|
const log = conf.api.activelog.includes(currentmod);
|
2023-12-07 12:04:19 +01:00
|
|
|
/**
|
|
|
|
* To manage any communication between Pagan
|
|
|
|
* mayor druid emailing/sms/paper from tribe register smtp, simcard, mail api to Person(s) / Pagan(s)
|
|
|
|
* volatile notification message from tribe activities to Pagans / person ()
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
const Notifications = {};
|
|
|
|
|
|
|
|
Notifications.get = (alias, tribeId) => {
|
2024-03-19 09:10:07 +01:00
|
|
|
const notiffile = `../../${req.params.tribeId}/notifications/${req.params.alias}.json`;
|
2023-12-07 12:04:19 +01:00
|
|
|
const msg = fs.existsSync(notiffile) ? fs.readJSONSync(notiffile) : {};
|
|
|
|
return {
|
|
|
|
status: 200,
|
|
|
|
ref: "Notification",
|
|
|
|
msg: "Messagelist",
|
|
|
|
data: { notif: [{ tribeId, msg }] },
|
|
|
|
};
|
|
|
|
};
|
2024-04-03 17:32:37 +02:00
|
|
|
/**
|
|
|
|
* Get statistic of registering email phone
|
|
|
|
*/
|
|
|
|
Notifications.statmaillist=(tribe)=>{
|
|
|
|
const statinfo={}
|
|
|
|
const src=`../../${tribe}/objects/maillinglists/*.json`
|
|
|
|
console.log(path.resolve(src))
|
|
|
|
glob.sync(src).forEach(f=>{
|
|
|
|
const name=path.basename(f,".json");
|
|
|
|
const mlst=fs.readJSONSync(f)
|
|
|
|
Object.keys(mlst).forEach(c=>{
|
|
|
|
mlst[c].srckeys.forEach(s=>{
|
|
|
|
if (!statinfo[s]) statinfo[s]={}
|
|
|
|
if (!statinfo[s][name]) statinfo[s][name]=0
|
|
|
|
statinfo[s][name]++
|
|
|
|
})
|
|
|
|
//console.log(c) recupere les contact tel ou email
|
|
|
|
})
|
|
|
|
})
|
2023-12-07 12:04:19 +01:00
|
|
|
|
2024-04-03 17:32:37 +02:00
|
|
|
return {status:200,ref:"Notifications",msg:"statistics",data:statinfo}
|
|
|
|
}
|
2023-12-29 13:38:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Register an typekey(email) or (phone) key into mailinglist for a tribe
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
Notifications.registertolist = (key, typekey, tribe, mlist, srckey, uuid) => {
|
|
|
|
key = key.toLowerCase();
|
2024-03-27 23:52:41 +01:00
|
|
|
typekey= (typekey=="telephone")? "telephonefr":typekey;
|
2023-12-29 13:38:47 +01:00
|
|
|
if (!Checkjson.testformat(key, typekey))
|
|
|
|
return {
|
|
|
|
status: 400,
|
|
|
|
ref: "Notifications",
|
2024-02-15 12:32:51 +01:00
|
|
|
msg: "formaterror",
|
2024-02-19 17:55:06 +01:00
|
|
|
data: { fielderr: typekey, format: typekey }
|
2023-12-29 13:38:47 +01:00
|
|
|
};
|
2024-02-19 17:55:06 +01:00
|
|
|
|
2024-03-19 09:10:07 +01:00
|
|
|
const destin = `../../${tribe}/objects/maillinglists/${typekey}_${mlist}.json`;
|
2024-02-19 17:55:06 +01:00
|
|
|
if (!fs.existsSync(destin)){
|
|
|
|
console.log(`######## Attention tentative d'ecriture non autorisé,le fichier n'existe pas ${destin} créer le à la main vide {}`)
|
|
|
|
return {status:406,ref:"Notifications",msg:"destinnotallow",data:{destin}}
|
|
|
|
}
|
|
|
|
|
2023-12-29 13:38:47 +01:00
|
|
|
const filestorage = fs.existsSync(destin) ? fs.readJsonSync(destin) : {};
|
2024-02-15 12:32:51 +01:00
|
|
|
//if (log) console.log(currentmod,`filestorage`,filestorage, key, (filestorage[key]));
|
2023-12-29 13:38:47 +01:00
|
|
|
if (filestorage[key]) {
|
|
|
|
filestorage[key].dt_update = dayjs().toISOString();
|
|
|
|
if (!filestorage[key].srckeys.includes(srckey))
|
|
|
|
filestorage[key].srckeys.push(srckey);
|
|
|
|
if (!filestorage[key].uuids.includes(uuid))
|
|
|
|
filestorage[key].uuids.push(uuid);
|
|
|
|
}else{
|
2024-02-15 12:32:51 +01:00
|
|
|
filestorage[key]={}
|
2023-12-29 13:38:47 +01:00
|
|
|
filestorage[key].dt_create=dayjs().toISOString();
|
|
|
|
filestorage[key].srckeys=[srckey];
|
|
|
|
filestorage[key].uuids=[uuid]
|
|
|
|
}
|
|
|
|
fs.outputJSONSync(destin, filestorage);
|
2024-02-15 12:32:51 +01:00
|
|
|
return {status:200,ref:"Notifications",msg:"registersuccess",data:{key, typekey, tribe, mlist, srckey, uuid}}
|
2023-12-29 13:38:47 +01:00
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Unsubscribe an eamil or phone from a mailinglist for a tribe
|
|
|
|
*/
|
2024-03-15 08:49:23 +01:00
|
|
|
Notifications.unregisterfromlist = (key, typekey, tribe,mlist) => {
|
|
|
|
key = key.toLowerCase();
|
|
|
|
|
2023-12-29 13:38:47 +01:00
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Message to send to an alias from an anonymous or not
|
|
|
|
*/
|
|
|
|
Notifications.sendcontact = (body, header) => {
|
|
|
|
|
|
|
|
}
|
2023-12-07 12:04:19 +01:00
|
|
|
Notifications.sendsms = async (data, tribeId) => {
|
|
|
|
/**
|
|
|
|
* Never use need wallet in mailjet to test
|
|
|
|
* To set up with mailjet see https://dev.mailjet.com/sms/guides/send-sms-api/#authentication
|
|
|
|
*
|
|
|
|
* @param {string} data.To a phone number with international +3360101010101
|
|
|
|
* @param {string} data.Text text to send
|
|
|
|
*
|
|
|
|
* a conf.sms with {url:"smsurl", Token:"", From:""}
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!conf.sms) {
|
|
|
|
return {
|
|
|
|
status: 412,
|
|
|
|
ref: "Notifications",
|
|
|
|
msg: "missingconf",
|
|
|
|
data: { tribe: tribeId },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
let missingk = [][("To", "Text")].forEach((k) => {
|
|
|
|
if (!data[k]) {
|
|
|
|
missingk.push(k);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (missingk.lenght > 0) {
|
|
|
|
return {
|
|
|
|
status: 428,
|
|
|
|
ref: "Notifications",
|
|
|
|
msg: "missingdata",
|
|
|
|
data: { missingk: missingk },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
let confsms = conf.sms;
|
|
|
|
if (
|
|
|
|
fs.existsSync(
|
2024-03-19 09:10:07 +01:00
|
|
|
`../../itm/${req.session.header.xtribe}.json`
|
2023-12-07 12:04:19 +01:00
|
|
|
)
|
|
|
|
) {
|
|
|
|
const conftrib = fs.readJSONSync(
|
2024-03-19 09:10:07 +01:00
|
|
|
`../../itm/${req.session.header.xtribe}.json`
|
2023-12-07 12:04:19 +01:00
|
|
|
);
|
|
|
|
if (conftrib.sms) confsms = conftrib.sms;
|
|
|
|
}
|
|
|
|
data.From = confsms.From;
|
|
|
|
const sendsms = await axios.post(confsms.url, {
|
|
|
|
headers: {
|
|
|
|
Authorization: `Bearer ${confsms.MJ_TOKEN}`,
|
|
|
|
"Content-Type": "application/json",
|
|
|
|
},
|
|
|
|
body: JSON.stringify(data),
|
|
|
|
});
|
|
|
|
if (sendsms.status == 200) {
|
|
|
|
return {
|
|
|
|
status: 200,
|
|
|
|
ref: "Notifications",
|
|
|
|
msg: "successfullsentsms",
|
|
|
|
data: {},
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
status: sendsms.status,
|
|
|
|
ref: "Notifications",
|
|
|
|
msg: "errsendsms",
|
|
|
|
data: { err: sendsms.data },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/* si tout se passe bien:
|
|
|
|
{
|
|
|
|
"From": "MJPilot",
|
|
|
|
"To": "+33600000000",
|
|
|
|
"Text": "Have a nice SMS flight with Mailjet !",
|
|
|
|
"MessageId": "2034075536371630429",
|
|
|
|
"SmsCount": 1,
|
|
|
|
"CreationTS": 1521626400,
|
|
|
|
"SentTS": 1521626402,
|
|
|
|
"Cost": {
|
|
|
|
"Value": 0.0012,
|
|
|
|
"Currency": "EUR"
|
|
|
|
},
|
|
|
|
"Status": {
|
|
|
|
"Code": 2,
|
|
|
|
"Name": "sent",
|
|
|
|
"Description": "Message sent"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
};
|
|
|
|
|
|
|
|
Notifications.sendmail = async (data, tribe) => {
|
|
|
|
/**
|
|
|
|
* See https://nodemailer.com/message/ for available fields to add
|
|
|
|
* @param {string} [data.from] an email authorized by smtp used priority from header xtribe
|
|
|
|
* @param {string} data.to list of email separate by ,
|
|
|
|
* @param {string} data.subject
|
|
|
|
* @param {string} data.html
|
|
|
|
* @param {string} data.text
|
|
|
|
* @param {string} [data.Cc] list of email in copy
|
|
|
|
* @param {string} [data.Bcc] list of email in hidden copy
|
|
|
|
* @param {string} [data.attachments] array of
|
|
|
|
* {filename:'filename.txt',content:'txt'},
|
|
|
|
* {filename:'img.svg',path:"https://....svg", contentType:'image/svg'}
|
|
|
|
* {filename:'img.svg',path:"https://....svg", contentType :'text/plain'}
|
|
|
|
* {filename:'img.png',path:"data:text/svg;base64.aGVsbG8gd29ybGQ="}
|
|
|
|
*
|
|
|
|
* @example data
|
|
|
|
* {"to":"wall-ants.ndda.fr",
|
|
|
|
* "subject":"Test",
|
|
|
|
* "html":"<h1>test welcome</h1>",
|
|
|
|
* "text":"test welcome",
|
|
|
|
* "attachments":[{filename:"text.txt",pathfile:"/media/phil/textA.txt","contenttype":"text/plain"}]
|
|
|
|
* }
|
|
|
|
* @return {object}
|
|
|
|
* { status: 200, ref:"pagans",msg:"",data: { } }
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
if (!conf.smtp || !conf.emailcontact) {
|
|
|
|
return {
|
|
|
|
status: 412,
|
|
|
|
ref: "Notifications",
|
|
|
|
msg: "missingconf",
|
|
|
|
data: { tribe: tribe },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if (!data.from) {
|
|
|
|
data.from = conf.emailcontact;
|
|
|
|
}
|
|
|
|
let missingk = [];
|
|
|
|
["from", "to", "subject", "html", "text"].forEach((k) => {
|
|
|
|
if (!data[k]) {
|
|
|
|
missingk.push(k);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (missingk.lenght > 0) {
|
|
|
|
return {
|
|
|
|
status: 428,
|
|
|
|
ref: "Notifications",
|
|
|
|
msg: "missingdata",
|
|
|
|
data: { missingk: missingk },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
let confsmtp = conf.smtp;
|
2024-03-19 09:10:07 +01:00
|
|
|
const conftribfile = `../../itm/${tribe}.json`;
|
2023-12-07 12:04:19 +01:00
|
|
|
if (fs.existsSync(conftribfile)) {
|
2023-12-29 13:38:47 +01:00
|
|
|
const conftrib = fs.readJSONSync(conftribfile);
|
2023-12-07 12:04:19 +01:00
|
|
|
confsmtp = conftrib.smtp;
|
|
|
|
if (!data.from) data.from = conftrib.emailcontact;
|
|
|
|
}
|
|
|
|
|
|
|
|
//const client = smtp.connect(confsmtp);
|
|
|
|
const transporter = await nodemailer.createTransport(confsmtp);
|
|
|
|
//@todo add attachments management
|
|
|
|
if (data.filelist) {
|
2023-12-29 13:38:47 +01:00
|
|
|
data.attachments = [];
|
2023-12-07 12:04:19 +01:00
|
|
|
let missingfile = [];
|
|
|
|
data.filelist.forEach((fo) => {
|
2023-12-29 13:38:47 +01:00
|
|
|
if (fs.existsSync(fo.pathfile)) {
|
|
|
|
|
|
|
|
} else { missingfile.push(fo.pathfile); }
|
2023-12-07 12:04:19 +01:00
|
|
|
});
|
|
|
|
if (missingfile.lenght > 0)
|
|
|
|
return {
|
|
|
|
status: 428,
|
|
|
|
ref: "Notifications",
|
|
|
|
msg: "missingfile",
|
|
|
|
data: { missingfile: missingfile },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
//console.log("data:", data);
|
|
|
|
const res = await transporter.sendMail(data);
|
|
|
|
if (
|
|
|
|
res.accepted &&
|
|
|
|
data.to.split(",").reduce((acc, m) => acc && res.accepted.includes(m), true)
|
|
|
|
) {
|
|
|
|
data.accepted = res.accepted;
|
|
|
|
data.rejected = res.rejected;
|
|
|
|
return {
|
|
|
|
status: 200,
|
|
|
|
ref: "Notifications",
|
|
|
|
msg: "successfullsentemail",
|
|
|
|
data,
|
|
|
|
};
|
|
|
|
} else if (res.accepted && res.rejected) {
|
|
|
|
data.accepted = res.accepted;
|
|
|
|
data.rejected = res.rejected;
|
|
|
|
return { status: 410, ref: "Notifications", msg: "errsendmail", data };
|
|
|
|
} else {
|
|
|
|
data.errmailer = res.err;
|
|
|
|
return { status: 417, ref: "Notifications", msg: "errsendmail", data };
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = Notifications;
|