commit 8262fb08ca3dbe172633e9e67f3cfbbc43941ed1
parent 23a87521e2c97476c01d203854eb5b7ce4a533df
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Fri, 8 Aug 2025 23:25:06 +0000
utils-nostr: add `reaction` nip-25 schemas, types, event parsing utils
Diffstat:
7 files changed, 69 insertions(+), 9 deletions(-)
diff --git a/utils-nostr/src/events/comment/lib.ts b/utils-nostr/src/events/comment/lib.ts
@@ -1,6 +1,6 @@
import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
-import { NostrEventComment } from "../../types/lib";
-import { NDKEventFigure } from "../../types/ndk";
+import { NostrEventComment } from "../../types/lib.js";
+import { NDKEventFigure } from "../../types/ndk.js";
import { tags_comment } from "../../utils/tags.js";
import { ndk_event } from "../lib.js";
diff --git a/utils-nostr/src/events/reaction/lib.ts b/utils-nostr/src/events/reaction/lib.ts
@@ -0,0 +1,18 @@
+import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";
+import { NostrEventReaction } from "../../types/lib.js";
+import { NDKEventFigure } from "../../types/ndk.js";
+import { tags_reaction } from "../../utils/tags.js";
+import { ndk_event } from "../lib.js";
+
+export const ndk_event_reaction = async (opts: NDKEventFigure<{ data: NostrEventReaction; }>): Promise<NDKEvent | undefined> => {
+ const { ndk, ndk_user, data } = opts;
+ return await ndk_event({
+ ndk,
+ ndk_user,
+ basis: {
+ kind: NDKKind.Reaction,
+ content: data.content,
+ tags: tags_reaction(data)
+ },
+ });
+};
+\ No newline at end of file
diff --git a/utils-nostr/src/events/reaction/parse.ts b/utils-nostr/src/events/reaction/parse.ts
@@ -0,0 +1,15 @@
+import { NDKEvent } from "@nostr-dev-kit/ndk";
+import { nostr_event_reaction_schema } from "../../schemas/lib.js";
+import { NostrEventReaction } from "../../types/lib.js";
+
+export const parse_nostr_reaction_event = (event: NDKEvent): NostrEventReaction | undefined => {
+ if (!event || typeof event.content !== 'string' || event.kind !== 7) return undefined;
+
+ try {
+ const parsed = JSON.parse(event.content);
+ const result = nostr_event_reaction_schema.parse(parsed);
+ return result;
+ } catch {
+ return undefined;
+ }
+};
diff --git a/utils-nostr/src/events/subscription.ts b/utils-nostr/src/events/subscription.ts
@@ -1,13 +1,15 @@
import { NDKEvent } from "@nostr-dev-kit/ndk";
-import { NostrEventComment, NostrEventListing, type NostrEventMetadata } from "../types/lib.js";
+import { NostrEventComment, NostrEventListing, NostrEventReaction, type NostrEventMetadata } from "../types/lib.js";
import { parse_nostr_comment_event } from "./comment/parse.js";
import { parse_nostr_listing_event } from "./listing/parse.js";
import { parse_nostr_metadata_event } from "./metadata/parse.js";
+import { parse_nostr_reaction_event } from "./reaction/parse.js";
export type NdkEventPayload =
| { kind: 0; metadata: NostrEventMetadata; }
| { kind: 30402; listing: NostrEventListing; }
- | { kind: 1111; listing: NostrEventComment; }
+ | { kind: 1111; comment: NostrEventComment; }
+ | { kind: 7; reaction: NostrEventReaction; }
export const on_ndk_event = (event: NDKEvent): NdkEventPayload | undefined => {
if (!event || typeof event.kind !== 'number') return undefined;
@@ -26,8 +28,14 @@ export const on_ndk_event = (event: NDKEvent): NdkEventPayload | undefined => {
case 1111: {
const data = parse_nostr_comment_event(event);
if (!data) return;
- return { kind: event.kind, listing: data };
+ return { kind: event.kind, comment: data };
+ };
+ case 7: {
+ const data = parse_nostr_reaction_event(event);
+ if (!data) return;
+ return { kind: event.kind, reaction: data };
};
+
default: return undefined;
}
};
diff --git a/utils-nostr/src/schemas/lib.ts b/utils-nostr/src/schemas/lib.ts
@@ -122,4 +122,9 @@ export const nostr_event_comment_schema = z.object({
root_event: nostr_event_referenced_schema,
ref_event: nostr_event_referenced_schema.optional(),
content: z.string().min(1),
-});
-\ No newline at end of file
+});
+
+export const nostr_event_reaction_schema = z.object({
+ ref_event: nostr_event_referenced_schema,
+ content: z.string().min(1),
+});
diff --git a/utils-nostr/src/types/lib.ts b/utils-nostr/src/types/lib.ts
@@ -1,5 +1,5 @@
import { z } from 'zod';
-import { nostr_event_comment_schema, nostr_event_listing_schema, nostr_event_metadata_schema, nostr_event_referenced_schema, nostr_tag_client_schema, nostr_tag_discount_schema, nostr_tag_image_schema, nostr_tag_listing_schema, nostr_tag_location_schema, nostr_tag_price_schema, nostr_tag_quantity_schema } from "../schemas/lib.js";
+import { nostr_event_comment_schema, nostr_event_listing_schema, nostr_event_metadata_schema, nostr_event_reaction_schema, nostr_event_referenced_schema, nostr_tag_client_schema, nostr_tag_discount_schema, nostr_tag_image_schema, nostr_tag_listing_schema, nostr_tag_location_schema, nostr_tag_price_schema, nostr_tag_quantity_schema } from "../schemas/lib.js";
export type NostrEventMetadata = z.infer<typeof nostr_event_metadata_schema>;
export type NostrEventListing = z.infer<typeof nostr_event_listing_schema>
@@ -12,6 +12,7 @@ export type NostrTagQuantity = z.infer<typeof nostr_tag_quantity_schema>
export type NostrTagListing = z.infer<typeof nostr_tag_listing_schema>
export type NostrEventComment = z.infer<typeof nostr_event_comment_schema>
export type NostrEventReferenced = z.infer<typeof nostr_event_referenced_schema>
+export type NostrEventReaction = z.infer<typeof nostr_event_reaction_schema>
export type NostrEventTag = string[];
export type NostrEventTags = NostrEventTag[];
diff --git a/utils-nostr/src/utils/tags.ts b/utils-nostr/src/utils/tags.ts
@@ -1,5 +1,5 @@
import ngeotags, { type InputData as NostrGeotagsInputData } from "nostr-geotags";
-import { NostrEventComment, NostrEventListing, NostrEventTag, NostrEventTagClient, NostrEventTagImage, NostrEventTagLocation, NostrEventTagPrice, NostrEventTagPriceDiscount, NostrEventTagQuantity, NostrEventTags } from "../types/lib.js";
+import { NostrEventComment, NostrEventListing, NostrEventReaction, NostrEventTag, NostrEventTagClient, NostrEventTagImage, NostrEventTagLocation, NostrEventTagPrice, NostrEventTagPriceDiscount, NostrEventTagQuantity, NostrEventTags } from "../types/lib.js";
export const tag_client = (opts: NostrEventTagClient, d_tag?: string): NostrEventTag => {
const tag = [`client`, opts.name];
@@ -107,4 +107,17 @@ export const tags_comment = (opts: NostrEventComment): NostrEventTags => {
];
return tags;
+};
+
+export const tags_reaction = (opts: NostrEventReaction): NostrEventTags => {
+ const { ref_event } = opts;
+ const ref_kind = ref_event.kind.toString();
+ const ref_author = ref_event.author;
+ const tags: NostrEventTags = [
+ [`e`, ref_event.id, ...ref_event.relays || ``],
+ [`p`, ref_author],
+ [`k`, ref_kind],
+ ];
+ if (ref_event.d_tag) tags.push([`a`, `${ref_kind}:${ref_author}:${ref_event.d_tag}`, ...ref_event.relays || ``])
+ return tags;
};
\ No newline at end of file