import rss from '@astrojs/rss';
import type { APIRoute } from 'astro';
import { escapeUTF8 } from 'entities';
import { getPostUrl, getSortedPosts } from '../runtime/lib/content';
import { siteLocale, siteTitle } from '../runtime/lib/site';
const RSS_EXT_NS = 'https://komorebi.keqing.moe/rss-ext';
function formatDateForFeed(date: Date) {
return date.toLocaleDateString(siteLocale);
}
function formatReadingTime(milliseconds: number) {
const totalSeconds = Math.ceil(milliseconds / 1000);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
const parts: string[] = [];
if (hours > 0) parts.push(`${hours} 小时`);
if (minutes > 0) parts.push(`${minutes} 分`);
if (seconds > 0 || totalSeconds === 0) parts.push(`${seconds} 秒`);
return parts.join(' ');
}
export const GET: APIRoute = async (context) => {
let site = context.site;
if (!site) {
site = new URL(context.url.origin);
}
const blog = await getSortedPosts();
return rss({
title: siteTitle,
description: `${siteTitle} RSS`,
site,
xmlns: {
k: RSS_EXT_NS,
},
items: blog.map((post) => {
const pubDateLabel = formatDateForFeed(post.data.pubDate);
const updatedAt = post.data.updatedDate;
const words = Math.round(post.readingStats.words);
const readingTimeLabel = formatReadingTime(post.readingStats.time);
const customDataParts = [
`${escapeUTF8(pubDateLabel)}`,
];
if (updatedAt) {
customDataParts.push(
`${escapeUTF8(formatDateForFeed(updatedAt))}`,
);
}
customDataParts.push(
`${words}`,
`${escapeUTF8(readingTimeLabel)}`,
);
return {
title: post.data.title,
pubDate: post.data.pubDate,
description: post.data.description,
link: getPostUrl(post.id),
customData: customDataParts.join(''),
};
}),
stylesheet: '/rss/styles.xsl',
});
};