/** * Copyright (c) 2025 favewa * SPDX-License-Identifier: AGPL-3.0-or-later */ import { withInterval } from "./temp.ts"; export interface Report { rkey: string; cid: string; title: string; excerpt: string; content: string; createdAt: string; tags?: string[]; visibility: string; date: Date; } async function xrpc( method: string, params: Record, ): Promise { const url = new URL(`https://blacksky.app/xrpc/${method}`); Object.entries(params).forEach(([key, value]) => { url.searchParams.set(key, value); }); const response = await fetch(url.toString()); if (!response.ok) { throw new Error(`XRPC call failed: ${response.statusText}`); } return await response.json(); } const rkey = (input: string) => input.slice(input.lastIndexOf("/") + 1 || 0); export const getCachedReports: () => Report[] = await withInterval( getPosts, 300, ); export async function getPosts(cursor?: string): Promise { const params: Record = { collection: "com.whtwnd.blog.entry", repo: "acpi.at", }; if (cursor) params.cursor = cursor; const response = await xrpc("com.atproto.repo.listRecords", params); if (!response) return []; const reports = (response.records as Record[]).map(( { cid, uri, value }, ) => ({ ...value, rkey: rkey(uri), date: new Date(value.createdAt), createdAt: new Date(value.createdAt).toISOString().slice(0, 10).replace( /-/g, ".", ), cid, } as Report)).filter((r) => r.visibility === "author").sort((a, b) => b.date as any - (a.date as any) ); return reports; } export async function retrieveReport(rkey: string): Promise { const response = await xrpc("com.atproto.repo.getRecord", { collection: "com.whtwnd.blog.entry", repo: "acpi.at", rkey, }); if (!response) return null; return { ...response.value, cid: response.cid, rkey, } as Report; }