2024-05-26 22:54:55 +02:00
|
|
|
var XMLParser = require("fast-xml-parser").XMLParser;
|
|
|
|
var http = require("http");
|
|
|
|
var https = require("https");
|
|
|
|
var fs = require("fs");
|
|
|
|
var MongoClient = require('mongodb').MongoClient;
|
|
|
|
var nodemailer = require("nodemailer");
|
|
|
|
|
|
|
|
var transporter = nodemailer.createTransport({
|
|
|
|
host: "localhost",
|
|
|
|
port: 25,
|
|
|
|
secure: false, // Use `true` for port 465, `false` for all other ports
|
|
|
|
tls: {
|
|
|
|
rejectUnauthorized: false
|
|
|
|
},
|
|
|
|
pool: true
|
|
|
|
});
|
|
|
|
|
|
|
|
var fromEmail = "root@localhost";
|
|
|
|
var mongoURL = "mongodb://localhost/newsletter";
|
|
|
|
var dbname = "newsletter";
|
|
|
|
|
|
|
|
function antiXSS(string) {
|
|
|
|
return string.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
|
|
}
|
|
|
|
|
|
|
|
function escapeRegExp(string) {
|
|
|
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
|
|
|
}
|
|
|
|
|
|
|
|
function connectMongo(callback) {
|
|
|
|
MongoClient.connect(mongoURL, function (err, db) {
|
|
|
|
if (err) throw err;
|
|
|
|
var dbo = db.db(dbname);
|
|
|
|
dbo.createCollection("emails", function (err, dbres) {
|
|
|
|
dbo.createCollection("posts", function (err, dbres) {
|
|
|
|
callback(dbo);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function formatTemplate(templateName, templateData, callback) {
|
|
|
|
fs.readFile(__dirname + "/" + templateName + ".template", function (err, data) {
|
|
|
|
if (err) throw err;
|
|
|
|
var tD = data.toString();
|
|
|
|
Object.keys(templateData).forEach(function (key) {
|
|
|
|
tD = tD.replace(new RegExp("\\{\\{" + escapeRegExp(key) + "\\}\\}", "g"), templateData[key]);
|
|
|
|
});
|
|
|
|
callback(tD);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
https.get("https://blog.svrjs.org/atom.xml", function (res) {
|
|
|
|
var data = "";
|
|
|
|
res.on("data", function (chunk) {
|
|
|
|
data += chunk.toString();
|
|
|
|
});
|
|
|
|
res.on("end", function () {
|
|
|
|
var parser = new XMLParser();
|
|
|
|
var parsedData = parser.parse(data);
|
|
|
|
var entries = parsedData.feed.entry;
|
|
|
|
connectMongo(function (db) {
|
|
|
|
db.collection("emails").find({}).toArray(function (err, emails) {
|
|
|
|
if (err) throw err;
|
|
|
|
var queue = [];
|
|
|
|
var ent = JSON.parse(JSON.stringify(entries)).reverse();
|
|
|
|
|
|
|
|
function getEntriesId(_id) {
|
|
|
|
if (!_id) _id = 0;
|
|
|
|
if (_id >= ent.length) {
|
|
|
|
process.exit(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
db.collection("posts").find({
|
|
|
|
id: ent[_id].id
|
|
|
|
}).toArray(function (err, result) {
|
|
|
|
if (err) throw err;
|
|
|
|
if (result.length == 0) {
|
|
|
|
db.collection("posts").insertOne({
|
|
|
|
id: ent[_id].id
|
|
|
|
}, function (err, dbres) {
|
|
|
|
if (err) throw err;
|
|
|
|
var _qid = _id;
|
|
|
|
|
|
|
|
function sendEmail(_id) {
|
|
|
|
if (!_id) _id = 0;
|
|
|
|
if (_id >= emails.length) {
|
|
|
|
getEntriesId(_id + 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var qim = ent[_qid].id.match(/https:\/\/blog\.svrjs\.org\/[0-9]+\/[0-9]+\/[0-9]+\/([^\/]+)/);
|
|
|
|
var imageURL = "https://blog.svrjs.org/images/covers/" + (qim ? qim[1] : "missing") + ".png";
|
|
|
|
formatTemplate("index.html", {
|
|
|
|
"title": antiXSS(ent[_qid].title),
|
2024-06-07 21:59:39 +02:00
|
|
|
"summary": ent[_qid].summary.replace(/(src|href)="\/(?!\/)/,"$1=\"https://blog.svrjs.org/"),
|
2024-05-26 22:54:55 +02:00
|
|
|
"image": antiXSS(imageURL),
|
|
|
|
"link": antiXSS(ent[_qid].id),
|
|
|
|
"unsubscribe": antiXSS("https://newsletter.svrjs.org/unsubscribe.svr?id=" + encodeURIComponent(emails[_id].unsubscribeId))
|
|
|
|
}, function (data) {
|
|
|
|
transporter.sendMail({
|
|
|
|
from: fromEmail,
|
|
|
|
to: emails[_id].email,
|
|
|
|
subject: ent[_qid].title + " - SVR.JS Blog Newsletter",
|
|
|
|
text: 'This message requires HTML to be viewed',
|
|
|
|
html: data
|
|
|
|
}, function (err, info) {
|
|
|
|
if (err) throw err;
|
|
|
|
sendEmail(_id + 1);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
sendEmail();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
getEntriesId(_id + 1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
getEntriesId();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|