61 lines
2.0 KiB
TypeScript
61 lines
2.0 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="text/html" 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" xmlns:nostr="urn:nostr:protocol">
|
|
<title>${profile.name} on Nostr (Articles)</title>
|
|
<link rel="alternate" type="text/html" href="${profile.profileUrl}" />
|
|
<link rel="alternate" type="application/nostr+json" href="nostr:${profile.npub}" />
|
|
<id>${feedId}</id>
|
|
<updated>${isoDate(lastUpdate)}</updated>
|
|
<icon>${profile.avatarImageUrl}</icon>
|
|
<author>
|
|
<name>${profile.name}</name>
|
|
<uri>${profile.profileUrl}</uri>
|
|
<nostr:uri>nostr:${profile.nprofile}</nostr:uri>
|
|
</author>
|
|
${articlesXml}
|
|
</feed>
|
|
`.trim();
|
|
}
|
|
|
|
export function cleanContentHtml(html: string) {
|
|
const cleanHtml = html.replace(
|
|
/<a class="anchor" aria-hidden="true"[^>]*>.*?<\/a>/gs,
|
|
"",
|
|
);
|
|
return cleanHtml;
|
|
}
|