Indicate missing sources in feeds dropdown, support node.js, optimization
This commit is contained in:
parent
7affc50925
commit
f55ced9f0c
3
README
3
README
@ -7,9 +7,8 @@ to be uploaded to a web server, or simply viewed in the browser. Tumblr and
|
|||||||
Twitter (through nitter) sources are supported.
|
Twitter (through nitter) sources are supported.
|
||||||
|
|
||||||
| Usage
|
| Usage
|
||||||
Rssssing only works with the Bun[1] runtime
|
|
||||||
|
|
||||||
- Run `bun run setup`, `npm run setup`, etc.
|
- Run `yarn run setup`, `npm run setup`, etc.
|
||||||
- Add usernames and such to the "feeds" array in config.js
|
- Add usernames and such to the "feeds" array in config.js
|
||||||
- `bun .`
|
- `bun .`
|
||||||
- Open `out/index.html` in a browser. Enjoy :)
|
- Open `out/index.html` in a browser. Enjoy :)
|
||||||
|
114
index.js
114
index.js
@ -1,12 +1,34 @@
|
|||||||
const fetch = require('node-fetch')
|
// const fetch = require('node-fetch')
|
||||||
const config = require('./config.js')
|
// const config = require('./config.js')
|
||||||
const Path = require('path')
|
// const Path = require('path')
|
||||||
|
// const { writeFile } = require('fs/promises')
|
||||||
|
|
||||||
let cache = require('./cache.json')
|
// let cache = require('./cache.json')
|
||||||
const { JSDOM } = require('jsdom')
|
// const { JSDOM } = require('jsdom')
|
||||||
|
|
||||||
|
import fetch from "node-fetch"
|
||||||
|
import Path from "path"
|
||||||
|
import FS from "fs/promises"
|
||||||
|
import { JSDOM } from "jsdom"
|
||||||
|
|
||||||
|
import config from "./config.js"
|
||||||
|
|
||||||
|
let cache = await FS.readFile('./cache.json', { encoding: 'utf-8' })
|
||||||
|
.then(json => JSON.parse(json) )
|
||||||
let waitingList = new Map()
|
let waitingList = new Map()
|
||||||
|
|
||||||
|
const write = async (path, content) => {
|
||||||
|
let dir = Path.dirname(path)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await FS.access(dir)
|
||||||
|
} catch(e) {
|
||||||
|
await FS.mkdir(dir, { recursive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
return await FS.writeFile(path, content)
|
||||||
|
}
|
||||||
|
|
||||||
const handleNitterUser = async user => {
|
const handleNitterUser = async user => {
|
||||||
let data
|
let data
|
||||||
let index = 0
|
let index = 0
|
||||||
@ -78,7 +100,7 @@ const fetchRss = async (hostname, path) => {
|
|||||||
waitingList.set(hostname, 0)
|
waitingList.set(hostname, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await fetch(new URL(path, 'https://' + hostname))
|
return await fetch(new URL(path, 'https://' + hostname) )
|
||||||
.then(response => {
|
.then(response => {
|
||||||
waitingList.set(hostname, config.courtesyWait)
|
waitingList.set(hostname, config.courtesyWait)
|
||||||
return response.text()
|
return response.text()
|
||||||
@ -150,11 +172,9 @@ const printFeed = async (sources, directory, header, viewOptions) => {
|
|||||||
let tooLongAgo = viewOptions.tooLongAgo ?
|
let tooLongAgo = viewOptions.tooLongAgo ?
|
||||||
(Date.now() - (Date.now() % oneDay)) - oneDay * viewOptions.tooLongAgo :
|
(Date.now() - (Date.now() % oneDay)) - oneDay * viewOptions.tooLongAgo :
|
||||||
0
|
0
|
||||||
let missingSources = 0
|
|
||||||
|
|
||||||
for(let source of sources) {
|
for(let source of sources) {
|
||||||
if(source == undefined) {
|
if(source == undefined) {
|
||||||
missingSources++
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,10 +186,6 @@ const printFeed = async (sources, directory, header, viewOptions) => {
|
|||||||
|
|
||||||
feed = feed.sort((a, b) => a.date < b.date)
|
feed = feed.sort((a, b) => a.date < b.date)
|
||||||
|
|
||||||
if(missingSources) {
|
|
||||||
console.log('Missing ' + missingSources + ' feeds!')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
|
|
||||||
let pages = []
|
let pages = []
|
||||||
@ -184,7 +200,7 @@ const printFeed = async (sources, directory, header, viewOptions) => {
|
|||||||
|
|
||||||
const writePage = (index, content) =>
|
const writePage = (index, content) =>
|
||||||
promises.push(
|
promises.push(
|
||||||
Bun.write(Path.join(directory, index == 0 ? 'index' : index) + '.html', content)
|
write(Path.join(directory, index == 0 ? 'index' : index.toString() ) + '.html', content)
|
||||||
)
|
)
|
||||||
|
|
||||||
for(let i = 0; i < pages.length; i++) {
|
for(let i = 0; i < pages.length; i++) {
|
||||||
@ -194,7 +210,7 @@ const printFeed = async (sources, directory, header, viewOptions) => {
|
|||||||
`<a href="data:text/html,">end</a>` :
|
`<a href="data:text/html,">end</a>` :
|
||||||
`<a href="${nextPage}.html">next</a>`
|
`<a href="${nextPage}.html">next</a>`
|
||||||
|
|
||||||
writePage(i, renderPage(`Page ${i + 1}`, pages[i], header, link))
|
writePage(i, renderPage(`Page ${i + 1}`, pages[i], header, link) )
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pages.length == 0) {
|
if(pages.length == 0) {
|
||||||
@ -213,9 +229,9 @@ const renderPage = (title, posts, header, footer) => {
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
width: 100vw;
|
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
float: right;
|
margin: 0 0 0 auto;
|
||||||
|
padding: 8px;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,23 +295,27 @@ const renderImage = image => `\
|
|||||||
<a href="${image}"><img src="${image}" loading="lazy"></img></a>`
|
<a href="${image}"><img src="${image}" loading="lazy"></img></a>`
|
||||||
|
|
||||||
const main = async () => {
|
const main = async () => {
|
||||||
|
let promises = []
|
||||||
let feeds = []
|
let feeds = []
|
||||||
let allSources = []
|
let sources = []
|
||||||
|
|
||||||
|
const wait = promise =>
|
||||||
|
promises.push(promise)
|
||||||
|
|
||||||
for(let feedName in config.feeds) {
|
for(let feedName in config.feeds) {
|
||||||
let feed = config.feeds[feedName]
|
let feed = config.feeds[feedName]
|
||||||
let sources = []
|
let feedSources = []
|
||||||
|
|
||||||
const subscribe = (sourcePromise, type, name) =>
|
const subscribe = (postPromise, type, name) =>
|
||||||
sourcePromise
|
postPromise
|
||||||
.catch(error => console.error(error) )
|
.catch(error => console.error(error) )
|
||||||
.then(source => {
|
.then(posts => {
|
||||||
sources.push(source)
|
feedSources.push(posts)
|
||||||
allSources.push({
|
sources.push({
|
||||||
type,
|
type,
|
||||||
name,
|
name,
|
||||||
link: Path.join(type, name),
|
link: Path.join(type, name),
|
||||||
source
|
posts
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -304,7 +324,7 @@ const main = async () => {
|
|||||||
await subscribe(handleNitterUser(user), 'nitter', user)
|
await subscribe(handleNitterUser(user), 'nitter', user)
|
||||||
}
|
}
|
||||||
console.log('Caching sources...')
|
console.log('Caching sources...')
|
||||||
Bun.write('cache.json', JSON.stringify(cache, null, 2))
|
wait(write('cache.json', JSON.stringify(cache, null, 2) ) )
|
||||||
}
|
}
|
||||||
|
|
||||||
if(feed.tumblr) {
|
if(feed.tumblr) {
|
||||||
@ -319,19 +339,27 @@ const main = async () => {
|
|||||||
name: feedName,
|
name: feedName,
|
||||||
main: feed.main,
|
main: feed.main,
|
||||||
view: feed.view,
|
view: feed.view,
|
||||||
sources,
|
sources: feedSources,
|
||||||
link
|
link
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildFeedNav = depth => {
|
const buildNav = depth => {
|
||||||
const buildLink = (page, name = page.link) => {
|
const root = '../'.repeat(depth)
|
||||||
let link = '../'.repeat(depth) + page.link
|
|
||||||
|
|
||||||
if(config.linkToIndex)
|
const buildLink = link =>
|
||||||
link += '/index.html'
|
config.linkToIndex ? link + 'index.html' : link
|
||||||
|
|
||||||
return `<li><a href="${link}">${name}</a></li>`
|
const renderEntry = (page, name = page.link) => {
|
||||||
|
let link = buildLink(root + page.link + '/')
|
||||||
|
let extra = ''
|
||||||
|
|
||||||
|
if(page.posts === undefined) {
|
||||||
|
console.log(page)
|
||||||
|
extra += ' (missing)'
|
||||||
|
}
|
||||||
|
|
||||||
|
return `<li><a href="${link}">${name}</a>${extra}</li>`
|
||||||
}
|
}
|
||||||
|
|
||||||
return `\
|
return `\
|
||||||
@ -341,14 +369,14 @@ const main = async () => {
|
|||||||
<section>
|
<section>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
${buildLink({ link: '' }, 'main')}
|
<li><a href="${buildLink(root)}">main</a></li>
|
||||||
${feeds.filter(feed => !feed.main).map(feed => buildLink(feed)).join('\n')}
|
${feeds.filter(feed => !feed.main).map(feed => renderEntry(feed)).join('\n')}
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
<hr>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
${allSources.map(source => buildLink(source)).join('\n')}
|
${sources.map(source => renderEntry(source)).join('\n')}
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
@ -357,17 +385,21 @@ ${allSources.map(source => buildLink(source)).join('\n')}
|
|||||||
<hr>`
|
<hr>`
|
||||||
}
|
}
|
||||||
|
|
||||||
let promises = []
|
let navs = [
|
||||||
|
buildNav(0),
|
||||||
|
buildNav(1),
|
||||||
|
buildNav(2)
|
||||||
|
]
|
||||||
|
|
||||||
console.log('Writing...')
|
console.log('Writing...')
|
||||||
for(let source of allSources) {
|
for(let source of sources) {
|
||||||
promises.push(
|
wait(
|
||||||
printFeed([ source.source ], Path.join('out', source.link), buildFeedNav(2), config.sourceView)
|
printFeed([ source.posts ], Path.join('out', source.link), navs[2], config.sourceView)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
for(let feed of feeds) {
|
for(let feed of feeds) {
|
||||||
promises.push(
|
wait(
|
||||||
printFeed(feed.sources, Path.join('out', feed.link), buildFeedNav(feed.main ? 0 : 1), feed.view)
|
printFeed(feed.sources, Path.join('out', feed.link), navs[feed.main ? 0 : 1], feed.view)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,5 +11,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jsdom": "^22.1.0",
|
"jsdom": "^22.1.0",
|
||||||
"node-fetch": "^3.3.1"
|
"node-fetch": "^3.3.1"
|
||||||
}
|
},
|
||||||
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user