import { parseCanonicalResourceUri } from "@atcute/lexicons/syntax"; import { datetimeOf, didOf, nsidOf, recordKeyOf, type AtUri, type KnotOrigin } from "$lib/api/syntax"; import { now as tidNow } from "@atcute/tid"; import type { OAuthUserAgent } from "@atcute/oauth-browser-client"; import type { BobbinContext, XrpcRequestInit } from "$lib/api/client"; import { jsonGet } from "$lib/api/_request"; import type { RecordView } from "$lib/api/records"; import { cobRefOf, createCob, eraseCob, type CobRef } from "$lib/api/cob"; import { rkeyFromUri } from "$lib/api/uri"; import { deleteRecord, putRecord } from "$lib/api/write"; import type * as OrgTangledFeedReaction from "$lib/api/lexicons/types/org/tangled/feed/reaction"; export type ReactionRecord = OrgTangledFeedReaction.Main; export const REACTION_COLLECTION = nsidOf("org.tangled.feed.reaction"); export interface ViewerReaction { uri: string; cid?: string; } // without a knot this is a string reaction on the writer's pds export const react = async ( agent: OAuthUserAgent, knot: KnotOrigin | undefined, subject: CobRef, reaction: ReactionRecord["reaction"] ): Promise => { const record: ReactionRecord = { $type: "org.tangled.feed.reaction", subject, reaction, createdAt: datetimeOf(new Date().toISOString()) }; if (!knot) return putRecord(agent, REACTION_COLLECTION, recordKeyOf(tidNow()), record); const { repo } = parseCanonicalResourceUri(subject.uri); return createCob(agent, knot, didOf(repo), REACTION_COLLECTION, record); }; export const unreact = async ( agent: OAuthUserAgent, knot: KnotOrigin | undefined, mine: ViewerReaction ): Promise => { if (!knot) return deleteRecord(agent, REACTION_COLLECTION, rkeyFromUri(mine.uri)); await eraseCob(agent, knot, cobRefOf(mine)); }; export interface ReactionListPage { cursor?: string | null; items: RecordView[]; } export const listReactions = ( ctx: BobbinContext, subject: AtUri, filter: { limit?: number; cursor?: string; order?: "asc" | "desc" } = {}, init?: XrpcRequestInit ) => jsonGet(ctx, "sh.tangled.feed.listReactions", { subject, ...filter }, init);