applesauce-actions 0.0.0-next-20251209200210 → 0.0.0-next-20251231055351

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 (50) hide show
  1. package/README.md +3 -3
  2. package/dist/action-runner.d.ts +53 -0
  3. package/dist/action-runner.js +91 -0
  4. package/dist/actions/app-data.d.ts +1 -1
  5. package/dist/actions/app-data.js +5 -5
  6. package/dist/actions/blocked-relays.d.ts +1 -6
  7. package/dist/actions/blocked-relays.js +30 -36
  8. package/dist/actions/blossom.d.ts +1 -1
  9. package/dist/actions/blossom.js +25 -32
  10. package/dist/actions/bookmarks.d.ts +4 -3
  11. package/dist/actions/bookmarks.js +64 -55
  12. package/dist/actions/calendar.d.ts +6 -3
  13. package/dist/actions/calendar.js +26 -12
  14. package/dist/actions/comment.d.ts +10 -0
  15. package/dist/actions/comment.js +43 -0
  16. package/dist/actions/contacts.d.ts +3 -3
  17. package/dist/actions/contacts.js +27 -27
  18. package/dist/actions/direct-message-relays.d.ts +7 -0
  19. package/dist/actions/direct-message-relays.js +47 -0
  20. package/dist/actions/favorite-relays.d.ts +1 -1
  21. package/dist/actions/favorite-relays.js +34 -33
  22. package/dist/actions/follow-sets.d.ts +1 -3
  23. package/dist/actions/follow-sets.js +32 -31
  24. package/dist/actions/index.d.ts +2 -1
  25. package/dist/actions/index.js +2 -1
  26. package/dist/actions/legacy-messages.d.ts +2 -2
  27. package/dist/actions/legacy-messages.js +24 -9
  28. package/dist/actions/lists.d.ts +1 -1
  29. package/dist/actions/lists.js +5 -3
  30. package/dist/actions/mailboxes.d.ts +1 -1
  31. package/dist/actions/mailboxes.js +31 -29
  32. package/dist/actions/mute.d.ts +1 -1
  33. package/dist/actions/mute.js +32 -60
  34. package/dist/actions/pins.d.ts +1 -3
  35. package/dist/actions/pins.js +20 -26
  36. package/dist/actions/profile.d.ts +1 -1
  37. package/dist/actions/profile.js +14 -9
  38. package/dist/actions/relay-sets.d.ts +1 -1
  39. package/dist/actions/relay-sets.js +36 -29
  40. package/dist/actions/search-relays.d.ts +1 -1
  41. package/dist/actions/search-relays.js +19 -19
  42. package/dist/actions/wrapped-messages.d.ts +4 -2
  43. package/dist/actions/wrapped-messages.js +35 -14
  44. package/dist/index.d.ts +1 -1
  45. package/dist/index.js +1 -1
  46. package/package.json +4 -4
  47. package/dist/action-hub.d.ts +0 -35
  48. package/dist/action-hub.js +0 -51
  49. package/dist/actions/dm-relays.d.ts +0 -7
  50. package/dist/actions/dm-relays.js +0 -38
@@ -0,0 +1,43 @@
1
+ import { CommentBlueprint } from "applesauce-common/blueprints";
2
+ import { castUser } from "applesauce-common/casts";
3
+ import { isCommentAddressPointer, isCommentEventPointer } from "applesauce-common/helpers/comment";
4
+ import { relaySet } from "applesauce-core/helpers";
5
+ import { isEvent } from "applesauce-core/helpers/event";
6
+ /**
7
+ * Extracts the pubkey from a parent event or CommentPointer.
8
+ * Returns undefined if the pubkey is not available.
9
+ */
10
+ function getParentPubkey(parent) {
11
+ if (isEvent(parent))
12
+ return parent.pubkey;
13
+ if (isCommentEventPointer(parent))
14
+ return parent.pubkey;
15
+ if (isCommentAddressPointer(parent))
16
+ return parent.pubkey;
17
+ // CommentExternalPointer doesn't have a pubkey
18
+ return undefined;
19
+ }
20
+ /**
21
+ * Creates a comment on an event or CommentPointer and publishes it to:
22
+ * - The parent event's author's inboxes (if the author exists and pubkey is available)
23
+ * - The current user's outboxes
24
+ */
25
+ export function CreateComment(parent, content, options) {
26
+ return async ({ factory, user, publish, events, sign }) => {
27
+ // Get the parent author's pubkey from the pointer/event (without loading the full event)
28
+ const parentAuthorPubkey = getParentPubkey(parent);
29
+ // Get the parent author's inboxes in parallel with resolving the event
30
+ const [parentAuthorInboxes, userOutboxes] = await Promise.all([
31
+ // Get inboxes if we have a pubkey and it's different from current user
32
+ parentAuthorPubkey ? castUser(parentAuthorPubkey, events).inboxes$.$first(1_000, undefined) : undefined,
33
+ // Get the current user's outboxes
34
+ user.outboxes$.$first(1_000, undefined),
35
+ ]);
36
+ // Create and sign the comment
37
+ const comment = await factory.create(CommentBlueprint, parent, content, options).then(sign);
38
+ // Combine all relay lists (remove duplicates)
39
+ const relays = relaySet(parentAuthorInboxes, userOutboxes);
40
+ // Publish to all relays (inboxes and outboxes)
41
+ await publish(comment, relays.length > 0 ? relays : undefined);
42
+ };
43
+ }
@@ -1,8 +1,8 @@
1
1
  import { ProfilePointer } from "applesauce-core/helpers/pointers";
2
- import { Action } from "../action-hub.js";
2
+ import { Action } from "../action-runner.js";
3
3
  /** An action that adds a pubkey to a users contacts event */
4
- export declare function FollowUser(pubkey: string, relay?: string, hidden?: boolean): Action;
4
+ export declare function FollowUser(user: string | ProfilePointer): Action;
5
5
  /** An action that removes a pubkey from a users contacts event */
6
- export declare function UnfollowUser(user: string | ProfilePointer, hidden?: boolean): Action;
6
+ export declare function UnfollowUser(user: string | ProfilePointer): Action;
7
7
  /** An action that creates a new kind 3 contacts lists, throws if a contact list already exists */
8
8
  export declare function NewContacts(pubkeys?: (string | ProfilePointer)[]): Action;
@@ -1,40 +1,40 @@
1
1
  import { kinds } from "applesauce-core/helpers/event";
2
- import { modifyHiddenTags, modifyPublicTags } from "applesauce-core/operations";
2
+ import { modifyPublicTags } from "applesauce-core/operations";
3
3
  import { addProfilePointerTag, removeProfilePointerTag } from "applesauce-core/operations/tag/common";
4
- /** An action that adds a pubkey to a users contacts event */
5
- export function FollowUser(pubkey, relay, hidden = false) {
6
- return async function* ({ events, factory, self }) {
7
- let contacts = events.getReplaceable(kinds.Contacts, self);
8
- const pointer = { pubkey, relays: relay ? [relay] : undefined };
9
- const operation = addProfilePointerTag(pointer);
10
- let draft;
11
- // No contact list, create one
12
- if (!contacts)
13
- draft = await factory.build({ kind: kinds.Contacts }, hidden ? modifyHiddenTags(operation) : modifyPublicTags(operation));
14
- else
15
- draft = await factory.modifyTags(contacts, hidden ? { hidden: operation } : operation);
16
- yield await factory.sign(draft);
4
+ import { firstValueFrom, of, timeout } from "rxjs";
5
+ function ModifyContactsEvent(operations) {
6
+ return async ({ events, factory, user, publish, sign }) => {
7
+ const [event, outboxes] = await Promise.all([
8
+ firstValueFrom(events.replaceable(kinds.Contacts, user.pubkey).pipe(timeout({ first: 1000, with: () => of(undefined) }))),
9
+ user.outboxes$.$first(1000, undefined),
10
+ ]);
11
+ const operation = modifyPublicTags(...operations);
12
+ // Modify or build new event
13
+ const signed = event
14
+ ? await factory.modify(event, operation).then(sign)
15
+ : await factory.build({ kind: kinds.Contacts }, operation).then(sign);
16
+ // Publish the event to the user's outboxes
17
+ await publish(signed, outboxes);
17
18
  };
18
19
  }
20
+ /** An action that adds a pubkey to a users contacts event */
21
+ export function FollowUser(user) {
22
+ return ModifyContactsEvent([addProfilePointerTag(user)]);
23
+ }
19
24
  /** An action that removes a pubkey from a users contacts event */
20
- export function UnfollowUser(user, hidden = false) {
21
- return async function* ({ events, factory, self }) {
22
- const contacts = events.getReplaceable(kinds.Contacts, self);
23
- // Unable to find a contacts event, so we can't unfollow
24
- if (!contacts)
25
- return;
26
- const operation = removeProfilePointerTag(user);
27
- const draft = await factory.modifyTags(contacts, hidden ? { hidden: operation } : operation);
28
- yield await factory.sign(draft);
29
- };
25
+ export function UnfollowUser(user) {
26
+ return ModifyContactsEvent([removeProfilePointerTag(user)]);
30
27
  }
31
28
  /** An action that creates a new kind 3 contacts lists, throws if a contact list already exists */
32
29
  export function NewContacts(pubkeys) {
33
- return async function* ({ events, factory, self }) {
30
+ return async ({ events, factory, self, user, publish, sign }) => {
34
31
  const contacts = events.getReplaceable(kinds.Contacts, self);
35
32
  if (contacts)
36
33
  throw new Error("Contact list already exists");
37
- const draft = await factory.build({ kind: kinds.Contacts }, pubkeys ? modifyPublicTags(...pubkeys.map((p) => addProfilePointerTag(p))) : undefined);
38
- yield await factory.sign(draft);
34
+ const signed = await factory
35
+ .build({ kind: kinds.Contacts }, pubkeys ? modifyPublicTags(...pubkeys.map((p) => addProfilePointerTag(p))) : undefined)
36
+ .then(sign);
37
+ // Publish the event to the user's outboxes
38
+ await publish(signed, await user.outboxes$.$first(1000, undefined));
39
39
  };
40
40
  }
@@ -0,0 +1,7 @@
1
+ import { Action } from "../action-runner.js";
2
+ /** An action that adds a relay to the 10050 DM relays event */
3
+ export declare function AddDirectMessageRelay(relay: string | string[]): Action;
4
+ /** An action that removes a relay from the 10050 DM relays event */
5
+ export declare function RemoveDirectMessageRelay(relay: string | string[]): Action;
6
+ /** Creates a new DM relays event */
7
+ export declare function NewDirectMessageRelays(relays?: string[]): Action;
@@ -0,0 +1,47 @@
1
+ import { firstValueFrom } from "applesauce-core";
2
+ import { kinds } from "applesauce-core/helpers/event";
3
+ import { addRelayTag, removeRelayTag } from "applesauce-core/operations/tag/relay";
4
+ import { modifyPublicTags } from "applesauce-core/operations/tags";
5
+ import { of, timeout } from "rxjs";
6
+ function ModifyDirectMessageRelaysEvent(operations) {
7
+ return async ({ events, factory, self, user, publish, sign }) => {
8
+ const [event, outboxes] = await Promise.all([
9
+ firstValueFrom(events
10
+ .replaceable(kinds.DirectMessageRelaysList, self)
11
+ .pipe(timeout({ first: 1000, with: () => of(undefined) }))),
12
+ user.outboxes$.$first(1000, undefined),
13
+ ]);
14
+ const operation = modifyPublicTags(...operations);
15
+ // Modify or build new event
16
+ const signed = event
17
+ ? await factory.modify(event, operation).then(sign)
18
+ : await factory.build({ kind: kinds.DirectMessageRelaysList }, operation).then(sign);
19
+ // Publish the event to the user's outboxes
20
+ await publish(signed, outboxes);
21
+ };
22
+ }
23
+ /** An action that adds a relay to the 10050 DM relays event */
24
+ export function AddDirectMessageRelay(relay) {
25
+ return ModifyDirectMessageRelaysEvent([
26
+ ...(Array.isArray(relay) ? relay.map((r) => addRelayTag(r)) : [addRelayTag(relay)]),
27
+ ]);
28
+ }
29
+ /** An action that removes a relay from the 10050 DM relays event */
30
+ export function RemoveDirectMessageRelay(relay) {
31
+ return ModifyDirectMessageRelaysEvent([
32
+ ...(Array.isArray(relay) ? relay.map((r) => removeRelayTag(r)) : [removeRelayTag(relay)]),
33
+ ]);
34
+ }
35
+ /** Creates a new DM relays event */
36
+ export function NewDirectMessageRelays(relays) {
37
+ return async ({ events, factory, self, user, publish, sign }) => {
38
+ const dmRelays = events.getReplaceable(kinds.DirectMessageRelaysList, self);
39
+ if (dmRelays)
40
+ throw new Error("DM relays event already exists");
41
+ const operations = relays?.map((r) => addRelayTag(r)) ?? [];
42
+ const signed = await factory
43
+ .build({ kind: kinds.DirectMessageRelaysList }, modifyPublicTags(...operations))
44
+ .then(sign);
45
+ await publish(signed, await user.outboxes$.$first(1000, undefined));
46
+ };
47
+ }
@@ -1,5 +1,5 @@
1
1
  import { AddressPointer } from "applesauce-core/helpers/pointers";
2
- import { Action } from "../action-hub.js";
2
+ import { Action } from "../action-runner.js";
3
3
  /** An action that adds a relay to the 10012 favorite relays event */
4
4
  export declare function AddFavoriteRelay(relay: string | string[], hidden?: boolean): Action;
5
5
  /** An action that removes a relay from the 10012 favorite relays event */
@@ -1,52 +1,50 @@
1
- import { FAVORITE_RELAYS_KIND } from "applesauce-common/helpers/lists";
1
+ import { FAVORITE_RELAYS_KIND } from "applesauce-common/helpers/relay-list";
2
2
  import { modifyHiddenTags, modifyPublicTags } from "applesauce-core/operations";
3
3
  import { addAddressPointerTag, removeAddressPointerTag } from "applesauce-core/operations/tag/common";
4
4
  import { addRelayTag, removeRelayTag } from "applesauce-core/operations/tag/relay";
5
- function getFavoriteRelaysEvent(events, self) {
6
- const event = events.getReplaceable(FAVORITE_RELAYS_KIND, self);
7
- if (!event)
8
- throw new Error("Can't find favorite relays event");
9
- return event;
5
+ function ModifyFavoriteRelaysEvent(operations, hidden = false) {
6
+ return async ({ factory, user, publish, sign }) => {
7
+ const [event, outboxes] = await Promise.all([
8
+ user.replaceable(FAVORITE_RELAYS_KIND).$first(1000, undefined),
9
+ user.outboxes$.$first(1000, undefined),
10
+ ]);
11
+ // create the event operation
12
+ const operation = hidden ? modifyHiddenTags(...operations) : modifyPublicTags(...operations);
13
+ // Modify or build new event
14
+ const signed = event
15
+ ? await factory.modify(event, operation).then(sign)
16
+ : await factory.build({ kind: FAVORITE_RELAYS_KIND }, operation).then(sign);
17
+ // Publish the event to the user's outboxes
18
+ await publish(signed, outboxes);
19
+ };
10
20
  }
11
21
  /** An action that adds a relay to the 10012 favorite relays event */
12
22
  export function AddFavoriteRelay(relay, hidden = false) {
13
- return async function* ({ events, factory, self }) {
14
- const favorites = getFavoriteRelaysEvent(events, self);
15
- const operation = Array.isArray(relay) ? relay.map((r) => addRelayTag(r)) : addRelayTag(relay);
16
- const draft = await factory.modifyTags(favorites, hidden ? { hidden: operation } : operation);
17
- yield await factory.sign(draft);
18
- };
23
+ if (typeof relay === "string")
24
+ relay = [relay];
25
+ return ModifyFavoriteRelaysEvent([...relay.map((r) => addRelayTag(r))], hidden);
19
26
  }
20
27
  /** An action that removes a relay from the 10012 favorite relays event */
21
28
  export function RemoveFavoriteRelay(relay, hidden = false) {
22
- return async function* ({ events, factory, self }) {
23
- const favorites = getFavoriteRelaysEvent(events, self);
24
- const operation = Array.isArray(relay) ? relay.map((r) => removeRelayTag(r)) : removeRelayTag(relay);
25
- const draft = await factory.modifyTags(favorites, hidden ? { hidden: operation } : operation);
26
- yield await factory.sign(draft);
27
- };
29
+ if (typeof relay === "string")
30
+ relay = [relay];
31
+ return ModifyFavoriteRelaysEvent([...relay.map((r) => removeRelayTag(r))], hidden);
28
32
  }
29
33
  /** An action that adds a relay set to the 10012 favorite relays event */
30
34
  export function AddFavoriteRelaySet(addr, hidden = false) {
31
- return async function* ({ events, factory, self }) {
32
- const favorites = getFavoriteRelaysEvent(events, self);
33
- const operation = Array.isArray(addr) ? addr.map((a) => addAddressPointerTag(a)) : addAddressPointerTag(addr);
34
- const draft = await factory.modifyTags(favorites, hidden ? { hidden: operation } : operation);
35
- yield await factory.sign(draft);
36
- };
35
+ if (!Array.isArray(addr))
36
+ addr = [addr];
37
+ return ModifyFavoriteRelaysEvent([...addr.map((a) => addAddressPointerTag(a))], hidden);
37
38
  }
38
39
  /** An action that removes a relay set from the 10012 favorite relays event */
39
40
  export function RemoveFavoriteRelaySet(addr, hidden = false) {
40
- return async function* ({ events, factory, self }) {
41
- const favorites = getFavoriteRelaysEvent(events, self);
42
- const operation = Array.isArray(addr) ? addr.map((a) => removeAddressPointerTag(a)) : removeAddressPointerTag(addr);
43
- const draft = await factory.modifyTags(favorites, hidden ? { hidden: operation } : operation);
44
- yield await factory.sign(draft);
45
- };
41
+ if (!Array.isArray(addr))
42
+ addr = [addr];
43
+ return ModifyFavoriteRelaysEvent([...addr.map((a) => removeAddressPointerTag(a))], hidden);
46
44
  }
47
45
  /** Creates a new favorite relays event */
48
46
  export function NewFavoriteRelays(relays, sets) {
49
- return async function* ({ events, factory, self }) {
47
+ return async ({ events, factory, self, user, publish, sign }) => {
50
48
  const favorites = events.getReplaceable(FAVORITE_RELAYS_KIND, self);
51
49
  if (favorites)
52
50
  throw new Error("Favorite relays event already exists");
@@ -70,7 +68,10 @@ export function NewFavoriteRelays(relays, sets) {
70
68
  if (sets?.hidden)
71
69
  hiddenOperations.push(...(sets?.hidden ?? []).map((s) => addAddressPointerTag(s)));
72
70
  }
73
- const draft = await factory.build({ kind: FAVORITE_RELAYS_KIND }, publicOperations.length ? modifyPublicTags(...publicOperations) : undefined, hiddenOperations.length ? modifyHiddenTags(...hiddenOperations) : undefined);
74
- yield await factory.sign(draft);
71
+ const signed = await factory
72
+ .build({ kind: FAVORITE_RELAYS_KIND }, publicOperations.length ? modifyPublicTags(...publicOperations) : undefined, hiddenOperations.length ? modifyHiddenTags(...hiddenOperations) : undefined)
73
+ .then(sign);
74
+ // Publish the event to the user's outboxes
75
+ await publish(signed, await user.outboxes$.$first(1000, undefined));
75
76
  };
76
77
  }
@@ -1,6 +1,6 @@
1
1
  import { NostrEvent } from "applesauce-core/helpers/event";
2
2
  import { ProfilePointer } from "applesauce-core/helpers/pointers";
3
- import { Action } from "../action-hub.js";
3
+ import { Action } from "../action-runner.js";
4
4
  /**
5
5
  * An action that creates a new follow set
6
6
  * @throws if a follow set already exists
@@ -16,7 +16,6 @@ export declare function CreateFollowSet(title: string, options?: {
16
16
  * @param pubkey the pubkey to add to the set
17
17
  * @param identifier the "d" tag of the follow set
18
18
  * @param hidden set to true to add to hidden follows
19
- * @throws if the follow set does not exist
20
19
  */
21
20
  export declare function AddUserToFollowSet(pubkey: (string | ProfilePointer)[] | string | ProfilePointer, identifier: NostrEvent | string, hidden?: boolean): Action;
22
21
  /**
@@ -24,7 +23,6 @@ export declare function AddUserToFollowSet(pubkey: (string | ProfilePointer)[] |
24
23
  * @param pubkey the pubkey to remove from the set
25
24
  * @param identifier the "d" tag of the follow set
26
25
  * @param hidden set to true to remove from hidden follows
27
- * @throws if the follow set does not exist
28
26
  */
29
27
  export declare function RemoveUserFromFollowSet(pubkey: (string | ProfilePointer)[] | string | ProfilePointer, identifier: NostrEvent | string, hidden?: boolean): Action;
30
28
  /**
@@ -1,27 +1,37 @@
1
1
  import * as List from "applesauce-common/operations/list";
2
2
  import { kinds } from "applesauce-core/helpers/event";
3
+ import { getReplaceableIdentifier } from "applesauce-core/helpers/event";
3
4
  import { modifyHiddenTags, modifyPublicTags } from "applesauce-core/operations";
4
5
  import { addProfilePointerTag, removeProfilePointerTag } from "applesauce-core/operations/tag/common";
5
- function getFollowSetEvent(events, self, identifier) {
6
- const set = typeof identifier === "string" ? events.getReplaceable(kinds.Followsets, self, identifier) : identifier;
7
- if (!set)
8
- throw new Error("Can't find follow set");
9
- if (set.kind !== kinds.Followsets)
10
- throw new Error("Event is not a follow set");
11
- return set;
6
+ function ModifyFollowSetEvent(operations, set, hidden = false) {
7
+ const identifier = typeof set === "string" ? set : getReplaceableIdentifier(set);
8
+ return async ({ factory, user, publish, sign }) => {
9
+ const [event, outboxes] = await Promise.all([
10
+ user.replaceable(kinds.Followsets, identifier).$first(1000, undefined),
11
+ user.outboxes$.$first(1000, undefined),
12
+ ]);
13
+ const operation = hidden ? modifyHiddenTags(...operations) : modifyPublicTags(...operations);
14
+ // Modify or build new event
15
+ const signed = event
16
+ ? await factory.modify(event, operation).then(sign)
17
+ : await factory.build({ kind: kinds.Followsets }, operation).then(sign);
18
+ // Publish the event to the user's outboxes
19
+ await publish(signed, outboxes);
20
+ };
12
21
  }
13
22
  /**
14
23
  * An action that creates a new follow set
15
24
  * @throws if a follow set already exists
16
25
  */
17
26
  export function CreateFollowSet(title, options) {
18
- return async function* ({ factory }) {
27
+ return async ({ factory, user, publish }) => {
19
28
  const draft = await factory.build({ kind: kinds.Followsets },
20
29
  // set list information
21
30
  List.setTitle(title), options?.description ? List.setDescription(options.description) : undefined, options?.image ? List.setImage(options.image) : undefined,
22
31
  // add pubkey tags
23
32
  options?.public ? modifyPublicTags(...options.public.map((p) => addProfilePointerTag(p))) : undefined, options?.hidden ? modifyHiddenTags(...options.hidden.map((p) => addProfilePointerTag(p))) : undefined);
24
- yield await factory.sign(draft);
33
+ const signed = await factory.sign(draft);
34
+ await publish(signed, await user.outboxes$.$first(1000, undefined));
25
35
  };
26
36
  }
27
37
  /**
@@ -29,34 +39,18 @@ export function CreateFollowSet(title, options) {
29
39
  * @param pubkey the pubkey to add to the set
30
40
  * @param identifier the "d" tag of the follow set
31
41
  * @param hidden set to true to add to hidden follows
32
- * @throws if the follow set does not exist
33
42
  */
34
43
  export function AddUserToFollowSet(pubkey, identifier, hidden = false) {
35
- return async function* ({ events, factory, self }) {
36
- const follows = getFollowSetEvent(events, self, identifier);
37
- const operations = Array.isArray(pubkey)
38
- ? pubkey.map((p) => addProfilePointerTag(p))
39
- : addProfilePointerTag(pubkey);
40
- const draft = await factory.modifyTags(follows, hidden ? { hidden: operations } : operations);
41
- yield await factory.sign(draft);
42
- };
44
+ return ModifyFollowSetEvent(Array.isArray(pubkey) ? pubkey.map((p) => addProfilePointerTag(p)) : [addProfilePointerTag(pubkey)], identifier, hidden);
43
45
  }
44
46
  /**
45
47
  * An action that removes a pubkey from a follow set
46
48
  * @param pubkey the pubkey to remove from the set
47
49
  * @param identifier the "d" tag of the follow set
48
50
  * @param hidden set to true to remove from hidden follows
49
- * @throws if the follow set does not exist
50
51
  */
51
52
  export function RemoveUserFromFollowSet(pubkey, identifier, hidden = false) {
52
- return async function* ({ events, factory, self }) {
53
- const follows = getFollowSetEvent(events, self, identifier);
54
- const operations = Array.isArray(pubkey)
55
- ? pubkey.map((p) => removeProfilePointerTag(p))
56
- : removeProfilePointerTag(pubkey);
57
- const draft = await factory.modifyTags(follows, hidden ? { hidden: operations } : operations);
58
- yield await factory.sign(draft);
59
- };
53
+ return ModifyFollowSetEvent(Array.isArray(pubkey) ? pubkey.map((p) => removeProfilePointerTag(p)) : [removeProfilePointerTag(pubkey)], identifier, hidden);
60
54
  }
61
55
  /**
62
56
  * An action that updates the title, description, or image of a follow set
@@ -65,9 +59,16 @@ export function RemoveUserFromFollowSet(pubkey, identifier, hidden = false) {
65
59
  * @throws if the follow set does not exist
66
60
  */
67
61
  export function UpdateFollowSetInformation(identifier, info) {
68
- return async function* ({ events, factory, self }) {
69
- const follows = getFollowSetEvent(events, self, identifier);
70
- const draft = await factory.modify(follows, info?.title ? List.setTitle(info.title) : undefined, info?.description ? List.setDescription(info.description) : undefined, info?.image ? List.setImage(info.image) : undefined);
71
- yield await factory.sign(draft);
62
+ return async ({ factory, sign, user, publish }) => {
63
+ const [event, outboxes] = await Promise.all([
64
+ user.replaceable(kinds.Followsets, identifier).$first(1000, undefined),
65
+ user.outboxes$.$first(1000, undefined),
66
+ ]);
67
+ if (!event)
68
+ throw new Error("Follow set not found");
69
+ const signed = await factory
70
+ .modify(event, info?.title ? List.setTitle(info.title) : undefined, info?.description ? List.setDescription(info.description) : undefined, info?.image ? List.setImage(info.image) : undefined)
71
+ .then(sign);
72
+ await publish(signed, outboxes);
72
73
  };
73
74
  }
@@ -3,8 +3,9 @@ export * from "./blocked-relays.js";
3
3
  export * from "./blossom.js";
4
4
  export * from "./bookmarks.js";
5
5
  export * from "./calendar.js";
6
+ export * from "./comment.js";
6
7
  export * from "./contacts.js";
7
- export * from "./dm-relays.js";
8
+ export * from "./direct-message-relays.js";
8
9
  export * from "./favorite-relays.js";
9
10
  export * from "./follow-sets.js";
10
11
  export * from "./legacy-messages.js";
@@ -3,8 +3,9 @@ export * from "./blocked-relays.js";
3
3
  export * from "./blossom.js";
4
4
  export * from "./bookmarks.js";
5
5
  export * from "./calendar.js";
6
+ export * from "./comment.js";
6
7
  export * from "./contacts.js";
7
- export * from "./dm-relays.js";
8
+ export * from "./direct-message-relays.js";
8
9
  export * from "./favorite-relays.js";
9
10
  export * from "./follow-sets.js";
10
11
  export * from "./legacy-messages.js";
@@ -1,6 +1,6 @@
1
- import { NostrEvent } from "applesauce-core/helpers/event";
2
1
  import { LegacyMessageBlueprintOptions } from "applesauce-common/blueprints";
3
- import { Action } from "../action-hub.js";
2
+ import { NostrEvent } from "applesauce-core/helpers/event";
3
+ import { Action } from "../action-runner.js";
4
4
  /** Sends a legacy NIP-04 message to a recipient */
5
5
  export declare function SendLegacyMessage(recipient: string, message: string, opts?: LegacyMessageBlueprintOptions): Action;
6
6
  /** Send a reply to a legacy message */
@@ -1,20 +1,35 @@
1
- import { kinds } from "applesauce-core/helpers/event";
2
1
  import { LegacyMessageBlueprint, LegacyMessageReplyBlueprint, } from "applesauce-common/blueprints";
2
+ import { castUser } from "applesauce-common/casts";
3
+ import { kinds } from "applesauce-core/helpers/event";
3
4
  /** Sends a legacy NIP-04 message to a recipient */
4
5
  export function SendLegacyMessage(recipient, message, opts) {
5
- return async function* ({ factory }) {
6
- const draft = await factory.create(LegacyMessageBlueprint, recipient, message, opts);
7
- // Return the signed message
8
- yield await factory.sign(draft);
6
+ return async ({ factory, sign, publish, events }) => {
7
+ const signed = await factory.create(LegacyMessageBlueprint, recipient, message, opts).then(sign);
8
+ // Get the recipient's inbox relays
9
+ const receiver = castUser(recipient, events);
10
+ const [inboxes, directMessageRelays] = await Promise.all([
11
+ receiver.inboxes$.$first(1_000, undefined),
12
+ receiver.directMessageRelays$.$first(1_000, undefined),
13
+ ]);
14
+ // Use the dm relays or inboxes as the inbox relays for the recipient
15
+ const relays = directMessageRelays ?? inboxes ?? undefined;
16
+ await publish(signed, relays);
9
17
  };
10
18
  }
11
19
  /** Send a reply to a legacy message */
12
20
  export function ReplyToLegacyMessage(parent, message, opts) {
13
- return async function* ({ factory }) {
21
+ return async ({ factory, sign, publish, events }) => {
14
22
  if (parent.kind !== kinds.EncryptedDirectMessage)
15
23
  throw new Error("Legacy messages can only reply to other legacy messages");
16
- const draft = await factory.create(LegacyMessageReplyBlueprint, parent, message, opts);
17
- // Return the signed message
18
- yield await factory.sign(draft);
24
+ const signed = await factory.create(LegacyMessageReplyBlueprint, parent, message, opts).then(sign);
25
+ // Get the recipient's inbox relays (the sender of the parent message)
26
+ const receiver = castUser(parent.pubkey, events);
27
+ const [inboxes, directMessageRelays] = await Promise.all([
28
+ receiver.inboxes$.$first(1_000, undefined),
29
+ receiver.directMessageRelays$.$first(1_000, undefined),
30
+ ]);
31
+ // Use the dm relays or inboxes as the inbox relays for the recipient
32
+ const relays = directMessageRelays ?? inboxes ?? undefined;
33
+ await publish(signed, relays);
19
34
  };
20
35
  }
@@ -1,6 +1,6 @@
1
1
  import { NostrEvent } from "applesauce-core/helpers/event";
2
2
  import { AddressPointer } from "applesauce-core/helpers/pointers";
3
- import { Action } from "../action-hub.js";
3
+ import { Action } from "../action-runner.js";
4
4
  /** An action that sets or removes a NIP-15 list information */
5
5
  export declare function SetListMetadata(list: NostrEvent | AddressPointer, info: {
6
6
  title?: string;
@@ -10,9 +10,11 @@ function getList(events, address) {
10
10
  }
11
11
  /** An action that sets or removes a NIP-15 list information */
12
12
  export function SetListMetadata(list, info) {
13
- return async function* ({ events, factory }) {
13
+ return async ({ events, factory, sign, publish }) => {
14
14
  list = getList(events, list);
15
- const draft = await factory.modify(list, List.setTitle(info.title ?? null), List.setDescription(info.description ?? null), List.setImage(info.image ?? null));
16
- yield await factory.sign(draft);
15
+ const signed = await factory
16
+ .modify(list, List.setTitle(info.title ?? null), List.setDescription(info.description ?? null), List.setImage(info.image ?? null))
17
+ .then(sign);
18
+ await publish(signed);
17
19
  };
18
20
  }
@@ -1,4 +1,4 @@
1
- import { Action } from "../action-hub.js";
1
+ import { Action } from "../action-runner.js";
2
2
  /** An action to create a new kind 10002 relay list event */
3
3
  export declare function CreateMailboxes(inboxes: string[], outboxes: string[]): Action;
4
4
  /** An action to add an inbox relay to the kind 10002 relay list */
@@ -1,65 +1,67 @@
1
+ import { getOutboxes, relaySet } from "applesauce-core/helpers";
1
2
  import { kinds } from "applesauce-core/helpers/event";
2
3
  import { addInboxRelay, addOutboxRelay, removeInboxRelay, removeOutboxRelay, } from "applesauce-core/operations/mailboxes";
3
4
  /** An action to create a new kind 10002 relay list event */
4
5
  export function CreateMailboxes(inboxes, outboxes) {
5
- return async function* ({ events, factory, self }) {
6
- const mailboxes = events.getReplaceable(kinds.RelayList, self);
6
+ return async ({ factory, user, publish, sign }) => {
7
+ const mailboxes = await user.replaceable(kinds.RelayList).$first(1000, undefined);
7
8
  if (mailboxes)
8
9
  throw new Error("Mailbox event already exists");
9
- const draft = await factory.build({ kind: kinds.RelayList }, ...inboxes.map(addInboxRelay), ...outboxes.map(addOutboxRelay));
10
- const signed = await factory.sign(draft);
11
- yield signed;
10
+ const signed = await factory
11
+ .build({ kind: kinds.RelayList }, ...inboxes.map(addInboxRelay), ...outboxes.map(addOutboxRelay))
12
+ .then(sign);
13
+ await publish(signed, relaySet(getOutboxes(signed)));
12
14
  };
13
15
  }
14
16
  /** An action to add an inbox relay to the kind 10002 relay list */
15
17
  export function AddInboxRelay(relay) {
16
- return async function* ({ events, factory, self }) {
18
+ return async ({ factory, user, publish, sign }) => {
17
19
  if (typeof relay === "string")
18
20
  relay = [relay];
19
- const mailboxes = events.getReplaceable(kinds.RelayList, self);
20
- const draft = mailboxes
21
- ? await factory.modify(mailboxes, ...relay.map(addInboxRelay))
22
- : await factory.build({ kind: kinds.RelayList }, ...relay.map(addInboxRelay));
23
- const signed = await factory.sign(draft);
24
- yield signed;
21
+ const mailboxes = await user.replaceable(kinds.RelayList).$first(1000, undefined);
22
+ const signed = mailboxes
23
+ ? await factory.modify(mailboxes, ...relay.map(addInboxRelay)).then(sign)
24
+ : await factory.build({ kind: kinds.RelayList }, ...relay.map(addInboxRelay)).then(sign);
25
+ // Publish the event to the old and new outboxes
26
+ await publish(signed, relaySet(getOutboxes(signed), mailboxes && getOutboxes(mailboxes)));
25
27
  };
26
28
  }
27
29
  /** An action to remove an inbox relay from the kind 10002 relay list */
28
30
  export function RemoveInboxRelay(relay) {
29
- return async function* ({ events, factory, self }) {
31
+ return async ({ factory, user, publish, sign }) => {
30
32
  if (typeof relay === "string")
31
33
  relay = [relay];
32
- const mailboxes = events.getReplaceable(kinds.RelayList, self);
34
+ const mailboxes = await user.replaceable(kinds.RelayList).$first(1000, undefined);
33
35
  if (!mailboxes)
34
36
  return;
35
- const draft = await factory.modify(mailboxes, ...relay.map(removeInboxRelay));
36
- const signed = await factory.sign(draft);
37
- yield signed;
37
+ const signed = await factory.modify(mailboxes, ...relay.map(removeInboxRelay)).then(sign);
38
+ // Publish to outboxes
39
+ await publish(signed, getOutboxes(signed));
38
40
  };
39
41
  }
40
42
  /** An action to add an outbox relay to the kind 10002 relay list */
41
43
  export function AddOutboxRelay(relay) {
42
- return async function* ({ events, factory, self }) {
44
+ return async ({ factory, user, publish, sign }) => {
43
45
  if (typeof relay === "string")
44
46
  relay = [relay];
45
- const mailboxes = events.getReplaceable(kinds.RelayList, self);
46
- const draft = mailboxes
47
- ? await factory.modify(mailboxes, ...relay.map(addOutboxRelay))
48
- : await factory.build({ kind: kinds.RelayList }, ...relay.map(addOutboxRelay));
49
- const signed = await factory.sign(draft);
50
- yield signed;
47
+ const mailboxes = await user.replaceable(kinds.RelayList).$first(1000, undefined);
48
+ const signed = mailboxes
49
+ ? await factory.modify(mailboxes, ...relay.map(addOutboxRelay)).then(sign)
50
+ : await factory.build({ kind: kinds.RelayList }, ...relay.map(addOutboxRelay)).then(sign);
51
+ // Publish to outboxes
52
+ await publish(signed, getOutboxes(signed));
51
53
  };
52
54
  }
53
55
  /** An action to remove an outbox relay from the kind 10002 relay list */
54
56
  export function RemoveOutboxRelay(relay) {
55
- return async function* ({ events, factory, self }) {
57
+ return async ({ factory, user, publish, sign }) => {
56
58
  if (typeof relay === "string")
57
59
  relay = [relay];
58
- const mailboxes = events.getReplaceable(kinds.RelayList, self);
60
+ const mailboxes = await user.replaceable(kinds.RelayList).$first(1000, undefined);
59
61
  if (!mailboxes)
60
62
  return;
61
- const draft = await factory.modify(mailboxes, ...relay.map(removeOutboxRelay));
62
- const signed = await factory.sign(draft);
63
- yield signed;
63
+ const signed = await factory.modify(mailboxes, ...relay.map(removeOutboxRelay)).then(sign);
64
+ // Publish to outboxes
65
+ await publish(signed, getOutboxes(signed));
64
66
  };
65
67
  }