Skip to content

Instantly share code, notes, and snippets.

@bobmonsour
Last active January 19, 2024 07:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bobmonsour/cef5341e8a63c4ef11415045ace27735 to your computer and use it in GitHub Desktop.
Save bobmonsour/cef5341e8a63c4ef11415045ace27735 to your computer and use it in GitHub Desktop.
Process an OPML file to generate an array of feeds
// Read from an OPML file and write to a JSON file, processing the OPML file
// and producing the following for each of the feed items in the file:
// name: title of the feed (from the title attribute)
// url: URL of the feed (from the htmlUrl attribute)
// feed: URL of the feed (from the xmlUrl attribute)
// feedtype: type of feed (from the type attribute)
//
// NOTE: This only extracts feeds from the "CSS" and "Eleventy" outlines.
// Remove that test if you wish to extract all of the feeds.
//
// Path: feedsformulti.js
import fs from "fs";
import xml2js from "xml2js";
import path from "path";
// Read the OPML file
const opml = fs.readFileSync("feeds.opml", "utf8");
function extractFeeds(outline) {
let feeds = [];
if (outline.$.text === "CSS" || outline.$.text === "Eleventy") {
if (outline.outline) {
for (let subOutline of outline.outline) {
if (subOutline.$.type === "rss") {
const attributes = subOutline.$;
const feedtype =
path.extname(attributes.xmlUrl) === ".json" ? "json" : "text";
feeds.push({
name: attributes.title,
url: attributes.htmlUrl,
feed: attributes.xmlUrl,
feedType: feedtype,
});
}
}
}
}
if (outline.outline) {
for (let subOutline of outline.outline) {
feeds = feeds.concat(extractFeeds(subOutline));
}
}
return feeds;
}
// Parse the OPML file
xml2js.parseString(opml, (err, result) => {
if (err) {
console.error(err);
return;
}
// Extract the feeds
const feeds = [];
for (let outline of result.opml.body[0].outline) {
feeds.push(...extractFeeds(outline));
}
// Write the feeds to a JSON file
fs.writeFileSync("multifeeds-full.json", JSON.stringify(feeds, null, 2));
});
@murtuzaalisurti
Copy link

awesome, will use it in my project https://github.com/murtuzaalisurti/rssed

@bobmonsour
Copy link
Author

I'm glad that you'll find this helpful. One thing to consider...I am filtering the opml items based on their inclusion in an outline named "Eleventy." For most feed readers, an outline equates to a folder. Also, my comment about only filtering based on "CSS" and "Eleventy" is not correct as the code only filters on "Eleventy."

@murtuzaalisurti
Copy link

I am aware of this fact, I discovered a new package from this gist, xml2js, that's what I am focusing on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment