Public
HTTP (deprecated)
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import { DOMParser } from "https://deno.land/x/deno_dom/deno-dom-wasm.ts";
import { Feed } from "npm:feed";
import ky from "npm:ky";
const BASE_URL = "https://midnight.pub";
// @see: https://git.sr.ht/~m15o/midnight-pub/tree/master/item/model/user.go#L28
const reUserFeed = /^\/(?<username>~[a-z0-9-_]+)\.(?<format>atom|rss)$/;
export default async function(req: Request): Promise<Response> {
const { pathname } = new URL(req.url);
const match = pathname.match(reUserFeed);
if (!match) {
return new Response(null, { status: 400 });
}
const { format, username } = match.groups;
const profileURL = new URL(`/${username}`, BASE_URL);
const posts = await grabPosts(profileURL);
const feed = new Feed({
id: profileURL.href,
link: profileURL.href,
title: username,
description: `${username}'s posts`,
author: {
name: username,
link: profileURL.href,
},
feedLinks: {
atom: req.url,
rss: req.url,
},
copyright: undefined, // I have no idea what to put there ¯\_(ツ)_/¯
});
posts.forEach(post =>
feed.addItem({
id: post.href,
link: post.href,
date: post.createdAt,
title: post.title,
description: post.title,
})
);
if (format === "rss") {
const headers = { "content-type": "application/xml" };
return new Response(feed.rss2(), { headers });
}
const headers = { "content-type": "application/atom+xml" };
return new Response(feed.atom1(), { headers });
}
async function grabPosts(profileURL: string | URL) {
const html = await ky.get(profileURL).text();
const doc = new DOMParser().parseFromString(html, "text/html");
const posts: HTMLAnchorElement[] = doc.querySelectorAll("a[href^=\"/posts/\"]");
return Array.from(posts).map(post => {
const href = new URL(post.getAttribute("href"), BASE_URL).href;
const offset = post.textContent.indexOf(" ");
const createdAt = new Date(post.textContent.slice(0, offset));
const title = post.textContent.slice(offset + 1);
return { href, createdAt, title };
});
}
vladimyr-midnightpubfeed.web.val.run
February 27, 2024