import { fetchJson } from "#lib/fetchJson.ts"; import type { Fetch } from "#lib/fetch.ts"; const BLOG_URLS = ["https://tangled.org/blog", "https://next-dev.tangled.org/blog"]; const BLOG_ORIGINS = new Set(BLOG_URLS.map((url) => new URL(url).origin)); const FEED_TTL = 5 * 60_000; export interface BlogFeedItem { url: string; title: string; summary?: string; image?: string; date_published: string; tags?: string[]; authors?: { name: string; url?: string }[]; } let cached: { expires: number; items: BlogFeedItem[] } | undefined; export const loadBlogFeed = async ( fetch: Fetch, timeout = 2500 ): Promise => { if (cached && cached.expires > Date.now()) return cached.items; const feeds = BLOG_URLS.map((blogUrl) => fetchJson<{ items?: BlogFeedItem[] }>(fetch, `${blogUrl}/feed.json`, timeout) ); for (const pending of feeds) { const feed = await pending; if (!Array.isArray(feed?.items)) continue; const items = feed.items.flatMap((item) => { const url = URL.parse(item.url); return url && BLOG_ORIGINS.has(url.origin) ? [{ ...item, url: url.href }] : []; }); cached = { expires: Date.now() + FEED_TTL, items }; return items; } return null; };