From 5c3f804a1409f769379c6afe93df171b72778215 Mon Sep 17 00:00:00 2001 From: dakedres Date: Wed, 10 Jan 2024 16:57:35 -0500 Subject: [PATCH] Support for multiple feeds & viewing individual sources --- .gitignore | 5 +- README | 8 ++- index.js | 163 ++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 125 insertions(+), 51 deletions(-) diff --git a/.gitignore b/.gitignore index 5e438ee..1e97e9c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,7 @@ node_modules/ # Artifacts /out/* /cache.json -/config.js \ No newline at end of file +/config.js + +# Testing +*.ignore \ No newline at end of file diff --git a/README b/README index 1ad47ff..8ec148a 100644 --- a/README +++ b/README @@ -2,11 +2,13 @@ ┏┓┏┏┏┏┓┏┓┏┓ ┛ ┛┛┛┛┗┛┗┗┫ ┛ -RSS-based art collator +Rsssing is an RSS-based feed for art blogs. It generates a series of web pages +to be uploaded to a web server, or simply viewed in the browser. Tumblr and +Twitter (through nitter) sources are supported. -Do not expect quality code. Only works with the Bun[1] runtime +| Usage +Rssssing only works with the Bun[1] runtime -Usage - Run `bun run setup`, `npm run setup`, etc. - Add usernames and such to the "feeds" array in config.js - `bun .` diff --git a/index.js b/index.js index 5a36c6f..bc7441c 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ const fetch = require('node-fetch') -const config = require('./config.js') +const config = require('./config.js.ignore') const Path = require('path') let cache = require('./cache.json') @@ -144,52 +144,60 @@ const processTumblr = (rss, user) => { const oneDay = 1000 * 60 * 60 * 24 -const print = async feeds => { +const printFeed = async (sources, directory, header) => { // Coalate - let masterFeed = [] + let feed = [] let tooLongAgo = (Date.now() - (Date.now() % oneDay)) - oneDay * config.tooLongAgo - let missingFeeds = 0 + let missingSources = 0 - for(let feed of feeds) { - if(feed == undefined) { - missingFeeds++ + for(let source of sources) { + if(source == undefined) { + missingSources++ continue } - for(let post of feed) { + for(let post of source) { if(tooLongAgo && post.date > tooLongAgo) - masterFeed.push(post) + feed.push(post) } } - masterFeed = masterFeed.sort((a, b) => a.date < b.date) + feed = feed.sort((a, b) => a.date < b.date) - if(missingFeeds) { - console.log('Missing ' + missingFeeds + ' feeds!') + if(missingSources) { + console.log('Missing ' + missingSources + ' feeds!') } // Render let pages = [] - for(let i = 0; i < Math.ceil(masterFeed.length / config.pageSize); i++) { - pages.push(masterFeed.slice(i * config.pageSize, (i + 1) * config.pageSize) ) + for(let i = 0; i < Math.ceil(feed.length / config.pageSize); i++) { + pages.push(feed.slice(i * config.pageSize, (i + 1) * config.pageSize) ) } // Write - console.log('Writing...') for(let i = 0; i < pages.length; i++) { - Bun.write('out/' + (i == 0 ? 'index' : i) + '.html', renderPage(pages[i], i, pages.length) ) + let nextPage = i + 1 + + let link = nextPage === pages.length ? + `end` : + `next` + + Bun.write( + Path.join(directory, (i == 0 ? 'index' : i) + '.html'), + renderPage(`Page ${i + 1}`, pages[i], header, link) + ) } } -const renderPage = (posts, index, pageCount) => { +const renderPage = (title, posts, header, footer) => { let html = `\ -Page ${index + 1} +${title} -\n` +` + + if(header) { + html += ` +
+${header} +
+` + } for(let post of posts) { let date = new Date(post.date) - html += `\ + html += ` ${post.images.map(renderImage).join('\n')} -

${post.user} ${date.getMonth()}/${date.getDate()}/${date.getFullYear()} open


\n` +

${post.user} ${date.getMonth()}/${date.getDate()}/${date.getFullYear()} open


` } - let nextPage = index + 1 + if(footer) { + html += ` - -let link = nextPage === pageCount ? - `end` : - `next` +` + } html += ` - ` return html @@ -247,30 +261,85 @@ const renderImage = image => `\ ` const main = async () => { - const feeds = [] + let feeds = [] + let allSources = [] - const subscribe = feedPromise => { - return feedPromise - .catch(error => { - console.error(error) - }) - .then(feed => { - feeds.push(feed) - }) + for(let feedName in config.feeds) { + let feed = config.feeds[feedName] + let sources = [] + + const subscribe = (sourcePromise, type, name) => + sourcePromise + .catch(error => console.error(error) ) + .then(source => { + sources.push(source) + allSources.push({ + type, + name, + link: Path.join(type, name), + source + }) + }) + + if(feed.nitter) { + for(let user of feed.nitter) { + await subscribe(handleNitterUser(user), 'nitter', user) + } + console.log('Caching sources...') + Bun.write('cache.json', JSON.stringify(cache, null, 2)) + } + + if(feed.tumblr) { + for(let user of feed.tumblr) { + await subscribe(handleTumblrUser(user), 'tumblr', user) + } + } + + let link = feed.main ? '' : feedName + + feeds.push({ + name: feedName, + main: feed.main, + sources, + link + }) } - console.log('Grabbing posts...') - for(let user of config.feeds.nitter) { - await subscribe(handleNitterUser(user) ) - } - console.log('Caching sources...') - Bun.write('cache.json', JSON.stringify(cache, null, 2)) + const buildFeedNav = depth => { + const buildLink = (page, name = page.link) => { + let link = '../'.repeat(depth) + page.link - for(let user of config.feeds.tumblr) { - await subscribe(handleTumblrUser(user) ) + if(config.linkToIndex) + link += '/index.html' + + return `
${name}
` + } + + return `\ +
+ +Feeds +
+${buildLink({ link: '' }, 'main')} +${feeds.filter(feed => !feed.main).map(feed => buildLink(feed)).join('\n')} +
+${allSources.map(source => buildLink(source)).join('\n')} +
+ +
+
` + } + + console.log('Writing...') + for(let source of allSources) { + console.log(source) + + await printFeed([ source.source ], Path.join('out', source.link), buildFeedNav(2)) + } + for(let feed of feeds) { + await printFeed(feed.sources, Path.join('out', feed.link), buildFeedNav(feed.main ? 0 : 1)) } - await print(feeds) console.log('Done!') }