diff --git a/nostr-java-api/src/main/java/nostr/api/EventNostr.java b/nostr-java-api/src/main/java/nostr/api/EventNostr.java new file mode 100644 index 000000000..bb604a113 --- /dev/null +++ b/nostr-java-api/src/main/java/nostr/api/EventNostr.java @@ -0,0 +1,57 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package nostr.api; + +import java.util.Map; + +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; +import nostr.base.PublicKey; +import nostr.event.impl.GenericEvent; +import nostr.id.Identity; + +/** + * @author guilhermegps + */ +public abstract class EventNostr extends Nostr { + + @Getter + @Setter + private T event; + + @Getter + private PublicKey recipient; + + public EventNostr sign() { + super.sign(getSender(), event); + + return this; + } + + public T send() { + super.send(this.event); + + return this.event; + } + + public T send(Map relays) { + super.setRelays(relays); + + return send(); + } + + public EventNostr setSender(@NonNull Identity sender) { + super.setSender(sender); + + return this; + } + + public EventNostr setRecipient(@NonNull PublicKey recipient) { + this.recipient = recipient; + + return this; + } +} diff --git a/nostr-java-api/src/main/java/nostr/api/NIP01.java b/nostr-java-api/src/main/java/nostr/api/NIP01.java index e71550a21..762f93ace 100644 --- a/nostr-java-api/src/main/java/nostr/api/NIP01.java +++ b/nostr-java-api/src/main/java/nostr/api/NIP01.java @@ -5,27 +5,31 @@ package nostr.api; import java.util.List; + import lombok.NonNull; -import nostr.api.factory.impl.NIP01.CloseMessageFactory; -import nostr.api.factory.impl.NIP01.EoseMessageFactory; -import nostr.api.factory.impl.NIP01.EventMessageFactory; -import nostr.api.factory.impl.NIP01.EventTagFactory; -import nostr.api.factory.impl.NIP01.FiltersFactory; -import nostr.api.factory.impl.NIP01.MetadataEventFactory; -import nostr.api.factory.impl.NIP01.NoticeMessageFactory; -import nostr.api.factory.impl.NIP01.PubKeyTagFactory; -import nostr.api.factory.impl.NIP01.ReqMessageFactory; -import nostr.api.factory.impl.NIP01.TextNoteEventFactory; +import nostr.api.factory.impl.NIP01Impl.AddressTagFactory; +import nostr.api.factory.impl.NIP01Impl.CloseMessageFactory; +import nostr.api.factory.impl.NIP01Impl.EoseMessageFactory; +import nostr.api.factory.impl.NIP01Impl.EphemeralEventFactory; +import nostr.api.factory.impl.NIP01Impl.EventMessageFactory; +import nostr.api.factory.impl.NIP01Impl.EventTagFactory; +import nostr.api.factory.impl.NIP01Impl.FiltersFactory; +import nostr.api.factory.impl.NIP01Impl.IdentifierTagFactory; +import nostr.api.factory.impl.NIP01Impl.MetadataEventFactory; +import nostr.api.factory.impl.NIP01Impl.NoticeMessageFactory; +import nostr.api.factory.impl.NIP01Impl.ParameterizedReplaceableEventFactory; +import nostr.api.factory.impl.NIP01Impl.PubKeyTagFactory; +import nostr.api.factory.impl.NIP01Impl.ReplaceableEventFactory; +import nostr.api.factory.impl.NIP01Impl.ReqMessageFactory; +import nostr.api.factory.impl.NIP01Impl.TextNoteEventFactory; import nostr.base.IEvent; import nostr.base.PublicKey; import nostr.base.Relay; import nostr.base.UserProfile; import nostr.event.BaseTag; import nostr.event.Marker; +import nostr.event.NIP01Event; import nostr.event.impl.Filters; -import nostr.event.impl.MetadataEvent; -import nostr.event.impl.ParameterizedReplaceableEvent; -import nostr.event.impl.TextNoteEvent; import nostr.event.list.EventList; import nostr.event.list.GenericTagQueryList; import nostr.event.list.KindList; @@ -40,12 +44,17 @@ import nostr.event.tag.IdentifierTag; import nostr.event.tag.PubKeyTag; import nostr.id.IIdentity; +import nostr.id.Identity; /** * * @author eric */ -public class NIP01 extends Nostr { +public class NIP01 extends EventNostr { + + public NIP01(@NonNull Identity sender) { + setSender(sender); + } /** * Create a NIP01 text note event without tags @@ -53,12 +62,18 @@ public class NIP01 extends Nostr { * @param content the content of the note * @return the text note without tags */ - public static TextNoteEvent createTextNoteEvent(@NonNull String content) { - return new TextNoteEventFactory(content).create(); + public NIP01 createTextNoteEvent(@NonNull String content) { + var event = new TextNoteEventFactory(getSender(), content).create(); + this.setEvent((T) event); + + return this; } - public static TextNoteEvent createTextNoteEvent(@NonNull IIdentity sender, @NonNull String content) { - return new TextNoteEventFactory(sender, content).create(); + public NIP01 createTextNoteEvent(@NonNull IIdentity sender, @NonNull String content) { + var event = new TextNoteEventFactory(sender, content).create(); + this.setEvent((T) event); + + return this; } /** @@ -68,28 +83,63 @@ public static TextNoteEvent createTextNoteEvent(@NonNull IIdentity sender, @NonN * @param content the content of the note * @return a text note event */ - public static TextNoteEvent createTextNoteEvent(@NonNull List tags, @NonNull String content) { - return new TextNoteEventFactory(tags, content).create(); + public NIP01 createTextNoteEvent(@NonNull List tags, @NonNull String content) { + var sender = getSender(); + var factory = (sender!=null) ? new TextNoteEventFactory(sender, tags, content) : new TextNoteEventFactory(tags, content); + var event = factory.create(); + setEvent((T) event); + + return this; } - public static TextNoteEvent createTextNoteEvent(@NonNull IIdentity sender, @NonNull List tags, @NonNull String content) { - return new TextNoteEventFactory(sender, tags, content).create(); + public NIP01 createMetadataEvent(@NonNull UserProfile profile) { + var sender = getSender(); + var event = (sender!=null) ? new MetadataEventFactory(sender, profile).create() : new MetadataEventFactory(profile).create(); + + this.setEvent((T) event); + return this; } /** - * Create a NIP01 metadata event - * - * @param profile the associated profile - * @return a metadata event associated for the profile + * Create a replaceable event + * @param kind the kind (10000 <= kind < 20000 || kind == 0 || kind == 3) + * @param content the content + * @return */ - public static MetadataEvent createMetadataEvent(@NonNull UserProfile profile) { - return new MetadataEventFactory(profile).create(); + public NIP01 createReplaceableEvent(@NonNull Integer kind, String content) { + var event = new ReplaceableEventFactory(getSender(), kind, content).create(); + + this.setEvent((T) event); + return this; } - - public static MetadataEvent createMetadataEvent(@NonNull IIdentity sender, @NonNull UserProfile profile) { - return new MetadataEventFactory(sender, profile).create(); + + /** + * Create a replaceable event + * @param tags the note's tags + * @param kind the kind (10000 <= kind < 20000 || kind == 0 || kind == 3) + * @param content the note's content + * @return + */ + public NIP01 createReplaceableEvent(@NonNull List tags, @NonNull Integer kind, String content) { + var event = new ReplaceableEventFactory(getSender(), tags, kind, content).create(); + + this.setEvent((T) event); + return this; } + /** + * Create an ephemeral event + * @param kind the kind (20000 <= n < 30000) + * @param content the note's content + * @return + */ + public NIP01 createEphemeralEvent(@NonNull Integer kind, String content) { + var event = new EphemeralEventFactory(getSender(), kind, content).create(); + + this.setEvent((T) event); + return this; + } + /** * Create a NIP01 event tag * @@ -234,44 +284,54 @@ public static NoticeMessage createNoticeMessage(@NonNull String message) { } /** - * + * * @param kind * @param comment - * @return + * @return */ - public static ParameterizedReplaceableEvent createParameterizedReplaceableEvent(@NonNull Integer kind, String comment) { - return NIP33.createParameterizedReplaceableEvent(kind, comment); + public NIP01 createParameterizedReplaceableEvent(@NonNull Integer kind, String comment) { + var event = new ParameterizedReplaceableEventFactory(getSender(), kind, comment).create(); + + this.setEvent((T) event); + return this; } - + /** - * + * * @param tags * @param kind * @param comment - * @return + * @return */ - public static ParameterizedReplaceableEvent createParameterizedReplaceableEvent(@NonNull List tags, @NonNull Integer kind, String comment) { - return NIP33.createParameterizedReplaceableEvent(tags, kind, comment); + public NIP01 createParameterizedReplaceableEvent(@NonNull List tags, @NonNull Integer kind, String comment) { + var event = new ParameterizedReplaceableEventFactory(getSender(), tags, kind, comment).create(); + + this.setEvent((T) event); + return this; } - + /** - * + * * @param id - * @return + * @return */ public static IdentifierTag createIdentifierTag(@NonNull String id) { - return NIP33.createIdentifierTag(id); + return new IdentifierTagFactory(id).create(); } /** - * + * * @param kind * @param publicKey * @param idTag * @param relay - * @return + * @return */ public static AddressTag createAddressTag(@NonNull Integer kind, @NonNull PublicKey publicKey, @NonNull IdentifierTag idTag, Relay relay) { - return NIP33.createAddressTag(kind, publicKey, idTag, relay); - } + var result = new AddressTagFactory(publicKey).create(); + result.setIdentifierTag(idTag); + result.setKind(kind); + result.setRelay(relay); + return result; + } } diff --git a/nostr-java-api/src/main/java/nostr/api/NIP04.java b/nostr-java-api/src/main/java/nostr/api/NIP04.java index b1daa01fb..12da09adc 100644 --- a/nostr-java-api/src/main/java/nostr/api/NIP04.java +++ b/nostr-java-api/src/main/java/nostr/api/NIP04.java @@ -4,44 +4,49 @@ */ package nostr.api; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.logging.Level; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; + import lombok.NonNull; import lombok.extern.java.Log; -import nostr.api.factory.impl.NIP04.DirectMessageEventFactory; +import nostr.api.factory.impl.NIP04Impl.DirectMessageEventFactory; import nostr.base.PublicKey; import nostr.event.BaseTag; +import nostr.event.NIP04Event; import nostr.event.impl.DirectMessageEvent; import nostr.event.impl.GenericEvent; import nostr.event.tag.PubKeyTag; import nostr.id.IIdentity; +import nostr.id.Identity; import nostr.id.IdentityHelper; import nostr.util.NostrException; -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.logging.Level; - /** * @author eric */ @Log -public class NIP04 extends Nostr { - - /** - * Create a NIP04 Encrypted Direct Message - * - * @param recipient the DM recipient - * @param content the DM content in clear-text - * @return the DM event - */ - public static DirectMessageEvent createDirectMessageEvent(@NonNull PublicKey recipient, @NonNull String content) { - return new DirectMessageEventFactory(recipient, content).create(); +@Deprecated(since = "NIP-44") +public class NIP04 extends EventNostr { + + public NIP04(@NonNull Identity sender, @NonNull PublicKey recipient) { + setSender(sender); + setRecipient(recipient); + } + + public NIP04 createDirectMessageEvent(@NonNull String content) { + var event = new DirectMessageEventFactory(getSender(), getRecipient(), content).create(); + this.setEvent((T) event); + + return this; } /** @@ -52,22 +57,21 @@ public static DirectMessageEvent createDirectMessageEvent(@NonNull PublicKey rec * @param content the DM content * @return the DM event */ - public static DirectMessageEvent createDirectMessageEvent(@NonNull List tags, @NonNull PublicKey recipient, @NonNull String content) { - return new DirectMessageEventFactory(tags, recipient, content).create(); + public NIP04 createDirectMessageEvent(@NonNull List tags, @NonNull PublicKey recipient, @NonNull String content) { + var event = new DirectMessageEventFactory(tags, recipient, content).create(); + this.setEvent((T) event); + + return this; } - /** - * Encrypt a DM event - * - * @param senderId - * @param dm the DM event - */ - public static void encrypt(@NonNull IIdentity senderId, @NonNull DirectMessageEvent dm) { + public NIP04 encrypt() { try { - new IdentityHelper(senderId).encryptDirectMessage(dm); + new IdentityHelper(getSender()).encryptDirectMessage((DirectMessageEvent) getEvent()); } catch (NostrException ex) { throw new RuntimeException(ex); } + + return this; } public static String encrypt(@NonNull IIdentity senderId, @NonNull String message, @NonNull PublicKey recipient) { diff --git a/nostr-java-api/src/main/java/nostr/api/NIP05.java b/nostr-java-api/src/main/java/nostr/api/NIP05.java index a54cf2f07..61fb7d47b 100644 --- a/nostr-java-api/src/main/java/nostr/api/NIP05.java +++ b/nostr-java-api/src/main/java/nostr/api/NIP05.java @@ -5,22 +5,30 @@ package nostr.api; import lombok.NonNull; -import nostr.api.factory.impl.NIP05.InternetIdentifierMetadataEventFactory; +import nostr.api.factory.impl.NIP05Impl.InternetIdentifierMetadataEventFactory; import nostr.base.UserProfile; -import nostr.event.impl.InternetIdentifierMetadataEvent; +import nostr.event.NIP05Event; +import nostr.id.Identity; /** * * @author eric */ -public class NIP05 { +public class NIP05 extends EventNostr { + + public NIP05(@NonNull Identity sender) { + setSender(sender); + } /** * Create an Internet Identifier Metadata (IIM) Event * @param profile the associate user profile * @return the IIM event */ - public static InternetIdentifierMetadataEvent createInternetIdentifierMetadataEvent(@NonNull UserProfile profile) { - return new InternetIdentifierMetadataEventFactory(profile).create(); + public NIP05 createInternetIdentifierMetadataEvent(@NonNull UserProfile profile) { + var event = new InternetIdentifierMetadataEventFactory(getSender(), profile).create(); + this.setEvent((T) event); + + return this; } } diff --git a/nostr-java-api/src/main/java/nostr/api/NIP08.java b/nostr-java-api/src/main/java/nostr/api/NIP08.java index b6305d79e..b1c8dc54c 100644 --- a/nostr-java-api/src/main/java/nostr/api/NIP08.java +++ b/nostr-java-api/src/main/java/nostr/api/NIP08.java @@ -5,33 +5,47 @@ package nostr.api; import java.util.List; + import lombok.NonNull; -import nostr.api.factory.impl.NIP08.MentionsEventFactory; -import nostr.base.PublicKey; +import nostr.api.factory.impl.NIP08Impl.MentionsEventFactory; +import nostr.event.BaseTag; +import nostr.event.NIP08Event; import nostr.event.impl.MentionsEvent; +import nostr.id.Identity; /** * * @author eric */ -public class NIP08 { - - /** - * Create a NIP08 mentions event without pubkey tags - * @param content the note's content - * @return the mentions event without pubkey tags - */ - public static MentionsEvent createMentionsEvent(@NonNull String content) { - return new MentionsEventFactory(content).create(); - } +@Deprecated(since = "NIP-27") +public class NIP08 extends EventNostr { + + public NIP08(@NonNull Identity sender) { + setSender(sender); + } /** * Create a NIP08 mentions event - * @param publicKeys the referenced public keys + * @param tags the referenced * @param content the note's content containing the references to the public keys * @return the mentions event */ - public static MentionsEvent createMentionsEvent(@NonNull List publicKeys, @NonNull String content) { - return new MentionsEventFactory(publicKeys, content).create(); + public NIP08 createMentionsEvent(@NonNull List tags, @NonNull String content) { + var event = new MentionsEvent(getSender().getPublicKey(), tags, content); + this.setEvent((T) event); + + return this; + } + + /** + * Create a NIP08 mentions event without pubkey tags + * @param content the note's content + * @return the mentions event without pubkey tags + */ + public NIP08 createMentionsEvent(@NonNull String content) { + var event = new MentionsEventFactory(content).create(); + this.setEvent((T) event); + + return this; } } diff --git a/nostr-java-api/src/main/java/nostr/api/NIP09.java b/nostr-java-api/src/main/java/nostr/api/NIP09.java index 1c6ef78ff..5ee35d32c 100644 --- a/nostr-java-api/src/main/java/nostr/api/NIP09.java +++ b/nostr-java-api/src/main/java/nostr/api/NIP09.java @@ -4,20 +4,24 @@ */ package nostr.api; -import java.util.ArrayList; import java.util.List; + import lombok.NonNull; -import nostr.api.factory.impl.NIP09.DeletionEventFactory; +import nostr.api.factory.impl.NIP09Impl.DeletionEventFactory; import nostr.event.BaseTag; -import nostr.event.impl.DeletionEvent; -import nostr.event.impl.GenericEvent; +import nostr.event.NIP09Event; import nostr.event.tag.EventTag; +import nostr.id.Identity; /** * * @author eric */ -public class NIP09 extends Nostr { +public class NIP09 extends EventNostr { + + public NIP09(@NonNull Identity sender) { + setSender(sender); + } /** * Create a NIP09 Deletion Event @@ -25,21 +29,25 @@ public class NIP09 extends Nostr { * @param tags list of event or address tags to be deleted * @return the deletion event */ - public static DeletionEvent createDeletionEvent(@NonNull List tags) { - return new DeletionEventFactory(tags).create(); + public NIP09 createDeletionEvent(@NonNull List tags) { + var event = new DeletionEventFactory(getSender(), tags).create(); + this.setEvent((T) event); + + return this; } /** * Create a NIP09 Deletion Event * - * @param event the (single) event to delete + * @param idEvent the id of event to delete * @return the deletion event */ - public static DeletionEvent createDeletionEvent(@NonNull GenericEvent event) { - EventTag tag = new EventTag(event.getId()); - List tags = new ArrayList<>(); - tags.add(tag); + public NIP09 createDeletionEvent(@NonNull String idEvent) { + List tags = List.of(new EventTag(idEvent)); + + var event = new DeletionEventFactory(tags).create(); + this.setEvent((T) event); - return new DeletionEventFactory(tags).create(); + return this; } } diff --git a/nostr-java-api/src/main/java/nostr/api/NIP16.java b/nostr-java-api/src/main/java/nostr/api/NIP16.java index e5be33e65..81bc14301 100644 --- a/nostr-java-api/src/main/java/nostr/api/NIP16.java +++ b/nostr-java-api/src/main/java/nostr/api/NIP16.java @@ -5,9 +5,10 @@ package nostr.api; import java.util.List; + import lombok.NonNull; -import nostr.api.factory.impl.NIP16.EphemeralEventFactory; -import nostr.api.factory.impl.NIP16.ReplaceableEventFactory; +import nostr.api.factory.impl.NIP16Impl.EphemeralEventFactory; +import nostr.api.factory.impl.NIP16Impl.ReplaceableEventFactory; import nostr.event.BaseTag; import nostr.event.impl.EphemeralEvent; import nostr.event.impl.ReplaceableEvent; @@ -16,6 +17,7 @@ * * @author eric */ +@Deprecated(since = "NIP-01") public class NIP16 extends Nostr { /** diff --git a/nostr-java-api/src/main/java/nostr/api/NIP172.java b/nostr-java-api/src/main/java/nostr/api/NIP172.java index bfe1b7d79..cc3e980c3 100644 --- a/nostr-java-api/src/main/java/nostr/api/NIP172.java +++ b/nostr-java-api/src/main/java/nostr/api/NIP172.java @@ -66,7 +66,7 @@ public static GenericEvent createJobRequestEvent(PublicKey pubKey, String jobTyp tags.add(new nostr.api.factory.impl.NIP42.RelaysTagFactory(relays).create()); tags.add(createBidTag(bidTagAmount, bidTagMaxPrice)); tags.add(new nostr.api.factory.impl.NIP40.ExpirationTagFactory(expiration).create()); - tags.add(new nostr.api.factory.impl.NIP33.IdentifierTagFactory(uniqueJobName).create()); + tags.add(new nostr.api.factory.impl.NIP01Impl.IdentifierTagFactory(uniqueJobName).create()); serviceProviders.forEach(p -> tags.add(PubKeyTag.builder().publicKey(p).build())); PublicKey sender = Identity.getInstance().getPublicKey(); diff --git a/nostr-java-api/src/main/java/nostr/api/NIP25.java b/nostr-java-api/src/main/java/nostr/api/NIP25.java index d2971b471..e0f972b5c 100644 --- a/nostr-java-api/src/main/java/nostr/api/NIP25.java +++ b/nostr-java-api/src/main/java/nostr/api/NIP25.java @@ -4,20 +4,25 @@ */ package nostr.api; -import java.net.URL; import java.util.List; + import lombok.NonNull; -import nostr.api.factory.impl.NIP25.ReactionEventFactory; +import nostr.api.factory.impl.NIP25Impl.ReactionEventFactory; import nostr.event.BaseTag; +import nostr.event.NIP25Event; import nostr.event.Reaction; import nostr.event.impl.GenericEvent; -import nostr.event.impl.ReactionEvent; +import nostr.id.Identity; /** * * @author eric */ -public class NIP25 extends Nostr { +public class NIP25 extends EventNostr { + + public NIP25(@NonNull Identity sender) { + setSender(sender); + } /** * Create a Reaction event @@ -25,46 +30,53 @@ public class NIP25 extends Nostr { * @param reaction * @return */ - public static ReactionEvent createReactionEvent(@NonNull GenericEvent event, @NonNull Reaction reaction) { - return new ReactionEventFactory(event, reaction).create(); + public NIP25 createReactionEvent(@NonNull GenericEvent event, @NonNull Reaction reaction) { + var e = new ReactionEventFactory(getSender(), event, reaction).create(); + this.setEvent((T) e); + + return this; } /** * Create a NIP25 Reaction event to react to a specific event * @param event the related event to react to - * @param content MAY be an emoji, or NIP-30 custom emoji - * @param emoji the emoji image url + * @param content MAY be an emoji * @return */ - public static ReactionEvent createReactionEvent(@NonNull GenericEvent event, @NonNull String content, URL emoji) { - return new ReactionEventFactory(event, content, emoji).create(); + public NIP25 createReactionEvent(@NonNull GenericEvent event, @NonNull String content) { + var e = new ReactionEventFactory(getSender(), event, content).create(); + this.setEvent((T) e); + + return this; } /** * Create a NIP25 Reaction event to react to several event and/or pubkeys * @param tags the list of events or pubkeys to react to - * @param content MAY be an emoji, or NIP-30 custom emoji - * @param emoji the emoji image url + * @param content MAY be an emoji * @return */ - public static ReactionEvent createReactionEvent(@NonNull List tags, @NonNull String content, URL emoji) { - return new ReactionEventFactory(tags, content, emoji).create(); + public NIP25 createReactionEvent(@NonNull List tags, @NonNull String content) { + var e = new ReactionEventFactory(getSender(), tags, content).create(); + this.setEvent((T) e); + + return this; } /** * * @param event */ - public static void like(@NonNull GenericEvent event) { - react(event, Reaction.LIKE.getEmoji(), null); + public void like(@NonNull GenericEvent event) { + react(event, Reaction.LIKE.getEmoji()); } /** * * @param event */ - public static void dislike(@NonNull GenericEvent event) { - react(event, Reaction.DISLIKE.getEmoji(), null); + public void dislike(@NonNull GenericEvent event) { + react(event, Reaction.DISLIKE.getEmoji()); } /** @@ -73,10 +85,10 @@ public static void dislike(@NonNull GenericEvent event) { * @param reaction * @param url */ - public static void react(@NonNull GenericEvent event, @NonNull String reaction, URL url) { - var reactionEvent = new ReactionEventFactory(event, reaction, url).create(); + public void react(@NonNull GenericEvent event, @NonNull String reaction) { + var e = new ReactionEventFactory(getSender(), event, reaction).create(); - Nostr.sign(reactionEvent); - Nostr.send(reactionEvent); + this.setEvent((T) e); + this.sign().send(); } } diff --git a/nostr-java-api/src/main/java/nostr/api/NIP33.java b/nostr-java-api/src/main/java/nostr/api/NIP33.java deleted file mode 100644 index 6f20beecd..000000000 --- a/nostr-java-api/src/main/java/nostr/api/NIP33.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license - * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template - */ -package nostr.api; - -import java.util.List; -import lombok.NonNull; -import nostr.api.factory.impl.NIP33.AddressTagFactory; -import nostr.api.factory.impl.NIP33.IdentifierTagFactory; -import nostr.api.factory.impl.NIP33.ParameterizedReplaceableEventFactory; -import nostr.base.PublicKey; -import nostr.base.Relay; -import nostr.event.BaseTag; -import nostr.event.impl.ParameterizedReplaceableEvent; -import nostr.event.tag.AddressTag; -import nostr.event.tag.IdentifierTag; - -/** - * - * @author eric - */ -public class NIP33 extends Nostr { - - /** - * - * @param kind - * @param comment - * @return - */ - public static ParameterizedReplaceableEvent createParameterizedReplaceableEvent(@NonNull Integer kind, String comment) { - return new ParameterizedReplaceableEventFactory(kind, comment).create(); - } - - /** - * - * @param tags - * @param kind - * @param comment - * @return - */ - public static ParameterizedReplaceableEvent createParameterizedReplaceableEvent(@NonNull List tags, @NonNull Integer kind, String comment) { - return new ParameterizedReplaceableEventFactory(tags, kind, comment).create(); - } - - /** - * - * @param id - * @return - */ - public static IdentifierTag createIdentifierTag(@NonNull String id) { - return new IdentifierTagFactory(id).create(); - } - - /** - * - * @param kind - * @param publicKey - * @param idTag - * @param relay - * @return - */ - public static AddressTag createAddressTag(@NonNull Integer kind, @NonNull PublicKey publicKey, @NonNull IdentifierTag idTag, Relay relay) { - var result = new AddressTagFactory(publicKey).create(); - result.setIdentifierTag(idTag); - result.setKind(kind); - result.setRelay(relay); - return result; - } -} diff --git a/nostr-java-api/src/main/java/nostr/api/NIP42.java b/nostr-java-api/src/main/java/nostr/api/NIP42.java index e5d6b0cb3..40c4339a5 100644 --- a/nostr-java-api/src/main/java/nostr/api/NIP42.java +++ b/nostr-java-api/src/main/java/nostr/api/NIP42.java @@ -5,6 +5,7 @@ package nostr.api; import java.util.List; + import lombok.NonNull; import nostr.api.factory.impl.NIP42.ChallengeTagFactory; import nostr.api.factory.impl.NIP42.ClientAuthenticationEventFactory; @@ -90,7 +91,7 @@ public static GenericMessage createRelayAuthenticationMessage(@NonNull String ch * @throws NostrException */ public static void auth(@NonNull String challenge, @NonNull Relay relay) throws NostrException { - Client client = Nostr.createClient(); + Client client = Client.getInstance(); client.auth(challenge, relay); } diff --git a/nostr-java-api/src/main/java/nostr/api/Nostr.java b/nostr-java-api/src/main/java/nostr/api/Nostr.java index 661fa68a9..867a22f3e 100644 --- a/nostr-java-api/src/main/java/nostr/api/Nostr.java +++ b/nostr-java-api/src/main/java/nostr/api/Nostr.java @@ -4,20 +4,21 @@ */ package nostr.api; +import java.util.Map; + +import lombok.Getter; import lombok.NonNull; import nostr.base.GenericTagQuery; import nostr.base.IElement; import nostr.base.IEvent; import nostr.base.ISignable; import nostr.base.Relay; -import nostr.base.Signature; import nostr.client.Client; import nostr.event.BaseEvent; import nostr.event.BaseMessage; import nostr.event.BaseTag; import nostr.event.impl.Filters; import nostr.event.impl.GenericEvent; -import nostr.event.json.codec.GenericEventDecoder; import nostr.event.json.codec.BaseEventEncoder; import nostr.event.json.codec.BaseMessageDecoder; import nostr.event.json.codec.BaseMessageEncoder; @@ -25,46 +26,69 @@ import nostr.event.json.codec.BaseTagEncoder; import nostr.event.json.codec.FiltersDecoder; import nostr.event.json.codec.FiltersEncoder; +import nostr.event.json.codec.GenericEventDecoder; import nostr.event.json.codec.GenericTagQueryEncoder; import nostr.id.IIdentity; import nostr.id.Identity; -import nostr.util.NostrException; /** * @author eric */ -public abstract class Nostr { +public class Nostr { - /** - * @param event - */ - public static void send(@NonNull IEvent event) { - var client = createClient(); - client.send(event); + private static Nostr INSTANCE; + + private Client client; + @Getter + private Identity sender; + + public static Nostr getInstance() { + return (INSTANCE == null) ? new Nostr() : INSTANCE; + } + + public Nostr setSender(@NonNull Identity sender) { + this.sender = sender; + + return this; + } + + public Nostr setRelays(Map relays) { + this.client = Client.getInstance(relays); + + return this; + } + + protected Client getClient() { + client = (client == null) ? Client.getInstance() : client; + + return client; + } + + public void send(@NonNull IEvent event) { + getClient().send(event); } - public static void send(@NonNull Filters filters, @NonNull String subscriptionId) { - var client = createClient(); - client.send(filters, subscriptionId); + public void send(@NonNull Filters filters, @NonNull String subscriptionId) { + getClient().send(filters, subscriptionId); } /** * @param signable * @return */ + public Nostr sign(@NonNull IIdentity identity, @NonNull ISignable signable) { + identity.sign(signable); - public static Signature sign(@NonNull IIdentity identity, @NonNull ISignable signable) { - return identity.sign(signable); + return this; } - public static Signature sign(@NonNull ISignable signable) { - Identity identity = Identity.getInstance(); - return identity.sign(signable); + public Nostr sign(@NonNull ISignable signable) { + sender.sign(signable); + + return this; } - /** - * - */ + public static class Json { // Events @@ -227,15 +251,4 @@ public static IElement decode(@NonNull String json, @NonNull Class clazz) { } } - - // Utils - - /** - * @return - */ - protected static Client createClient() { - - return Client.getInstance(); - } - } diff --git a/nostr-java-api/src/main/java/nostr/api/factory/EventFactory.java b/nostr-java-api/src/main/java/nostr/api/factory/EventFactory.java index dadf35f0d..afdd7a514 100644 --- a/nostr-java-api/src/main/java/nostr/api/factory/EventFactory.java +++ b/nostr-java-api/src/main/java/nostr/api/factory/EventFactory.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.List; + import lombok.Data; import nostr.base.IEvent; import nostr.base.PublicKey; @@ -25,6 +26,10 @@ public abstract class EventFactory { private final String content; private final List tags; + public EventFactory(IIdentity identity) { + this(identity, new ArrayList<>(), null); + } + protected EventFactory() { this.identity = Identity.getInstance(); this.content = null; @@ -43,14 +48,14 @@ public EventFactory(List tags, String content) { this.identity = Identity.getInstance(); } - public EventFactory(IIdentity identity, String content) { - this(identity, new ArrayList<>(), content); + public EventFactory(IIdentity sender, String content) { + this(sender, new ArrayList<>(), content); } - public EventFactory(IIdentity identity, List tags, String content) { + public EventFactory(IIdentity sender, List tags, String content) { this.content = content; this.tags = tags; - this.identity = identity; + this.identity = sender; } public abstract T create(); diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP01.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP01Impl.java similarity index 60% rename from nostr-java-api/src/main/java/nostr/api/factory/impl/NIP01.java rename to nostr-java-api/src/main/java/nostr/api/factory/impl/NIP01Impl.java index c61eaa9a7..67d68df3d 100644 --- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP01.java +++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP01Impl.java @@ -5,6 +5,7 @@ package nostr.api.factory.impl; import java.util.List; + import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; @@ -15,11 +16,15 @@ import nostr.api.factory.MessageFactory; import nostr.base.IEvent; import nostr.base.PublicKey; +import nostr.base.Relay; import nostr.base.UserProfile; import nostr.event.BaseTag; import nostr.event.Marker; +import nostr.event.impl.EphemeralEvent; import nostr.event.impl.Filters; import nostr.event.impl.MetadataEvent; +import nostr.event.impl.ParameterizedReplaceableEvent; +import nostr.event.impl.ReplaceableEvent; import nostr.event.impl.TextNoteEvent; import nostr.event.list.EventList; import nostr.event.list.GenericTagQueryList; @@ -30,15 +35,18 @@ import nostr.event.message.EventMessage; import nostr.event.message.NoticeMessage; import nostr.event.message.ReqMessage; +import nostr.event.tag.AddressTag; import nostr.event.tag.EventTag; +import nostr.event.tag.IdentifierTag; import nostr.event.tag.PubKeyTag; import nostr.id.IIdentity; +import nostr.id.Identity; /** * * @author eric */ -public class NIP01 { +public class NIP01Impl { @Data @EqualsAndHashCode(callSuper = false) @@ -63,7 +71,7 @@ public TextNoteEventFactory(@NonNull IIdentity sender, @NonNull List ta @Override public TextNoteEvent create() { - var event = new nostr.event.impl.TextNoteEvent(getSender(), getTags(), getContent()); + var event = new TextNoteEvent(getSender(), getTags(), getContent()); getTags().forEach(t -> event.addTag(t)); return event; } @@ -76,7 +84,6 @@ public static class MetadataEventFactory extends EventFactory { private UserProfile profile; public MetadataEventFactory(@NonNull UserProfile profile) { - super(null); this.profile = profile; } @@ -180,6 +187,128 @@ public ReqMessage create() { } } + @Data + @EqualsAndHashCode(callSuper = false) + public static class ReplaceableEventFactory extends EventFactory { + + private final Integer kind; + + public ReplaceableEventFactory(@NonNull Integer kind, @NonNull String content) { + super(content); + this.kind = kind; + } + + public ReplaceableEventFactory(@NonNull Identity sender, @NonNull Integer kind, @NonNull String content) { + super(sender, content); + this.kind = kind; + } + + public ReplaceableEventFactory(@NonNull List tags, @NonNull Integer kind, @NonNull String content) { + super(tags, content); + this.kind = kind; + } + + public ReplaceableEventFactory(@NonNull Identity sender, @NonNull List tags, @NonNull Integer kind, @NonNull String content) { + super(sender, tags, content); + this.kind = kind; + } + + @Override + public ReplaceableEvent create() { + return new ReplaceableEvent(getSender(), kind, getTags(), getContent()); + } + } + + @Data + @EqualsAndHashCode(callSuper = false) + public static class EphemeralEventFactory extends EventFactory { + + private final Integer kind; + + public EphemeralEventFactory(@NonNull Integer kind, @NonNull String content) { + super(content); + this.kind = kind; + } + + public EphemeralEventFactory(@NonNull Identity sender, @NonNull Integer kind, @NonNull String content) { + super(sender, content); + this.kind = kind; + } + + @Override + public EphemeralEvent create() { + return new EphemeralEvent(getSender(), kind, getTags(), getContent()); + } + + } + + @Data + @EqualsAndHashCode(callSuper = false) + public static class ParameterizedReplaceableEventFactory extends EventFactory { + + private final Integer kind; + + public ParameterizedReplaceableEventFactory(Integer kind, String comment) { + super(comment); + this.kind = kind; + } + + public ParameterizedReplaceableEventFactory(@NonNull Identity sender, Integer kind, String comment) { + super(sender, comment); + this.kind = kind; + } + + public ParameterizedReplaceableEventFactory(@NonNull List tags, Integer kind, String comment) { + super(tags, comment); + this.kind = kind; + } + + public ParameterizedReplaceableEventFactory(@NonNull Identity sender, @NonNull List tags, Integer kind, String comment) { + super(sender, tags, comment); + this.kind = kind; + } + + @Override + public ParameterizedReplaceableEvent create() { + return new ParameterizedReplaceableEvent(getSender(), kind, getTags(), getContent()); + } + } + + @Data + @EqualsAndHashCode(callSuper = false) + public static class IdentifierTagFactory extends AbstractTagFactory { + + private final String id; + + public IdentifierTagFactory(String id) { + this.id = id; + } + + @Override + public IdentifierTag create() { + return new IdentifierTag(id); + } + } + + @Data + @EqualsAndHashCode(callSuper = false) + public static class AddressTagFactory extends AbstractTagFactory { + + private Integer kind; + private final PublicKey publicKey; + private IdentifierTag identifierTag; + private Relay relay; + + public AddressTagFactory(@NonNull PublicKey publicKey) { + this.publicKey = publicKey; + } + + @Override + public AddressTag create() { + return new AddressTag(kind, publicKey, identifierTag, relay); + } + } + @Data @EqualsAndHashCode(callSuper = false) @AllArgsConstructor diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP04.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP04Impl.java similarity index 97% rename from nostr-java-api/src/main/java/nostr/api/factory/impl/NIP04.java rename to nostr-java-api/src/main/java/nostr/api/factory/impl/NIP04Impl.java index a50baaedb..3c52da007 100644 --- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP04.java +++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP04Impl.java @@ -5,6 +5,7 @@ package nostr.api.factory.impl; import java.util.List; + import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NonNull; @@ -18,7 +19,8 @@ * * @author eric */ -public class NIP04 { +@Deprecated(since = "NIP-44") +public class NIP04Impl { @Data @EqualsAndHashCode(callSuper = false) diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP05.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP05.java index 28e48d55b..aea62190b 100644 --- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP05.java +++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP05.java @@ -25,7 +25,6 @@ public static class InternetIdentifierMetadataEventFactory extends EventFactory< private final UserProfile profile; public InternetIdentifierMetadataEventFactory(@NonNull UserProfile profile) { - super(null); this.profile = profile; } diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP05Impl.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP05Impl.java new file mode 100644 index 000000000..554fd16cb --- /dev/null +++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP05Impl.java @@ -0,0 +1,37 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package nostr.api.factory.impl; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NonNull; +import nostr.api.factory.EventFactory; +import nostr.base.UserProfile; +import nostr.event.impl.InternetIdentifierMetadataEvent; +import nostr.id.Identity; + +/** + * + * @author eric + */ +public class NIP05Impl { + + @Data + @EqualsAndHashCode(callSuper = false) + public static class InternetIdentifierMetadataEventFactory extends EventFactory { + + private final UserProfile profile; + + public InternetIdentifierMetadataEventFactory(@NonNull Identity sender, @NonNull UserProfile profile) { + super(sender, null); + this.profile = profile; + } + + @Override + public InternetIdentifierMetadataEvent create() { + return new InternetIdentifierMetadataEvent(getSender(), profile); + } + } +} diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP08.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP08Impl.java similarity index 90% rename from nostr-java-api/src/main/java/nostr/api/factory/impl/NIP08.java rename to nostr-java-api/src/main/java/nostr/api/factory/impl/NIP08Impl.java index d8bbf9a25..cd73844d7 100644 --- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP08.java +++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP08Impl.java @@ -17,7 +17,8 @@ * * @author eric */ -public class NIP08 { +@Deprecated(since = "NIP-27") +public class NIP08Impl { public static class MentionsEventFactory extends EventFactory { @@ -37,7 +38,7 @@ public MentionsEventFactory(@NonNull Identity sender, @NonNull List p @Override public MentionsEvent create() { - var event = new nostr.event.impl.MentionsEvent(getSender(), getTags(), getContent()); + var event = new MentionsEvent(getSender(), getTags(), getContent()); getTags().forEach(t -> event.addTag(t)); return event; } diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP09.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP09Impl.java similarity index 80% rename from nostr-java-api/src/main/java/nostr/api/factory/impl/NIP09.java rename to nostr-java-api/src/main/java/nostr/api/factory/impl/NIP09Impl.java index 5085625d6..a0134f150 100644 --- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP09.java +++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP09Impl.java @@ -17,25 +17,25 @@ * * @author eric */ -public class NIP09 { +public class NIP09Impl { @Data @EqualsAndHashCode(callSuper = false) public static class DeletionEventFactory extends EventFactory { - - public DeletionEventFactory() { - super(null); - } + + public DeletionEventFactory(Identity sender) { + super(sender); + } public DeletionEventFactory(List tags) { super(tags, null); } - @Deprecated - public DeletionEventFactory(Identity sender) { - super(sender, null); + public DeletionEventFactory(Identity sender, List tags) { + super(sender, tags, null); } + @Override public DeletionEvent create() { return new DeletionEvent(getSender(), getTags()); diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP16.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP16Impl.java similarity index 94% rename from nostr-java-api/src/main/java/nostr/api/factory/impl/NIP16.java rename to nostr-java-api/src/main/java/nostr/api/factory/impl/NIP16Impl.java index d560c6eea..4ffe1c060 100644 --- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP16.java +++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP16Impl.java @@ -5,6 +5,7 @@ package nostr.api.factory.impl; import java.util.List; + import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NonNull; @@ -18,10 +19,12 @@ * * @author eric */ -public class NIP16 { +@Deprecated(since = "NIP-01") +public class NIP16Impl { @Data @EqualsAndHashCode(callSuper = false) + @Deprecated(since = "NIP-01") public static class ReplaceableEventFactory extends EventFactory { private final Integer kind; @@ -54,6 +57,7 @@ public ReplaceableEvent create() { @Data @EqualsAndHashCode(callSuper = false) + @Deprecated(since = "NIP-01") public static class EphemeralEventFactory extends EventFactory { private final Integer kind; diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP25.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP25Impl.java similarity index 79% rename from nostr-java-api/src/main/java/nostr/api/factory/impl/NIP25.java rename to nostr-java-api/src/main/java/nostr/api/factory/impl/NIP25Impl.java index 53dda09fb..c16fadb5f 100644 --- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP25.java +++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP25Impl.java @@ -4,8 +4,8 @@ */ package nostr.api.factory.impl; -import java.net.URL; import java.util.List; + import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NonNull; @@ -21,71 +21,61 @@ * @author eric */ // TESTME -public class NIP25 { +public class NIP25Impl { @Data @EqualsAndHashCode(callSuper = false) public static class ReactionEventFactory extends EventFactory { public final GenericEvent event; - private final URL emoji; public ReactionEventFactory(@NonNull GenericEvent event, Reaction reaction) { super(reaction.getEmoji()); this.event = event; - this.emoji = null; + } + + public ReactionEventFactory(@NonNull GenericEvent event, String reaction) { + super(reaction); + this.event = event; } public ReactionEventFactory(@NonNull Identity sender, @NonNull GenericEvent event, Reaction reaction) { super(sender, reaction.getEmoji()); this.event = event; - this.emoji = null; } public ReactionEventFactory(@NonNull List tags, @NonNull GenericEvent event, String reaction) { super(tags, reaction); this.event = event; - this.emoji = null; } public ReactionEventFactory(@NonNull Identity sender, @NonNull List tags, @NonNull GenericEvent event, String reaction) { super(sender, tags, reaction); this.event = event; - this.emoji = null; - } - - public ReactionEventFactory(@NonNull GenericEvent event, String content, URL emoji) { - super(content); - this.event = event; - this.emoji = emoji; } - public ReactionEventFactory(@NonNull Identity sender, @NonNull GenericEvent event, String content, URL emoji) { + public ReactionEventFactory(@NonNull Identity sender, @NonNull GenericEvent event, String content) { super(sender, content); this.event = event; - this.emoji = emoji; } - public ReactionEventFactory(@NonNull List tags, String content, URL emoji) { + public ReactionEventFactory(@NonNull List tags, String content) { super(tags, content); - this.emoji = emoji; this.event = null; } - public ReactionEventFactory(@NonNull Identity sender, @NonNull List tags, String content, URL emoji) { + public ReactionEventFactory(@NonNull Identity sender, @NonNull List tags, String content) { super(sender, tags, content); - this.emoji = emoji; this.event = null; } @Override public ReactionEvent create() { var reaction = getContent(); - var url = getEmoji(); return event != null ? - new ReactionEvent(getSender(), event, reaction, url) : - new ReactionEvent(getSender(), getTags(), reaction, url); + new ReactionEvent(getSender(), event, reaction) : + new ReactionEvent(getSender(), getTags(), reaction); } } diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP28.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP28.java index 394d63ec6..ced37b668 100644 --- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP28.java +++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP28.java @@ -4,6 +4,8 @@ */ package nostr.api.factory.impl; +import static nostr.util.NostrUtil.escapeJsonString; + import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NonNull; @@ -19,8 +21,6 @@ import nostr.event.impl.MuteUserEvent; import nostr.id.Identity; -import static nostr.util.NostrUtil.escapeJsonString; - /** * * @author eric @@ -34,7 +34,6 @@ public static class ChannelCreateEventFactory extends EventFactory { private String reason; public MuteUserEventFactory(@NonNull PublicKey mutedUser, @NonNull String reason) { - super(null); this.mutedUser = mutedUser; this.reason = reason; } diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP33.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP33.java deleted file mode 100644 index f5fc3ef2f..000000000 --- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP33.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license - * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template - */ -package nostr.api.factory.impl; - -import java.util.List; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NonNull; -import nostr.api.factory.AbstractTagFactory; -import nostr.api.factory.EventFactory; -import nostr.base.PublicKey; -import nostr.base.Relay; -import nostr.event.BaseTag; -import nostr.event.impl.ParameterizedReplaceableEvent; -import nostr.event.tag.AddressTag; -import nostr.event.tag.IdentifierTag; -import nostr.id.Identity; - -/** - * - * @author eric - */ -public class NIP33 { - - @Data - @EqualsAndHashCode(callSuper = false) - public static class ParameterizedReplaceableEventFactory extends EventFactory { - - private final Integer kind; - - public ParameterizedReplaceableEventFactory(Integer kind, String comment) { - super(comment); - this.kind = kind; - } - - public ParameterizedReplaceableEventFactory(@NonNull Identity sender, Integer kind, String comment) { - super(sender, comment); - this.kind = kind; - } - - public ParameterizedReplaceableEventFactory(@NonNull List tags, Integer kind, String comment) { - super(tags, comment); - this.kind = kind; - } - - public ParameterizedReplaceableEventFactory(@NonNull Identity sender, @NonNull List tags, Integer kind, String comment) { - super(sender, tags, comment); - this.kind = kind; - } - - @Override - public ParameterizedReplaceableEvent create() { - return new ParameterizedReplaceableEvent(getSender(), kind, getTags(), getContent()); - } - } - - @Data - @EqualsAndHashCode(callSuper = false) - public static class IdentifierTagFactory extends AbstractTagFactory { - - private final String id; - - public IdentifierTagFactory(String id) { - this.id = id; - } - - @Override - public IdentifierTag create() { - return new IdentifierTag(id); - } - } - - @Data - @EqualsAndHashCode(callSuper = false) - public static class AddressTagFactory extends AbstractTagFactory { - - private Integer kind; - private final PublicKey publicKey; - private IdentifierTag identifierTag; - private Relay relay; - - public AddressTagFactory(@NonNull PublicKey publicKey) { - this.publicKey = publicKey; - } - - @Override - public AddressTag create() { - return new AddressTag(kind, publicKey, identifierTag, relay); - } - } -} diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP42.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP42.java index 84f54fc4f..dd1aa63aa 100644 --- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP42.java +++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP42.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; + import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; @@ -37,7 +38,6 @@ public static class ClientAuthenticationEventFactory extends EventFactory> futureRelays; - private final ThreadPoolExecutor threadPool; - private IRequestHandler requestHandler; + private final List> futureRelays = new ArrayList<>(); + private final IRequestHandler requestHandler = new DefaultRequestHandler(); +// TODO: remove getter + @Getter + private final ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool(); - private Client() throws IOException { - this.futureRelays = new ArrayList<>(); - this.requestHandler = new DefaultRequestHandler(); - this.threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool(); + public Client() throws IOException { this.init(); } - private Client(Map relays) { - this.futureRelays = new ArrayList<>(); - this.requestHandler = new DefaultRequestHandler(); - this.threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool(); + public Client(Map relays) { this.init(relays); } public static Client getInstance() { if (INSTANCE == null) { - try { - INSTANCE = new Client(); - - do { - try { - log.log(Level.INFO, "Waiting for relays' connections to open..."); - Thread.sleep(5000); - } catch (InterruptedException ex) { - throw new RuntimeException(ex); - } - } while (INSTANCE.getThreadPool().getCompletedTaskCount() < (INSTANCE.getRelays().size() / 2)); - - } catch (IOException ex) { - log.log(Level.SEVERE, null, ex); - throw new RuntimeException(ex); - } + try { + INSTANCE = new Client(); + } catch (IOException ex) { + log.log(Level.SEVERE, null, ex); + throw new RuntimeException(ex); + } } - return INSTANCE; + return INSTANCE.waitConnection(); } public static Client getInstance(Map relays) { - if (INSTANCE == null) { - INSTANCE = new Client(relays); - } + INSTANCE = (INSTANCE == null) ? new Client(relays) : INSTANCE; - return INSTANCE; + return INSTANCE.waitConnection(); } + public Client waitConnection() { + do { + try { + log.log(Level.INFO, "Waiting for relays' connections to open..."); + Thread.sleep(5000); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } + } while (this.threadPool.getCompletedTaskCount() < (this.getRelays().size() / 2)); + + return this; + } + public List getRelays() { return futureRelays.parallelStream() .filter(fr -> { @@ -129,7 +130,7 @@ public void send(@NonNull String subscriptionId) { } // TODO - Make private? - public void send(@NonNull BaseMessage message) { + public void send(@NonNull BaseMessage message) { log.log(Level.INFO, "Sending message {0}", message); diff --git a/nostr-java-crypto/src/main/java/nostr/crypto/schnorr/Schnorr.java b/nostr-java-crypto/src/main/java/nostr/crypto/schnorr/Schnorr.java index f18ed53ee..0370b6a48 100644 --- a/nostr-java-crypto/src/main/java/nostr/crypto/schnorr/Schnorr.java +++ b/nostr-java-crypto/src/main/java/nostr/crypto/schnorr/Schnorr.java @@ -14,7 +14,6 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider; -import lombok.extern.java.Log; import nostr.crypto.Point; import nostr.util.NostrUtil; diff --git a/nostr-java-event/src/main/java/nostr/event/NIP01Event.java b/nostr-java-event/src/main/java/nostr/event/NIP01Event.java new file mode 100644 index 000000000..077c1ad53 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/NIP01Event.java @@ -0,0 +1,28 @@ +package nostr.event; + +import java.util.ArrayList; +import java.util.List; + +import lombok.NoArgsConstructor; +import nostr.base.PublicKey; +import nostr.event.impl.GenericEvent; + +/** + * @author guilhermegps + */ +@NoArgsConstructor +public abstract class NIP01Event extends GenericEvent { + + public NIP01Event(PublicKey pubKey, Kind kind, ArrayList tags) { + super(pubKey, kind, tags); + } + + public NIP01Event(PublicKey pubKey, Kind kind, List tags, String content) { + super(pubKey, kind, tags, content); + } + + public NIP01Event(PublicKey sender, Integer kind, List tags, String content) { + super(sender, kind, tags, content); + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/NIP04Event.java b/nostr-java-event/src/main/java/nostr/event/NIP04Event.java new file mode 100644 index 000000000..35b4ef9ce --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/NIP04Event.java @@ -0,0 +1,24 @@ +package nostr.event; + +import java.util.List; + +import lombok.NoArgsConstructor; +import nostr.base.PublicKey; +import nostr.event.impl.GenericEvent; + +/** + * @author guilhermegps + */ +@NoArgsConstructor +@Deprecated(since = "NIP-44") +public abstract class NIP04Event extends GenericEvent { + + public NIP04Event(PublicKey pubKey, Kind kind, List tags, String content) { + super(pubKey, kind, tags, content); + } + + public NIP04Event(PublicKey pubKey, Kind kind) { + super(pubKey, kind); + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/NIP05Event.java b/nostr-java-event/src/main/java/nostr/event/NIP05Event.java new file mode 100644 index 000000000..b32fb2516 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/NIP05Event.java @@ -0,0 +1,17 @@ +package nostr.event; + +import lombok.NoArgsConstructor; +import nostr.base.PublicKey; +import nostr.event.impl.GenericEvent; + +/** + * @author guilhermegps + */ +@NoArgsConstructor +public abstract class NIP05Event extends GenericEvent { + + public NIP05Event(PublicKey pubKey, Kind kind) { + super(pubKey, kind); + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/NIP08Event.java b/nostr-java-event/src/main/java/nostr/event/NIP08Event.java new file mode 100644 index 000000000..9e99abf86 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/NIP08Event.java @@ -0,0 +1,20 @@ +package nostr.event; + +import java.util.List; + +import lombok.NoArgsConstructor; +import nostr.base.PublicKey; +import nostr.event.impl.GenericEvent; + +/** + * @author guilhermegps + */ +@NoArgsConstructor +@Deprecated(since = "NIP-27") +public abstract class NIP08Event extends GenericEvent { + + public NIP08Event(PublicKey pubKey, Kind kind, List tags, String content) { + super(pubKey, kind, tags, content); + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/NIP09Event.java b/nostr-java-event/src/main/java/nostr/event/NIP09Event.java new file mode 100644 index 000000000..586303f9c --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/NIP09Event.java @@ -0,0 +1,19 @@ +package nostr.event; + +import java.util.List; + +import lombok.NoArgsConstructor; +import nostr.base.PublicKey; +import nostr.event.impl.GenericEvent; + +/** + * @author guilhermegps + */ +@NoArgsConstructor +public abstract class NIP09Event extends GenericEvent { + + public NIP09Event(PublicKey pubKey, Kind kind, List tags, String content) { + super(pubKey, kind, tags, content); + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/NIP25Event.java b/nostr-java-event/src/main/java/nostr/event/NIP25Event.java new file mode 100644 index 000000000..700f761fa --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/NIP25Event.java @@ -0,0 +1,31 @@ +package nostr.event; + +import java.util.List; + +import lombok.NoArgsConstructor; +import nostr.base.PublicKey; +import nostr.event.impl.GenericEvent; + +/** + * @author guilhermegps + */ +@NoArgsConstructor +public abstract class NIP25Event extends GenericEvent { + + public NIP25Event(PublicKey pubKey, Kind kind, List tags) { + super(pubKey, kind, tags); + } + + public NIP25Event(PublicKey pubKey, Kind kind, List tags, String content) { + super(pubKey, kind, tags, content); + } + + public NIP25Event(PublicKey sender, Integer kind, List tags, String content) { + super(sender, kind, tags, content); + } + + public NIP25Event(PublicKey pubKey, Kind reaction) { + super(pubKey, reaction); + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/impl/CheckoutEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/CheckoutEvent.java index 5c764d68d..c50a27e3d 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/CheckoutEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/CheckoutEvent.java @@ -1,9 +1,11 @@ package nostr.event.impl; import com.fasterxml.jackson.annotation.JsonValue; + import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.NoArgsConstructor; import nostr.base.PublicKey; import nostr.base.annotation.Event; import nostr.event.IContent; @@ -13,12 +15,11 @@ * @author eric */ @Data +@NoArgsConstructor @EqualsAndHashCode(callSuper = false) @Event(name = "", nip = 15) public abstract class CheckoutEvent extends DirectMessageEvent { - protected CheckoutEvent() {} - public CheckoutEvent(PublicKey sender, PublicKey recipient, IContent content) { super(sender, recipient, content.toString()); } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/CreateOrUpdateProductEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/CreateOrUpdateProductEvent.java index 98d24ac8c..1b833195e 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/CreateOrUpdateProductEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/CreateOrUpdateProductEvent.java @@ -1,6 +1,7 @@ package nostr.event.impl; import java.util.List; + import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NonNull; @@ -17,9 +18,6 @@ @Event(name = "", nip = 15) public class CreateOrUpdateProductEvent extends NostrMarketplaceEvent { - private CreateOrUpdateProductEvent() { - super(); - } public CreateOrUpdateProductEvent(PublicKey sender, List tags, @NonNull Product product) { super(sender, 30018, tags, product); } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/CreateOrUpdateStallEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/CreateOrUpdateStallEvent.java index e862e0aa3..ac18ce3e1 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/CreateOrUpdateStallEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/CreateOrUpdateStallEvent.java @@ -1,9 +1,11 @@ package nostr.event.impl; -import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; import java.util.UUID; + +import com.fasterxml.jackson.annotation.JsonProperty; + import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -23,10 +25,6 @@ @Event(name = "Create or update a stall", nip = 15) public class CreateOrUpdateStallEvent extends NostrMarketplaceEvent { - protected CreateOrUpdateStallEvent() { - super(); - } - public CreateOrUpdateStallEvent(PublicKey sender, List tags, @NonNull Stall stall) { super(sender, 30017, tags, stall); } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/DeletionEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/DeletionEvent.java index ba843733d..7de21b398 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/DeletionEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/DeletionEvent.java @@ -2,12 +2,14 @@ package nostr.event.impl; import java.util.List; -import nostr.event.Kind; -import nostr.base.PublicKey; + import lombok.Data; import lombok.EqualsAndHashCode; +import nostr.base.PublicKey; import nostr.base.annotation.Event; import nostr.event.BaseTag; +import nostr.event.Kind; +import nostr.event.NIP09Event; /** * @@ -16,7 +18,7 @@ @Data @EqualsAndHashCode(callSuper = false) @Event(name = "Event Deletion", nip = 9) -public class DeletionEvent extends GenericEvent { +public class DeletionEvent extends NIP09Event { public DeletionEvent(PublicKey pubKey, List tags, String content) { super(pubKey, Kind.DELETION, tags, content); diff --git a/nostr-java-event/src/main/java/nostr/event/impl/DirectMessageEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/DirectMessageEvent.java index 5820afc70..136a11b9d 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/DirectMessageEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/DirectMessageEvent.java @@ -1,21 +1,22 @@ package nostr.event.impl; import java.util.List; + +import lombok.NoArgsConstructor; import nostr.base.PublicKey; -import nostr.event.Kind; import nostr.base.annotation.Event; import nostr.event.BaseTag; +import nostr.event.Kind; +import nostr.event.NIP04Event; import nostr.event.tag.PubKeyTag; /** * * @author squirrel */ +@NoArgsConstructor @Event(name = "Encrypted Direct Message", nip = 4) -public class DirectMessageEvent extends GenericEvent { - - protected DirectMessageEvent() { - } +public class DirectMessageEvent extends NIP04Event { public DirectMessageEvent(PublicKey sender, List tags, String content) { super(sender, Kind.ENCRYPTED_DIRECT_MESSAGE, tags, content); diff --git a/nostr-java-event/src/main/java/nostr/event/impl/EphemeralEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/EphemeralEvent.java index 086f656d9..276a36356 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/EphemeralEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/EphemeralEvent.java @@ -2,12 +2,13 @@ import java.util.ArrayList; import java.util.List; -import nostr.base.PublicKey; + import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.extern.java.Log; +import nostr.base.PublicKey; import nostr.base.annotation.Event; import nostr.event.BaseTag; +import nostr.event.NIP01Event; import nostr.event.tag.PubKeyTag; /** @@ -16,8 +17,8 @@ */ @Data @EqualsAndHashCode(callSuper = false) -@Event(name = "Ephemeral Events", nip = 16) -public class EphemeralEvent extends GenericEvent { +@Event(name = "Ephemeral Events", nip = 1) +public class EphemeralEvent extends NIP01Event { public EphemeralEvent(PublicKey pubKey, Integer kind, List tags, String content) { super(pubKey, kind, tags, content); @@ -31,6 +32,13 @@ public EphemeralEvent(PublicKey sender, Integer kind, PublicKey recipient) { this(sender, kind, new ArrayList<>()); this.addTag(PubKeyTag.builder().publicKey(recipient).build()); } - - // TODO - Validate the kind. + + @Override + protected void validate() { + var n = getKind(); + if (20000 <= n && n < 30000) + return; + + throw new AssertionError("Invalid kind value. Must be between 20000 and 30000.", null); + } } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/GenericEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/GenericEvent.java index f189d7225..e9e37c28c 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/GenericEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/GenericEvent.java @@ -4,14 +4,15 @@ import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.time.Instant; +import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import java.util.ArrayList; import lombok.Data; import lombok.EqualsAndHashCode; @@ -39,6 +40,7 @@ * * @author squirrel */ +@Log @Data @EqualsAndHashCode(callSuper = false) public class GenericEvent extends BaseEvent implements ISignable, IGenericElement { @@ -93,6 +95,11 @@ public GenericEvent() { this.attributes = new ArrayList<>(); } + public GenericEvent(@NonNull String id) { + this.id = id; + this.attributes = new ArrayList<>(); + } + public GenericEvent(@NonNull PublicKey pubKey, @NonNull Kind kind) { this(pubKey, kind, new ArrayList<>(), null); } @@ -162,6 +169,9 @@ public void update() { this.id = NostrUtil.bytesToHex(NostrUtil.sha256(_serializedEvent)); } catch (NostrException | NoSuchAlgorithmException ex) { throw new RuntimeException(ex); + } catch (AssertionError ex) { + log.log(Level.WARNING, ex.getMessage()); + throw new RuntimeException(ex); } } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java index 46899ea65..750a3bd71 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java @@ -1,18 +1,21 @@ package nostr.event.impl; +import static nostr.util.NostrUtil.escapeJsonString; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import nostr.event.Kind; -import nostr.base.PublicKey; + +import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NonNull; -import lombok.extern.java.Log; +import nostr.base.PublicKey; import nostr.base.UserProfile; import nostr.base.annotation.Event; +import nostr.event.Kind; +import nostr.event.NIP05Event; import nostr.event.util.Nip05Validator; import nostr.util.NostrException; -import static nostr.util.NostrUtil.escapeJsonString; /** * @@ -21,7 +24,7 @@ @Data @EqualsAndHashCode(callSuper = false) @Event(name = "Internet Identifier Metadata Event", nip = 5) -public final class InternetIdentifierMetadataEvent extends GenericEvent { +public final class InternetIdentifierMetadataEvent extends NIP05Event { public InternetIdentifierMetadataEvent(PublicKey pubKey, @NonNull UserProfile profile) { super(pubKey, Kind.SET_METADATA); @@ -31,7 +34,7 @@ public InternetIdentifierMetadataEvent(PublicKey pubKey, @NonNull UserProfile pr private void init(UserProfile profile) { try { // NIP-05 validator - Nip05Validator.builder().nip05(profile.getName()).publicKey(getPubKey()).build().validate(); + Nip05Validator.builder().nip05(profile.getNip05()).publicKey(profile.getPublicKey()).build().validate(); setContent(profile); } catch (NostrException ex) { @@ -43,7 +46,7 @@ private void setContent(UserProfile profile) { try { ObjectMapper objectMapper = new ObjectMapper(); - String jsonString = objectMapper.writeValueAsString(profile); + String jsonString = objectMapper.writeValueAsString(new Nip05Obj(profile.getName(), profile.getNip05())); // Escape the JSON string String escapedJsonString = escapeJsonString(jsonString); @@ -53,4 +56,11 @@ private void setContent(UserProfile profile) { throw new RuntimeException(ex); } } + + @Data + @AllArgsConstructor + public final class Nip05Obj{ + private String name; + private String nip05; + } } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/MentionsEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/MentionsEvent.java index d7dd61e8a..a4491bea2 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/MentionsEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/MentionsEvent.java @@ -1,15 +1,16 @@ package nostr.event.impl; import java.util.List; -import nostr.event.tag.PubKeyTag; -import nostr.event.Kind; -import nostr.base.PublicKey; +import java.util.concurrent.atomic.AtomicInteger; + import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.extern.java.Log; -import nostr.base.ITag; +import nostr.base.PublicKey; import nostr.base.annotation.Event; import nostr.event.BaseTag; +import nostr.event.Kind; +import nostr.event.NIP08Event; +import nostr.event.tag.PubKeyTag; /** * @@ -18,7 +19,7 @@ @Data @EqualsAndHashCode(callSuper = false) @Event(name = "Handling Mentions", nip = 8) -public final class MentionsEvent extends GenericEvent { +public final class MentionsEvent extends NIP08Event { public MentionsEvent(PublicKey pubKey, List tags, String content) { super(pubKey, Kind.TEXT_NOTE, tags, content); @@ -28,13 +29,12 @@ public MentionsEvent(PublicKey pubKey, List tags, String content) { public void update() { super.update(); - int index = 0; + AtomicInteger counter = new AtomicInteger(0); // TODO - Refactor with the EntityAttributeUtil class - while (getTags().iterator().hasNext()) { - ITag tag = getTags().iterator().next(); - String replacement = "#[" + index++ + "]"; + getTags().forEach(tag -> { + String replacement = "#[" + counter.getAndIncrement() + "]"; setContent(this.getContent().replace(((PubKeyTag) tag).getPublicKey().toString(), replacement)); - } + }); } } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/MetadataEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/MetadataEvent.java index b29a76cad..52e41e482 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/MetadataEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/MetadataEvent.java @@ -1,22 +1,21 @@ package nostr.event.impl; -import java.util.logging.Level; +import java.util.ArrayList; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; -import java.util.ArrayList; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.extern.java.Log; import nostr.base.IEncoder; -import nostr.base.UserProfile; import nostr.base.PublicKey; +import nostr.base.UserProfile; import nostr.base.annotation.Event; import nostr.event.BaseTag; import nostr.event.Kind; +import nostr.event.NIP01Event; /** * @@ -25,7 +24,7 @@ @Data @EqualsAndHashCode(callSuper = false) @Event(name = "Metadata") -public final class MetadataEvent extends GenericEvent { +public final class MetadataEvent extends NIP01Event { private static final String NAME_PATTERN = "\\w[\\w\\-]+\\w"; diff --git a/nostr-java-event/src/main/java/nostr/event/impl/NostrMarketplaceEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/NostrMarketplaceEvent.java index 5d64bdb11..9c335afbf 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/NostrMarketplaceEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/NostrMarketplaceEvent.java @@ -1,10 +1,12 @@ package nostr.event.impl; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.ArrayList; import java.util.List; import java.util.UUID; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; @@ -28,9 +30,6 @@ @Event(name = "", nip = 15) public abstract class NostrMarketplaceEvent extends ParameterizedReplaceableEvent { - protected NostrMarketplaceEvent() { - super(); - } public NostrMarketplaceEvent(PublicKey sender, Integer kind, List tags, IContent content) { super(sender, kind, tags, content.toString()); } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/ParameterizedReplaceableEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ParameterizedReplaceableEvent.java index ee18501be..acebe4adf 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/ParameterizedReplaceableEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ParameterizedReplaceableEvent.java @@ -1,12 +1,13 @@ package nostr.event.impl; import java.util.List; + import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.extern.java.Log; import nostr.base.PublicKey; import nostr.base.annotation.Event; import nostr.event.BaseTag; +import nostr.event.NIP01Event; /** * @@ -14,14 +15,19 @@ */ @Data @EqualsAndHashCode(callSuper = false) -@Event(name = "Parameterized Replaceable Events", nip = 33) -public class ParameterizedReplaceableEvent extends ReplaceableEvent { +@Event(name = "Parameterized Replaceable Events", nip = 1) +public class ParameterizedReplaceableEvent extends NIP01Event { - protected ParameterizedReplaceableEvent() { - super(); + public ParameterizedReplaceableEvent(PublicKey sender, Integer kind, List tags, String content) { + super(sender, kind, tags, content); } - public ParameterizedReplaceableEvent(PublicKey sender, Integer kind, List tags, String content) { - super(sender, kind, tags, content, 30_000, 40_000); + @Override + protected void validate() { + var n = getKind(); + if (30000 <= n && n < 40000) + return; + + throw new AssertionError("Invalid kind value. Must be between 30000 and 40000", null); } } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/ReactionEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ReactionEvent.java index 646b7d338..1ae62c247 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/ReactionEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ReactionEvent.java @@ -1,18 +1,15 @@ package nostr.event.impl; -import java.net.URL; -import java.util.ArrayList; import java.util.List; -import nostr.event.Kind; -import nostr.base.PublicKey; -import nostr.event.Reaction; + import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NonNull; -import lombok.extern.java.Log; -import nostr.base.ElementAttribute; +import nostr.base.PublicKey; import nostr.base.annotation.Event; import nostr.event.BaseTag; +import nostr.event.Kind; +import nostr.event.NIP25Event; +import nostr.event.Reaction; import nostr.event.tag.EventTag; /** @@ -22,7 +19,7 @@ @Data @EqualsAndHashCode(callSuper = false) @Event(name = "Reactions", nip = 25) -public class ReactionEvent extends GenericEvent { +public class ReactionEvent extends NIP25Event { public ReactionEvent(PublicKey pubKey, List tags, Reaction reaction) { super(pubKey, Kind.REACTION, tags, reaction.getEmoji()); @@ -34,23 +31,27 @@ public ReactionEvent(PublicKey pubKey, GenericEvent event, Reaction reaction) { this.addTag(EventTag.builder().idEvent(event.getId()).build()); } - public ReactionEvent(PublicKey pubKey, GenericEvent event, String content, @NonNull URL emoji) { + public ReactionEvent(PublicKey pubKey, GenericEvent event, String content) { super(pubKey, Kind.REACTION); this.setContent(content); this.addTag(EventTag.builder().idEvent(event.getId()).build()); - addEmojiTag(content, emoji, getTags()); } - public ReactionEvent(PublicKey pubKey, List tags, String content, @NonNull URL emoji) { - super(pubKey, Kind.REACTION, tags); + public ReactionEvent(PublicKey pubKey, String idEvent, String content) { + super(pubKey, Kind.REACTION); this.setContent(content); - addEmojiTag(content, emoji, tags); + this.addTag(EventTag.builder().idEvent(idEvent).build()); } - private void addEmojiTag(String content, URL emoji, List tags) { - List attributes = new ArrayList<>(); - attributes.add(ElementAttribute.builder().name("shortcode").nip(30).value(content).build()); - attributes.add(ElementAttribute.builder().name("url").nip(30).value(emoji.toString()).build()); - tags.add(new GenericTag("emoji", 30, attributes)); + public ReactionEvent(PublicKey pubKey, List tags, String content) { + super(pubKey, Kind.REACTION, tags); + this.setContent(content); } + +// private void addEmojiTag(String content, URL emoji, List tags) { +// List attributes = new ArrayList<>(); +// attributes.add(ElementAttribute.builder().name("shortcode").nip(30).value(content).build()); +// attributes.add(ElementAttribute.builder().name("url").nip(30).value(emoji.toString()).build()); +// tags.add(new GenericTag("emoji", 30, attributes)); +// } } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/ReplaceableEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ReplaceableEvent.java index 617abbe8a..bea6c4b64 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/ReplaceableEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ReplaceableEvent.java @@ -1,12 +1,13 @@ package nostr.event.impl; import java.util.List; -import nostr.base.PublicKey; + import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.extern.java.Log; +import nostr.base.PublicKey; import nostr.base.annotation.Event; import nostr.event.BaseTag; +import nostr.event.NIP01Event; /** * @@ -14,32 +15,19 @@ */ @Data @EqualsAndHashCode(callSuper = false) -@Event(name = "Replaceable Events", nip = 16) -public class ReplaceableEvent extends GenericEvent { - - private final int minKind; - private final int maxKind; - - protected ReplaceableEvent() { - this.minKind = 0; - this.maxKind = 0; - } +@Event(name = "Replaceable Events", nip = 1) +public class ReplaceableEvent extends NIP01Event { public ReplaceableEvent(PublicKey sender, Integer kind, List tags, String content) { - this(sender, kind, tags, content, 10_000, 20_000); - } - - protected ReplaceableEvent(PublicKey sender, Integer kind, List tags, String content, int minKind, int maxKind) { super(sender, kind, tags, content); - this.minKind = minKind; - this.maxKind = maxKind; } @Override protected void validate() { - if (this.getKind() >= this.minKind && this.getKind() < this.maxKind) { + var n = getKind(); + if ((10000 <= n && n < 20000) || n == 0 || n == 3) return; - } - throw new AssertionError(String.format("Invalid kind value. Must be between %d and %d (excl)", this.minKind, this.maxKind), null); + + throw new AssertionError("Invalid kind value. Must be between 10000 and 20000 or egual 0 or 3", null); } } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/TextNoteEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/TextNoteEvent.java index 92d1e98ac..ae6dd050b 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/TextNoteEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/TextNoteEvent.java @@ -2,17 +2,19 @@ package nostr.event.impl; import java.util.List; + import nostr.base.PublicKey; -import nostr.event.Kind; import nostr.base.annotation.Event; import nostr.event.BaseTag; +import nostr.event.Kind; +import nostr.event.NIP01Event; /** * * @author squirrel */ @Event(name = "Text Note") -public class TextNoteEvent extends GenericEvent { +public class TextNoteEvent extends NIP01Event { public TextNoteEvent(PublicKey pubKey, List tags, String content) { super(pubKey, Kind.TEXT_NOTE, tags, content); diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventEncoder.java index c625933b0..3037023b3 100644 --- a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventEncoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventEncoder.java @@ -1,13 +1,12 @@ package nostr.event.json.codec; -import com.fasterxml.jackson.core.JsonProcessingException; import java.lang.reflect.Field; +import com.fasterxml.jackson.core.JsonProcessingException; + import lombok.AllArgsConstructor; import lombok.Data; -import lombok.extern.java.Log; import nostr.base.IEncoder; -import static nostr.base.IEncoder.MAPPER; import nostr.base.NipUtil; import nostr.base.Relay; import nostr.event.BaseEvent; diff --git a/nostr-java-event/src/main/java/nostr/event/tag/PubKeyTag.java b/nostr-java-event/src/main/java/nostr/event/tag/PubKeyTag.java index 8ed32e9e7..014d5cd28 100644 --- a/nostr-java-event/src/main/java/nostr/event/tag/PubKeyTag.java +++ b/nostr-java-event/src/main/java/nostr/event/tag/PubKeyTag.java @@ -45,6 +45,10 @@ public class PubKeyTag extends BaseTag { @JsonInclude(JsonInclude.Include.NON_NULL) private String petName; + public PubKeyTag(@NonNull PublicKey publicKey) { + this.publicKey = publicKey; + } + public PubKeyTag(@NonNull PublicKey publicKey, String mainRelayUrl, String petName) { this.publicKey = publicKey; this.mainRelayUrl = mainRelayUrl; diff --git a/nostr-java-event/src/main/java/nostr/event/util/Nip05Validator.java b/nostr-java-event/src/main/java/nostr/event/util/Nip05Validator.java index f1c6d6925..712b53c00 100644 --- a/nostr-java-event/src/main/java/nostr/event/util/Nip05Validator.java +++ b/nostr-java-event/src/main/java/nostr/event/util/Nip05Validator.java @@ -9,6 +9,7 @@ import java.net.URL; import java.util.Map; import java.util.logging.Level; + import lombok.Builder; import lombok.Data; import lombok.extern.java.Log; @@ -33,8 +34,9 @@ public class Nip05Validator { public void validate() throws NostrException { if (this.nip05 != null) { - var localPart = nip05.split("@")[0]; - var domain = nip05.split("@")[1]; + var splited = nip05.split("@"); + var localPart = splited[0]; + var domain = splited[1]; if (!localPart.matches(LOCAL_PART_PATTERN)) { throw new NostrException("Invalid syntax in nip05 attribute."); @@ -45,6 +47,7 @@ public void validate() throws NostrException { log.log(Level.FINE, "Validating {0}@{1}", new Object[]{localPart, domain}); validatePublicKey(domain, localPart); } catch (IOException | URISyntaxException ex) { + log.log(Level.SEVERE, ex.getMessage()); throw new NostrException(ex); } } diff --git a/nostr-java-examples/src/main/java/nostr/examples/NostrApiExamples.java b/nostr-java-examples/src/main/java/nostr/examples/NostrApiExamples.java index 0bc548356..400d6a440 100644 --- a/nostr-java-examples/src/main/java/nostr/examples/NostrApiExamples.java +++ b/nostr-java-examples/src/main/java/nostr/examples/NostrApiExamples.java @@ -5,20 +5,20 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.LogManager; + import lombok.extern.java.Log; import nostr.api.NIP01; import nostr.api.NIP04; import nostr.api.NIP05; import nostr.api.NIP08; import nostr.api.NIP09; -import nostr.api.NIP16; import nostr.api.NIP25; import nostr.api.NIP28; import nostr.api.Nostr; @@ -30,8 +30,16 @@ import nostr.event.Reaction; import nostr.event.impl.ChannelCreateEvent; import nostr.event.impl.ChannelMessageEvent; +import nostr.event.impl.DeletionEvent; +import nostr.event.impl.DirectMessageEvent; +import nostr.event.impl.EphemeralEvent; import nostr.event.impl.Filters; import nostr.event.impl.GenericEvent; +import nostr.event.impl.InternetIdentifierMetadataEvent; +import nostr.event.impl.MentionsEvent; +import nostr.event.impl.MetadataEvent; +import nostr.event.impl.ReactionEvent; +import nostr.event.impl.TextNoteEvent; import nostr.event.list.KindList; import nostr.event.tag.EventTag; import nostr.event.tag.PubKeyTag; @@ -45,16 +53,18 @@ @Log public class NostrApiExamples { - private static final Identity RECEIVER = Identity.generateRandomIdentity(); + private static final Identity RECIPIENT = Identity.generateRandomIdentity(); private static final Identity SENDER = Identity.generateRandomIdentity(); - private static final UserProfile PROFILE = new UserProfile(SENDER.getPublicKey(), "erict875", "erict875@nostr-java.io", "It's me!", null); + private static final UserProfile PROFILE = new UserProfile(SENDER.getPublicKey(), "Nostr Guy", "guy@nostr-java.io", "It's me!", null); + private final static Map RELAYS = Map.of("lol", "nos.lol", "damus", "relay.damus.io", "ZBD", + "nostr.zebedee.cloud", "taxi", "relay.taxi", "mom", "nostr.mom"); static { final LogManager logManager = LogManager.getLogManager(); try (final InputStream is = NostrApiExamples.class - .getResourceAsStream("/logging.properties")) { - logManager.readConfiguration(is); + .getResourceAsStream("/logging.properties")) { + logManager.readConfiguration(is); } catch (IOException ex) { System.exit(-1000); } @@ -65,7 +75,7 @@ public class NostrApiExamples { throw new RuntimeException(e); } } - + public static void main(String[] args) throws Exception { try { log.log(Level.FINE, "================= The Beginning"); @@ -73,64 +83,64 @@ public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newFixedThreadPool(10); - executor.submit(() -> { - sendTextNoteEvent(); - }); - - executor.submit(() -> { - sendEncryptedDirectMessage(); - }); - - executor.submit(() -> { - mentionsEvent(); - }); - - executor.submit(() -> { - deletionEvent(); - }); - - executor.submit(() -> { - metaDataEvent(); - }); - - executor.submit(() -> { - ephemerealEvent(); - }); - - executor.submit(() -> { - reactionEvent(); - }); - - executor.submit(() -> { - replaceableEvent(); - }); - +// executor.submit(() -> { +// metaDataEvent(); +// }); +// +// executor.submit(() -> { +// sendTextNoteEvent(); +// }); + +// executor.submit(() -> { +// sendEncryptedDirectMessage(); +// }); + +// executor.submit(() -> { +// mentionsEvent(); +// }); + +// executor.submit(() -> { +// deletionEvent(); +// }); +// +// executor.submit(() -> { +// ephemerealEvent(); +// }); +// +// executor.submit(() -> { +// reactionEvent(); +// }); +// +// executor.submit(() -> { +// replaceableEvent(); +// }); +// executor.submit(() -> { internetIdMetadata(); }); - - executor.submit(() -> { - filters(); - }); - - executor.submit(() -> { - createChannel(); - }); - executor.submit(() -> { - updateChannelMetadata(); - }); - - executor.submit(() -> { - sendChannelMessage(); - }); - - executor.submit(() -> { - hideMessage(); - }); - - executor.submit(() -> { - muteUser(); - }); +// +// executor.submit(() -> { +// filters(); +// }); +// +// executor.submit(() -> { +// createChannel(); +// }); +// executor.submit(() -> { +// updateChannelMetadata(); +// }); +// +// executor.submit(() -> { +// sendChannelMessage(); +// }); +// +// executor.submit(() -> { +// hideMessage(); +// }); +// +// executor.submit(() -> { +// muteUser(); +// }); stop(executor); @@ -144,102 +154,115 @@ public static void main(String[] args) throws Exception { } } - private static void sendTextNoteEvent() { + private static TextNoteEvent sendTextNoteEvent() { logHeader("sendTextNoteEvent"); - PubKeyTag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build(); - List tags = new ArrayList<>(); - tags.add(rcptTag); + List tags = List.of(new PubKeyTag(RECIPIENT.getPublicKey())); - var event = NIP01.createTextNoteEvent(tags, "Hello world, I'm here on nostr-java API!"); - Nostr.sign(event); - Nostr.send(event); + var nip01 = new NIP01(SENDER); + nip01.createTextNoteEvent(tags, "Hello world, I'm here on nostr-java API!") + .sign() + .send(RELAYS); + + return nip01.getEvent(); } private static void sendEncryptedDirectMessage() { logHeader("sendEncryptedDirectMessage"); - var event2 = NIP04.createDirectMessageEvent(RECEIVER.getPublicKey(), "Hello Nakamoto!"); - NIP04.encrypt(SENDER, event2); - Nostr.sign(event2); - Nostr.send(event2); + var nip04 = new NIP04(SENDER, RECIPIENT.getPublicKey()); + nip04.createDirectMessageEvent("Hello Nakamoto!") + .encrypt() + .sign() + .send(RELAYS); } private static void mentionsEvent() { logHeader("mentionsEvent"); - List publicKeys = new ArrayList<>(); - publicKeys.add(RECEIVER.getPublicKey()); + List tags = List.of(new PubKeyTag(RECIPIENT.getPublicKey())); - var event = NIP08.createMentionsEvent(publicKeys, "Hello #[1]"); - Nostr.sign(event); - Nostr.send(event); + var nip08 = new NIP08(SENDER); + nip08.createMentionsEvent(tags, "Hello #[0]") + .sign() + .send(RELAYS); } - private static void deletionEvent() { - logHeader("deletionEvent"); - - var event = NIP01.createTextNoteEvent("Hello Astral, Please delete me!"); - Nostr.sign(event); - Nostr.send(event); + private static void deletionEvent() { + logHeader("deletionEvent"); - List tags = new ArrayList<>(); - tags.add(EventTag.builder().idEvent(event.getId()).build()); - var delEvent = NIP09.createDeletionEvent(tags); + var event = sendTextNoteEvent(); + List tags = List.of(new EventTag(event.getId())); - Nostr.sign(delEvent); - Nostr.send(delEvent); - } + var nip09 = new NIP09(SENDER); + nip09.createDeletionEvent(tags) + .sign() + .send(); + } - private static void metaDataEvent() { + private static MetadataEvent metaDataEvent() { logHeader("metaDataEvent"); - var event = NIP01.createMetadataEvent(PROFILE); - Nostr.sign(event); - Nostr.send(event); + var nip01 = new NIP01(SENDER); + nip01.createMetadataEvent(PROFILE) + .sign() + .send(RELAYS); + + return nip01.getEvent(); } private static void ephemerealEvent() { - logHeader("ephemerealEvent"); - - var event = NIP16.createEphemeralEvent(Integer.SIZE, "An ephemereal event"); - Nostr.sign(event); - Nostr.send(event); + logHeader("ephemeralEvent"); + var nip01 = new NIP01(SENDER); + nip01.createEphemeralEvent(21000, "An ephemeral event") + .sign() + .send(RELAYS); } private static void reactionEvent() { logHeader("reactionEvent"); - var event = NIP01.createTextNoteEvent("Hello Astral, Please like me!"); - Nostr.sign(event); - Nostr.send(event); - - var reactionEvent = NIP25.createReactionEvent(event, Reaction.LIKE); - Nostr.sign(reactionEvent); - Nostr.send(reactionEvent); + var nip01 = new NIP01(SENDER); + var event = nip01.createTextNoteEvent("Hello Astral, Please like me!") + .sign() + .send(RELAYS); + + var nip25 = new NIP25(RECIPIENT); + nip25.createReactionEvent(event, Reaction.LIKE) + .sign() + .send(RELAYS); + + nip25.createReactionEvent(event, "💩") + .sign() + .send(); } private static void replaceableEvent() { logHeader("replaceableEvent"); - var event = NIP01.createTextNoteEvent("Hello Astral, Please replace me!"); - Nostr.sign(event); - Nostr.send(event); + var nip01 = new NIP01(SENDER); + var event = nip01.createTextNoteEvent("Hello Astral, Please replace me!") + .sign() + .send(RELAYS); - List tags = new ArrayList<>(); - tags.add(EventTag.builder().idEvent(event.getId()).build()); - var replaceableEvent = NIP16.createReplaceableEvent(tags, 15_000, "New content"); - Nostr.sign(replaceableEvent); - Nostr.send(replaceableEvent); + nip01.createReplaceableEvent(List.of(new EventTag(event.getId())), 15_000, "New content") + .sign() + .send(); } private static void internetIdMetadata() { logHeader("internetIdMetadata"); - - var event = NIP05.createInternetIdentifierMetadataEvent(PROFILE); - Nostr.sign(event); - Nostr.send(event); + var profile = UserProfile.builder() + .name("Guilherme Gps") + .publicKey(new PublicKey("21ef0d8541375ae4bca85285097fba370f7e540b5a30e5e75670c16679f9d144")) + .nip05("me@guilhermegps.com.br") + .build(); + + var nip05 = new NIP05(SENDER); + nip05.createInternetIdentifierMetadataEvent(profile) + .sign() + .send(RELAYS); } public static void filters() { @@ -251,7 +274,7 @@ public static void filters() { Filters filters = NIP01.createFilters(null, null, kindList, null, null, null, null, null, null); String subId = "subId" + System.currentTimeMillis(); - Nostr.send(filters, subId); + Nostr.getInstance().send(filters, subId); } private static GenericEvent createChannel() { @@ -261,8 +284,7 @@ private static GenericEvent createChannel() { var channel = new ChannelProfile("JNostr Channel", "This is a channel to test NIP28 in nostr-java", "https://cdn.pixabay.com/photo/2020/05/19/13/48/cartoon-5190942_960_720.jpg"); var event = NIP28.createChannelCreateEvent(channel); - Nostr.sign(event); - Nostr.send(event); + Nostr.getInstance().sign(SENDER, event).send(event); return event; } catch (MalformedURLException | URISyntaxException ex) { @@ -285,8 +307,7 @@ private static void updateChannelMetadata() { var event = NIP28.createChannelCreateEvent(channel); event.addTag(tag); - Nostr.sign(event); - Nostr.send(event); + Nostr.getInstance().sign(SENDER, event).send(event); } catch (MalformedURLException | URISyntaxException ex) { throw new RuntimeException(ex); } @@ -299,8 +320,7 @@ private static GenericEvent sendChannelMessage() { var channelCreateEvent = createChannel(); GenericEvent event = NIP28.createChannelMessageEvent((ChannelCreateEvent) channelCreateEvent, "Hello everybody!"); - Nostr.sign(event); - Nostr.send(event); + Nostr.getInstance().sign(SENDER, event).send(event); return event; } @@ -312,8 +332,7 @@ private static GenericEvent hideMessage() { GenericEvent event = NIP28.createHideMessageEvent((ChannelMessageEvent) channelMessageEvent, "Dick pic"); - Nostr.sign(event); - Nostr.send(event); + Nostr.getInstance().sign(SENDER, event).send(event); return event; } @@ -321,10 +340,9 @@ private static GenericEvent hideMessage() { private static GenericEvent muteUser() { logHeader("muteUser"); - GenericEvent event = NIP28.createMuteUserEvent(RECEIVER.getPublicKey(), "Posting dick pics"); + GenericEvent event = NIP28.createMuteUserEvent(RECIPIENT.getPublicKey(), "Posting dick pics"); - Nostr.sign(event); - Nostr.send(event); + Nostr.getInstance().sign(SENDER, event).send(event); return event; } @@ -332,10 +350,10 @@ private static GenericEvent muteUser() { private static void logAccountsData() { String msg = "################################ ACCOUNTS BEGINNING ################################" + '\n' + "*** RECEIVER ***" + '\n' + - '\n' + "* PrivateKey: " + RECEIVER.getPrivateKey().getBech32() + - '\n' + "* PrivateKey HEX: " + RECEIVER.getPrivateKey().toString() + - '\n' + "* PublicKey: " + RECEIVER.getPublicKey().getBech32() + - '\n' + "* PublicKey HEX: " + RECEIVER.getPublicKey().toString() + + '\n' + "* PrivateKey: " + RECIPIENT.getPrivateKey().getBech32() + + '\n' + "* PrivateKey HEX: " + RECIPIENT.getPrivateKey().toString() + + '\n' + "* PublicKey: " + RECIPIENT.getPublicKey().getBech32() + + '\n' + "* PublicKey HEX: " + RECIPIENT.getPublicKey().toString() + '\n' + '\n' + "*** SENDER ***" + '\n' + '\n' + "* PrivateKey: " + SENDER.getPrivateKey().getBech32() + '\n' + "* PrivateKey HEX: " + SENDER.getPrivateKey().toString() + diff --git a/nostr-java-id/src/main/java/nostr/id/Identity.java b/nostr-java-id/src/main/java/nostr/id/Identity.java index 967e991c1..e2d89d38f 100644 --- a/nostr-java-id/src/main/java/nostr/id/Identity.java +++ b/nostr-java-id/src/main/java/nostr/id/Identity.java @@ -1,5 +1,8 @@ package nostr.id; +import java.io.IOException; +import java.util.logging.Level; + import lombok.Data; import lombok.NonNull; import lombok.ToString; @@ -13,9 +16,6 @@ import nostr.util.AbstractBaseConfiguration; import nostr.util.NostrException; -import java.io.IOException; -import java.util.logging.Level; - /** * @author squirrel */ @@ -73,8 +73,8 @@ public Signature sign(@NonNull ISignable signable) { } /** - * @return A strong pseudo random Identity - */ + * @return A strong pseudo random identity + */ public static Identity generateRandomIdentity() { return new Identity(PrivateKey.generateRandomPrivKey()); } diff --git a/nostr-java-id/src/main/java/nostr/id/IdentityHelper.java b/nostr-java-id/src/main/java/nostr/id/IdentityHelper.java index bf32804e5..efc147953 100644 --- a/nostr-java-id/src/main/java/nostr/id/IdentityHelper.java +++ b/nostr-java-id/src/main/java/nostr/id/IdentityHelper.java @@ -1,9 +1,32 @@ package nostr.id; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Base64; +import java.util.logging.Level; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.math.ec.custom.sec.SecP256K1Curve; + import lombok.AllArgsConstructor; import lombok.NonNull; import lombok.extern.java.Log; -import nostr.base.*; +import nostr.base.ISignable; +import nostr.base.ITag; +import nostr.base.PrivateKey; +import nostr.base.PublicKey; +import nostr.base.Signature; import nostr.crypto.schnorr.Schnorr; import nostr.event.impl.DirectMessageEvent; import nostr.event.impl.GenericEvent; @@ -11,23 +34,6 @@ import nostr.event.tag.PubKeyTag; import nostr.util.NostrException; import nostr.util.NostrUtil; -import org.bouncycastle.math.ec.ECPoint; -import org.bouncycastle.math.ec.custom.sec.SecP256K1Curve; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import java.util.Base64; -import java.util.logging.Level; @AllArgsConstructor @Log diff --git a/nostr-java-test/src/test/java/nostr/test/event/ApiEventTest.java b/nostr-java-test/src/test/java/nostr/test/event/ApiEventTest.java index f8dbf2e3c..7154cfc6f 100644 --- a/nostr-java-test/src/test/java/nostr/test/event/ApiEventTest.java +++ b/nostr-java-test/src/test/java/nostr/test/event/ApiEventTest.java @@ -1,10 +1,15 @@ package nostr.test.event; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.HashMap; import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + import nostr.api.NIP01; import nostr.api.NIP04; import nostr.api.NIP15; @@ -17,12 +22,12 @@ import nostr.event.BaseTag; import nostr.event.impl.CreateOrUpdateStallEvent; import nostr.event.impl.CreateOrUpdateStallEvent.Stall; +import nostr.event.impl.DirectMessageEvent; import nostr.event.impl.NostrMarketplaceEvent; import nostr.event.impl.NostrMarketplaceEvent.Product.Spec; +import nostr.event.impl.TextNoteEvent; import nostr.id.Identity; import nostr.util.NostrException; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; /** * @@ -41,7 +46,9 @@ public void testNIP01CreateTextNoteEvent() throws NostrException { List tags = new ArrayList<>(); tags.add(recipient); - var instance = NIP01.createTextNoteEvent(tags, "Hello simplified nostr-java!"); + var nip01 = new NIP01(Identity.getInstance()); + var instance = nip01.createTextNoteEvent(tags, "Hello simplified nostr-java!") + .getEvent(); instance.update(); Assertions.assertNotNull(instance.getId()); @@ -57,11 +64,13 @@ public void testNIP01CreateTextNoteEvent() throws NostrException { public void testNIP01SendTextNoteEvent() { System.out.println("testNIP01SendTextNoteEvent"); - var instance = NIP01.createTextNoteEvent("Hello simplified nostr-java!"); + var nip01 = new NIP01(Identity.getInstance()); + var instance = nip01.createTextNoteEvent("Hello simplified nostr-java!") + .sign(); - var signature = Nostr.sign(instance); + var signature = instance.getEvent().getSignature(); Assertions.assertNotNull(signature); - Nostr.send(instance); + instance.send(); } @Test @@ -70,10 +79,13 @@ public void testNIP04SendDirectMessage() { PublicKey nostr_java = new PublicKey(NOSTR_JAVA_PUBKEY); - var instance = NIP04.createDirectMessageEvent(nostr_java, "Quand on n'a que l'amour pour tracer un chemin et forcer le destin..."); - var signature = Nostr.sign(instance); + var nip04 = new NIP04(Identity.getInstance(), nostr_java); + var instance = nip04.createDirectMessageEvent("Quand on n'a que l'amour pour tracer un chemin et forcer le destin...") + .sign(); + + var signature = instance.getEvent().getSignature(); Assertions.assertNotNull(signature); - Nostr.send(instance); + instance.send(); } @Test @@ -82,10 +94,11 @@ public void testNIP04EncryptDecrypt() throws NostrException { var nostr_java = new PublicKey(NOSTR_JAVA_PUBKEY); - var instance = NIP04.createDirectMessageEvent(nostr_java, "Quand on n'a que l'amour pour tracer un chemin et forcer le destin..."); - NIP04.encrypt(Identity.getInstance(), instance); - Nostr.sign(instance); - var message = NIP04.decrypt(Identity.getInstance(), instance); + var nip04 = new NIP04(Identity.getInstance(), nostr_java); + var instance = nip04.createDirectMessageEvent("Quand on n'a que l'amour pour tracer un chemin et forcer le destin...") + .encrypt() + .sign(); + var message = NIP04.decrypt(Identity.getInstance(), instance.getEvent()); Assertions.assertEquals("Quand on n'a que l'amour pour tracer un chemin et forcer le destin...", message); } @@ -98,9 +111,10 @@ public void testNIP15CreateStallEvent() throws JsonProcessingException { // Create and send the nostr event var instance = NIP15.createCreateOrUpdateStallEvent(stall); - var signature = Nostr.sign(instance); + Nostr.getInstance().sign(instance); + var signature = instance.getSignature(); Assertions.assertNotNull(signature); - Nostr.send(instance); + Nostr.getInstance().send(instance); // Fetch the content and compare with the above original var content = instance.getContent(); @@ -118,16 +132,17 @@ public void testNIP15UpdateStallEvent() { // Create and send the nostr event var instance = NIP15.createCreateOrUpdateStallEvent(stall); - var signature = Nostr.sign(instance); + Nostr.getInstance().sign(instance); + var signature = instance.getSignature(); Assertions.assertNotNull(signature); - Nostr.send(instance); + Nostr.getInstance().send(instance); // Update the shipping var shipping = stall.getShipping(); shipping.setCost(20.00f); instance = NIP15.createCreateOrUpdateStallEvent(stall); - Nostr.sign(instance); - Nostr.send(instance); + Nostr.getInstance().sign(instance); + Nostr.getInstance().send(instance); } @Test @@ -146,8 +161,8 @@ public void testNIP15CreateProductEvent() { categories.add("Hommes"); var instance = NIP15.createCreateOrUpdateProductEvent(product, categories); - Nostr.sign(instance); - Nostr.send(instance); + Nostr.getInstance().sign(instance); + Nostr.getInstance().send(instance); } @Test @@ -166,14 +181,14 @@ public void testNIP15UpdateProductEvent() { categories.add("Hommes"); var instance = NIP15.createCreateOrUpdateProductEvent(product, categories); - Nostr.sign(instance); - Nostr.send(instance); + Nostr.getInstance().sign(instance); + Nostr.getInstance().send(instance); product.setDescription("Un nouveau bijou en or"); categories.add("bagues"); - Nostr.sign(instance); - Nostr.send(instance); + Nostr.getInstance().sign(instance); + Nostr.getInstance().send(instance); } @Test