Desde aquél triste día en el que cerraron Google Reader y descargue por primera vez mi archivo opml
con todos los feeds que leía, no he dejado de hacer respaldos, tengo aproximadamente 20 archivos opml
en los cuales se pueden ver mis intereses de en ese momento por los blogs y sitios que leía.
Ahora que utilizo newsboat
el formato que utilizan para guardar los feeds es muy particular, por lo tanto que creado un pequeño script que corre en node
para poder generar un archivo opml
que es compatible con otros lectores de feeds, en caso de querer migrar.
package.json
{
"dependencies": {
"lodash": "^4.17.21",
"xmlbuilder": "^15.1.1"
}
}
index.js
const fs = require("fs");
const builder = require("xmlbuilder");
const escape = require("lodash/escape");
const urlRegex =
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/;
const titleRegex = /"(.*?)"/;
try {
// Load urls file
const data = fs.readFileSync("./urls", "UTF-8");
const lines = data.split(/\r?\n/);
const tags = {};
const notags = [];
lines.forEach((line) => {
if (line) {
const cleanLine = line.replace("!", "").replace("~", "");
// Find urls
if (cleanLine.startsWith("http")) {
const url = cleanLine.match(urlRegex);
const title = cleanLine.match(titleRegex);
// Split the line to get the tags
const split = cleanLine.split('"');
// Get the last tag
const tag = !cleanLine.endsWith('"') ? `${split[split.length - 1]}`.trim() : "";
if (!tags[tag]) {
// Create tag
tags[tag] = [];
}
if (url[1] && title[1]) {
if (tag) {
// Add feed to tag
tags[tag].push({
title: escape(`${title[1]}`.trim()),
url: escape(`${url[1]}`.trim()),
});
} else {
// Feeds without tag
notags.push({
title: escape(`${title[1]}`.trim()),
url: escape(`${url[1]}`.trim()),
});
}
}
}
}
});
const opmlObj = {
opml: {
"@version": "2.0",
head: {},
body: {
outline: Object.keys(tags)
.map((name) => ({
"@text": name,
outline: tags[name].map((feed) => ({
"@title": feed.title,
"@text": feed.title,
"@xmlUrl": feed.url,
"@type": "rss",
"@version": "RSS",
})),
}))
.concat(
notags.map((feed) => ({
"@title": feed.title,
"@text": feed.title,
"@xmlUrl": feed.url,
"@type": "rss",
"@version": "RSS",
}))
),
},
},
};
const opml = builder.create(opmlObj, { encoding: "utf-8" });
console.log(opml.end({ pretty: true }));
} catch (err) {
console.error(err);
}
Lo que hace el script es leer linea por linea el archivo urls
de newsboat y encontrar la url, el título que se encuentra dentro de ""
y los tags que son las palabras separadas por espacios que van al final. Con estos datos genera el opml
y guarda las urls de los feeds dentro de las “categorías” basadas en el último tag.
En esta ocasión todo se imprime en pantalla, pero es posible guardarlo en un archivo de la siguiente manera:
node index.js > 20221109.opml
Este es mi resultado: https://files.abeestrada.com/opml/20221109.xml
Se puede validar el archivo en: http://validator.opml.org
Referencias: