import { getDb } from "@/lib/mongo";
import { getSiteUrl } from "@/lib/site";
export const dynamic = "force-dynamic";
function escapeXml(input: string) {
return input
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
function stripMarkdown(input: string) {
return input
.replace(/```[\s\S]*?```/g, " ")
.replace(/`[^`]*`/g, " ")
.replace(/!\[[^\]]*]\([^)]+\)/g, " ")
.replace(/\[([^\]]*)\]\([^)]+\)/g, "$1")
.replace(/[#>*_~\-]+/g, " ")
.replace(/\s+/g, " ")
.trim();
}
export async function GET() {
const db = await getDb();
const posts = await db
.collection("posts")
.find({}, { projection: { title: 1, slug: 1, markdown: 1, createdAt: 1, updatedAt: 1 } })
.sort({ createdAt: -1 })
.limit(50)
.toArray();
const siteUrl = getSiteUrl();
const now = new Date().toUTCString();
const items = posts
.map((post: any) => {
const link = `${siteUrl}/p/${post.slug}`;
const description = stripMarkdown(post.markdown || "").slice(0, 200);
const pubDate = new Date(post.createdAt || post.updatedAt || Date.now()).toUTCString();
return [
"- ",
`${escapeXml(post.title || "未命名")}`,
`${escapeXml(link)}`,
`${escapeXml(link)}`,
`${pubDate}`,
`${escapeXml(description)}`,
"
"
].join("");
})
.join("");
const xml = `
OPC Feed
${escapeXml(siteUrl)}
Public feed
${now}
${items}
`;
return new Response(xml, {
headers: {
"Content-Type": "application/rss+xml; charset=utf-8"
}
});
}