56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
import Article from "./models/article.ts";
|
|
import Profile from "./models/profile.ts";
|
|
import { isoDate } from "./dates.ts";
|
|
|
|
export async function profileAtomFeed(
|
|
profile: Profile,
|
|
articles: Article[],
|
|
): Promise<string> {
|
|
const feedId = `tag:${profile.nip05},nostr-p-${profile.pubkey}-k-30023`;
|
|
const lastUpdate = articles.sort((a, b) => b.updatedAt - a.updatedAt)[0]
|
|
?.updatedAt;
|
|
let articlesXml = "";
|
|
|
|
for (const article of articles) {
|
|
const contentHtml = await article.buildContentHtml();
|
|
const articleId =
|
|
`tag:${profile.nip05},nostr-p-${profile.pubkey}-d-${article.identifier}-k-30023`;
|
|
articlesXml += `
|
|
<entry>
|
|
<id>${articleId}</id>
|
|
<title>${article.title}</title>
|
|
<link href="${article.url}" />
|
|
<link rel="alternate" type="application/nostr+json" href="nostr:${article.naddr}">
|
|
<updated>${isoDate(article.updatedAt)}</updated>
|
|
<published>${isoDate(article.publishedAt)}</published>
|
|
<summary>${article.summary}</summary>
|
|
<content type="html"><![CDATA[
|
|
${cleanContentHtml(contentHtml)}
|
|
]]></content>
|
|
</entry>
|
|
`;
|
|
}
|
|
|
|
return `
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
<title>${profile.name} on Nostr (Articles)</title>
|
|
<id>${feedId}</id>
|
|
<updated>${isoDate(lastUpdate)}</updated>
|
|
<icon>${profile.avatarImageUrl}</icon>
|
|
<author>
|
|
<name>${name}</name>
|
|
</author>
|
|
${articlesXml}
|
|
</feed>
|
|
`.trim();
|
|
}
|
|
|
|
export function cleanContentHtml(html: string) {
|
|
const cleanHtml = html.replace(
|
|
/<a class="anchor" aria-hidden="true"[^>]*>.*?<\/a>/gs,
|
|
"",
|
|
);
|
|
return cleanHtml;
|
|
}
|