Skip to content

Instantly share code, notes, and snippets.

@CennoxX
Last active October 30, 2025 11:17
Show Gist options
  • Save CennoxX/7a4b18542ac24618330904373b337cee to your computer and use it in GitHub Desktop.
Save CennoxX/7a4b18542ac24618330904373b337cee to your computer and use it in GitHub Desktop.
A Google Apps Script to monitor RSS and Atom feeds, automatically detect new entries, and send email notifications with the new post.
function monitor(feedName, url, author, filter = null) {
console.log(feedName);
let startTime = Date.now();
let scriptProperties = PropertiesService.getScriptProperties();
let lastUpdate = scriptProperties.getProperty(`lastUpdate${feedName}`);
let errorCount = parseInt(scriptProperties.getProperty(`errorCount${feedName}`) || "0");
let root;
try {
let res = UrlFetchApp.fetch(url);
root = XmlService.parse(res.getContentText().replace(/content:encoded/g, "content").replace(/&#(\w.+?);/g, (_, p) => {return String.fromCharCode(p)})).getRootElement();
scriptProperties.deleteProperty(`errorCount${feedName}`);
} catch (e) {
errorCount++;
scriptProperties.setProperty(`errorCount${feedName}`, errorCount.toString());
console.error(`${feedName} failed`, errorCount, lastUpdate);
if (errorCount < 24)
return;
throw e;
}
let ns = root.getNamespace();
let entries = root.getChild("channel", ns)?.getChildren("item", ns) || root.getChildren("entry", ns);
entries.reverse().forEach(entry => {
let published = entry.getChild("updated", ns)?.getText() || entry.getChild("pubDate", ns)?.getText();
if (new Date(published) <= new Date(lastUpdate))
return;
scriptProperties.setProperty(`lastUpdate${feedName}`, published);
let title = entry.getChild("title", ns).getText().replace(/&amp;#(\w.+?);/g, (_, p) => {return String.fromCharCode(p)});
let content = entry.getChild("content", ns)?.getText() || entry.getChild("description", ns)?.getText() || entry.getChild("summary", ns)?.getText() || "";
let link = entry.getChild("link", ns).getAttribute("href")?.getValue() || entry.getChild("link", ns).getText().replace(/\?.*/, "");
let body = `<b>${title}</b> von ${author}<br /><a href="${link}">${link}</a><br /><div style="width:700px">${content}</div>`;
if (!filter || link.match(filter))
MailApp.sendEmail({to: Session.getActiveUser().getEmail(), subject: title, htmlBody: body, name: author});
});
let duration = (Date.now() - startTime) / 1000;
console.log(`${duration.toFixed(3)} s`);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment