/**
* Copyright (c) 2025 miwa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#!/usr/bin/env -S deno run --allow-net --allow-write
/**
* Copyright (c) 2025 miwa
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { getPosts, type Report } from "../utils/atproto.ts";
function escapeXml(unsafe: string): string {
return unsafe
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
function stripHtml(html: string): string {
return html
.replace(/<[^>]+>/g, " ")
.replace(/\s+/g, " ")
.trim();
}
function generateRSSItem(report: Report): string {
const link = `https://acpi.at/reports/${report.rkey}`;
const description = report.excerpt ||
stripHtml(report.content).substring(0, 200);
return [
` - `,
` ${escapeXml(report.title)}`,
` ${link}`,
` ${link}`,
` ${report.date.toUTCString()}`,
` ${escapeXml(description)}`,
`
`,
].join("\n");
}
async function generateRSS() {
const reports = await getPosts();
const items = reports.map(generateRSSItem);
const xml = [
``,
``,
` `,
` $reports - acpi.at`,
` https://acpi.at/reports`,
` thoughts, ramblings, and occasional coherence`,
items.join("\n"),
` `,
``,
].join("\n");
await Deno.writeTextFile("./static/rss.xml", xml);
console.log("done");
}
if (import.meta.main) {
await generateRSS();
}