EDIT : I solved it a bit
I had two approaches to leverage the MyAnimeList RSS feed and the RSS Reader plugin:
- Extracting RSS Feeds from RSS-ReaderThe goal here is to:
- Find the RSS feed
- Identify each item and create a note for that item
- Check if a note already exists and if so, overwrite it with the new note
- Import a note template and reuse metadata present in the RSS feedIn essence, this is feasible as it automates what can be done by simply pressing a button.
It is interesting because the RSS Reader plugin bypasses CORS issues (which I don’t fully understand) that prevent me from processing the RSS feed directly.
However, my script did not succeed mainly because I could not find the variable name in RSS Reader that holds the content of my feeds.
- Convert the RSS Feed JSON File into Separate Notes
Since I couldn’t figure out how to name the feed content for retrieval, I decided to directly access the JSON file at the location: .obsidian\plugins\rss-reader
. I wanted to transform a JSON file containing all the metadata of all the works from all feeds into several Obsidian notes (one for each work), with each note organized into a folder corresponding to its feed. I planned to use Templater to create these notes and fill in the frontmatter and content based on the JSON data.
This option turned out to be successful! With the help of ChatGPT, I managed to create a Templater script that:
- Recognizes the different RSS-Reader feeds
- Creates a note for each item in each feed and sorts them into different folders (here, manga are sorted into “manga” and anime into “anime”, with both subfolders organized under “SOURCES/Myanimelist”)
- Formats each note using the (very few) metadata from the feedI’m including this script below
I remain convinced that Option 1 is better; I just don’t know how to “communicate” with RSS-Reader. The script could be optimized by creating a macro with QuickAdd (a JS script to fetch the feed and a Templater script to format each item), but I don’t want to overcomplicate things here.Hopefully, this will help some or that experienced coders will be able to develop a more elegant solution.
The script :
<%*
const fs = require('fs');
const path = require('path');
// Function to create a directory if it does not exist
function ensureDirectoryExistence(dirPath) {
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
}
}
// Function to sanitize a file name by removing invalid characters
function sanitizeFileName(name) {
return name.replace(/[:\/\?<>\\\*\|"]/g, '').trim();
}
// Function to clean content and remove hyphens
function cleanContent(content) {
return content.replace(/^[\s]*- /gm, '').trim();
}
// Function to extract the last chapter number from the content
function extractChapter(content) {
// Search for numbers at the end of the content
const matches = content.match(/(\d+)(?!.*\d)/);
return matches ? matches[0] : '';
}
// Function to create a note for a given item (anime or manga)
async function createNoteForItem(item, folderName, tag) {
const sanitizedTitle = sanitizeFileName(item.title);
const noteFolder = path.join(app.vault.adapter.basePath, 'SOURCES', 'Myanimelist', folderName);
const finalPath = path.join(noteFolder, `${sanitizedTitle}.md`);
// Determine the reading status and clean the content
const cleanedContent = cleanContent(item.content);
const completedStatus = cleanedContent.toLowerCase().includes('completed') ? 'Read' : 'To Read';
const chapter = extractChapter(cleanedContent);
const coverImage = item.cover ? `` : 'No cover available';
const rating = item.rating || 'No rating';
// Note template
const noteContent = `---
author: ${item.creator || 'Unknown'}
chapters: ${chapter}
cover: ${coverImage}
rating: ${rating}
dateAdded: ${item.pubDate || 'Unknown'}
dateRead: ''
shelves:
- ${completedStatus}
---
[[NL ${item.title}]]
***
# Metadata
MOC ::
Source ::
Project ::
Area ::
Tags :: ${tag}
Date :: ${tp.date.now("YYYY-MM-DD")}
Note No. ${tp.date.now("YYYYMMDDHHmmss")}
`;
// Ensure the directory exists before creating the note
ensureDirectoryExistence(noteFolder);
// Directly create the note with the appropriate content
await fs.promises.writeFile(finalPath, noteContent);
}
// Path to the data.json file in the .obsidian/plugins/rss-reader folder
const dataPath = path.join(app.vault.adapter.basePath, '.obsidian', 'plugins', 'rss-reader', 'data.json');
// Read and parse the data.json file
const data = JSON.parse(fs.readFileSync(dataPath, 'utf8'));
// Iterate over RSS feeds (Anime and Manga)
for (const feed of data.items) {
// Determine the content type (Manga or Anime) based on the "feed" value
const folderName = feed.title.includes("Manga") ? 'Manga' : 'Anime';
const tag = folderName === 'Manga' ? '#SOURCE/book📖/manga' : '#SOURCE/book📖/anime';
for (const item of feed.items) {
// Create a note for the item in the appropriate folder
await createNoteForItem(item, folderName, tag);
}
}
%>