~james/core

core/web/src/lib/api/reaction.ts -rw-r--r-- 2.1 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 15 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import { parseCanonicalResourceUri } from "@atcute/lexicons/syntax";
import {
	datetimeOf,
	didOf,
	nsidOf,
	recordKeyOf,
	type AtUri,
	type KnotOrigin
} from "#lib/api/syntax.ts";
import { now as tidNow } from "@atcute/tid";
import type { OAuthUserAgent } from "@atcute/oauth-browser-client";
import type { BobbinContext, XrpcRequestInit } from "#lib/api/client.ts";
import { jsonGet } from "#lib/api/_request.ts";
import type { RecordView } from "#lib/api/records.ts";
import { cobRefOf, createCob, eraseCob, type CobRef } from "#lib/api/cob.ts";
import { rkeyFromUri } from "#lib/api/uri.ts";
import { deleteRecord, putRecord } from "#lib/api/write.ts";
import type * as OrgTangledFeedReaction from "#lib/api/lexicons/types/org/tangled/feed/reaction.ts";

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<CobRef> => {
	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<void> => {
	if (!knot) return deleteRecord(agent, REACTION_COLLECTION, rkeyFromUri(mine.uri));
	await eraseCob(agent, knot, cobRefOf(mine));
};

export interface ReactionListPage {
	cursor?: string | null;
	items: RecordView<ReactionRecord>[];
}

export const listReactions = (
	ctx: BobbinContext,
	subject: AtUri,
	filter: { limit?: number; cursor?: string; order?: "asc" | "desc" } = {},
	init?: XrpcRequestInit
) => jsonGet<ReactionListPage>(ctx, "org.tangled.feed.listReactions", { subject, ...filter }, init);