"use server"; import { AtpAgent } from "@atproto/api"; import { ProfileViewDetailed } from "@atproto/api/dist/client/types/app/bsky/actor/defs"; import { getIdentityData } from "actions/getIdentityData"; import { Json } from "supabase/database.types"; import { supabaseServerClient } from "supabase/serverClient"; import { idResolver } from "./idResolver"; import { Cursor } from "./getReaderFeed"; export async function getSubscriptions(cursor?: Cursor | null): Promise<{ nextCursor: null | Cursor; subscriptions: PublicationSubscription[]; }> { let auth_res = await getIdentityData(); if (!auth_res?.atp_did) return { subscriptions: [], nextCursor: null }; let query = supabaseServerClient .from("publication_subscriptions") .select(`*, publications(*, documents_in_publications(*, documents(*)))`) .order(`created_at`, { ascending: false }) .order(`uri`, { ascending: false }) .order("indexed_at", { ascending: false, referencedTable: "publications.documents_in_publications", }) .limit(1, { referencedTable: "publications.documents_in_publications" }) .limit(25) .eq("identity", auth_res.atp_did); if (cursor) { query = query.or( `created_at.lt.${cursor.timestamp},and(created_at.eq.${cursor.timestamp},uri.lt.${cursor.uri})`, ); } let { data: pubs, error } = await query; const hydratedSubscriptions: PublicationSubscription[] = await Promise.all( pubs?.map(async (pub) => { let id = await idResolver.did.resolve(pub.publications?.identity_did!); return { ...pub.publications!, authorProfile: id?.alsoKnownAs?.[0] ? { handle: `@${id.alsoKnownAs[0].slice(5)}` } : undefined, }; }) || [], ); const nextCursor = pubs && pubs.length > 0 ? { timestamp: pubs[pubs.length - 1].created_at, uri: pubs[pubs.length - 1].uri, } : null; return { subscriptions: hydratedSubscriptions, nextCursor, }; } export type PublicationSubscription = { authorProfile?: { handle: string }; record: Json; uri: string; documents_in_publications: { documents: { data?: Json; indexed_at: string } | null; }[]; };