applesauce-common 0.0.0-next-20251203172109

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 (225) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -0
  3. package/dist/blueprints/app-data.d.ts +5 -0
  4. package/dist/blueprints/app-data.js +10 -0
  5. package/dist/blueprints/calendar.d.ts +5 -0
  6. package/dist/blueprints/calendar.js +7 -0
  7. package/dist/blueprints/channels.d.ts +6 -0
  8. package/dist/blueprints/channels.js +13 -0
  9. package/dist/blueprints/comment.d.ts +12 -0
  10. package/dist/blueprints/comment.js +15 -0
  11. package/dist/blueprints/delete.d.ts +9 -0
  12. package/dist/blueprints/delete.js +14 -0
  13. package/dist/blueprints/file-metadata.d.ts +8 -0
  14. package/dist/blueprints/file-metadata.js +11 -0
  15. package/dist/blueprints/follow-set.d.ts +11 -0
  16. package/dist/blueprints/follow-set.js +21 -0
  17. package/dist/blueprints/gift-wrap.d.ts +5 -0
  18. package/dist/blueprints/gift-wrap.js +6 -0
  19. package/dist/blueprints/group.d.ts +9 -0
  20. package/dist/blueprints/group.js +17 -0
  21. package/dist/blueprints/highlight.d.ts +20 -0
  22. package/dist/blueprints/highlight.js +12 -0
  23. package/dist/blueprints/index.d.ts +23 -0
  24. package/dist/blueprints/index.js +24 -0
  25. package/dist/blueprints/legacy-message.d.ts +7 -0
  26. package/dist/blueprints/legacy-message.js +29 -0
  27. package/dist/blueprints/live-stream.d.ts +6 -0
  28. package/dist/blueprints/live-stream.js +9 -0
  29. package/dist/blueprints/note.d.ts +16 -0
  30. package/dist/blueprints/note.js +30 -0
  31. package/dist/blueprints/picture-post.d.ts +12 -0
  32. package/dist/blueprints/picture-post.js +17 -0
  33. package/dist/blueprints/poll.d.ts +41 -0
  34. package/dist/blueprints/poll.js +33 -0
  35. package/dist/blueprints/profile.d.ts +3 -0
  36. package/dist/blueprints/profile.js +7 -0
  37. package/dist/blueprints/reaction.d.ts +10 -0
  38. package/dist/blueprints/reaction.js +14 -0
  39. package/dist/blueprints/share.d.ts +12 -0
  40. package/dist/blueprints/share.js +25 -0
  41. package/dist/blueprints/stream.d.ts +6 -0
  42. package/dist/blueprints/stream.js +7 -0
  43. package/dist/blueprints/torrent.d.ts +23 -0
  44. package/dist/blueprints/torrent.js +25 -0
  45. package/dist/blueprints/wrapped-message.d.ts +20 -0
  46. package/dist/blueprints/wrapped-message.js +64 -0
  47. package/dist/helpers/app-data.d.ts +39 -0
  48. package/dist/helpers/app-data.js +68 -0
  49. package/dist/helpers/app-handler.d.ts +22 -0
  50. package/dist/helpers/app-handler.js +67 -0
  51. package/dist/helpers/article.d.ts +14 -0
  52. package/dist/helpers/article.js +24 -0
  53. package/dist/helpers/blossom.d.ts +11 -0
  54. package/dist/helpers/blossom.js +40 -0
  55. package/dist/helpers/bolt11.d.ts +10 -0
  56. package/dist/helpers/bolt11.js +17 -0
  57. package/dist/helpers/bookmark.d.ts +30 -0
  58. package/dist/helpers/bookmark.js +96 -0
  59. package/dist/helpers/calendar-event.d.ts +39 -0
  60. package/dist/helpers/calendar-event.js +121 -0
  61. package/dist/helpers/calendar-rsvp.d.ts +15 -0
  62. package/dist/helpers/calendar-rsvp.js +38 -0
  63. package/dist/helpers/calendar.d.ts +6 -0
  64. package/dist/helpers/calendar.js +11 -0
  65. package/dist/helpers/channels.d.ts +13 -0
  66. package/dist/helpers/channels.js +27 -0
  67. package/dist/helpers/comment.d.ts +47 -0
  68. package/dist/helpers/comment.js +185 -0
  69. package/dist/helpers/content.d.ts +3 -0
  70. package/dist/helpers/content.js +8 -0
  71. package/dist/helpers/emoji.d.ts +21 -0
  72. package/dist/helpers/emoji.js +34 -0
  73. package/dist/helpers/encrypted-content-cache.d.ts +22 -0
  74. package/dist/helpers/encrypted-content-cache.js +138 -0
  75. package/dist/helpers/file-metadata.d.ts +55 -0
  76. package/dist/helpers/file-metadata.js +130 -0
  77. package/dist/helpers/gift-wrap.d.ts +66 -0
  78. package/dist/helpers/gift-wrap.js +204 -0
  79. package/dist/helpers/groups-helper.d.ts +6 -0
  80. package/dist/helpers/groups-helper.js +9 -0
  81. package/dist/helpers/groups.d.ts +26 -0
  82. package/dist/helpers/groups.js +49 -0
  83. package/dist/helpers/hashtag.d.ts +2 -0
  84. package/dist/helpers/hashtag.js +7 -0
  85. package/dist/helpers/highlight.d.ts +45 -0
  86. package/dist/helpers/highlight.js +76 -0
  87. package/dist/helpers/index.d.ts +37 -0
  88. package/dist/helpers/index.js +37 -0
  89. package/dist/helpers/legacy-messages.d.ts +31 -0
  90. package/dist/helpers/legacy-messages.js +49 -0
  91. package/dist/helpers/lists.d.ts +58 -0
  92. package/dist/helpers/lists.js +110 -0
  93. package/dist/helpers/lnurl.d.ts +8 -0
  94. package/dist/helpers/lnurl.js +44 -0
  95. package/dist/helpers/mailboxes.d.ts +7 -0
  96. package/dist/helpers/mailboxes.js +49 -0
  97. package/dist/helpers/messages.d.ts +31 -0
  98. package/dist/helpers/messages.js +57 -0
  99. package/dist/helpers/mute.d.ts +33 -0
  100. package/dist/helpers/mute.js +111 -0
  101. package/dist/helpers/picture-post.d.ts +5 -0
  102. package/dist/helpers/picture-post.js +6 -0
  103. package/dist/helpers/poll.d.ts +46 -0
  104. package/dist/helpers/poll.js +78 -0
  105. package/dist/helpers/reaction.d.ts +8 -0
  106. package/dist/helpers/reaction.js +56 -0
  107. package/dist/helpers/relay-discovery.d.ts +87 -0
  108. package/dist/helpers/relay-discovery.js +126 -0
  109. package/dist/helpers/reports.d.ts +28 -0
  110. package/dist/helpers/reports.js +38 -0
  111. package/dist/helpers/share.d.ts +19 -0
  112. package/dist/helpers/share.js +58 -0
  113. package/dist/helpers/stream-chat.d.ts +4 -0
  114. package/dist/helpers/stream-chat.js +9 -0
  115. package/dist/helpers/stream.d.ts +31 -0
  116. package/dist/helpers/stream.js +81 -0
  117. package/dist/helpers/threading.d.ts +55 -0
  118. package/dist/helpers/threading.js +94 -0
  119. package/dist/helpers/torrent.d.ts +55 -0
  120. package/dist/helpers/torrent.js +270 -0
  121. package/dist/helpers/user-status.d.ts +18 -0
  122. package/dist/helpers/user-status.js +22 -0
  123. package/dist/helpers/wrapped-messages.d.ts +14 -0
  124. package/dist/helpers/wrapped-messages.js +23 -0
  125. package/dist/helpers/zap.d.ts +46 -0
  126. package/dist/helpers/zap.js +125 -0
  127. package/dist/index.d.ts +5 -0
  128. package/dist/index.js +6 -0
  129. package/dist/models/blossom.d.ts +11 -0
  130. package/dist/models/blossom.js +18 -0
  131. package/dist/models/bookmarks.d.ts +8 -0
  132. package/dist/models/bookmarks.js +24 -0
  133. package/dist/models/calendar.d.ts +6 -0
  134. package/dist/models/calendar.js +15 -0
  135. package/dist/models/channels.d.ts +11 -0
  136. package/dist/models/channels.js +61 -0
  137. package/dist/models/comments.d.ts +11 -0
  138. package/dist/models/comments.js +17 -0
  139. package/dist/models/gift-wrap.d.ts +7 -0
  140. package/dist/models/gift-wrap.js +20 -0
  141. package/dist/models/index.d.ts +15 -0
  142. package/dist/models/index.js +16 -0
  143. package/dist/models/legacy-messages.d.ts +14 -0
  144. package/dist/models/legacy-messages.js +64 -0
  145. package/dist/models/mutes.d.ts +16 -0
  146. package/dist/models/mutes.js +34 -0
  147. package/dist/models/pins.d.ts +4 -0
  148. package/dist/models/pins.js +10 -0
  149. package/dist/models/reactions.d.ts +11 -0
  150. package/dist/models/reactions.js +21 -0
  151. package/dist/models/thread.d.ts +33 -0
  152. package/dist/models/thread.js +93 -0
  153. package/dist/models/user-status.d.ts +11 -0
  154. package/dist/models/user-status.js +32 -0
  155. package/dist/models/wrapped-messages.d.ts +31 -0
  156. package/dist/models/wrapped-messages.js +76 -0
  157. package/dist/models/zaps.d.ts +9 -0
  158. package/dist/models/zaps.js +26 -0
  159. package/dist/operations/app-data.d.ts +6 -0
  160. package/dist/operations/app-data.js +21 -0
  161. package/dist/operations/blossom.d.ts +5 -0
  162. package/dist/operations/blossom.js +13 -0
  163. package/dist/operations/calendar-event.d.ts +34 -0
  164. package/dist/operations/calendar-event.js +72 -0
  165. package/dist/operations/calendar-rsvp.d.ts +10 -0
  166. package/dist/operations/calendar-rsvp.js +35 -0
  167. package/dist/operations/calendar.d.ts +9 -0
  168. package/dist/operations/calendar.js +15 -0
  169. package/dist/operations/channel.d.ts +4 -0
  170. package/dist/operations/channel.js +10 -0
  171. package/dist/operations/client.d.ts +4 -0
  172. package/dist/operations/client.js +23 -0
  173. package/dist/operations/comment.d.ts +4 -0
  174. package/dist/operations/comment.js +11 -0
  175. package/dist/operations/file-metadata.d.ts +4 -0
  176. package/dist/operations/file-metadata.js +21 -0
  177. package/dist/operations/geohash.d.ts +5 -0
  178. package/dist/operations/geohash.js +17 -0
  179. package/dist/operations/gift-wrap.d.ts +13 -0
  180. package/dist/operations/gift-wrap.js +93 -0
  181. package/dist/operations/group.d.ts +11 -0
  182. package/dist/operations/group.js +34 -0
  183. package/dist/operations/hashtags.d.ts +7 -0
  184. package/dist/operations/hashtags.js +17 -0
  185. package/dist/operations/highlight.d.ts +18 -0
  186. package/dist/operations/highlight.js +47 -0
  187. package/dist/operations/index.d.ts +28 -0
  188. package/dist/operations/index.js +28 -0
  189. package/dist/operations/legacy-message.d.ts +6 -0
  190. package/dist/operations/legacy-message.js +13 -0
  191. package/dist/operations/list.d.ts +7 -0
  192. package/dist/operations/list.js +14 -0
  193. package/dist/operations/live-stream.d.ts +4 -0
  194. package/dist/operations/live-stream.js +11 -0
  195. package/dist/operations/media-attachment.d.ts +4 -0
  196. package/dist/operations/media-attachment.js +12 -0
  197. package/dist/operations/note.d.ts +9 -0
  198. package/dist/operations/note.js +42 -0
  199. package/dist/operations/picture-post.d.ts +4 -0
  200. package/dist/operations/picture-post.js +14 -0
  201. package/dist/operations/poll-response.d.ts +9 -0
  202. package/dist/operations/poll-response.js +20 -0
  203. package/dist/operations/poll.d.ts +19 -0
  204. package/dist/operations/poll.js +42 -0
  205. package/dist/operations/reaction.d.ts +7 -0
  206. package/dist/operations/reaction.js +39 -0
  207. package/dist/operations/share.d.ts +8 -0
  208. package/dist/operations/share.js +34 -0
  209. package/dist/operations/stream-chat.d.ts +7 -0
  210. package/dist/operations/stream-chat.js +27 -0
  211. package/dist/operations/stream.d.ts +41 -0
  212. package/dist/operations/stream.js +83 -0
  213. package/dist/operations/tag/bookmarks.d.ts +6 -0
  214. package/dist/operations/tag/bookmarks.js +20 -0
  215. package/dist/operations/tag/index.d.ts +1 -0
  216. package/dist/operations/tag/index.js +1 -0
  217. package/dist/operations/torrent.d.ts +33 -0
  218. package/dist/operations/torrent.js +66 -0
  219. package/dist/operations/wrapped-message.d.ts +12 -0
  220. package/dist/operations/wrapped-message.js +28 -0
  221. package/dist/operations/zap-split.d.ts +10 -0
  222. package/dist/operations/zap-split.js +20 -0
  223. package/dist/register.d.ts +11 -0
  224. package/dist/register.js +13 -0
  225. package/package.json +91 -0
@@ -0,0 +1,31 @@
1
+ import { NostrEvent } from "applesauce-core/helpers/event";
2
+ import { Rumor } from "./gift-wrap.js";
3
+ /**
4
+ * Groups messages into bubble sets based on the pubkey and time
5
+ *
6
+ * @param messages - The messages to group
7
+ * @param buffer - Minimum number of seconds between message groups
8
+ * @returns The grouped messages
9
+ */
10
+ export declare function groupMessageEvents<T extends {
11
+ created_at: number;
12
+ pubkey: string;
13
+ }>(messages: T[], buffer?: number): T[][];
14
+ /**
15
+ * Returns all pubkeys of participants of a conversation
16
+ * @param participants - A conversation identifier (pubkey1:pubkey2:pubkey3), or a users pubkey, or a list of participant pubkeys, or a rumor message
17
+ * @returns The participants of the conversation
18
+ */
19
+ export declare function getConversationParticipants(participants: string | string[] | Rumor | NostrEvent): string[];
20
+ /**
21
+ * Creates a conversation identifier from a users pubkey and alist of correspondants
22
+ * @param participants - The participants of the conversation
23
+ * @returns The conversation identifier
24
+ */
25
+ export declare function createConversationIdentifier(...participants: (string | string[])[]): string;
26
+ /**
27
+ * Returns the conversation identifier for a wrapped direct message
28
+ * @param message - The NIP-17 Rumor or NIP-04 message event
29
+ * @returns The conversation identifier
30
+ */
31
+ export declare function getConversationIdentifierFromMessage(message: Rumor | NostrEvent): string;
@@ -0,0 +1,57 @@
1
+ import { kinds } from "applesauce-core/helpers/event";
2
+ import { isPTag } from "applesauce-core/helpers/tags";
3
+ /**
4
+ * Groups messages into bubble sets based on the pubkey and time
5
+ *
6
+ * @param messages - The messages to group
7
+ * @param buffer - Minimum number of seconds between message groups
8
+ * @returns The grouped messages
9
+ */
10
+ export function groupMessageEvents(messages, buffer = 5 * 60) {
11
+ const groups = [];
12
+ for (const message of messages) {
13
+ const group = groups[groups.length - 1];
14
+ const last = group?.[0];
15
+ if (group && last?.pubkey === message.pubkey && Math.abs(message.created_at - last.created_at) < buffer)
16
+ group.push(message);
17
+ else
18
+ groups.push([message]);
19
+ }
20
+ return groups;
21
+ }
22
+ /**
23
+ * Returns all pubkeys of participants of a conversation
24
+ * @param participants - A conversation identifier (pubkey1:pubkey2:pubkey3), or a users pubkey, or a list of participant pubkeys, or a rumor message
25
+ * @returns The participants of the conversation
26
+ */
27
+ export function getConversationParticipants(participants) {
28
+ let participantList;
29
+ if (typeof participants === "string") {
30
+ participantList = participants.split(":");
31
+ }
32
+ else if (Array.isArray(participants)) {
33
+ participantList = participants;
34
+ }
35
+ else {
36
+ if (participants.kind !== kinds.EncryptedDirectMessage && participants.kind !== kinds.PrivateDirectMessage)
37
+ throw new Error("Can only get participants from direct message event (4, 14)");
38
+ participantList = [participants.pubkey, ...participants.tags.filter(isPTag).map((t) => t[1])];
39
+ }
40
+ return Array.from(new Set(participantList));
41
+ }
42
+ /**
43
+ * Creates a conversation identifier from a users pubkey and alist of correspondants
44
+ * @param participants - The participants of the conversation
45
+ * @returns The conversation identifier
46
+ */
47
+ export function createConversationIdentifier(...participants) {
48
+ return Array.from(new Set(participants.flat())).sort().join(":");
49
+ }
50
+ /**
51
+ * Returns the conversation identifier for a wrapped direct message
52
+ * @param message - The NIP-17 Rumor or NIP-04 message event
53
+ * @returns The conversation identifier
54
+ */
55
+ export function getConversationIdentifierFromMessage(message) {
56
+ return createConversationIdentifier(getConversationParticipants(message));
57
+ }
@@ -0,0 +1,33 @@
1
+ import { NostrEvent } from "applesauce-core/helpers/event";
2
+ import { HiddenContentSigner } from "applesauce-core/helpers/hidden-content";
3
+ export declare const MutePublicSymbol: unique symbol;
4
+ export declare const MuteHiddenSymbol: unique symbol;
5
+ /** Type for unlocked mute events */
6
+ export type UnlockedMutes = {
7
+ [MuteHiddenSymbol]: Mutes;
8
+ };
9
+ export type Mutes = {
10
+ pubkeys: Set<string>;
11
+ threads: Set<string>;
12
+ hashtags: Set<string>;
13
+ words: Set<string>;
14
+ };
15
+ /** Merges any number of mute sets */
16
+ export declare function mergeMutes(...mutes: Mutes[]): Mutes;
17
+ /** Parses mute tags */
18
+ export declare function parseMutedTags(tags: string[][]): Mutes;
19
+ /** Returns muted things */
20
+ export declare function getMutedThings(mute: NostrEvent): Mutes;
21
+ /** Returns only the public muted things from a mute event */
22
+ export declare function getPublicMutedThings(mute: NostrEvent): Mutes;
23
+ /** Checks if the hidden mutes are unlocked */
24
+ export declare function isHiddenMutesUnlocked<T extends NostrEvent>(mute: T): mute is T & UnlockedMutes;
25
+ /** Returns the hidden muted content if the event is unlocked */
26
+ export declare function getHiddenMutedThings<T extends NostrEvent & UnlockedMutes>(mute: T): Mutes;
27
+ export declare function getHiddenMutedThings<T extends NostrEvent>(mute: T): Mutes | undefined;
28
+ /** Unlocks the hidden mutes */
29
+ export declare function unlockHiddenMutes(mute: NostrEvent, signer: HiddenContentSigner): Promise<Mutes>;
30
+ /** Creates a RegExp for matching muted words */
31
+ export declare function createMutedWordsRegExp(mutedWords: string[]): RegExp;
32
+ /** Returns true if the event matches the mutes */
33
+ export declare function matchMutes(mutes: Mutes, event: NostrEvent): boolean;
@@ -0,0 +1,111 @@
1
+ import { getOrComputeCachedValue } from "applesauce-core/helpers/cache";
2
+ import { kinds, notifyEventUpdate } from "applesauce-core/helpers/event";
3
+ import { isETag, isPTag, isTTag } from "applesauce-core/helpers/tags";
4
+ import { getIndexableTags } from "applesauce-core/helpers/filter";
5
+ import { getHiddenTags, isHiddenTagsUnlocked, unlockHiddenTags } from "applesauce-core/helpers/hidden-tags";
6
+ import { getNip10References } from "./threading.js";
7
+ export const MutePublicSymbol = Symbol.for("mute-public");
8
+ export const MuteHiddenSymbol = Symbol.for("mute-hidden");
9
+ /** Merges any number of mute sets */
10
+ export function mergeMutes(...mutes) {
11
+ const mute = { pubkeys: new Set(), threads: new Set(), hashtags: new Set(), words: new Set() };
12
+ for (const m of mutes) {
13
+ for (const pubkey of m.pubkeys)
14
+ mute.pubkeys.add(pubkey);
15
+ for (const thread of m.threads)
16
+ mute.threads.add(thread);
17
+ for (const hashtag of m.hashtags)
18
+ mute.hashtags.add(hashtag);
19
+ for (const word of m.words)
20
+ mute.words.add(word);
21
+ }
22
+ return mute;
23
+ }
24
+ /** Parses mute tags */
25
+ export function parseMutedTags(tags) {
26
+ const pubkeys = new Set(tags.filter(isPTag).map((t) => t[1]));
27
+ const threads = new Set(tags.filter(isETag).map((t) => t[1]));
28
+ const hashtags = new Set(tags.filter(isTTag).map((t) => t[1].toLocaleLowerCase()));
29
+ const words = new Set(tags.filter((t) => t[0] === "word" && t[1]).map((t) => t[1].toLocaleLowerCase()));
30
+ return { pubkeys, threads, hashtags, words };
31
+ }
32
+ /** Returns muted things */
33
+ export function getMutedThings(mute) {
34
+ const hidden = getHiddenMutedThings(mute);
35
+ const mutes = getPublicMutedThings(mute);
36
+ if (hidden)
37
+ return mergeMutes(hidden, mutes);
38
+ return mutes;
39
+ }
40
+ /** Returns only the public muted things from a mute event */
41
+ export function getPublicMutedThings(mute) {
42
+ return getOrComputeCachedValue(mute, MutePublicSymbol, () => parseMutedTags(mute.tags));
43
+ }
44
+ /** Checks if the hidden mutes are unlocked */
45
+ export function isHiddenMutesUnlocked(mute) {
46
+ return isHiddenTagsUnlocked(mute) && Reflect.has(mute, MuteHiddenSymbol);
47
+ }
48
+ export function getHiddenMutedThings(mute) {
49
+ if (isHiddenMutesUnlocked(mute))
50
+ return mute[MuteHiddenSymbol];
51
+ // get hidden tags
52
+ const tags = getHiddenTags(mute);
53
+ if (!tags)
54
+ return undefined;
55
+ // parse muted tags
56
+ const mutes = parseMutedTags(tags);
57
+ // set cached value
58
+ Reflect.set(mute, MuteHiddenSymbol, mutes);
59
+ return mutes;
60
+ }
61
+ /** Unlocks the hidden mutes */
62
+ export async function unlockHiddenMutes(mute, signer) {
63
+ if (isHiddenMutesUnlocked(mute))
64
+ return mute[MuteHiddenSymbol];
65
+ // Unlock hidden tags
66
+ await unlockHiddenTags(mute, signer);
67
+ // get hidden mutes
68
+ const mutes = getHiddenMutedThings(mute);
69
+ if (!mutes)
70
+ throw new Error("Failed to unlock hidden mutes");
71
+ // Notify event store
72
+ notifyEventUpdate(mute);
73
+ return mutes;
74
+ }
75
+ /** Creates a RegExp for matching muted words */
76
+ export function createMutedWordsRegExp(mutedWords) {
77
+ // Escape special characters and join with |
78
+ const escapedWords = mutedWords.map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
79
+ // Create the RegExp with word boundaries and case insensitive flag
80
+ return new RegExp(`\\b(${escapedWords.join("|")})\\b`, "gi");
81
+ }
82
+ /** Returns true if the event matches the mutes */
83
+ export function matchMutes(mutes, event) {
84
+ // Filter on muted pubkeys
85
+ if (mutes.pubkeys.size > 0) {
86
+ if (mutes.pubkeys.has(event.pubkey))
87
+ return true;
88
+ }
89
+ // Filter on muted hashtags`
90
+ if (mutes.hashtags.size > 0) {
91
+ const tags = getIndexableTags(event);
92
+ for (let tag of mutes.hashtags) {
93
+ if (tags.has("t:" + tag))
94
+ return true;
95
+ }
96
+ }
97
+ // Filter on muted threads
98
+ if (mutes.threads.size > 0 && event.kind === kinds.ShortTextNote) {
99
+ const refs = getNip10References(event);
100
+ if (refs.root?.e && mutes.threads.has(refs.root.e.id))
101
+ return true;
102
+ }
103
+ // Filter on muted words
104
+ if (mutes.words.size > 0) {
105
+ const regExp = createMutedWordsRegExp(Array.from(mutes.words));
106
+ if (regExp.test(event.content))
107
+ return true;
108
+ }
109
+ // Event does not match any mutes
110
+ return false;
111
+ }
@@ -0,0 +1,5 @@
1
+ import { NostrEvent } from "applesauce-core/helpers/event";
2
+ import { FileMetadata } from "./file-metadata.js";
3
+ export declare const PICTURE_POST_KIND = 20;
4
+ /** Return the media attachments from a kind 20 media post */
5
+ export declare function getPicturePostAttachments(post: NostrEvent): FileMetadata[];
@@ -0,0 +1,6 @@
1
+ import { getMediaAttachments } from "./file-metadata.js";
2
+ export const PICTURE_POST_KIND = 20;
3
+ /** Return the media attachments from a kind 20 media post */
4
+ export function getPicturePostAttachments(post) {
5
+ return getMediaAttachments(post);
6
+ }
@@ -0,0 +1,46 @@
1
+ import { NostrEvent } from "applesauce-core/helpers/event";
2
+ export declare const POLL_KIND = 1068;
3
+ export declare const POLL_RESPONSE_KIND = 1018;
4
+ export declare const PollOptionsSymbol: unique symbol;
5
+ export interface PollOption {
6
+ id: string;
7
+ label: string;
8
+ }
9
+ export type PollType = "singlechoice" | "multiplechoice";
10
+ /**
11
+ * Get the poll question/label from a poll event
12
+ * Returns the content field which contains the poll question
13
+ */
14
+ export declare function getPollQuestion(event: NostrEvent): string;
15
+ /**
16
+ * Get the poll options from a poll event
17
+ * Returns array of options with id and label
18
+ */
19
+ export declare function getPollOptions(event: NostrEvent): PollOption[];
20
+ /**
21
+ * Get the relays specified for poll responses (from 'relay' tags)
22
+ * Returns undefined if no relays are specified
23
+ */
24
+ export declare function getPollRelays(event: NostrEvent): string[];
25
+ /**
26
+ * Get the poll type from a poll event (from 'polltype' tag)
27
+ * Returns "singlechoice" or "multiplechoice", defaults to "singlechoice"
28
+ */
29
+ export declare function getPollType(event: NostrEvent): PollType;
30
+ /**
31
+ * Get the poll expiration timestamp (from 'endsAt' tag)
32
+ * Returns undefined if no expiration is set
33
+ */
34
+ export declare function getPollEndsAt(event: NostrEvent): number | undefined;
35
+ /**
36
+ * Get the poll ID that a response is referencing (from 'e' tag)
37
+ * Returns undefined if no poll reference is found
38
+ */
39
+ export declare function getPollResponsePollId(event: NostrEvent): string | undefined;
40
+ /** Get the selected option IDs from a poll response event (from 'response' tags) */
41
+ export declare function getPollResponseOptions(event: NostrEvent): string[];
42
+ /**
43
+ * Gets the options that a user has voted for in a poll event
44
+ * Returns undefined if the response is not valid
45
+ */
46
+ export declare function getPollResponseVotes(poll: NostrEvent, response: NostrEvent): string[] | undefined;
@@ -0,0 +1,78 @@
1
+ import { getOrComputeCachedValue } from "applesauce-core/helpers/cache";
2
+ import { getTagValue } from "applesauce-core/helpers/event";
3
+ // NIP-88 Poll kinds
4
+ export const POLL_KIND = 1068;
5
+ export const POLL_RESPONSE_KIND = 1018;
6
+ // Cache symbols
7
+ export const PollOptionsSymbol = Symbol.for("poll-options");
8
+ /**
9
+ * Get the poll question/label from a poll event
10
+ * Returns the content field which contains the poll question
11
+ */
12
+ export function getPollQuestion(event) {
13
+ return event.content;
14
+ }
15
+ /**
16
+ * Get the poll options from a poll event
17
+ * Returns array of options with id and label
18
+ */
19
+ export function getPollOptions(event) {
20
+ return getOrComputeCachedValue(event, PollOptionsSymbol, () => {
21
+ return event.tags
22
+ .filter((tag) => tag[0] === "option" && tag.length >= 3)
23
+ .map((tag) => ({
24
+ id: tag[1],
25
+ label: tag[2],
26
+ }));
27
+ });
28
+ }
29
+ /**
30
+ * Get the relays specified for poll responses (from 'relay' tags)
31
+ * Returns undefined if no relays are specified
32
+ */
33
+ export function getPollRelays(event) {
34
+ return event.tags.filter((tag) => tag[0] === "relay" && tag.length >= 2).map((tag) => tag[1]);
35
+ }
36
+ /**
37
+ * Get the poll type from a poll event (from 'polltype' tag)
38
+ * Returns "singlechoice" or "multiplechoice", defaults to "singlechoice"
39
+ */
40
+ export function getPollType(event) {
41
+ const type = getTagValue(event, "polltype");
42
+ return type === "multiplechoice" || type === "singlechoice" ? type : "singlechoice";
43
+ }
44
+ /**
45
+ * Get the poll expiration timestamp (from 'endsAt' tag)
46
+ * Returns undefined if no expiration is set
47
+ */
48
+ export function getPollEndsAt(event) {
49
+ const endsAt = getTagValue(event, "endsAt");
50
+ return endsAt ? parseInt(endsAt, 10) : undefined;
51
+ }
52
+ /**
53
+ * Get the poll ID that a response is referencing (from 'e' tag)
54
+ * Returns undefined if no poll reference is found
55
+ */
56
+ export function getPollResponsePollId(event) {
57
+ return getTagValue(event, "e");
58
+ }
59
+ /** Get the selected option IDs from a poll response event (from 'response' tags) */
60
+ export function getPollResponseOptions(event) {
61
+ return event.tags.filter((tag) => tag[0] === "response" && tag.length >= 2).map((tag) => tag[1]);
62
+ }
63
+ /**
64
+ * Gets the options that a user has voted for in a poll event
65
+ * Returns undefined if the response is not valid
66
+ */
67
+ export function getPollResponseVotes(poll, response) {
68
+ if (poll.id !== getPollResponsePollId(response))
69
+ return;
70
+ const pollOptions = getPollOptions(poll);
71
+ const responseOptions = getPollResponseOptions(response);
72
+ const votes = responseOptions.filter((opts) => pollOptions.some((option) => option.id === opts));
73
+ const type = getPollType(poll);
74
+ // If its a single choice poll, return the first vote
75
+ if (type === "singlechoice")
76
+ return votes.length === 1 ? [votes[0]] : undefined;
77
+ return Array.from(new Set(votes));
78
+ }
@@ -0,0 +1,8 @@
1
+ import { NostrEvent } from "applesauce-core/helpers/event";
2
+ import { AddressPointer, EventPointer } from "applesauce-core/helpers/pointers";
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 "applesauce-core/helpers/cache";
2
+ import { getTagValue } from "applesauce-core/helpers/event";
3
+ import { getAddressPointerFromATag, getEventPointerFromETag, getProfilePointerFromPTag, } from "applesauce-core/helpers/pointers";
4
+ import { mergeRelaySets } from "applesauce-core/helpers/relays";
5
+ import { isATag, isETag, isPTag } from "applesauce-core/helpers/tags";
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,87 @@
1
+ import { KnownEvent, NostrEvent } from "applesauce-core/helpers/event";
2
+ export declare const RELAY_DISCOVERY_KIND = 30166;
3
+ export declare const RELAY_MONITOR_ANNOUNCEMENT_KIND = 10166;
4
+ export type RelayDiscoveryEvent = KnownEvent<typeof RELAY_DISCOVERY_KIND>;
5
+ export type RelayMonitorAnnouncementEvent = KnownEvent<typeof RELAY_MONITOR_ANNOUNCEMENT_KIND>;
6
+ /**
7
+ * Gets the relay URL from a relay discovery event (from the `d` tag)
8
+ * This is the normalized relay URL or hex-encoded pubkey for non-URL relays
9
+ */
10
+ export declare function getRelayDiscoveryURL(event: NostrEvent): string | undefined;
11
+ /**
12
+ * Gets the round-trip time (RTT) for a specific operation type
13
+ * @param event - The relay discovery event
14
+ * @param type - The RTT type: 'open', 'read', or 'write'
15
+ * @returns The RTT in milliseconds, or undefined if not found
16
+ */
17
+ export declare function getRelayDiscoveryRTT(event: NostrEvent, type: "open" | "read" | "write"): number | undefined;
18
+ /**
19
+ * Gets the network type from a relay discovery event (from the `n` tag)
20
+ * Should be one of: clearnet, tor, i2p, loki
21
+ */
22
+ export declare function getRelayDiscoveryNetworkType(event: NostrEvent): string | undefined;
23
+ /**
24
+ * Gets all relay attributes from a relay discovery event (from `W` tags)
25
+ * Attributes describe the relay type/characteristics
26
+ */
27
+ export declare function getRelayDiscoveryAttributes(event: NostrEvent): string[];
28
+ /**
29
+ * Gets all supported NIPs from a relay discovery event (from `N` tags)
30
+ * Returns an array of NIP numbers as strings
31
+ */
32
+ export declare function getRelayDiscoverySupportedNIPs(event: NostrEvent): string[];
33
+ /**
34
+ * Gets all requirements from a relay discovery event (from `R` tags)
35
+ * False values are prefixed with `!` (e.g., `!payment`, `!auth`)
36
+ * Returns an array of requirement strings
37
+ */
38
+ export declare function getRelayDiscoveryRequirements(event: NostrEvent): string[];
39
+ /**
40
+ * Gets all topics from a relay discovery event (from `t` tags)
41
+ */
42
+ export declare function getRelayDiscoveryTopics(event: NostrEvent): string[];
43
+ /**
44
+ * Gets all accepted and unaccepted kinds from a relay discovery event (from `k` tags)
45
+ * Unaccepted kinds are prefixed with `!`
46
+ * Returns an array of kind strings
47
+ */
48
+ export declare function getRelayDiscoveryAcceptedKinds(event: NostrEvent): string[];
49
+ /**
50
+ * Gets the geohash from a relay discovery event (from the `g` tag)
51
+ * This is a NIP-52 geohash
52
+ */
53
+ export declare function getRelayDiscoveryGeohash(event: NostrEvent): string | undefined;
54
+ /**
55
+ * Validates that an event is a proper relay discovery event
56
+ * Checks that the event is kind 30166 and has the required `d` tag
57
+ */
58
+ export declare function isValidRelayDiscovery(event?: NostrEvent): event is RelayDiscoveryEvent;
59
+ /**
60
+ * Gets the frequency at which a monitor publishes events (from the `frequency` tag)
61
+ * Returns the frequency in seconds
62
+ */
63
+ export declare function getMonitorFrequency(event: NostrEvent): number | undefined;
64
+ /**
65
+ * Gets all timeout values from a relay monitor announcement (from `timeout` tags)
66
+ * Returns an array of objects with optional test type and timeout value
67
+ * Index 1 is the timeout in milliseconds, index 2 (optional) is the test type
68
+ */
69
+ export declare function getMonitorTimeouts(event: NostrEvent): Array<{
70
+ test?: string;
71
+ timeout: number;
72
+ }>;
73
+ /**
74
+ * Gets all checks conducted by a monitor (from `c` tags)
75
+ * Examples include: open, read, write, auth, nip11, dns, geo
76
+ */
77
+ export declare function getMonitorChecks(event: NostrEvent): string[];
78
+ /**
79
+ * Gets the geohash from a relay monitor announcement (from the `g` tag)
80
+ * This is a NIP-52 geohash
81
+ */
82
+ export declare function getMonitorGeohash(event: NostrEvent): string | undefined;
83
+ /**
84
+ * Validates that an event is a proper relay monitor announcement
85
+ * Checks that the event is kind 10166
86
+ */
87
+ export declare function isValidRelayMonitorAnnouncement(event?: NostrEvent): event is RelayMonitorAnnouncementEvent;
@@ -0,0 +1,126 @@
1
+ import { getTagValue } from "applesauce-core/helpers/event";
2
+ // NIP-66 Relay Discovery Kinds
3
+ export const RELAY_DISCOVERY_KIND = 30166;
4
+ export const RELAY_MONITOR_ANNOUNCEMENT_KIND = 10166;
5
+ /**
6
+ * Gets the relay URL from a relay discovery event (from the `d` tag)
7
+ * This is the normalized relay URL or hex-encoded pubkey for non-URL relays
8
+ */
9
+ export function getRelayDiscoveryURL(event) {
10
+ return getTagValue(event, "d");
11
+ }
12
+ /**
13
+ * Gets the round-trip time (RTT) for a specific operation type
14
+ * @param event - The relay discovery event
15
+ * @param type - The RTT type: 'open', 'read', or 'write'
16
+ * @returns The RTT in milliseconds, or undefined if not found
17
+ */
18
+ export function getRelayDiscoveryRTT(event, type) {
19
+ const value = getTagValue(event, `rtt-${type}`);
20
+ return value ? parseInt(value, 10) : undefined;
21
+ }
22
+ /**
23
+ * Gets the network type from a relay discovery event (from the `n` tag)
24
+ * Should be one of: clearnet, tor, i2p, loki
25
+ */
26
+ export function getRelayDiscoveryNetworkType(event) {
27
+ return getTagValue(event, "n");
28
+ }
29
+ /**
30
+ * Gets all relay attributes from a relay discovery event (from `W` tags)
31
+ * Attributes describe the relay type/characteristics
32
+ */
33
+ export function getRelayDiscoveryAttributes(event) {
34
+ return event.tags.filter((t) => t[0] === "W" && t[1]).map((t) => t[1]);
35
+ }
36
+ /**
37
+ * Gets all supported NIPs from a relay discovery event (from `N` tags)
38
+ * Returns an array of NIP numbers as strings
39
+ */
40
+ export function getRelayDiscoverySupportedNIPs(event) {
41
+ return event.tags.filter((t) => t[0] === "N" && t[1]).map((t) => t[1]);
42
+ }
43
+ /**
44
+ * Gets all requirements from a relay discovery event (from `R` tags)
45
+ * False values are prefixed with `!` (e.g., `!payment`, `!auth`)
46
+ * Returns an array of requirement strings
47
+ */
48
+ export function getRelayDiscoveryRequirements(event) {
49
+ return event.tags.filter((t) => t[0] === "R" && t[1]).map((t) => t[1]);
50
+ }
51
+ /**
52
+ * Gets all topics from a relay discovery event (from `t` tags)
53
+ */
54
+ export function getRelayDiscoveryTopics(event) {
55
+ return event.tags.filter((t) => t[0] === "t" && t[1]).map((t) => t[1]);
56
+ }
57
+ /**
58
+ * Gets all accepted and unaccepted kinds from a relay discovery event (from `k` tags)
59
+ * Unaccepted kinds are prefixed with `!`
60
+ * Returns an array of kind strings
61
+ */
62
+ export function getRelayDiscoveryAcceptedKinds(event) {
63
+ return event.tags.filter((t) => t[0] === "k" && t[1]).map((t) => t[1]);
64
+ }
65
+ /**
66
+ * Gets the geohash from a relay discovery event (from the `g` tag)
67
+ * This is a NIP-52 geohash
68
+ */
69
+ export function getRelayDiscoveryGeohash(event) {
70
+ return getTagValue(event, "g");
71
+ }
72
+ /**
73
+ * Validates that an event is a proper relay discovery event
74
+ * Checks that the event is kind 30166 and has the required `d` tag
75
+ */
76
+ export function isValidRelayDiscovery(event) {
77
+ if (!event)
78
+ return false;
79
+ if (event.kind !== RELAY_DISCOVERY_KIND)
80
+ return false;
81
+ return !!getRelayDiscoveryURL(event);
82
+ }
83
+ /**
84
+ * Gets the frequency at which a monitor publishes events (from the `frequency` tag)
85
+ * Returns the frequency in seconds
86
+ */
87
+ export function getMonitorFrequency(event) {
88
+ const value = getTagValue(event, "frequency");
89
+ return value ? parseInt(value, 10) : undefined;
90
+ }
91
+ /**
92
+ * Gets all timeout values from a relay monitor announcement (from `timeout` tags)
93
+ * Returns an array of objects with optional test type and timeout value
94
+ * Index 1 is the timeout in milliseconds, index 2 (optional) is the test type
95
+ */
96
+ export function getMonitorTimeouts(event) {
97
+ return event.tags
98
+ .filter((t) => t[0] === "timeout" && t[1])
99
+ .map((t) => ({
100
+ timeout: parseInt(t[1], 10),
101
+ test: t[2] || undefined,
102
+ }));
103
+ }
104
+ /**
105
+ * Gets all checks conducted by a monitor (from `c` tags)
106
+ * Examples include: open, read, write, auth, nip11, dns, geo
107
+ */
108
+ export function getMonitorChecks(event) {
109
+ return event.tags.filter((t) => t[0] === "c" && t[1]).map((t) => t[1]);
110
+ }
111
+ /**
112
+ * Gets the geohash from a relay monitor announcement (from the `g` tag)
113
+ * This is a NIP-52 geohash
114
+ */
115
+ export function getMonitorGeohash(event) {
116
+ return getTagValue(event, "g");
117
+ }
118
+ /**
119
+ * Validates that an event is a proper relay monitor announcement
120
+ * Checks that the event is kind 10166
121
+ */
122
+ export function isValidRelayMonitorAnnouncement(event) {
123
+ if (!event)
124
+ return false;
125
+ return event.kind === RELAY_MONITOR_ANNOUNCEMENT_KIND;
126
+ }