Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
Erin | 5104d3b568 |
60
index.mjs
60
index.mjs
|
@ -1,30 +1,44 @@
|
|||
import * as fs from 'node:fs';
|
||||
import express from 'express';
|
||||
import http from 'node:http';
|
||||
|
||||
const sites = fs.readFileSync('./webring.txt', 'utf-8')
|
||||
// split lines
|
||||
.split(/\r?\n/)
|
||||
// trim whitespace from each line
|
||||
.map(site => site.trim())
|
||||
// exclude empty lines and lines that start with # because why not
|
||||
.filter(site => site && !site.startsWith('#'));
|
||||
|
||||
// modulo that does the right thing with negatives
|
||||
// https://stackoverflow.com/a/4467559
|
||||
const mod = (n, m) => ((n % m) + m) % m;
|
||||
const stripURL = s => s.replace(/(^https?:\/\/|\/$)/g, '')
|
||||
|
||||
function handle (offset, request, response) {
|
||||
const from = request.query.from;
|
||||
const index = sites.findIndex(site => site === from);
|
||||
if (!from || index === -1) {
|
||||
response.status(400).send('the provided site is not in the webring');
|
||||
return;
|
||||
const sitesArray = fs.readFileSync('./webring.txt', 'utf-8')
|
||||
.match(/(?<!#.*)https?:\/\/[^\s]+(?=\s*$)/gmi)
|
||||
|
||||
const sitesLookup = sitesArray.map(stripURL).reduce((acc, current, index) => ({
|
||||
...acc, [current]: {
|
||||
'/next': sitesArray[mod(index + 1, sitesArray.length)],
|
||||
'/prev': sitesArray[mod(index - 1, sitesArray.length)],
|
||||
}
|
||||
response.redirect(301, sites[mod(index + offset, sites.length)]);
|
||||
}), {})
|
||||
|
||||
const redirect = (response, url) => {
|
||||
response.setHeader('Location', url)
|
||||
response.statusCode = 301
|
||||
response.end()
|
||||
}
|
||||
|
||||
express()
|
||||
.get('/prev', (request, response) => handle(-1, request, response))
|
||||
.get('/next', (request, response) => handle(+1, request, response))
|
||||
.get('/list', (_, response) => response.type('txt').send(sites.join('\n')))
|
||||
.listen(process.env.PORT || 8080);
|
||||
const handle = (direction, from, response) => {
|
||||
const destination = sitesLookup[stripURL(from)]?.[direction]
|
||||
|
||||
if (destination)
|
||||
return redirect(response, destination)
|
||||
|
||||
response.statusCode = 400
|
||||
response.end('the provided site is not in the webring')
|
||||
}
|
||||
|
||||
http.createServer((request, response) => {
|
||||
const url = new URL(request.url, `http://${request.headers.host}`);
|
||||
|
||||
if (url.pathname === '/prev' || url.pathname === '/next') {
|
||||
return handle(url.pathname, url.searchParams.get('from'), response)
|
||||
} else if (url.pathname === '/list') {
|
||||
return response.setHeader('Content-Type', 'text/plain').end(sitesArray.join('\n'))
|
||||
}
|
||||
|
||||
response.statusCode = 404
|
||||
response.end('not found')
|
||||
}).listen(process.env.PORT || 8080)
|
||||
|
|
Loading…
Reference in a new issue