applesauce-core 1.2.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +7 -13
  2. package/dist/event-store/{database.d.ts → event-set.d.ts} +36 -21
  3. package/dist/event-store/{database.js → event-set.js} +98 -67
  4. package/dist/event-store/event-store.d.ts +64 -25
  5. package/dist/event-store/event-store.js +164 -207
  6. package/dist/event-store/index.d.ts +1 -1
  7. package/dist/event-store/index.js +1 -1
  8. package/dist/event-store/interface.d.ts +71 -13
  9. package/dist/helpers/app-handlers.d.ts +23 -0
  10. package/dist/helpers/app-handlers.js +68 -0
  11. package/dist/helpers/article.d.ts +9 -0
  12. package/dist/helpers/article.js +21 -0
  13. package/dist/helpers/bolt11.d.ts +1 -0
  14. package/dist/helpers/bolt11.js +2 -0
  15. package/dist/helpers/bookmarks.js +1 -2
  16. package/dist/helpers/emoji.d.ts +10 -2
  17. package/dist/helpers/emoji.js +21 -3
  18. package/dist/helpers/encrypted-content-cache.d.ts +15 -0
  19. package/dist/helpers/encrypted-content-cache.js +125 -0
  20. package/dist/helpers/encrypted-content.d.ts +48 -0
  21. package/dist/helpers/encrypted-content.js +65 -0
  22. package/dist/helpers/encryption.d.ts +5 -0
  23. package/dist/helpers/encryption.js +10 -0
  24. package/dist/helpers/event.d.ts +5 -8
  25. package/dist/helpers/event.js +25 -11
  26. package/dist/helpers/expiration.d.ts +6 -0
  27. package/dist/helpers/expiration.js +16 -0
  28. package/dist/helpers/filter.d.ts +1 -3
  29. package/dist/helpers/filter.js +1 -3
  30. package/dist/helpers/gift-wraps.d.ts +17 -5
  31. package/dist/helpers/gift-wraps.js +65 -27
  32. package/dist/helpers/groups.d.ts +5 -0
  33. package/dist/helpers/groups.js +12 -2
  34. package/dist/helpers/hidden-content.d.ts +27 -32
  35. package/dist/helpers/hidden-content.js +35 -65
  36. package/dist/helpers/hidden-tags.d.ts +23 -4
  37. package/dist/helpers/hidden-tags.js +39 -4
  38. package/dist/helpers/index.d.ts +11 -1
  39. package/dist/helpers/index.js +11 -1
  40. package/dist/helpers/legacy-messages.d.ts +21 -0
  41. package/dist/helpers/legacy-messages.js +39 -0
  42. package/dist/helpers/lists.d.ts +3 -1
  43. package/dist/helpers/lists.js +9 -3
  44. package/dist/helpers/messages.d.ts +11 -0
  45. package/dist/helpers/messages.js +19 -0
  46. package/dist/helpers/mutes.js +1 -1
  47. package/dist/helpers/pointers.d.ts +33 -9
  48. package/dist/helpers/pointers.js +80 -44
  49. package/dist/helpers/profile.d.ts +10 -2
  50. package/dist/helpers/profile.js +33 -4
  51. package/dist/helpers/reactions.d.ts +8 -0
  52. package/dist/helpers/reactions.js +56 -0
  53. package/dist/helpers/reports.d.ts +28 -0
  54. package/dist/helpers/reports.js +38 -0
  55. package/dist/helpers/share.d.ts +10 -1
  56. package/dist/helpers/share.js +22 -8
  57. package/dist/helpers/url.d.ts +4 -0
  58. package/dist/helpers/url.js +20 -0
  59. package/dist/helpers/user-status.js +2 -1
  60. package/dist/helpers/wrapped-messages.d.ts +23 -0
  61. package/dist/helpers/wrapped-messages.js +38 -0
  62. package/dist/helpers/zap.d.ts +8 -5
  63. package/dist/helpers/zap.js +11 -6
  64. package/dist/index.d.ts +2 -2
  65. package/dist/index.js +2 -2
  66. package/dist/models/blossom.d.ts +3 -0
  67. package/dist/models/blossom.js +8 -0
  68. package/dist/models/bookmarks.d.ts +8 -0
  69. package/dist/{queries → models}/bookmarks.js +9 -9
  70. package/dist/models/channels.d.ts +11 -0
  71. package/dist/{queries → models}/channels.js +9 -9
  72. package/dist/models/comments.d.ts +4 -0
  73. package/dist/models/comments.js +11 -0
  74. package/dist/models/common.d.ts +16 -0
  75. package/dist/models/common.js +176 -0
  76. package/dist/models/contacts.d.ts +8 -0
  77. package/dist/{queries → models}/contacts.js +10 -10
  78. package/dist/models/encrypted-content.d.ts +4 -0
  79. package/dist/models/encrypted-content.js +11 -0
  80. package/dist/models/gift-wrap.d.ts +7 -0
  81. package/dist/models/gift-wrap.js +20 -0
  82. package/dist/{queries → models}/index.d.ts +6 -2
  83. package/dist/{queries → models}/index.js +6 -2
  84. package/dist/models/legacy-messages.d.ts +8 -0
  85. package/dist/models/legacy-messages.js +29 -0
  86. package/dist/models/mailboxes.d.ts +6 -0
  87. package/dist/{queries → models}/mailboxes.js +2 -2
  88. package/dist/models/mutes.d.ts +8 -0
  89. package/dist/{queries → models}/mutes.js +9 -9
  90. package/dist/models/pins.d.ts +4 -0
  91. package/dist/{queries → models}/pins.js +3 -3
  92. package/dist/models/profile.d.ts +4 -0
  93. package/dist/models/profile.js +14 -0
  94. package/dist/models/reactions.d.ts +4 -0
  95. package/dist/{queries → models}/reactions.js +2 -2
  96. package/dist/models/relays.d.ts +27 -0
  97. package/dist/{queries → models}/relays.js +13 -13
  98. package/dist/{queries → models}/thread.d.ts +6 -5
  99. package/dist/{queries → models}/thread.js +4 -3
  100. package/dist/models/user-status.d.ts +11 -0
  101. package/dist/{queries → models}/user-status.js +5 -5
  102. package/dist/models/wrapped-messages.d.ts +25 -0
  103. package/dist/models/wrapped-messages.js +61 -0
  104. package/dist/models/zaps.d.ts +9 -0
  105. package/dist/{queries → models}/zaps.js +11 -3
  106. package/dist/observable/claim-events.d.ts +3 -3
  107. package/dist/observable/claim-events.js +4 -4
  108. package/dist/observable/claim-latest.d.ts +3 -3
  109. package/dist/observable/claim-latest.js +4 -4
  110. package/dist/observable/index.d.ts +3 -1
  111. package/dist/observable/index.js +3 -1
  112. package/dist/observable/map-events-timeline.d.ts +7 -0
  113. package/dist/observable/map-events-timeline.js +9 -0
  114. package/dist/observable/map-events-to-store.d.ts +5 -0
  115. package/dist/observable/map-events-to-store.js +12 -0
  116. package/dist/observable/simple-timeout.d.ts +1 -0
  117. package/dist/observable/simple-timeout.js +1 -0
  118. package/dist/observable/watch-event-updates.d.ts +7 -0
  119. package/dist/observable/watch-event-updates.js +25 -0
  120. package/package.json +11 -16
  121. package/dist/__tests__/exports.test.d.ts +0 -1
  122. package/dist/__tests__/exports.test.js +0 -17
  123. package/dist/__tests__/fixtures.d.ts +0 -8
  124. package/dist/__tests__/fixtures.js +0 -20
  125. package/dist/event-store/__tests__/event-store.test.d.ts +0 -1
  126. package/dist/event-store/__tests__/event-store.test.js +0 -354
  127. package/dist/helpers/__tests__/blossom.test.d.ts +0 -1
  128. package/dist/helpers/__tests__/blossom.test.js +0 -13
  129. package/dist/helpers/__tests__/bookmarks.test.d.ts +0 -1
  130. package/dist/helpers/__tests__/bookmarks.test.js +0 -88
  131. package/dist/helpers/__tests__/comment.test.d.ts +0 -1
  132. package/dist/helpers/__tests__/comment.test.js +0 -249
  133. package/dist/helpers/__tests__/contacts.test.d.ts +0 -1
  134. package/dist/helpers/__tests__/contacts.test.js +0 -34
  135. package/dist/helpers/__tests__/emoji.test.d.ts +0 -1
  136. package/dist/helpers/__tests__/emoji.test.js +0 -15
  137. package/dist/helpers/__tests__/event.test.d.ts +0 -1
  138. package/dist/helpers/__tests__/event.test.js +0 -36
  139. package/dist/helpers/__tests__/events.test.d.ts +0 -1
  140. package/dist/helpers/__tests__/events.test.js +0 -32
  141. package/dist/helpers/__tests__/exports.test.d.ts +0 -1
  142. package/dist/helpers/__tests__/exports.test.js +0 -220
  143. package/dist/helpers/__tests__/file-metadata.test.d.ts +0 -1
  144. package/dist/helpers/__tests__/file-metadata.test.js +0 -103
  145. package/dist/helpers/__tests__/hidden-tags.test.d.ts +0 -1
  146. package/dist/helpers/__tests__/hidden-tags.test.js +0 -29
  147. package/dist/helpers/__tests__/mailboxes.test.d.ts +0 -1
  148. package/dist/helpers/__tests__/mailboxes.test.js +0 -81
  149. package/dist/helpers/__tests__/mutes.test.d.ts +0 -1
  150. package/dist/helpers/__tests__/mutes.test.js +0 -55
  151. package/dist/helpers/__tests__/nip-19.test.d.ts +0 -1
  152. package/dist/helpers/__tests__/nip-19.test.js +0 -42
  153. package/dist/helpers/__tests__/relays.test.d.ts +0 -1
  154. package/dist/helpers/__tests__/relays.test.js +0 -21
  155. package/dist/helpers/__tests__/tags.test.d.ts +0 -1
  156. package/dist/helpers/__tests__/tags.test.js +0 -24
  157. package/dist/helpers/__tests__/threading.test.d.ts +0 -1
  158. package/dist/helpers/__tests__/threading.test.js +0 -41
  159. package/dist/helpers/direct-messages.d.ts +0 -4
  160. package/dist/helpers/direct-messages.js +0 -5
  161. package/dist/helpers/nip-19.d.ts +0 -18
  162. package/dist/helpers/nip-19.js +0 -56
  163. package/dist/observable/__tests__/claim-events.test.d.ts +0 -1
  164. package/dist/observable/__tests__/claim-events.test.js +0 -23
  165. package/dist/observable/__tests__/claim-latest.test.d.ts +0 -1
  166. package/dist/observable/__tests__/claim-latest.test.js +0 -37
  167. package/dist/observable/__tests__/exports.test.d.ts +0 -1
  168. package/dist/observable/__tests__/exports.test.js +0 -18
  169. package/dist/observable/__tests__/listen-latest-updates.test.d.ts +0 -1
  170. package/dist/observable/__tests__/listen-latest-updates.test.js +0 -55
  171. package/dist/observable/__tests__/simple-timeout.test.d.ts +0 -1
  172. package/dist/observable/__tests__/simple-timeout.test.js +0 -34
  173. package/dist/observable/listen-latest-updates.d.ts +0 -5
  174. package/dist/observable/listen-latest-updates.js +0 -12
  175. package/dist/promise/__tests__/exports.test.d.ts +0 -1
  176. package/dist/promise/__tests__/exports.test.js +0 -11
  177. package/dist/queries/__tests__/exports.test.d.ts +0 -1
  178. package/dist/queries/__tests__/exports.test.js +0 -41
  179. package/dist/queries/blossom.d.ts +0 -2
  180. package/dist/queries/blossom.js +0 -5
  181. package/dist/queries/bookmarks.d.ts +0 -8
  182. package/dist/queries/channels.d.ts +0 -11
  183. package/dist/queries/comments.d.ts +0 -4
  184. package/dist/queries/comments.js +0 -11
  185. package/dist/queries/contacts.d.ts +0 -8
  186. package/dist/queries/mailboxes.d.ts +0 -6
  187. package/dist/queries/mutes.d.ts +0 -8
  188. package/dist/queries/pins.d.ts +0 -4
  189. package/dist/queries/profile.d.ts +0 -4
  190. package/dist/queries/profile.js +0 -7
  191. package/dist/queries/reactions.d.ts +0 -4
  192. package/dist/queries/relays.d.ts +0 -27
  193. package/dist/queries/simple.d.ts +0 -16
  194. package/dist/queries/simple.js +0 -21
  195. package/dist/queries/user-status.d.ts +0 -11
  196. package/dist/queries/zaps.d.ts +0 -5
  197. package/dist/query-store/__tests__/exports.test.d.ts +0 -1
  198. package/dist/query-store/__tests__/exports.test.js +0 -12
  199. package/dist/query-store/__tests__/query-store.test.d.ts +0 -1
  200. package/dist/query-store/__tests__/query-store.test.js +0 -63
  201. package/dist/query-store/index.d.ts +0 -1
  202. package/dist/query-store/index.js +0 -1
  203. package/dist/query-store/query-store.d.ts +0 -54
  204. package/dist/query-store/query-store.js +0 -102
@@ -0,0 +1,39 @@
1
+ import { getEncryptedContent, isEncryptedContentLocked, lockEncryptedContent, unlockEncryptedContent, } from "./encrypted-content.js";
2
+ import { getTagValue } from "./index.js";
3
+ /** Checks if a legacy direct message content is encrypted */
4
+ export function isLegacyMessageLocked(event) {
5
+ return isEncryptedContentLocked(event);
6
+ }
7
+ /**
8
+ * Returns the corraspondant of a legacy direct message
9
+ * @throws if no corraspondant is found
10
+ */
11
+ export function getLegacyMessageCorraspondant(message, self) {
12
+ const corraspondant = message.pubkey === self ? getTagValue(message, "p") : message.pubkey;
13
+ if (!corraspondant)
14
+ throw new Error("No corraspondant found");
15
+ return corraspondant;
16
+ }
17
+ /** Returns the parent message id of a legacy message */
18
+ export function getLegacyMessageParent(message) {
19
+ return getTagValue(message, "e");
20
+ }
21
+ /**
22
+ * Returns the decrypted content of a direct message
23
+ * @param message - The message to decrypt
24
+ * @param self - The public key of the user
25
+ * @param signer - The signer to use to decrypt the message
26
+ * @returns The decrypted content of the message
27
+ */
28
+ export async function unlockLegacyMessage(message, self, signer) {
29
+ const cached = getEncryptedContent(message);
30
+ if (cached)
31
+ return cached;
32
+ const corraspondant = getLegacyMessageCorraspondant(message, self);
33
+ // Unlock the encrypted content
34
+ return await unlockEncryptedContent(message, corraspondant, signer);
35
+ }
36
+ /** Clears the cached plaintext of a direct message */
37
+ export async function lockLegacyMessage(message) {
38
+ lockEncryptedContent(message);
39
+ }
@@ -1,5 +1,5 @@
1
- import { AddressPointer, EventPointer, ProfilePointer } from "nostr-tools/nip19";
2
1
  import { NostrEvent } from "nostr-tools";
2
+ import { AddressPointer, EventPointer, ProfilePointer } from "nostr-tools/nip19";
3
3
  export declare const FAVORITE_RELAYS_KIND = 10012;
4
4
  export type ReadListTags = "public" | "hidden" | "all";
5
5
  /** Returns all the tags of a list or set */
@@ -28,6 +28,8 @@ export declare function isAddressPointerInList(list: NostrEvent, pointer: string
28
28
  * @param type - Which types of tags to check
29
29
  */
30
30
  export declare function isProfilePointerInList(list: NostrEvent, pointer: string | ProfilePointer, type?: ReadListTags): boolean;
31
+ /** Returns if an event is in a list */
32
+ export declare function isEventInList(list: NostrEvent, event: NostrEvent): boolean;
31
33
  /**
32
34
  * Returns all the EventPointer in a list or set
33
35
  * @param list - The list or set to get the event pointers from
@@ -1,9 +1,9 @@
1
1
  import { isAddressableKind, isReplaceableKind } from "nostr-tools/kinds";
2
+ import { getReplaceableIdentifier, isReplaceable } from "./event.js";
2
3
  import { getHiddenTags } from "./hidden-tags.js";
3
- import { getAddressPointerFromATag, getCoordinateFromAddressPointer, getEventPointerFromETag, getProfilePointerFromPTag, } from "./pointers.js";
4
- import { isATag, isETag, isPTag, processTags } from "./tags.js";
5
- import { getReplaceableIdentifier } from "./event.js";
4
+ import { getAddressPointerForEvent, getAddressPointerFromATag, getCoordinateFromAddressPointer, getEventPointerFromETag, getProfilePointerFromPTag, } from "./pointers.js";
6
5
  import { mergeRelaySets } from "./relays.js";
6
+ import { isATag, isETag, isPTag, processTags } from "./tags.js";
7
7
  export const FAVORITE_RELAYS_KIND = 10012;
8
8
  /** Returns all the tags of a list or set */
9
9
  export function getListTags(list, type) {
@@ -53,6 +53,12 @@ export function isProfilePointerInList(list, pointer, type) {
53
53
  const tags = getListTags(list, type);
54
54
  return tags.some((t) => t[0] === "p" && t[1] === pubkey);
55
55
  }
56
+ /** Returns if an event is in a list */
57
+ export function isEventInList(list, event) {
58
+ return isReplaceable(event.kind)
59
+ ? isAddressPointerInList(list, getAddressPointerForEvent(event))
60
+ : isEventPointerInList(list, event);
61
+ }
56
62
  /**
57
63
  * Returns all the EventPointer in a list or set
58
64
  * @param list - The list or set to get the event pointers from
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Groups messages into bubble sets based on the pubkey and time
3
+ *
4
+ * @param messages - The messages to group
5
+ * @param buffer - Minimum number of seconds between message groups
6
+ * @returns The grouped messages
7
+ */
8
+ export declare function groupMessageEvents<T extends {
9
+ created_at: number;
10
+ pubkey: string;
11
+ }>(messages: T[], buffer?: number): T[][];
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Groups messages into bubble sets based on the pubkey and time
3
+ *
4
+ * @param messages - The messages to group
5
+ * @param buffer - Minimum number of seconds between message groups
6
+ * @returns The grouped messages
7
+ */
8
+ export function groupMessageEvents(messages, buffer = 5 * 60) {
9
+ const groups = [];
10
+ for (const message of messages) {
11
+ const group = groups[groups.length - 1];
12
+ const last = group?.[0];
13
+ if (group && last?.pubkey === message.pubkey && Math.abs(message.created_at - last.created_at) < buffer)
14
+ group.push(message);
15
+ else
16
+ groups.push([message]);
17
+ }
18
+ return groups;
19
+ }
@@ -1,8 +1,8 @@
1
1
  import { kinds } from "nostr-tools";
2
- import { isETag, isPTag, isTTag } from "./tags.js";
3
2
  import { getOrComputeCachedValue } from "./cache.js";
4
3
  import { getHiddenTags, isHiddenTagsLocked } from "./hidden-tags.js";
5
4
  import { getIndexableTags, getNip10References } from "./index.js";
5
+ import { isETag, isPTag, isTTag } from "./tags.js";
6
6
  export const MutePublicSymbol = Symbol.for("mute-public");
7
7
  export const MuteHiddenSymbol = Symbol.for("mute-hidden");
8
8
  /** Merges any number of mute sets */
@@ -1,5 +1,6 @@
1
- import { AddressPointer, DecodeResult, EventPointer, ProfilePointer } from "nostr-tools/nip19";
1
+ import { AddressPointer, EventPointer, ProfilePointer, decode } from "nostr-tools/nip19";
2
2
  import { NostrEvent } from "nostr-tools";
3
+ export type DecodeResult = ReturnType<typeof decode>;
3
4
  export type AddressPointerWithoutD = Omit<AddressPointer, "identifier"> & {
4
5
  identifier?: string;
5
6
  };
@@ -21,23 +22,23 @@ export declare function encodeDecodeResult(result: DecodeResult): "" | `nprofile
21
22
  */
22
23
  export declare function getEventPointerFromETag(tag: string[]): EventPointer;
23
24
  /**
24
- * Gets an EventPointer form a "q" tag
25
+ * Gets an EventPointer form a common "q" tag
25
26
  * @throws
26
27
  */
27
28
  export declare function getEventPointerFromQTag(tag: string[]): EventPointer;
28
29
  /**
29
- * Get an AddressPointer from an "a" tag
30
+ * Get an AddressPointer from a common "a" tag
30
31
  * @throws
31
32
  */
32
33
  export declare function getAddressPointerFromATag(tag: string[]): AddressPointer;
33
34
  /**
34
- * Gets a ProfilePointer from a "p" tag
35
+ * Gets a ProfilePointer from a common "p" tag
35
36
  * @throws
36
37
  */
37
38
  export declare function getProfilePointerFromPTag(tag: string[]): ProfilePointer;
38
- /** Parses "e", "a", "p", and "q" tags into a pointer */
39
- export declare function getPointerFromTag(tag: string[]): DecodeResult | null;
39
+ /** Checks if a pointer is an AddressPointer */
40
40
  export declare function isAddressPointer(pointer: DecodeResult["data"]): pointer is AddressPointer;
41
+ /** Checks if a pointer is an EventPointer */
41
42
  export declare function isEventPointer(pointer: DecodeResult["data"]): pointer is EventPointer;
42
43
  /** Returns the coordinate string for an AddressPointer */
43
44
  export declare function getCoordinateFromAddressPointer(pointer: AddressPointer): string;
@@ -46,10 +47,33 @@ export declare function getCoordinateFromAddressPointer(pointer: AddressPointer)
46
47
  * @throws
47
48
  */
48
49
  export declare function getAddressPointerForEvent(event: NostrEvent, relays?: string[]): AddressPointer;
50
+ /** Returns an EventPointer for an event */
51
+ export declare function getEventPointerForEvent(event: NostrEvent, relays?: string[]): EventPointer;
49
52
  /**
50
- * Returns an EventPointer for an event
53
+ * Returns a pointer for a given event
51
54
  * @throws
52
55
  */
53
- export declare function getEventPointerForEvent(event: NostrEvent, relays?: string[]): EventPointer;
54
- /** Returns a pointer for a given event */
55
56
  export declare function getPointerForEvent(event: NostrEvent, relays?: string[]): DecodeResult;
57
+ /** Adds relay hints to a pointer object that has a relays array */
58
+ export declare function addRelayHintsToPointer<T extends {
59
+ relays?: string[];
60
+ }>(pointer: T, relays?: Iterable<string>): T;
61
+ /** Gets the hex pubkey from any nip-19 encoded string */
62
+ export declare function normalizeToPubkey(str: string): string;
63
+ /** Converts hex to nsec strings into Uint8 secret keys */
64
+ export declare function normalizeToSecretKey(str: string | Uint8Array): Uint8Array;
65
+ /**
66
+ * Merges two event points and keeps all relays
67
+ * @throws if the ids are different
68
+ */
69
+ export declare function mergeEventPointers(a: EventPointer, b: EventPointer): EventPointer;
70
+ /**
71
+ * Merges two address pointers and keeps all relays
72
+ * @throws if the kinds, pubkeys, or identifiers are different
73
+ */
74
+ export declare function mergeAddressPointers(a: AddressPointer, b: AddressPointer): AddressPointer;
75
+ /**
76
+ * Merges two profile pointers and keeps all relays
77
+ * @throws if the pubkeys are different
78
+ */
79
+ export declare function mergeProfilePointers(a: ProfilePointer, b: ProfilePointer): ProfilePointer;
@@ -1,8 +1,10 @@
1
1
  import { naddrEncode, neventEncode, noteEncode, nprofileEncode, npubEncode, nsecEncode, } from "nostr-tools/nip19";
2
- import { getPublicKey, kinds } from "nostr-tools";
2
+ import { getPublicKey, kinds, nip19 } from "nostr-tools";
3
3
  import { getReplaceableIdentifier } from "./event.js";
4
4
  import { isAddressableKind } from "nostr-tools/kinds";
5
- import { isSafeRelayURL } from "./relays.js";
5
+ import { isSafeRelayURL, mergeRelaySets } from "./relays.js";
6
+ import { isHexKey } from "./string.js";
7
+ import { hexToBytes } from "@noble/hashes/utils";
6
8
  export function parseCoordinate(a, requireD = false, silent = true) {
7
9
  const parts = a.split(":");
8
10
  const kind = parts[0] ? parseInt(parts[0]) : undefined;
@@ -79,7 +81,7 @@ export function getEventPointerFromETag(tag) {
79
81
  return pointer;
80
82
  }
81
83
  /**
82
- * Gets an EventPointer form a "q" tag
84
+ * Gets an EventPointer form a common "q" tag
83
85
  * @throws
84
86
  */
85
87
  export function getEventPointerFromQTag(tag) {
@@ -93,7 +95,7 @@ export function getEventPointerFromQTag(tag) {
93
95
  return pointer;
94
96
  }
95
97
  /**
96
- * Get an AddressPointer from an "a" tag
98
+ * Get an AddressPointer from a common "a" tag
97
99
  * @throws
98
100
  */
99
101
  export function getAddressPointerFromATag(tag) {
@@ -105,44 +107,27 @@ export function getAddressPointerFromATag(tag) {
105
107
  return pointer;
106
108
  }
107
109
  /**
108
- * Gets a ProfilePointer from a "p" tag
110
+ * Gets a ProfilePointer from a common "p" tag
109
111
  * @throws
110
112
  */
111
113
  export function getProfilePointerFromPTag(tag) {
112
114
  if (!tag[1])
113
115
  throw new Error("Missing pubkey in tag");
116
+ if (!isHexKey(tag[1]))
117
+ throw new Error("Invalid pubkey");
114
118
  const pointer = { pubkey: tag[1] };
115
119
  if (tag[2] && isSafeRelayURL(tag[2]))
116
120
  pointer.relays = [tag[2]];
117
121
  return pointer;
118
122
  }
119
- /** Parses "e", "a", "p", and "q" tags into a pointer */
120
- export function getPointerFromTag(tag) {
121
- try {
122
- switch (tag[0]) {
123
- case "e":
124
- return { type: "nevent", data: getEventPointerFromETag(tag) };
125
- case "a":
126
- return {
127
- type: "naddr",
128
- data: getAddressPointerFromATag(tag),
129
- };
130
- case "p":
131
- return { type: "nprofile", data: getProfilePointerFromPTag(tag) };
132
- // NIP-18 quote tags
133
- case "q":
134
- return { type: "nevent", data: getEventPointerFromETag(tag) };
135
- }
136
- }
137
- catch (error) { }
138
- return null;
139
- }
123
+ /** Checks if a pointer is an AddressPointer */
140
124
  export function isAddressPointer(pointer) {
141
125
  return (typeof pointer !== "string" &&
142
126
  Reflect.has(pointer, "identifier") &&
143
127
  Reflect.has(pointer, "pubkey") &&
144
128
  Reflect.has(pointer, "kind"));
145
129
  }
130
+ /** Checks if a pointer is an EventPointer */
146
131
  export function isEventPointer(pointer) {
147
132
  return typeof pointer !== "string" && Reflect.has(pointer, "id");
148
133
  }
@@ -165,10 +150,7 @@ export function getAddressPointerForEvent(event, relays) {
165
150
  relays,
166
151
  };
167
152
  }
168
- /**
169
- * Returns an EventPointer for an event
170
- * @throws
171
- */
153
+ /** Returns an EventPointer for an event */
172
154
  export function getEventPointerForEvent(event, relays) {
173
155
  return {
174
156
  id: event.id,
@@ -177,29 +159,83 @@ export function getEventPointerForEvent(event, relays) {
177
159
  relays,
178
160
  };
179
161
  }
180
- /** Returns a pointer for a given event */
162
+ /**
163
+ * Returns a pointer for a given event
164
+ * @throws
165
+ */
181
166
  export function getPointerForEvent(event, relays) {
182
167
  if (kinds.isAddressableKind(event.kind)) {
183
- const d = getReplaceableIdentifier(event);
184
168
  return {
185
169
  type: "naddr",
186
- data: {
187
- identifier: d,
188
- kind: event.kind,
189
- pubkey: event.pubkey,
190
- relays,
191
- },
170
+ data: getAddressPointerForEvent(event, relays),
192
171
  };
193
172
  }
194
173
  else {
195
174
  return {
196
175
  type: "nevent",
197
- data: {
198
- id: event.id,
199
- kind: event.kind,
200
- author: event.pubkey,
201
- relays,
202
- },
176
+ data: getEventPointerForEvent(event, relays),
203
177
  };
204
178
  }
205
179
  }
180
+ /** Adds relay hints to a pointer object that has a relays array */
181
+ export function addRelayHintsToPointer(pointer, relays) {
182
+ if (!relays)
183
+ return pointer;
184
+ else
185
+ return { ...pointer, relays: mergeRelaySets(relays, pointer.relays) };
186
+ }
187
+ /** Gets the hex pubkey from any nip-19 encoded string */
188
+ export function normalizeToPubkey(str) {
189
+ if (isHexKey(str))
190
+ return str;
191
+ else {
192
+ const decode = nip19.decode(str);
193
+ const pubkey = getPubkeyFromDecodeResult(decode);
194
+ if (!pubkey)
195
+ throw new Error(`Cant find pubkey in ${decode.type}`);
196
+ return pubkey;
197
+ }
198
+ }
199
+ /** Converts hex to nsec strings into Uint8 secret keys */
200
+ export function normalizeToSecretKey(str) {
201
+ if (str instanceof Uint8Array)
202
+ return str;
203
+ else if (isHexKey(str))
204
+ return hexToBytes(str);
205
+ else {
206
+ const decode = nip19.decode(str);
207
+ if (decode.type !== "nsec")
208
+ throw new Error(`Cant get secret key from ${decode.type}`);
209
+ return decode.data;
210
+ }
211
+ }
212
+ /**
213
+ * Merges two event points and keeps all relays
214
+ * @throws if the ids are different
215
+ */
216
+ export function mergeEventPointers(a, b) {
217
+ if (a.id !== b.id)
218
+ throw new Error("Cant merge event pointers with different ids");
219
+ const relays = mergeRelaySets(a.relays, b.relays);
220
+ return { id: a.id, kind: a.kind ?? b.kind, author: a.author ?? b.author, relays };
221
+ }
222
+ /**
223
+ * Merges two address pointers and keeps all relays
224
+ * @throws if the kinds, pubkeys, or identifiers are different
225
+ */
226
+ export function mergeAddressPointers(a, b) {
227
+ if (a.kind !== b.kind || a.pubkey !== b.pubkey || a.identifier !== b.identifier)
228
+ throw new Error("Cant merge address pointers with different kinds, pubkeys, or identifiers");
229
+ const relays = mergeRelaySets(a.relays, b.relays);
230
+ return { ...a, relays };
231
+ }
232
+ /**
233
+ * Merges two profile pointers and keeps all relays
234
+ * @throws if the pubkeys are different
235
+ */
236
+ export function mergeProfilePointers(a, b) {
237
+ if (a.pubkey !== b.pubkey)
238
+ throw new Error("Cant merge profile pointers with different pubkeys");
239
+ const relays = mergeRelaySets(a.relays, b.relays);
240
+ return { ...a, relays };
241
+ }
@@ -21,5 +21,13 @@ export type ProfileContent = {
21
21
  export declare function getProfileContent(event: NostrEvent): ProfileContent;
22
22
  /** Checks if the content of the kind 0 event is valid JSON */
23
23
  export declare function isValidProfile(profile?: NostrEvent): boolean;
24
- /** Gets the display name from a profile with fallbacks */
25
- export declare function getDisplayName(metadata?: ProfileContent): string | undefined;
24
+ /** Gets the profile picture from a nostr event or profile content with fallback */
25
+ export declare function getProfilePicture(metadata: ProfileContent | NostrEvent | undefined): string | undefined;
26
+ export declare function getProfilePicture(metadata: ProfileContent | NostrEvent | undefined, fallback: string): string;
27
+ export declare function getProfilePicture(metadata: ProfileContent | NostrEvent | undefined, fallback?: string): string | undefined;
28
+ /** Gets the display name from a profile with fallback */
29
+ export declare function getDisplayName(metadata: NostrEvent, fallback?: string): string;
30
+ export declare function getDisplayName(metadata: undefined): undefined;
31
+ export declare function getDisplayName(metadata: ProfileContent | undefined): string | undefined;
32
+ export declare function getDisplayName(metadata: ProfileContent | NostrEvent | undefined, fallback: string): string;
33
+ export declare function getDisplayName(metadata: ProfileContent | NostrEvent | undefined, fallback?: string): string | undefined;
@@ -1,4 +1,5 @@
1
1
  import { kinds } from "nostr-tools";
2
+ import { npubEncode } from "nostr-tools/nip19";
2
3
  import { getOrComputeCachedValue } from "./cache.js";
3
4
  export const ProfileContentSymbol = Symbol.for("profile-content");
4
5
  /** Returns the parsed profile content for a kind 0 event */
@@ -19,7 +20,7 @@ export function getProfileContent(event) {
19
20
  export function isValidProfile(profile) {
20
21
  if (!profile)
21
22
  return false;
22
- if (profile.kind !== kinds.Metadata)
23
+ if (profile.kind !== kinds.Metadata && profile.kind !== kinds.Handlerinformation)
23
24
  return false;
24
25
  try {
25
26
  getProfileContent(profile);
@@ -29,7 +30,35 @@ export function isValidProfile(profile) {
29
30
  return false;
30
31
  }
31
32
  }
32
- /** Gets the display name from a profile with fallbacks */
33
- export function getDisplayName(metadata) {
34
- return metadata?.display_name?.trim() || metadata?.displayName?.trim() || metadata?.name?.trim();
33
+ export function getProfilePicture(metadata, fallback) {
34
+ if (!metadata)
35
+ return fallback;
36
+ // Get the metadata from the nostr event
37
+ if ("pubkey" in metadata && "id" in metadata && "sig" in metadata) {
38
+ if (isValidProfile(metadata))
39
+ metadata = getProfileContent(metadata);
40
+ else
41
+ metadata = undefined;
42
+ }
43
+ // Return the display name or fallback
44
+ return (metadata?.picture || metadata?.image || fallback)?.trim();
45
+ }
46
+ export function getDisplayName(metadata, fallback) {
47
+ if (!metadata)
48
+ return fallback;
49
+ // Get the metadata from the nostr event
50
+ if ("pubkey" in metadata && "id" in metadata && "sig" in metadata) {
51
+ // Set the fallback to the npub if not set
52
+ if (!fallback) {
53
+ const npub = npubEncode(metadata.pubkey);
54
+ fallback = npub.slice(0, 5 + 4) + "…" + npub.slice(-4);
55
+ }
56
+ // Get the profile content
57
+ if (isValidProfile(metadata))
58
+ metadata = getProfileContent(metadata);
59
+ else
60
+ metadata = undefined;
61
+ }
62
+ // Return the display name or fallback
63
+ return (metadata?.display_name || metadata?.displayName || metadata?.name || fallback)?.trim();
35
64
  }
@@ -0,0 +1,8 @@
1
+ import { NostrEvent } from "nostr-tools";
2
+ import { AddressPointer, EventPointer } from "nostr-tools/nip19";
3
+ export declare const ReactionEventPointerSymbol: unique symbol;
4
+ export declare const ReactionAddressPointerSymbol: unique symbol;
5
+ /** Returns the EventPointer for a reaction event */
6
+ export declare function getReactionEventPointer(event: NostrEvent): EventPointer | undefined;
7
+ /** Returns the AddressPointer for a reaction event */
8
+ export declare function getReactionAddressPointer(event: NostrEvent): AddressPointer | undefined;
@@ -0,0 +1,56 @@
1
+ import { getOrComputeCachedValue } from "./cache.js";
2
+ import { getTagValue } from "./event.js";
3
+ import { getAddressPointerFromATag, getEventPointerFromETag, getProfilePointerFromPTag } from "./pointers.js";
4
+ import { mergeRelaySets } from "./relays.js";
5
+ import { isATag, isETag, isPTag } from "./tags.js";
6
+ const isInteger = (str) => Number.isInteger(Number(str));
7
+ export const ReactionEventPointerSymbol = Symbol("reaction-event-pointer");
8
+ export const ReactionAddressPointerSymbol = Symbol("reaction-address-pointer");
9
+ /** Returns the EventPointer for a reaction event */
10
+ export function getReactionEventPointer(event) {
11
+ return getOrComputeCachedValue(event, ReactionEventPointerSymbol, () => {
12
+ const eTag = event.tags.find(isETag);
13
+ if (!eTag)
14
+ return undefined;
15
+ // Get the event pointer from the e tag
16
+ const pointer = getEventPointerFromETag(eTag);
17
+ if (!pointer)
18
+ return undefined;
19
+ // set the kind if there is a k tag
20
+ const k = getTagValue(event, "k");
21
+ if (k && isInteger(k))
22
+ pointer.kind = parseInt(k);
23
+ // Get the author from the p tag if not set
24
+ if (!pointer.author) {
25
+ const p = event.tags.find(isPTag);
26
+ if (p) {
27
+ const author = getProfilePointerFromPTag(p);
28
+ pointer.author = author.pubkey;
29
+ // Copy relay hints from "p" tag
30
+ if (author.relays)
31
+ pointer.relays = mergeRelaySets(author.relays, pointer.relays);
32
+ }
33
+ }
34
+ return pointer;
35
+ });
36
+ }
37
+ /** Returns the AddressPointer for a reaction event */
38
+ export function getReactionAddressPointer(event) {
39
+ return getOrComputeCachedValue(event, ReactionAddressPointerSymbol, () => {
40
+ const aTag = event.tags.find(isATag);
41
+ if (!aTag)
42
+ return undefined;
43
+ const pointer = getAddressPointerFromATag(aTag);
44
+ if (!pointer)
45
+ return undefined;
46
+ // Get extra relay hints from the p tag
47
+ const p = event.tags.find(isPTag);
48
+ if (p) {
49
+ const author = getProfilePointerFromPTag(p);
50
+ // Copy relay hints from "p" tag
51
+ if (author.relays)
52
+ pointer.relays = mergeRelaySets(author.relays, pointer.relays);
53
+ }
54
+ return pointer;
55
+ });
56
+ }
@@ -0,0 +1,28 @@
1
+ import { NostrEvent } from "nostr-tools";
2
+ export declare const ParsedReportSymbol: unique symbol;
3
+ export declare enum ReportReason {
4
+ nudity = "nudity",
5
+ malware = "malware",
6
+ profanity = "profanity",
7
+ illegal = "illegal",
8
+ spam = "spam",
9
+ impersonation = "impersonation",
10
+ other = "other"
11
+ }
12
+ export type ReportedUser = {
13
+ type: "user";
14
+ event: NostrEvent;
15
+ pubkey: string;
16
+ reason?: ReportReason;
17
+ };
18
+ export type ReportedEvent = {
19
+ type: "event";
20
+ event: NostrEvent;
21
+ comment?: string;
22
+ id: string;
23
+ pubkey: string;
24
+ reason?: ReportReason;
25
+ blobs?: string[];
26
+ };
27
+ /** Reads a report event as either a user or event report */
28
+ export declare function getReported(report: NostrEvent): ReportedEvent | ReportedUser;
@@ -0,0 +1,38 @@
1
+ import { isETag, isPTag } from "./tags.js";
2
+ import { getOrComputeCachedValue } from "./cache.js";
3
+ export const ParsedReportSymbol = Symbol("parsed-report");
4
+ export var ReportReason;
5
+ (function (ReportReason) {
6
+ ReportReason["nudity"] = "nudity";
7
+ ReportReason["malware"] = "malware";
8
+ ReportReason["profanity"] = "profanity";
9
+ ReportReason["illegal"] = "illegal";
10
+ ReportReason["spam"] = "spam";
11
+ ReportReason["impersonation"] = "impersonation";
12
+ ReportReason["other"] = "other";
13
+ })(ReportReason || (ReportReason = {}));
14
+ /** Reads a report event as either a user or event report */
15
+ export function getReported(report) {
16
+ return getOrComputeCachedValue(report, ParsedReportSymbol, () => {
17
+ const p = report.tags.find(isPTag);
18
+ if (!p)
19
+ throw new Error("Report missing p tag");
20
+ const comment = report.content ? report.content.trim() : undefined;
21
+ const e = report.tags.find(isETag);
22
+ // Event report
23
+ if (e) {
24
+ const blobs = report.tags.filter((t) => t[0] === "x" && t[1]).map((t) => t[1]);
25
+ return {
26
+ type: "event",
27
+ event: report,
28
+ comment,
29
+ id: e[1],
30
+ pubkey: p[1],
31
+ reason: e[2],
32
+ blobs,
33
+ };
34
+ }
35
+ // User report
36
+ return { type: "user", event: report, comment, pubkey: p[1], reason: p[2] };
37
+ });
38
+ }
@@ -1,4 +1,13 @@
1
1
  import { NostrEvent } from "nostr-tools";
2
+ import { AddressPointer, EventPointer } from "nostr-tools/nip19";
2
3
  export declare const SharedEventSymbol: unique symbol;
4
+ export declare const SharedEventPointerSymbol: unique symbol;
5
+ export declare const SharedAddressPointerSymbol: unique symbol;
6
+ /** Returns the event pointer of a kind 6 or 16 share event */
7
+ export declare function getSharedEventPointer(event: NostrEvent): EventPointer | undefined;
8
+ /** Returns the address pointer of a kind 6 or 16 share event */
9
+ export declare function getSharedAddressPointer(event: NostrEvent): AddressPointer | undefined;
3
10
  /** Returns the stringified event in the content of a kind 6 or 16 share event */
4
- export declare function parseSharedEvent(event: NostrEvent): NostrEvent | undefined;
11
+ export declare function getEmbededSharedEvent(event: NostrEvent): NostrEvent | undefined;
12
+ /** @deprecated use getEmbededSharedEvent instead */
13
+ export declare const parseSharedEvent: typeof getEmbededSharedEvent;
@@ -1,12 +1,26 @@
1
- import { safeParse } from "./json.js";
1
+ import { nip18 } from "nostr-tools";
2
2
  import { getOrComputeCachedValue } from "./cache.js";
3
+ import { isATag } from "./tags.js";
4
+ import { getAddressPointerFromATag } from "./pointers.js";
3
5
  export const SharedEventSymbol = Symbol.for("shared-event");
4
- /** Returns the stringified event in the content of a kind 6 or 16 share event */
5
- export function parseSharedEvent(event) {
6
- return getOrComputeCachedValue(event, SharedEventSymbol, () => {
7
- const json = safeParse(event.content);
8
- if (!json)
9
- return;
10
- return json;
6
+ export const SharedEventPointerSymbol = Symbol.for("shared-event-pointer");
7
+ export const SharedAddressPointerSymbol = Symbol.for("shared-address-pointer");
8
+ /** Returns the event pointer of a kind 6 or 16 share event */
9
+ export function getSharedEventPointer(event) {
10
+ return getOrComputeCachedValue(event, SharedEventPointerSymbol, () => nip18.getRepostedEventPointer(event));
11
+ }
12
+ /** Returns the address pointer of a kind 6 or 16 share event */
13
+ export function getSharedAddressPointer(event) {
14
+ return getOrComputeCachedValue(event, SharedAddressPointerSymbol, () => {
15
+ const a = event.tags.find(isATag);
16
+ if (!a)
17
+ return undefined;
18
+ return getAddressPointerFromATag(a);
11
19
  });
12
20
  }
21
+ /** Returns the stringified event in the content of a kind 6 or 16 share event */
22
+ export function getEmbededSharedEvent(event) {
23
+ return getOrComputeCachedValue(event, SharedEventSymbol, () => nip18.getRepostedEvent(event));
24
+ }
25
+ /** @deprecated use getEmbededSharedEvent instead */
26
+ export const parseSharedEvent = getEmbededSharedEvent;
@@ -14,6 +14,10 @@ export declare function isStreamURL(url: string | URL): boolean;
14
14
  export declare function isAudioURL(url: string | URL): boolean;
15
15
  /** Tests if two URLs are the same */
16
16
  export declare function isSameURL(a: string | URL, b: string | URL): boolean;
17
+ /** Adds a protocol to a URL string if its missing one */
18
+ export declare function ensureProtocol(url: string, protocol?: string): string;
19
+ /** Converts a URL to a WebSocket URL */
20
+ export declare function ensureWebSocketURL<T extends string | URL>(url: T): T;
17
21
  /**
18
22
  * Normalizes a string into a relay URL
19
23
  * Does not remove the trailing slash