From 44a43af09c1521688ac871754cd46b5fdc584629 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 1 Jun 2023 07:17:25 +0100 Subject: [PATCH 01/37] Extensive refactoring and Bugfixes --- .../main/java/nostr/base/NostrKeyPair.java | 27 - .../nostr/event/impl/ChannelCreateEvent.java | 20 - .../event/impl/ChannelMetadataEvent.java | 20 - .../nostr/event/impl/HideMessageEvent.java | 20 - .../java/nostr/event/impl/MentionsEvent.java | 57 -- .../java/nostr/event/impl/MetadataEvent.java | 80 --- .../java/nostr/event/impl/MuteUserEvent.java | 20 - .../serializer/CustomBaseListSerializer.java | 65 -- .../java/nostr/examples/NostrExamples.java | 657 ------------------ .../nb-configuration.xml | 0 {nostr-base => nostr-java-base}/pom.xml | 8 +- .../src/main/java/module-info.java | 0 .../src/main/java/nostr/base/BaseKey.java | 0 .../src/main/java/nostr/base/Channel.java | 0 .../main/java/nostr/base/ChannelProfile.java | 20 + .../src/main/java/nostr/base/Command.java | 0 .../main/java/nostr/base/ContentReason.java | 16 +- .../java/nostr/base/ElementAttribute.java | 0 .../main/java/nostr/base/GenericTagQuery.java | 0 .../java/nostr/base/IBech32Encodable.java | 0 .../src/main/java/nostr/base/IElement.java | 0 .../src/main/java/nostr/base/IEvent.java | 0 .../main/java/nostr/base/IGenericElement.java | 0 .../src/main/java/nostr/base/IHandler.java | 0 .../src/main/java/nostr/base/IKey.java | 0 .../src/main/java/nostr/base/IMarshaller.java | 0 .../src/main/java/nostr/base/INostrList.java | 0 .../src/main/java/nostr/base/ISignable.java | 0 .../src/main/java/nostr/base/ITag.java | 0 .../main/java/nostr/base/IUnmarshaller.java | 0 .../src/main/java/nostr/base/KeyType.java | 0 .../src/main/java/nostr/base/NipUtil.java | 15 +- .../src/main/java/nostr/base/PrivateKey.java | 0 .../src/main/java/nostr/base/Profile.java | 27 + .../src/main/java/nostr/base/PublicKey.java | 0 .../src/main/java/nostr/base/Relay.java | 46 +- .../src/main/java/nostr/base/Signature.java | 0 .../src/main/java/nostr/base/UserProfile.java | 26 +- .../nostr/base/annotation/DefaultHandler.java | 0 .../java/nostr/base/annotation/Event.java | 0 .../java/nostr/base/annotation/JsonList.java | 0 .../nostr/base/annotation/JsonString.java | 0 .../main/java/nostr/base/annotation/Key.java | 0 .../main/java/nostr/base/annotation/Tag.java | 0 .../src/main/resources/app.properties | 4 + .../nb-configuration.xml | 0 {nostr-crypto => nostr-java-crypto}/pom.xml | 8 +- .../src/main/java/module-info.java | 0 .../src/main/java/nostr/crypto/Pair.java | 0 .../src/main/java/nostr/crypto/Point.java | 0 .../main/java/nostr/crypto/bech32/Bech32.java | 0 .../nostr/crypto/bech32/Bech32Prefix.java | 0 .../java/nostr/crypto/schnorr/Schnorr.java | 0 {nostr-event => nostr-java-event}/README.md | 0 .../nb-configuration.xml | 0 {nostr-event => nostr-java-event}/pom.xml | 8 +- .../src/main/java/module-info.java | 0 .../src/main/java/nostr/event/BaseEvent.java | 0 .../main/java/nostr/event/BaseMessage.java | 0 .../src/main/java/nostr/event/BaseTag.java | 0 .../src/main/java/nostr/event/Kind.java | 0 .../src/main/java/nostr/event/Marker.java | 0 .../src/main/java/nostr/event/Reaction.java | 0 .../nostr/event/impl/ChannelCreateEvent.java | 44 ++ .../nostr/event/impl/ChannelMessageEvent.java | 7 +- .../event/impl/ChannelMetadataEvent.java | 42 ++ .../event/impl/ClientAuthenticationEvent.java | 32 +- .../java/nostr/event/impl/DeletionEvent.java | 7 + .../nostr/event/impl/DirectMessageEvent.java | 7 + .../java/nostr/event/impl/EphemeralEvent.java | 6 + .../main/java/nostr/event/impl/Filters.java | 0 .../java/nostr/event/impl/GenericEvent.java | 47 +- .../java/nostr/event/impl/GenericMessage.java | 0 .../java/nostr/event/impl/GenericTag.java | 0 .../nostr/event/impl/HideMessageEvent.java | 27 + .../impl/InternetIdentifierMetadataEvent.java | 47 +- .../java/nostr/event/impl/MentionsEvent.java | 40 ++ .../java/nostr/event/impl/MetadataEvent.java | 71 ++ .../java/nostr/event/impl/MuteUserEvent.java | 26 + .../main/java/nostr/event/impl/OtsEvent.java | 0 .../java/nostr/event/impl/ReactionEvent.java | 11 +- .../nostr/event/impl/ReplaceableEvent.java | 15 +- .../java/nostr/event/impl/TextNoteEvent.java | 0 .../main/java/nostr/event/list/BaseList.java | 0 .../main/java/nostr/event/list/EventList.java | 0 .../java/nostr/event/list/FiltersList.java | 0 .../nostr/event/list/GenericTagQueryList.java | 0 .../main/java/nostr/event/list/KindList.java | 0 .../java/nostr/event/list/PubKeyTagList.java | 0 .../java/nostr/event/list/PublicKeyList.java | 0 .../main/java/nostr/event/list/TagList.java | 0 .../marshaller/impl/ElementMarshaller.java | 25 +- .../marshaller/impl/FilterMarshaller.java | 3 +- .../marshaller/impl/GenericTagMarshaller.java | 25 +- .../marshaller/impl/MessageMarshaller.java | 0 .../marshaller/impl/OstEventMarshaller.java | 0 .../event/marshaller/impl/TagMarshaller.java | 25 +- .../java/nostr/event/message/AuthMessage.java | 0 .../nostr/event/message/CloseMessage.java | 0 .../event/message/ContactListMessage.java | 2 + .../java/nostr/event/message/EoseMessage.java | 0 .../nostr/event/message/EventMessage.java | 0 .../nostr/event/message/NoticeMessage.java | 0 .../java/nostr/event/message/OkMessage.java | 6 + .../java/nostr/event/message/ReqMessage.java | 0 .../serializer/CustomBaseListSerializer.java | 64 ++ .../CustomGenericTagListSerializer.java | 45 +- .../CustomGenericTagSerializer.java | 47 +- .../CustomIdEventListSerializer.java | 19 +- .../event/serializer/CustomTagSerializer.java | 46 +- .../java/nostr/event/tag/DelegationTag.java | 0 .../main/java/nostr/event/tag/EventTag.java | 0 .../main/java/nostr/event/tag/NonceTag.java | 0 .../main/java/nostr/event/tag/PubKeyTag.java | 0 .../main/java/nostr/event/tag/SubjectTag.java | 0 .../java/nostr/event/util/Nip05Validator.java | 0 .../nb-configuration.xml | 0 .../nbactions.xml | 0 .../pom.xml | 18 +- .../src/main/java/module-info.java | 0 .../java/nostr/examples/FilterRelays.java | 0 .../java/nostr/examples/NostrExamples.java | 651 +++++++++++++++++ .../src/main/resources/logging.properties | 0 .../nb-configuration.xml | 0 {nostr-id => nostr-java-id}/pom.xml | 48 +- .../src/main/java/module-info.java | 0 .../src/main/java/nostr/id/Client.java | 44 +- .../src/main/java/nostr/id/Identity.java | 34 +- .../src/main/resources/profile.properties | 0 .../src/main/resources/relays.properties | 0 .../nb-configuration.xml | 0 {nostr-test => nostr-java-test}/pom.xml | 16 +- .../main/java/nostr/test/EntityFactory.java | 219 ++++++ .../java/nostr/test/base/NostrUtilTest.java | 0 .../java/nostr/test/crypto/CryptoTest.java | 0 .../test/java/nostr/test/event/EventTest.java | 32 +- .../test/java/nostr/test/id/ClientTest.java | 19 +- .../test/java/nostr/test/id/IdentityTest.java | 1 - .../src/test/resources/app.properties | 3 + .../src/test/resources/profile.properties | 0 .../nb-configuration.xml | 0 {nostr-util => nostr-java-util}/pom.xml | 4 +- .../src/main/java/module-info.java | 1 + .../nostr/util/AbstractBaseConfiguration.java | 32 +- .../nostr/util/ApplicationConfiguration.java | 85 +++ .../main/java/nostr/util/NostrException.java | 0 .../src/main/java/nostr/util/NostrUtil.java | 0 .../nostr/util/UnsupportedNIPException.java | 0 .../pom.xml | 13 +- .../src/main/java/module-info.java | 2 + .../provider/DefaultCommandHandler.java | 14 +- ...str.ws.handler.command.spi.ICommandHandler | 0 .../pom.xml | 10 +- .../src/main/java/module-info.java | 0 .../handler/command/spi/ICommandHandler.java | 3 +- .../nostr/ws/handler/spi/IRequestHandler.java | 0 .../ws/handler/spi/IResponseHandler.java | 0 .../pom.xml | 8 +- .../src/main/java/module-info.java | 0 .../provider/DefaultRequestHandler.java | 0 .../nostr.ws.handler.spi.IRequestHandler | 0 .../pom.xml | 11 +- .../src/main/java/module-info.java | 0 .../handler/provider/ResponseHandlerImpl.java | 0 .../nostr.ws.handler.spi.IResponseHandler | 0 .../nb-configuration.xml | 0 {nostr-ws => nostr-java-ws}/pom.xml | 12 +- .../src/main/java/module-info.java | 0 .../java/nostr/ws/ClientListenerEndPoint.java | 13 - .../src/main/java/nostr/ws/Connection.java | 2 +- .../src/main/resources/logging.properties | 0 .../main/java/nostr/test/EntityFactory.java | 265 ------- pom.xml | 26 +- 173 files changed, 1846 insertions(+), 1620 deletions(-) delete mode 100644 nostr-base/src/main/java/nostr/base/NostrKeyPair.java delete mode 100644 nostr-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java delete mode 100644 nostr-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java delete mode 100644 nostr-event/src/main/java/nostr/event/impl/HideMessageEvent.java delete mode 100644 nostr-event/src/main/java/nostr/event/impl/MentionsEvent.java delete mode 100644 nostr-event/src/main/java/nostr/event/impl/MetadataEvent.java delete mode 100644 nostr-event/src/main/java/nostr/event/impl/MuteUserEvent.java delete mode 100644 nostr-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java delete mode 100644 nostr-examples/src/main/java/nostr/examples/NostrExamples.java rename {nostr-base => nostr-java-base}/nb-configuration.xml (100%) rename {nostr-base => nostr-java-base}/pom.xml (85%) rename {nostr-base => nostr-java-base}/src/main/java/module-info.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/BaseKey.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/Channel.java (100%) create mode 100644 nostr-java-base/src/main/java/nostr/base/ChannelProfile.java rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/Command.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/ContentReason.java (64%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/ElementAttribute.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/GenericTagQuery.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/IBech32Encodable.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/IElement.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/IEvent.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/IGenericElement.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/IHandler.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/IKey.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/IMarshaller.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/INostrList.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/ISignable.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/ITag.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/IUnmarshaller.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/KeyType.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/NipUtil.java (72%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/PrivateKey.java (100%) create mode 100644 nostr-java-base/src/main/java/nostr/base/Profile.java rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/PublicKey.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/Relay.java (62%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/Signature.java (100%) rename nostr-base/src/main/java/nostr/base/Profile.java => nostr-java-base/src/main/java/nostr/base/UserProfile.java (66%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/annotation/DefaultHandler.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/annotation/Event.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/annotation/JsonList.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/annotation/JsonString.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/annotation/Key.java (100%) rename {nostr-base => nostr-java-base}/src/main/java/nostr/base/annotation/Tag.java (100%) create mode 100644 nostr-java-base/src/main/resources/app.properties rename {nostr-crypto => nostr-java-crypto}/nb-configuration.xml (100%) rename {nostr-crypto => nostr-java-crypto}/pom.xml (89%) rename {nostr-crypto => nostr-java-crypto}/src/main/java/module-info.java (100%) rename {nostr-crypto => nostr-java-crypto}/src/main/java/nostr/crypto/Pair.java (100%) rename {nostr-crypto => nostr-java-crypto}/src/main/java/nostr/crypto/Point.java (100%) rename {nostr-crypto => nostr-java-crypto}/src/main/java/nostr/crypto/bech32/Bech32.java (100%) rename {nostr-crypto => nostr-java-crypto}/src/main/java/nostr/crypto/bech32/Bech32Prefix.java (100%) rename {nostr-crypto => nostr-java-crypto}/src/main/java/nostr/crypto/schnorr/Schnorr.java (100%) rename {nostr-event => nostr-java-event}/README.md (100%) rename {nostr-event => nostr-java-event}/nb-configuration.xml (100%) rename {nostr-event => nostr-java-event}/pom.xml (83%) rename {nostr-event => nostr-java-event}/src/main/java/module-info.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/BaseEvent.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/BaseMessage.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/BaseTag.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/Kind.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/Marker.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/Reaction.java (100%) create mode 100644 nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/ChannelMessageEvent.java (65%) create mode 100644 nostr-java-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java (60%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/DeletionEvent.java (68%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/DirectMessageEvent.java (59%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/EphemeralEvent.java (74%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/Filters.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/GenericEvent.java (80%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/GenericMessage.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/GenericTag.java (100%) create mode 100644 nostr-java-event/src/main/java/nostr/event/impl/HideMessageEvent.java rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java (52%) create mode 100644 nostr-java-event/src/main/java/nostr/event/impl/MentionsEvent.java create mode 100644 nostr-java-event/src/main/java/nostr/event/impl/MetadataEvent.java create mode 100644 nostr-java-event/src/main/java/nostr/event/impl/MuteUserEvent.java rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/OtsEvent.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/ReactionEvent.java (59%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/ReplaceableEvent.java (50%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/impl/TextNoteEvent.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/list/BaseList.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/list/EventList.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/list/FiltersList.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/list/GenericTagQueryList.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/list/KindList.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/list/PubKeyTagList.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/list/PublicKeyList.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/list/TagList.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java (78%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java (92%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java (62%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/marshaller/impl/MessageMarshaller.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java (62%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/message/AuthMessage.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/message/CloseMessage.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/message/ContactListMessage.java (92%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/message/EoseMessage.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/message/EventMessage.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/message/NoticeMessage.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/message/OkMessage.java (78%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/message/ReqMessage.java (100%) create mode 100644 nostr-java-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/serializer/CustomGenericTagListSerializer.java (54%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/serializer/CustomGenericTagSerializer.java (51%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/serializer/CustomIdEventListSerializer.java (65%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/serializer/CustomTagSerializer.java (50%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/tag/DelegationTag.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/tag/EventTag.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/tag/NonceTag.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/tag/PubKeyTag.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/tag/SubjectTag.java (100%) rename {nostr-event => nostr-java-event}/src/main/java/nostr/event/util/Nip05Validator.java (100%) rename {nostr-examples => nostr-java-examples}/nb-configuration.xml (100%) rename {nostr-examples => nostr-java-examples}/nbactions.xml (100%) rename {nostr-examples => nostr-java-examples}/pom.xml (71%) rename {nostr-examples => nostr-java-examples}/src/main/java/module-info.java (100%) rename {nostr-examples => nostr-java-examples}/src/main/java/nostr/examples/FilterRelays.java (100%) create mode 100644 nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java rename {nostr-examples => nostr-java-examples}/src/main/resources/logging.properties (100%) rename {nostr-id => nostr-java-id}/nb-configuration.xml (100%) rename {nostr-id => nostr-java-id}/pom.xml (51%) rename {nostr-id => nostr-java-id}/src/main/java/module-info.java (100%) rename {nostr-id => nostr-java-id}/src/main/java/nostr/id/Client.java (82%) rename {nostr-id => nostr-java-id}/src/main/java/nostr/id/Identity.java (92%) rename {nostr-id => nostr-java-id}/src/main/resources/profile.properties (100%) rename {nostr-id => nostr-java-id}/src/main/resources/relays.properties (100%) rename {nostr-test => nostr-java-test}/nb-configuration.xml (100%) rename {nostr-test => nostr-java-test}/pom.xml (85%) create mode 100644 nostr-java-test/src/main/java/nostr/test/EntityFactory.java rename {nostr-test => nostr-java-test}/src/test/java/nostr/test/base/NostrUtilTest.java (100%) rename {nostr-test => nostr-java-test}/src/test/java/nostr/test/crypto/CryptoTest.java (100%) rename {nostr-test => nostr-java-test}/src/test/java/nostr/test/event/EventTest.java (86%) rename {nostr-test => nostr-java-test}/src/test/java/nostr/test/id/ClientTest.java (67%) rename {nostr-test => nostr-java-test}/src/test/java/nostr/test/id/IdentityTest.java (97%) create mode 100644 nostr-java-test/src/test/resources/app.properties rename {nostr-test => nostr-java-test}/src/test/resources/profile.properties (100%) rename {nostr-util => nostr-java-util}/nb-configuration.xml (100%) rename {nostr-util => nostr-java-util}/pom.xml (89%) rename {nostr-util => nostr-java-util}/src/main/java/module-info.java (91%) rename nostr-base/src/main/java/nostr/base/BaseConfiguration.java => nostr-java-util/src/main/java/nostr/util/AbstractBaseConfiguration.java (75%) create mode 100644 nostr-java-util/src/main/java/nostr/util/ApplicationConfiguration.java rename {nostr-util => nostr-java-util}/src/main/java/nostr/util/NostrException.java (100%) rename {nostr-util => nostr-java-util}/src/main/java/nostr/util/NostrUtil.java (100%) rename {nostr-util => nostr-java-util}/src/main/java/nostr/util/UnsupportedNIPException.java (100%) rename {nostr-ws-response-handler-provider => nostr-java-ws-handler-default-command}/pom.xml (76%) rename {nostr-ws-handler-default-command => nostr-java-ws-handler-default-command}/src/main/java/module-info.java (93%) rename {nostr-ws-handler-default-command => nostr-java-ws-handler-default-command}/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java (78%) rename {nostr-ws-handler-default-command => nostr-java-ws-handler-default-command}/src/main/resources/META-INF/services/nostr.ws.handler.command.spi.ICommandHandler (100%) rename {nostr-ws-handler => nostr-java-ws-handler-interface}/pom.xml (77%) rename {nostr-ws-handler => nostr-java-ws-handler-interface}/src/main/java/module-info.java (100%) rename {nostr-ws-handler => nostr-java-ws-handler-interface}/src/main/java/nostr/ws/handler/command/spi/ICommandHandler.java (92%) rename {nostr-ws-handler => nostr-java-ws-handler-interface}/src/main/java/nostr/ws/handler/spi/IRequestHandler.java (100%) rename {nostr-ws-handler => nostr-java-ws-handler-interface}/src/main/java/nostr/ws/handler/spi/IResponseHandler.java (100%) rename {nostr-ws-request-handler-provider => nostr-java-ws-request-handler-provider}/pom.xml (77%) rename {nostr-ws-request-handler-provider => nostr-java-ws-request-handler-provider}/src/main/java/module-info.java (100%) rename {nostr-ws-request-handler-provider => nostr-java-ws-request-handler-provider}/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java (100%) rename {nostr-ws-request-handler-provider/src/main => nostr-java-ws-request-handler-provider/src/test}/resources/META-INF/services/nostr.ws.handler.spi.IRequestHandler (100%) rename {nostr-ws-handler-default-command => nostr-java-ws-response-handler-provider}/pom.xml (78%) rename {nostr-ws-response-handler-provider => nostr-java-ws-response-handler-provider}/src/main/java/module-info.java (100%) rename {nostr-ws-response-handler-provider => nostr-java-ws-response-handler-provider}/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java (100%) rename {nostr-ws-response-handler-provider => nostr-java-ws-response-handler-provider}/src/main/resources/META-INF/services/nostr.ws.handler.spi.IResponseHandler (100%) rename {nostr-ws => nostr-java-ws}/nb-configuration.xml (100%) rename {nostr-ws => nostr-java-ws}/pom.xml (84%) rename {nostr-ws => nostr-java-ws}/src/main/java/module-info.java (100%) rename {nostr-ws => nostr-java-ws}/src/main/java/nostr/ws/ClientListenerEndPoint.java (87%) rename {nostr-ws => nostr-java-ws}/src/main/java/nostr/ws/Connection.java (96%) rename {nostr-ws => nostr-java-ws}/src/main/resources/logging.properties (100%) delete mode 100644 nostr-test/src/main/java/nostr/test/EntityFactory.java diff --git a/nostr-base/src/main/java/nostr/base/NostrKeyPair.java b/nostr-base/src/main/java/nostr/base/NostrKeyPair.java deleted file mode 100644 index f4ca988b..00000000 --- a/nostr-base/src/main/java/nostr/base/NostrKeyPair.java +++ /dev/null @@ -1,27 +0,0 @@ - -package nostr.base; - -import lombok.Builder; -import lombok.Data; -import lombok.ToString; -import lombok.extern.java.Log; -import nostr.base.annotation.JsonString; - -/** - * - * @author squirrel - */ -@Data -@Log -@ToString -@Builder -@Deprecated(forRemoval = true) -public final class NostrKeyPair { - - @JsonString - private final PublicKey publicKey; - - @JsonString - @ToString.Exclude - private final PrivateKey privateKey; -} diff --git a/nostr-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java b/nostr-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java deleted file mode 100644 index 19c95e58..00000000 --- a/nostr-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java +++ /dev/null @@ -1,20 +0,0 @@ -package nostr.event.impl; - -import lombok.NonNull; -import nostr.base.PublicKey; -import nostr.base.annotation.Event; -import nostr.event.Kind; -import nostr.event.list.TagList; - -/** - * @author guilhermegps - * - */ -@Event(name = "Create Channel", nip = 28) -public class ChannelCreateEvent extends GenericEvent { - - public ChannelCreateEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { - super(pubKey, Kind.CHANNEL_CREATE, tags, content); - } - -} diff --git a/nostr-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java b/nostr-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java deleted file mode 100644 index 6b61d9f2..00000000 --- a/nostr-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java +++ /dev/null @@ -1,20 +0,0 @@ -package nostr.event.impl; - -import lombok.NonNull; -import nostr.base.PublicKey; -import nostr.base.annotation.Event; -import nostr.event.Kind; -import nostr.event.list.TagList; - -/** - * @author guilhermegps - * - */ -@Event(name = "Channel Metadata", nip = 28) -public class ChannelMetadataEvent extends GenericEvent { - - public ChannelMetadataEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { - super(pubKey, Kind.CHANNEL_METADATA, tags, content); - } - -} diff --git a/nostr-event/src/main/java/nostr/event/impl/HideMessageEvent.java b/nostr-event/src/main/java/nostr/event/impl/HideMessageEvent.java deleted file mode 100644 index 3c5c013f..00000000 --- a/nostr-event/src/main/java/nostr/event/impl/HideMessageEvent.java +++ /dev/null @@ -1,20 +0,0 @@ -package nostr.event.impl; - -import lombok.NonNull; -import nostr.base.PublicKey; -import nostr.base.annotation.Event; -import nostr.event.Kind; -import nostr.event.list.TagList; - -/** - * @author guilhermegps - * - */ -@Event(name = "Hide Message on Channel", nip = 28) -public class HideMessageEvent extends GenericEvent { - - public HideMessageEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { - super(pubKey, Kind.HIDE_MESSAGE, tags, content); - } - -} diff --git a/nostr-event/src/main/java/nostr/event/impl/MentionsEvent.java b/nostr-event/src/main/java/nostr/event/impl/MentionsEvent.java deleted file mode 100644 index 53bba55f..00000000 --- a/nostr-event/src/main/java/nostr/event/impl/MentionsEvent.java +++ /dev/null @@ -1,57 +0,0 @@ - -package nostr.event.impl; - -import java.beans.IntrospectionException; -import java.lang.reflect.InvocationTargetException; -import java.security.NoSuchAlgorithmException; -import nostr.event.tag.PubKeyTag; -import nostr.event.Kind; -import nostr.base.PublicKey; -import java.util.List; -import java.util.logging.Level; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.extern.java.Log; -import nostr.base.annotation.Event; -import nostr.event.list.PubKeyTagList; -import nostr.event.list.TagList; -import nostr.util.NostrException; - -/** - * - * @author squirrel - */ -@Data -@EqualsAndHashCode(callSuper = false) -@Event(name = "Handling Mentions", nip = 8) -@Log -public final class MentionsEvent extends GenericEvent { - - public final PubKeyTagList mentionees; - - public MentionsEvent(PublicKey pubKey, TagList tags, String content, PubKeyTagList mentionees) { - super(pubKey, Kind.TEXT_NOTE, tags, content); - this.mentionees = mentionees; - } - - @SuppressWarnings("unchecked") - @Override - public void update() throws NostrException { - try { - super.update(); - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException | NostrException ex) { - log.log(Level.SEVERE, null, ex); - throw new NostrException(ex); - } - - this.getTags().addAll(mentionees); - - int index = 0; - final List pkTagList = mentionees.getList(); - - for (PubKeyTag t : pkTagList) { - String replacement = "#[" + index++ + "]"; - setContent(this.getContent().replace(t.getPublicKey().toString(), replacement)); - } - } -} diff --git a/nostr-event/src/main/java/nostr/event/impl/MetadataEvent.java b/nostr-event/src/main/java/nostr/event/impl/MetadataEvent.java deleted file mode 100644 index 1fa313f8..00000000 --- a/nostr-event/src/main/java/nostr/event/impl/MetadataEvent.java +++ /dev/null @@ -1,80 +0,0 @@ - -package nostr.event.impl; - -import java.beans.IntrospectionException; -import java.lang.reflect.InvocationTargetException; -import java.security.NoSuchAlgorithmException; -import java.util.logging.Level; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.extern.java.Log; -import nostr.base.IMarshaller; -import nostr.base.Profile; -import nostr.base.PublicKey; -import nostr.base.annotation.Event; -import nostr.event.Kind; -import nostr.event.list.TagList; -import nostr.util.NostrException; - -/** - * - * @author squirrel - */ -@Data -@EqualsAndHashCode(callSuper = false) -@Event(name = "Metadata") -@Log -public final class MetadataEvent extends GenericEvent { - - private static final String NAME_PATTERN = "\\w[\\w\\-]+\\w"; - - @JsonIgnore - private Profile profile; - - public MetadataEvent(PublicKey pubKey, TagList tagList, Profile profile) throws NostrException { - super(pubKey, Kind.SET_METADATA, tagList); - this.profile = profile; - - this.validate(); - } - - private void validate() throws NostrException { - var valid = this.profile.getName().matches(NAME_PATTERN); - if (!valid) { - throw new NostrException("Invalid profile name: " + this.profile); - } - } - - @Override - public void update() throws NostrException { - setContent(); - - try { - super.update(); - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException ex) { - log.log(Level.SEVERE, null, ex); - throw new NostrException(ex); - } - } - - private void setContent() { - var mapper = IMarshaller.MAPPER; - try { - ObjectNode objNode = JsonNodeFactory.instance.objectNode(); - objNode.set("name", mapper.valueToTree(this.getProfile().getName())); - objNode.set("about", mapper.valueToTree(this.getProfile().getAbout())); - objNode.set("picture", mapper.valueToTree(this.getProfile().getPicture().toString())); - - setContent(mapper.writeValueAsString(objNode)); - } catch (Exception e) { - log.log(Level.SEVERE, null, e); - throw new RuntimeException(e); - } - } - -} diff --git a/nostr-event/src/main/java/nostr/event/impl/MuteUserEvent.java b/nostr-event/src/main/java/nostr/event/impl/MuteUserEvent.java deleted file mode 100644 index 2f866db3..00000000 --- a/nostr-event/src/main/java/nostr/event/impl/MuteUserEvent.java +++ /dev/null @@ -1,20 +0,0 @@ -package nostr.event.impl; - -import lombok.NonNull; -import nostr.base.PublicKey; -import nostr.base.annotation.Event; -import nostr.event.Kind; -import nostr.event.list.TagList; - -/** - * @author guilhermegps - * - */ -@Event(name = "Mute User on Channel", nip = 28) -public class MuteUserEvent extends GenericEvent { - - public MuteUserEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { - super(pubKey, Kind.MUTE_USER, tags, content); - } - -} diff --git a/nostr-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java b/nostr-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java deleted file mode 100644 index fb5b2ff5..00000000 --- a/nostr-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java +++ /dev/null @@ -1,65 +0,0 @@ -package nostr.event.serializer; - -import java.io.IOException; -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.logging.Level; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -import lombok.extern.java.Log; -import nostr.base.IMarshaller; -import nostr.event.list.BaseList; - - -/** - * @author guilhermegps - * - */ -@Log -public class CustomBaseListSerializer extends JsonSerializer { - - @Override - public void serialize(BaseList value, JsonGenerator gen, SerializerProvider serializers) { - try { - var list = value.getList().parallelStream().map(obj -> toJson(obj)) - .collect(Collectors.toList()); - - gen.writePOJO(list); - } catch (IOException e) { - log.log(Level.SEVERE, null, e); - throw new RuntimeException(e); - } - } - - protected JsonNode toJson(Object obj) { - var mapper = IMarshaller.MAPPER; - try { - JsonNode node = mapper.valueToTree(obj); - - if(node.isObject()) { - Iterator> fields = node.fields(); - - var list = StreamSupport.stream( - Spliterators.spliteratorUnknownSize(fields, Spliterator.ORDERED), false) - .map(f -> f.getValue().asText().toLowerCase() ) - .collect(Collectors.toList()); - - return mapper.valueToTree(list); - } - - return node; - } catch (Exception e) { - log.log(Level.SEVERE, null, e); - throw new RuntimeException(e); - } - } - -} diff --git a/nostr-examples/src/main/java/nostr/examples/NostrExamples.java b/nostr-examples/src/main/java/nostr/examples/NostrExamples.java deleted file mode 100644 index bff3dd9d..00000000 --- a/nostr-examples/src/main/java/nostr/examples/NostrExamples.java +++ /dev/null @@ -1,657 +0,0 @@ -package nostr.examples; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -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.base.Channel; -import nostr.base.ContentReason; -import nostr.base.ITag; -import nostr.base.Profile; -import nostr.base.PublicKey; -import nostr.event.Kind; -import nostr.event.Marker; -import nostr.event.Reaction; -import nostr.event.impl.ChannelCreateEvent; -import nostr.event.impl.ChannelMessageEvent; -import nostr.event.impl.ChannelMetadataEvent; -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.GenericMessage; -import nostr.event.impl.HideMessageEvent; -import nostr.event.impl.InternetIdentifierMetadataEvent; -import nostr.event.impl.MentionsEvent; -import nostr.event.impl.MetadataEvent; -import nostr.event.impl.MuteUserEvent; -import nostr.event.impl.ReactionEvent; -import nostr.event.impl.ReplaceableEvent; -import nostr.event.impl.TextNoteEvent; -import nostr.event.list.KindList; -import nostr.event.list.PubKeyTagList; -import nostr.event.list.TagList; -import nostr.event.message.EventMessage; -import nostr.event.message.ReqMessage; -import nostr.event.tag.EventTag; -import nostr.event.tag.PubKeyTag; -import nostr.id.Client; -import nostr.id.Identity; -import nostr.util.NostrException; -import nostr.util.UnsupportedNIPException; - -/** - * - * @author squirrel - */ -@Log -public class NostrExamples { - - private static final Identity RECEIVER = Identity.generateRandomIdentity(); - private static final Identity SENDER = Identity.generateRandomIdentity(); - private static final Profile PROFILE = Profile.builder() - .name("test") - .about("Hey, it's me!") - .publicKey(SENDER.getPublicKey()) - .build(); - private final static Map RELAYS = Map.of("brb", "brb.io", "damus", "relay.damus.io", "ZBD", "nostr.zebedee.cloud", "taxi", "relay.taxi", "vision", "relay.nostr.vision"); - //private final static Client CLIENT = new Client(RELAYS); - private final static Client CLIENT = Client.getInstance(RELAYS); - - static { - final LogManager logManager = LogManager.getLogManager(); - try (final InputStream is = NostrExamples.class.getResourceAsStream("/logging.properties")) { - logManager.readConfiguration(is); - } catch (IOException ex) { - System.exit(-1000); - } - - try { - PROFILE.setPicture(new URL("https://images.unsplash.com/photo-1462888210965-cdf193fb74de")); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - } - - public static void main(String[] args) throws IOException, Exception { - try { -// Wait it until tried to connect to a half of relays - while(CLIENT.getThreadPool().getCompletedTaskCount() < (RELAYS.size()/2)) { - Thread.sleep(5000); - } - - log.log(Level.FINE, "================= The Beginning"); - logAccountsData(); - - ExecutorService executor = Executors.newFixedThreadPool(10); - - executor.submit(() -> { - try { - sendTextNoteEvent(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - sendEncryptedDirectMessage(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - mentionsEvent(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - deletionEvent(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - metaDataEvent(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - ephemerealEvent(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - reactionEvent(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - replaceableEvent(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - internetIdMetadata(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - filters(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - createChannel(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - updateChannelMetadata(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - sendChannelMessage(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - hideMessage(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - executor.submit(() -> { - try { - muteUser(); - } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); - } - }); - - stop(executor); - - if (executor.isTerminated()) { - log.log(Level.FINE, "================== The End"); - } - - } catch (IllegalArgumentException ex) { - log.log(Level.SEVERE, null, ex); - throw new NostrException(ex); - } - } - - private static void sendTextNoteEvent() throws NostrException { - logHeader("sendTextNoteEvent"); - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - ITag pkSenderTag = PubKeyTag.builder().publicKey(publicKeySender).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(pkSenderTag); - - GenericEvent event = new TextNoteEvent(publicKeySender, tagList, - "Hello world, I'm here on nostr-java API!"); - - SENDER.sign(event); - GenericMessage message = new EventMessage(event); - - CLIENT.send(message); - } catch (UnsupportedNIPException ex) { - log.log(Level.WARNING, null, ex); - } - } - - private static void sendEncryptedDirectMessage() throws NostrException { - logHeader("sendEncryptedDirectMessage"); - - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - ITag pkeyRcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build(); - TagList tagList = new TagList(); - tagList.add(pkeyRcptTag); - - var event2 = new DirectMessageEvent(publicKeySender, tagList, "Hello Nakamoto!"); - - SENDER.encryptDirectMessage(event2); - SENDER.sign(event2); - - GenericMessage message = new EventMessage(event2); - - CLIENT.send(message); - - } catch (UnsupportedNIPException ex) { - log.log(Level.WARNING, null, ex); - } - } - - private static void mentionsEvent() throws NostrException { - logHeader("mentionsEvent"); - - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - ITag pkeySenderTag = PubKeyTag.builder().publicKey(publicKeySender).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(pkeySenderTag); - - PubKeyTagList mentionees = new PubKeyTagList(); - mentionees.add(PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build()); - - GenericEvent event = new MentionsEvent(publicKeySender, tagList, "Hello " + RECEIVER.getPublicKey().toString(), mentionees); - SENDER.sign(event); - - log.log(Level.FINER, ">>>>>>>>>>>> Event: {0}", event); - - GenericMessage message = new EventMessage(event); - - CLIENT.send(message); - - } catch (UnsupportedNIPException ex) { - log.log(Level.WARNING, null, ex); - } - } - - private static void deletionEvent() throws NostrException { - logHeader("deletionEvent"); - - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - ITag pkSenderTag = PubKeyTag.builder().publicKey(publicKeySender).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(pkSenderTag); - - GenericEvent event = new TextNoteEvent(publicKeySender, tagList, "Hello Astral, Please delete me!"); - - SENDER.sign(event); - GenericMessage message = new EventMessage(event); - - CLIENT.send(message); - - tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(event.getId()).build()); - GenericEvent delEvent = new DeletionEvent(publicKeySender, tagList); - - SENDER.sign(delEvent); - message = new EventMessage(delEvent); - - CLIENT.send(message); - - } catch (UnsupportedNIPException ex) { - log.log(Level.WARNING, null, ex); - } - } - - private static void metaDataEvent() throws NostrException { - logHeader("metaDataEvent"); - - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - TagList tagList = new TagList(); - ITag pkSenderTag = PubKeyTag.builder().publicKey(publicKeySender).petName("nostr-java").build(); - tagList.add(pkSenderTag); - - var event = new MetadataEvent(publicKeySender, tagList, PROFILE); - - SENDER.sign(event); - GenericMessage message = new EventMessage(event); - - CLIENT.send(message); - - } catch (UnsupportedNIPException ex) { - log.log(Level.WARNING, null, ex); - } - } - - private static void ephemerealEvent() throws NostrException { - logHeader("ephemerealEvent"); - - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - ITag pkSenderTag = PubKeyTag.builder().publicKey(publicKeySender).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(pkSenderTag); - - GenericEvent event = new EphemeralEvent(publicKeySender, tagList); - - SENDER.sign(event); - GenericMessage message = new EventMessage(event); - - CLIENT.send(message); - } catch (UnsupportedNIPException ex) { - log.log(Level.WARNING, null, ex); - } - } - - private static void reactionEvent() throws NostrException { - logHeader("reactionEvent"); - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - ITag pkSenderTag = PubKeyTag.builder().publicKey(publicKeySender).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(pkSenderTag); - - GenericEvent event = new TextNoteEvent(publicKeySender, tagList, "Hello Astral, Please like me!"); - - SENDER.sign(event); - GenericMessage message = new EventMessage(event); - - CLIENT.send(message); - - tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(event.getId()).build()); - tagList.add(PubKeyTag.builder().publicKey(publicKeySender).build()); - GenericEvent reactionEvent = new ReactionEvent(publicKeySender, tagList, Reaction.LIKE, event); - - SENDER.sign(reactionEvent); - message = new EventMessage(reactionEvent); - - CLIENT.send(message); - - } catch (UnsupportedNIPException ex) { - log.log(Level.WARNING, null, ex); - } - } - - private static void replaceableEvent() throws NostrException { - logHeader("replaceableEvent"); - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - ITag pkSenderTag = PubKeyTag.builder().publicKey(publicKeySender).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(pkSenderTag); - - GenericEvent event = new TextNoteEvent(publicKeySender, tagList, "Hello Astral, Please replace me!"); - - SENDER.sign(event); - GenericMessage message = new EventMessage(event); - - CLIENT.send(message); - - tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(event.getId()).build()); - GenericEvent replaceableEvent = new ReplaceableEvent(publicKeySender, tagList, "New content", event); - - SENDER.sign(replaceableEvent); - message = new EventMessage(replaceableEvent); - - CLIENT.send(message); - - } catch (UnsupportedNIPException ex) { - log.log(Level.WARNING, null, ex); - } - } - - private static void internetIdMetadata() throws NostrException { - logHeader("internetIdMetadata"); - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - ITag pkSenderTag = PubKeyTag.builder().publicKey(publicKeySender).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(pkSenderTag); - - GenericEvent event = new InternetIdentifierMetadataEvent(publicKeySender, tagList, PROFILE); - - SENDER.sign(event); - GenericMessage message = new EventMessage(event); - - CLIENT.send(message); - - } catch (UnsupportedNIPException ex) { - log.log(Level.WARNING, null, ex); - } - } - - // FIXME - public static void filters() throws NostrException { - logHeader("filters"); - try { - KindList kindList = new KindList(); - kindList.add(Kind.EPHEMEREAL_EVENT); - kindList.add(Kind.TEXT_NOTE); - - Filters filters = Filters.builder().kinds(kindList).limit(10).build(); - - String subId = "subId" + System.currentTimeMillis(); - GenericMessage message = new ReqMessage(subId, filters); - - CLIENT.send(message); - } catch (Exception ex) { - throw new NostrException(ex); - } - } - - private static GenericEvent createChannel() throws NostrException { - logHeader("createChannel"); - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - var channel = Channel.builder().name("JNostr Channel") - .about("This is a channel to test NIP28 in nostr-java") - .picture("https://cdn.pixabay.com/photo/2020/05/19/13/48/cartoon-5190942_960_720.jpg").build(); - GenericEvent event = new ChannelCreateEvent(publicKeySender, new TagList(), channel.toString()); - - SENDER.sign(event); - GenericMessage message = new EventMessage(event); - - CLIENT.send(message); - - return event; - } catch (Exception ex) { - throw new NostrException(ex); - } - } - - private static void updateChannelMetadata() throws NostrException { - logHeader("updateChannelMetadata"); - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - var channelCreateEvent = createChannel(); - - var tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(channelCreateEvent.getId()) - .recommendedRelayUrl(CLIENT.getRelays().stream().findFirst().get().getUri()).build()); - - var channel = Channel.builder().name("test change name") - .about("This is a channel to test NIP28 in nostr-java | changed") - .picture("https://cdn.pixabay.com/photo/2020/05/19/13/48/cartoon-5190942_960_720.jpg").build(); - GenericEvent event = new ChannelMetadataEvent(publicKeySender, tagList, channel.toString()); - - SENDER.sign(event); - var message = new EventMessage(event); - - CLIENT.send(message); - } catch (Exception ex) { - throw new NostrException(ex); - } - } - - private static GenericEvent sendChannelMessage() throws NostrException { - logHeader("sendChannelMessage"); - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - var channelCreateEvent = createChannel(); - - var tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(channelCreateEvent.getId()) - .recommendedRelayUrl(CLIENT.getRelays().stream().findFirst().get().getUri()) - .marker(Marker.ROOT) - .build()); - - GenericEvent event = new ChannelMessageEvent(publicKeySender, tagList, "Hello everybody!"); - - SENDER.sign(event); - var message = new EventMessage(event); - - CLIENT.send(message); - - return event; - } catch (Exception ex) { - throw new NostrException(ex); - } - } - - private static GenericEvent hideMessage() throws NostrException { - logHeader("hideMessage"); - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - var channelMessageEvent = sendChannelMessage(); - - var tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(channelMessageEvent.getId()).build()); - - GenericEvent event = new HideMessageEvent(publicKeySender, tagList, - ContentReason.builder().reason("Dick pic").build().toString()); - - SENDER.sign(event); - var message = new EventMessage(event); - - CLIENT.send(message); - - return event; - } catch (Exception ex) { - throw new NostrException(ex); - } - } - - private static GenericEvent muteUser() throws NostrException { - logHeader("muteUser"); - try { - final PublicKey publicKeySender = SENDER.getPublicKey(); - - var tagList = new TagList(); - tagList.add(PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build()); - - GenericEvent event = new MuteUserEvent(publicKeySender, tagList, - ContentReason.builder().reason("Posting dick pics").build().toString()); - - SENDER.sign(event); - var message = new EventMessage(event); - - CLIENT.send(message); - - return event; - } catch (Exception ex) { - throw new NostrException(ex); - } - } - -// public static void sensitiveContentNote(Identity wallet, Client client) throws NostrException { -// logHeader("sensitiveContentNote"); -// try { -// // Create the attribute value list -// List values = new ArrayList<>(); -// values.add("sensitive content"); -// -// // Create the attributes -// final ElementAttribute attr = ElementAttribute.builder().nip(36).isString(true).name("reason").valueList(values).build(); -// Set attributes = new HashSet<>(); -// attributes.add(attr); -// -// GenericTag sensitiveContentTag = new GenericTag(1, "", attributes); -// } catch (UnsupportedNIPException ex) { -// log.log(Level.WARNING, null, ex); -// } catch (Exception ex) { -// throw new NostrException(ex); -// } -// -// } - - private static void logAccountsData() throws NostrException { - StringBuilder msg = new StringBuilder("################################ ACCOUNTS BEGINNING ################################") - .append('\n').append("*** RECEIVER ***").append('\n') - .append('\n').append("* PrivateKey: ").append(RECEIVER.getPrivateKey().getBech32()) - .append('\n').append("* PrivateKey HEX: ").append(RECEIVER.getPrivateKey().toString()) - .append('\n').append("* PublicKey: ").append(RECEIVER.getPublicKey().getBech32()) - .append('\n').append("* PublicKey HEX: ").append(RECEIVER.getPublicKey().toString()) - .append('\n').append('\n').append("*** SENDER ***").append('\n') - .append('\n').append("* PrivateKey: ").append(SENDER.getPrivateKey().getBech32()) - .append('\n').append("* PrivateKey HEX: ").append(SENDER.getPrivateKey().toString()) - .append('\n').append("* PublicKey: ").append(SENDER.getPublicKey().getBech32()) - .append('\n').append("* PublicKey HEX: ").append(SENDER.getPublicKey().toString()) - .append('\n').append('\n').append("################################ ACCOUNTS END ################################"); - - log.log(Level.INFO, msg.toString()); - } - - private static void logHeader(String header) { - for (int i = 0; i < 30; i++) { - System.out.print("#"); - } - System.out.println(); - System.out.println("\t" + header); - for (int i = 0; i < 30; i++) { - System.out.print("#"); - } - System.out.println(); - } - - private static void stop(ExecutorService executor) { - try { - executor.shutdown(); - executor.awaitTermination(60, TimeUnit.SECONDS); - } catch (InterruptedException e) { - log.log(Level.SEVERE, "termination interrupted"); - } finally { - if (!executor.isTerminated()) { - log.log(Level.SEVERE, "killing non-finished tasks"); - } - executor.shutdownNow(); - } - } -} diff --git a/nostr-base/nb-configuration.xml b/nostr-java-base/nb-configuration.xml similarity index 100% rename from nostr-base/nb-configuration.xml rename to nostr-java-base/nb-configuration.xml diff --git a/nostr-base/pom.xml b/nostr-java-base/pom.xml similarity index 85% rename from nostr-base/pom.xml rename to nostr-java-base/pom.xml index 8b3245ca..24e59440 100644 --- a/nostr-base/pom.xml +++ b/nostr-java-base/pom.xml @@ -6,10 +6,10 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-base + nostr-java-base jar @@ -26,12 +26,12 @@ ${project.groupId} - nostr-util + nostr-java-util ${project.version} ${project.groupId} - nostr-crypto + nostr-java-crypto ${project.version} diff --git a/nostr-base/src/main/java/module-info.java b/nostr-java-base/src/main/java/module-info.java similarity index 100% rename from nostr-base/src/main/java/module-info.java rename to nostr-java-base/src/main/java/module-info.java diff --git a/nostr-base/src/main/java/nostr/base/BaseKey.java b/nostr-java-base/src/main/java/nostr/base/BaseKey.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/BaseKey.java rename to nostr-java-base/src/main/java/nostr/base/BaseKey.java diff --git a/nostr-base/src/main/java/nostr/base/Channel.java b/nostr-java-base/src/main/java/nostr/base/Channel.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/Channel.java rename to nostr-java-base/src/main/java/nostr/base/Channel.java diff --git a/nostr-java-base/src/main/java/nostr/base/ChannelProfile.java b/nostr-java-base/src/main/java/nostr/base/ChannelProfile.java new file mode 100644 index 00000000..f95d3226 --- /dev/null +++ b/nostr-java-base/src/main/java/nostr/base/ChannelProfile.java @@ -0,0 +1,20 @@ +package nostr.base; + +import java.net.URL; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * + * @author eric + */ +@Data +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class ChannelProfile extends Profile { + + public ChannelProfile(String name, String about, URL picture) { + super(name, about, picture); + } +} diff --git a/nostr-base/src/main/java/nostr/base/Command.java b/nostr-java-base/src/main/java/nostr/base/Command.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/Command.java rename to nostr-java-base/src/main/java/nostr/base/Command.java diff --git a/nostr-base/src/main/java/nostr/base/ContentReason.java b/nostr-java-base/src/main/java/nostr/base/ContentReason.java similarity index 64% rename from nostr-base/src/main/java/nostr/base/ContentReason.java rename to nostr-java-base/src/main/java/nostr/base/ContentReason.java index 35c11ed9..318960a8 100644 --- a/nostr-base/src/main/java/nostr/base/ContentReason.java +++ b/nostr-java-base/src/main/java/nostr/base/ContentReason.java @@ -17,16 +17,16 @@ public class ContentReason { private String reason; - + @Override public String toString() { - ObjectMapper mapper = new ObjectMapper(); - - try { - return mapper.writeValueAsString(this); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } + ObjectMapper mapper = new ObjectMapper(); + + try { + return mapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } } } diff --git a/nostr-base/src/main/java/nostr/base/ElementAttribute.java b/nostr-java-base/src/main/java/nostr/base/ElementAttribute.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/ElementAttribute.java rename to nostr-java-base/src/main/java/nostr/base/ElementAttribute.java diff --git a/nostr-base/src/main/java/nostr/base/GenericTagQuery.java b/nostr-java-base/src/main/java/nostr/base/GenericTagQuery.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/GenericTagQuery.java rename to nostr-java-base/src/main/java/nostr/base/GenericTagQuery.java diff --git a/nostr-base/src/main/java/nostr/base/IBech32Encodable.java b/nostr-java-base/src/main/java/nostr/base/IBech32Encodable.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/IBech32Encodable.java rename to nostr-java-base/src/main/java/nostr/base/IBech32Encodable.java diff --git a/nostr-base/src/main/java/nostr/base/IElement.java b/nostr-java-base/src/main/java/nostr/base/IElement.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/IElement.java rename to nostr-java-base/src/main/java/nostr/base/IElement.java diff --git a/nostr-base/src/main/java/nostr/base/IEvent.java b/nostr-java-base/src/main/java/nostr/base/IEvent.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/IEvent.java rename to nostr-java-base/src/main/java/nostr/base/IEvent.java diff --git a/nostr-base/src/main/java/nostr/base/IGenericElement.java b/nostr-java-base/src/main/java/nostr/base/IGenericElement.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/IGenericElement.java rename to nostr-java-base/src/main/java/nostr/base/IGenericElement.java diff --git a/nostr-base/src/main/java/nostr/base/IHandler.java b/nostr-java-base/src/main/java/nostr/base/IHandler.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/IHandler.java rename to nostr-java-base/src/main/java/nostr/base/IHandler.java diff --git a/nostr-base/src/main/java/nostr/base/IKey.java b/nostr-java-base/src/main/java/nostr/base/IKey.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/IKey.java rename to nostr-java-base/src/main/java/nostr/base/IKey.java diff --git a/nostr-base/src/main/java/nostr/base/IMarshaller.java b/nostr-java-base/src/main/java/nostr/base/IMarshaller.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/IMarshaller.java rename to nostr-java-base/src/main/java/nostr/base/IMarshaller.java diff --git a/nostr-base/src/main/java/nostr/base/INostrList.java b/nostr-java-base/src/main/java/nostr/base/INostrList.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/INostrList.java rename to nostr-java-base/src/main/java/nostr/base/INostrList.java diff --git a/nostr-base/src/main/java/nostr/base/ISignable.java b/nostr-java-base/src/main/java/nostr/base/ISignable.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/ISignable.java rename to nostr-java-base/src/main/java/nostr/base/ISignable.java diff --git a/nostr-base/src/main/java/nostr/base/ITag.java b/nostr-java-base/src/main/java/nostr/base/ITag.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/ITag.java rename to nostr-java-base/src/main/java/nostr/base/ITag.java diff --git a/nostr-base/src/main/java/nostr/base/IUnmarshaller.java b/nostr-java-base/src/main/java/nostr/base/IUnmarshaller.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/IUnmarshaller.java rename to nostr-java-base/src/main/java/nostr/base/IUnmarshaller.java diff --git a/nostr-base/src/main/java/nostr/base/KeyType.java b/nostr-java-base/src/main/java/nostr/base/KeyType.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/KeyType.java rename to nostr-java-base/src/main/java/nostr/base/KeyType.java diff --git a/nostr-base/src/main/java/nostr/base/NipUtil.java b/nostr-java-base/src/main/java/nostr/base/NipUtil.java similarity index 72% rename from nostr-base/src/main/java/nostr/base/NipUtil.java rename to nostr-java-base/src/main/java/nostr/base/NipUtil.java index aab912f2..a5c714e8 100644 --- a/nostr-base/src/main/java/nostr/base/NipUtil.java +++ b/nostr-java-base/src/main/java/nostr/base/NipUtil.java @@ -21,18 +21,19 @@ public static boolean checkSupport(@NonNull Relay relay, @NonNull Field field) { } public static boolean checkSupport(@NonNull Relay relay, IElement element) { - if (element == null) + if (element == null) { return true; + } var nip = 1; if (element instanceof IEvent event) { - var e = element.getClass().getDeclaredAnnotation(Event.class); - nip = (e==null) ? event.getNip() : e.nip(); - } else if(element instanceof ITag) { - var t = element.getClass().getDeclaredAnnotation(Tag.class); - nip = (t==null) ? nip : t.nip(); + var e = element.getClass().getDeclaredAnnotation(Event.class); + nip = (e == null) ? event.getNip() : e.nip(); + } else if (element instanceof ITag) { + var t = element.getClass().getDeclaredAnnotation(Tag.class); + nip = (t == null) ? nip : t.nip(); } - + return relay.getSupportedNips().contains(nip); } diff --git a/nostr-base/src/main/java/nostr/base/PrivateKey.java b/nostr-java-base/src/main/java/nostr/base/PrivateKey.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/PrivateKey.java rename to nostr-java-base/src/main/java/nostr/base/PrivateKey.java diff --git a/nostr-java-base/src/main/java/nostr/base/Profile.java b/nostr-java-base/src/main/java/nostr/base/Profile.java new file mode 100644 index 00000000..82e8459f --- /dev/null +++ b/nostr-java-base/src/main/java/nostr/base/Profile.java @@ -0,0 +1,27 @@ +package nostr.base; + +import java.net.URL; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * + * @author eric + */ +@Data +@ToString +@EqualsAndHashCode +@AllArgsConstructor +public abstract class Profile { + + private final String name; + + @ToString.Exclude + private String about; + + @ToString.Exclude + private URL picture; + +} diff --git a/nostr-base/src/main/java/nostr/base/PublicKey.java b/nostr-java-base/src/main/java/nostr/base/PublicKey.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/PublicKey.java rename to nostr-java-base/src/main/java/nostr/base/PublicKey.java diff --git a/nostr-base/src/main/java/nostr/base/Relay.java b/nostr-java-base/src/main/java/nostr/base/Relay.java similarity index 62% rename from nostr-base/src/main/java/nostr/base/Relay.java rename to nostr-java-base/src/main/java/nostr/base/Relay.java index 1218f949..96e2cd8b 100644 --- a/nostr-base/src/main/java/nostr/base/Relay.java +++ b/nostr-java-base/src/main/java/nostr/base/Relay.java @@ -1,5 +1,6 @@ package nostr.base; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; import java.util.List; @@ -64,64 +65,93 @@ public String getName() { @AllArgsConstructor public static class RelayInformationDocument { + @JsonProperty private String name; + @JsonProperty private String description; + @JsonProperty private String pubkey; + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private String contact; @Builder.Default + @JsonProperty("supported_nipd") + @JsonIgnoreProperties(ignoreUnknown = true) private List supportedNips = new ArrayList<>(); @Builder.Default + @JsonProperty("supported_nip_extensions") + @JsonIgnoreProperties(ignoreUnknown = true) private List supportedNipExtensions = new ArrayList<>(); + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private String software; + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private String version; + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private Limitation limitation; + @JsonProperty("payments_url") private String paymentsUrl; + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private Fees fees; @Data public static class Limitation { @JsonProperty("max_message_length") + @JsonIgnoreProperties(ignoreUnknown = true) private int maxMessageLength; @JsonProperty("max_subscriptions") + @JsonIgnoreProperties(ignoreUnknown = true) private int maxSubscriptions; @JsonProperty("max_filters") + @JsonIgnoreProperties(ignoreUnknown = true) private int maxFilters; @JsonProperty("max_limit") + @JsonIgnoreProperties(ignoreUnknown = true) private int maxLimit; @JsonProperty("max_subid_length") + @JsonIgnoreProperties(ignoreUnknown = true) private int maxSubIdLength; @JsonProperty("min_prefix") + @JsonIgnoreProperties(ignoreUnknown = true) private int minPrefix; @JsonProperty("max_event_tags") + @JsonIgnoreProperties(ignoreUnknown = true) private int maxEventTags; @JsonProperty("max_content_length") + @JsonIgnoreProperties(ignoreUnknown = true) private int maxContentLength; @JsonProperty("min_pow_difficulty") + @JsonIgnoreProperties(ignoreUnknown = true) private int minPowDifficulty; @JsonProperty("auth_required") + @JsonIgnoreProperties(ignoreUnknown = true) private boolean authRequired; @JsonProperty("payment_required") + @JsonIgnoreProperties(ignoreUnknown = true) private boolean paymentRequired; } @@ -129,23 +159,37 @@ public static class Limitation { @Data public static class Fees { + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private List admission; + + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private List publication; @Data public static class AdmissionFee { + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private int amount; + + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private String unit; } @Data public static class PublicationFee { + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private int amount; + + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) private String unit; } } - } } diff --git a/nostr-base/src/main/java/nostr/base/Signature.java b/nostr-java-base/src/main/java/nostr/base/Signature.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/Signature.java rename to nostr-java-base/src/main/java/nostr/base/Signature.java diff --git a/nostr-base/src/main/java/nostr/base/Profile.java b/nostr-java-base/src/main/java/nostr/base/UserProfile.java similarity index 66% rename from nostr-base/src/main/java/nostr/base/Profile.java rename to nostr-java-base/src/main/java/nostr/base/UserProfile.java index 98b4b6e9..0be4aea1 100644 --- a/nostr-base/src/main/java/nostr/base/Profile.java +++ b/nostr-java-base/src/main/java/nostr/base/UserProfile.java @@ -1,11 +1,10 @@ package nostr.base; +import java.net.URL; import nostr.crypto.bech32.Bech32; import nostr.crypto.bech32.Bech32Prefix; -import java.net.URL; import java.util.logging.Level; -import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -16,28 +15,25 @@ * * @author squirrel */ -@Builder @Data -@ToString -@EqualsAndHashCode +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) @Log -public final class Profile implements IBech32Encodable { +public final class UserProfile extends Profile implements IBech32Encodable { - private final String name; - - @ToString.Exclude private final PublicKey publicKey; - private String about; - - @ToString.Exclude - private URL picture; - private String nip05; + public UserProfile(PublicKey publicKey, String nip05, String name, String about, URL picture) { + super(name, about, picture); + this.publicKey = publicKey; + this.nip05 = nip05; + } + @Override public String toBech32() { - try { + try { return Bech32.encode(Bech32.Encoding.BECH32, Bech32Prefix.NPROFILE.getCode(), this.publicKey.getRawData()); } catch (NostrException ex) { log.log(Level.SEVERE, null, ex); diff --git a/nostr-base/src/main/java/nostr/base/annotation/DefaultHandler.java b/nostr-java-base/src/main/java/nostr/base/annotation/DefaultHandler.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/annotation/DefaultHandler.java rename to nostr-java-base/src/main/java/nostr/base/annotation/DefaultHandler.java diff --git a/nostr-base/src/main/java/nostr/base/annotation/Event.java b/nostr-java-base/src/main/java/nostr/base/annotation/Event.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/annotation/Event.java rename to nostr-java-base/src/main/java/nostr/base/annotation/Event.java diff --git a/nostr-base/src/main/java/nostr/base/annotation/JsonList.java b/nostr-java-base/src/main/java/nostr/base/annotation/JsonList.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/annotation/JsonList.java rename to nostr-java-base/src/main/java/nostr/base/annotation/JsonList.java diff --git a/nostr-base/src/main/java/nostr/base/annotation/JsonString.java b/nostr-java-base/src/main/java/nostr/base/annotation/JsonString.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/annotation/JsonString.java rename to nostr-java-base/src/main/java/nostr/base/annotation/JsonString.java diff --git a/nostr-base/src/main/java/nostr/base/annotation/Key.java b/nostr-java-base/src/main/java/nostr/base/annotation/Key.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/annotation/Key.java rename to nostr-java-base/src/main/java/nostr/base/annotation/Key.java diff --git a/nostr-base/src/main/java/nostr/base/annotation/Tag.java b/nostr-java-base/src/main/java/nostr/base/annotation/Tag.java similarity index 100% rename from nostr-base/src/main/java/nostr/base/annotation/Tag.java rename to nostr-java-base/src/main/java/nostr/base/annotation/Tag.java diff --git a/nostr-java-base/src/main/resources/app.properties b/nostr-java-base/src/main/resources/app.properties new file mode 100644 index 00000000..7090dc10 --- /dev/null +++ b/nostr-java-base/src/main/resources/app.properties @@ -0,0 +1,4 @@ +profile=profile.properties +client=client.properties +relays=relays.properties +config.folder=.nostr-java \ No newline at end of file diff --git a/nostr-crypto/nb-configuration.xml b/nostr-java-crypto/nb-configuration.xml similarity index 100% rename from nostr-crypto/nb-configuration.xml rename to nostr-java-crypto/nb-configuration.xml diff --git a/nostr-crypto/pom.xml b/nostr-java-crypto/pom.xml similarity index 89% rename from nostr-crypto/pom.xml rename to nostr-java-crypto/pom.xml index 70172687..1282eaec 100644 --- a/nostr-crypto/pom.xml +++ b/nostr-java-crypto/pom.xml @@ -6,12 +6,12 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-crypto + nostr-java-crypto jar - nostr-crypto + A simple Java implementation (no external libs) of Sipa's Python reference implementation test vectors for BIP340 Schnorr signatures for secp256k1. Inspired/Copied from: @@ -29,7 +29,7 @@ ${project.groupId} - nostr-util + nostr-java-util ${project.version} diff --git a/nostr-crypto/src/main/java/module-info.java b/nostr-java-crypto/src/main/java/module-info.java similarity index 100% rename from nostr-crypto/src/main/java/module-info.java rename to nostr-java-crypto/src/main/java/module-info.java diff --git a/nostr-crypto/src/main/java/nostr/crypto/Pair.java b/nostr-java-crypto/src/main/java/nostr/crypto/Pair.java similarity index 100% rename from nostr-crypto/src/main/java/nostr/crypto/Pair.java rename to nostr-java-crypto/src/main/java/nostr/crypto/Pair.java diff --git a/nostr-crypto/src/main/java/nostr/crypto/Point.java b/nostr-java-crypto/src/main/java/nostr/crypto/Point.java similarity index 100% rename from nostr-crypto/src/main/java/nostr/crypto/Point.java rename to nostr-java-crypto/src/main/java/nostr/crypto/Point.java diff --git a/nostr-crypto/src/main/java/nostr/crypto/bech32/Bech32.java b/nostr-java-crypto/src/main/java/nostr/crypto/bech32/Bech32.java similarity index 100% rename from nostr-crypto/src/main/java/nostr/crypto/bech32/Bech32.java rename to nostr-java-crypto/src/main/java/nostr/crypto/bech32/Bech32.java diff --git a/nostr-crypto/src/main/java/nostr/crypto/bech32/Bech32Prefix.java b/nostr-java-crypto/src/main/java/nostr/crypto/bech32/Bech32Prefix.java similarity index 100% rename from nostr-crypto/src/main/java/nostr/crypto/bech32/Bech32Prefix.java rename to nostr-java-crypto/src/main/java/nostr/crypto/bech32/Bech32Prefix.java diff --git a/nostr-crypto/src/main/java/nostr/crypto/schnorr/Schnorr.java b/nostr-java-crypto/src/main/java/nostr/crypto/schnorr/Schnorr.java similarity index 100% rename from nostr-crypto/src/main/java/nostr/crypto/schnorr/Schnorr.java rename to nostr-java-crypto/src/main/java/nostr/crypto/schnorr/Schnorr.java diff --git a/nostr-event/README.md b/nostr-java-event/README.md similarity index 100% rename from nostr-event/README.md rename to nostr-java-event/README.md diff --git a/nostr-event/nb-configuration.xml b/nostr-java-event/nb-configuration.xml similarity index 100% rename from nostr-event/nb-configuration.xml rename to nostr-java-event/nb-configuration.xml diff --git a/nostr-event/pom.xml b/nostr-java-event/pom.xml similarity index 83% rename from nostr-event/pom.xml rename to nostr-java-event/pom.xml index 881acb42..4383d360 100644 --- a/nostr-event/pom.xml +++ b/nostr-java-event/pom.xml @@ -6,10 +6,10 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-event + nostr-java-event jar @@ -22,12 +22,12 @@ ${project.groupId} - nostr-base + nostr-java-base ${project.version} ${project.groupId} - nostr-util + nostr-java-util ${project.version} diff --git a/nostr-event/src/main/java/module-info.java b/nostr-java-event/src/main/java/module-info.java similarity index 100% rename from nostr-event/src/main/java/module-info.java rename to nostr-java-event/src/main/java/module-info.java diff --git a/nostr-event/src/main/java/nostr/event/BaseEvent.java b/nostr-java-event/src/main/java/nostr/event/BaseEvent.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/BaseEvent.java rename to nostr-java-event/src/main/java/nostr/event/BaseEvent.java diff --git a/nostr-event/src/main/java/nostr/event/BaseMessage.java b/nostr-java-event/src/main/java/nostr/event/BaseMessage.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/BaseMessage.java rename to nostr-java-event/src/main/java/nostr/event/BaseMessage.java diff --git a/nostr-event/src/main/java/nostr/event/BaseTag.java b/nostr-java-event/src/main/java/nostr/event/BaseTag.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/BaseTag.java rename to nostr-java-event/src/main/java/nostr/event/BaseTag.java diff --git a/nostr-event/src/main/java/nostr/event/Kind.java b/nostr-java-event/src/main/java/nostr/event/Kind.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/Kind.java rename to nostr-java-event/src/main/java/nostr/event/Kind.java diff --git a/nostr-event/src/main/java/nostr/event/Marker.java b/nostr-java-event/src/main/java/nostr/event/Marker.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/Marker.java rename to nostr-java-event/src/main/java/nostr/event/Marker.java diff --git a/nostr-event/src/main/java/nostr/event/Reaction.java b/nostr-java-event/src/main/java/nostr/event/Reaction.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/Reaction.java rename to nostr-java-event/src/main/java/nostr/event/Reaction.java diff --git a/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java new file mode 100644 index 00000000..817bfb17 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java @@ -0,0 +1,44 @@ +package nostr.event.impl; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.NonNull; +import nostr.base.ChannelProfile; +import nostr.base.PublicKey; +import nostr.base.annotation.Event; +import nostr.event.Kind; +import static nostr.event.impl.GenericEvent.escapeJsonString; +import nostr.event.list.TagList; + +/** + * @author guilhermegps + * + */ +@Event(name = "Create Channel", nip = 28) +public class ChannelCreateEvent extends GenericEvent { + + public ChannelCreateEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { + super(pubKey, Kind.CHANNEL_CREATE, tags, content); + } + + public ChannelCreateEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, ChannelProfile profile) { + super(pubKey, Kind.CHANNEL_CREATE, tags); + this.setContent(profile); + } + + private void setContent(ChannelProfile profile) { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(profile); + + // Escape the JSON string + String escapedJsonString = escapeJsonString(jsonString); + + this.setContent(escapedJsonString); + } catch (JsonProcessingException ex) { + throw new RuntimeException(ex); + } + } + +} diff --git a/nostr-event/src/main/java/nostr/event/impl/ChannelMessageEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ChannelMessageEvent.java similarity index 65% rename from nostr-event/src/main/java/nostr/event/impl/ChannelMessageEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/ChannelMessageEvent.java index 529e4ae8..9122fb0c 100644 --- a/nostr-event/src/main/java/nostr/event/impl/ChannelMessageEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ChannelMessageEvent.java @@ -13,8 +13,7 @@ @Event(name = "Channel Message", nip = 28) public class ChannelMessageEvent extends GenericEvent { - public ChannelMessageEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { - super(pubKey, Kind.CHANNEL_MESSAGE, tags, content); - } - + public ChannelMessageEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { + super(pubKey, Kind.CHANNEL_MESSAGE, tags, content); + } } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java new file mode 100644 index 00000000..c98871a7 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java @@ -0,0 +1,42 @@ +package nostr.event.impl; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.NonNull; +import nostr.base.ChannelProfile; +import nostr.base.PublicKey; +import nostr.base.annotation.Event; +import nostr.event.Kind; +import nostr.event.list.TagList; + +/** + * @author guilhermegps + * + */ +@Event(name = "Channel Metadata", nip = 28) +public class ChannelMetadataEvent extends GenericEvent { + + public ChannelMetadataEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { + super(pubKey, Kind.CHANNEL_METADATA, tags, content); + } + + public ChannelMetadataEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, ChannelProfile profile) { + super(pubKey, Kind.CHANNEL_METADATA, tags); + this.setContent(profile); + } + + private void setContent(ChannelProfile profile) { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = objectMapper.writeValueAsString(profile); + + // Escape the JSON string + String escapedJsonString = escapeJsonString(jsonString); + + this.setContent(escapedJsonString); + } catch (JsonProcessingException ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/nostr-event/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java similarity index 60% rename from nostr-event/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java index e2fe1c56..a79f2109 100644 --- a/nostr-event/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java @@ -3,6 +3,8 @@ import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.logging.Logger; import lombok.NonNull; import nostr.base.ElementAttribute; import nostr.base.ITag; @@ -24,6 +26,7 @@ public ClientAuthenticationEvent(@NonNull PublicKey pubKey, @NonNull TagList tag } public ClientAuthenticationEvent(@NonNull PublicKey pubKey, String challenge, @NonNull Set relays) { + super(pubKey, Kind.CLIENT_AUTH); Set chAttributes = new HashSet<>(); var attribute = ElementAttribute.builder().nip(42).name("challenge").value(challenge).build(); @@ -46,13 +49,36 @@ public ClientAuthenticationEvent(@NonNull PublicKey pubKey, String challenge, @N } }); - this.setPubKey(pubKey); - this.setKind(Kind.CLIENT_AUTH.getValue()); this.setNip(42); } + public ClientAuthenticationEvent(@NonNull PublicKey pubKey, String challenge, @NonNull Relay relay) { + super(pubKey, Kind.CLIENT_AUTH); + + try { + Set chAttributes = new HashSet<>(); + var attribute = ElementAttribute.builder().nip(42).name("challenge").value(challenge).build(); + chAttributes.add(attribute); + + this.setTags(new TagList()); + ITag chTag = new GenericTag(42, "challenge", chAttributes); + + this.addTag(chTag); + + final Set relayAttributes = new HashSet<>(); + final ElementAttribute relayAttribute = getRelayAttribute(relay); + relayAttributes.add(relayAttribute); + final ITag relayTag = new GenericTag(42, "relay", relayAttributes); + this.addTag(relayTag); + + this.setNip(42); + } catch (ExecutionException | InterruptedException ex) { + throw new RuntimeException(ex); + } + } + private static ElementAttribute getRelayAttribute(Relay relay) throws ExecutionException, InterruptedException { - return ElementAttribute.builder().nip(42).name("relay").value(relay.getUri()).build(); + return ElementAttribute.builder().nip(42).name("uri").value(relay.getUri()).build(); } } diff --git a/nostr-event/src/main/java/nostr/event/impl/DeletionEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/DeletionEvent.java similarity index 68% rename from nostr-event/src/main/java/nostr/event/impl/DeletionEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/DeletionEvent.java index 12e4aaf4..139ff7bf 100644 --- a/nostr-event/src/main/java/nostr/event/impl/DeletionEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/DeletionEvent.java @@ -1,12 +1,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.annotation.Event; import nostr.event.list.TagList; +import nostr.event.tag.EventTag; /** * @@ -24,4 +26,9 @@ public DeletionEvent(PublicKey pubKey, TagList tagList, String content) { public DeletionEvent(PublicKey pubKey, TagList tagList) { this(pubKey, tagList, "Deletion request"); } + + public DeletionEvent(PublicKey pubKey, List eventsToDelete) { + super(pubKey, Kind.DELETION); + eventsToDelete.stream().map(e -> e.getId()).forEach(eId -> addTag(EventTag.builder().idEvent(eId).build())); + } } diff --git a/nostr-event/src/main/java/nostr/event/impl/DirectMessageEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/DirectMessageEvent.java similarity index 59% rename from nostr-event/src/main/java/nostr/event/impl/DirectMessageEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/DirectMessageEvent.java index 1905e19b..ad9281c8 100644 --- a/nostr-event/src/main/java/nostr/event/impl/DirectMessageEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/DirectMessageEvent.java @@ -4,6 +4,7 @@ import nostr.event.Kind; import nostr.base.annotation.Event; import nostr.event.list.TagList; +import nostr.event.tag.PubKeyTag; /** * @@ -15,4 +16,10 @@ public class DirectMessageEvent extends GenericEvent { public DirectMessageEvent(PublicKey sender, TagList tags, String content) { super(sender, Kind.ENCRYPTED_DIRECT_MESSAGE, tags, content); } + + public DirectMessageEvent(PublicKey sender, PublicKey recipient, String content) { + super(sender, Kind.ENCRYPTED_DIRECT_MESSAGE); + this.setContent(content); + this.addTag(PubKeyTag.builder().publicKey(recipient).build()); + } } diff --git a/nostr-event/src/main/java/nostr/event/impl/EphemeralEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/EphemeralEvent.java similarity index 74% rename from nostr-event/src/main/java/nostr/event/impl/EphemeralEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/EphemeralEvent.java index efabec24..468c64c3 100644 --- a/nostr-event/src/main/java/nostr/event/impl/EphemeralEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/EphemeralEvent.java @@ -7,6 +7,7 @@ import lombok.extern.java.Log; import nostr.base.annotation.Event; import nostr.event.list.TagList; +import nostr.event.tag.PubKeyTag; /** * @@ -25,4 +26,9 @@ public EphemeralEvent(PublicKey pubKey, TagList tags, String content) { public EphemeralEvent(PublicKey pubKey, TagList tags) { this(pubKey, tags, "..."); } + + public EphemeralEvent(PublicKey sender, PublicKey recipient) { + super(sender, Kind.EPHEMEREAL_EVENT); + this.addTag(PubKeyTag.builder().publicKey(recipient).build()); + } } diff --git a/nostr-event/src/main/java/nostr/event/impl/Filters.java b/nostr-java-event/src/main/java/nostr/event/impl/Filters.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/impl/Filters.java rename to nostr-java-event/src/main/java/nostr/event/impl/Filters.java diff --git a/nostr-event/src/main/java/nostr/event/impl/GenericEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/GenericEvent.java similarity index 80% rename from nostr-event/src/main/java/nostr/event/impl/GenericEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/GenericEvent.java index 8563cad0..ad7a13ae 100644 --- a/nostr-event/src/main/java/nostr/event/impl/GenericEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/GenericEvent.java @@ -18,7 +18,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.extern.java.Log; import nostr.base.ElementAttribute; @@ -91,10 +90,10 @@ public class GenericEvent extends BaseEvent implements ISignable, IGenericElemen @JsonIgnore @EqualsAndHashCode.Exclude private final Set attributes; - + public GenericEvent() { this.attributes = new HashSet<>(); - } + } public GenericEvent(@NonNull PublicKey pubKey, @NonNull Kind kind) { this(pubKey, kind, new TagList(), null); @@ -122,17 +121,12 @@ public GenericEvent(@NonNull PublicKey pubKey, @NonNull Integer kind, @NonNull T @Override public String toBech32() { if (!isSigned()) { - try { - this.update(); - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException | NostrException ex) { - log.log(Level.SEVERE, null, ex); - throw new RuntimeException(ex); - } + this.update(); } + try { return Bech32.toBech32(Bech32Prefix.NOTE, this.getId()); } catch (NostrException ex) { - log.log(Level.SEVERE, null, ex); throw new RuntimeException(ex); } } @@ -147,6 +141,10 @@ public void setTags(TagList tags) { } public void addTag(ITag tag) { + if (this.tags == null) { + this.tags = new TagList(); + } + List list = tags.getList(); if (!list.contains(tag)) { @@ -155,12 +153,19 @@ public void addTag(ITag tag) { } } - public void update() throws NoSuchAlgorithmException, IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException, NostrException { - this.createdAt = Instant.now().getEpochSecond(); + public void update() { + + try { + this.validate(); + + this.createdAt = Instant.now().getEpochSecond(); - this._serializedEvent = this.serialize().getBytes(StandardCharsets.UTF_8); + this._serializedEvent = this.serialize().getBytes(StandardCharsets.UTF_8); - this.id = NostrUtil.bytesToHex(NostrUtil.sha256(_serializedEvent)); + this.id = NostrUtil.bytesToHex(NostrUtil.sha256(_serializedEvent)); + } catch (NostrException | NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } } @Transient @@ -173,6 +178,20 @@ public void addAttribute(ElementAttribute attribute) { this.attributes.add(attribute); } + protected void validate() { + + } + + protected static String escapeJsonString(String jsonString) { + return jsonString.replace("\\", "\\\\") + .replace("\"", "\\\"") + .replace("\b", "\\b") + .replace("\f", "\\f") + .replace("\n", "\\n") + .replace("\r", "\\r") + .replace("\t", "\\t"); + } + @SuppressWarnings("unchecked") private String serialize() throws NostrException { var mapper = IMarshaller.MAPPER; diff --git a/nostr-event/src/main/java/nostr/event/impl/GenericMessage.java b/nostr-java-event/src/main/java/nostr/event/impl/GenericMessage.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/impl/GenericMessage.java rename to nostr-java-event/src/main/java/nostr/event/impl/GenericMessage.java diff --git a/nostr-event/src/main/java/nostr/event/impl/GenericTag.java b/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/impl/GenericTag.java rename to nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java diff --git a/nostr-java-event/src/main/java/nostr/event/impl/HideMessageEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/HideMessageEvent.java new file mode 100644 index 00000000..f7bf5e79 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/impl/HideMessageEvent.java @@ -0,0 +1,27 @@ +package nostr.event.impl; + +import lombok.NonNull; +import nostr.base.PublicKey; +import nostr.base.annotation.Event; +import nostr.event.Kind; +import nostr.event.list.TagList; +import nostr.event.tag.EventTag; + +/** + * @author guilhermegps + * + */ +@Event(name = "Hide Message on Channel", nip = 28) +public class HideMessageEvent extends GenericEvent { + + public HideMessageEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { + super(pubKey, Kind.HIDE_MESSAGE, tags, content); + } + + public HideMessageEvent(@NonNull PublicKey pubKey, GenericEvent event, String content) { + super(pubKey, Kind.HIDE_MESSAGE); + this.setContent(content); + this.addTag(EventTag.builder().idEvent(event.getId()).build()); + } + +} diff --git a/nostr-event/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java similarity index 52% rename from nostr-event/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java index f3c57593..43ac2785 100644 --- a/nostr-event/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/InternetIdentifierMetadataEvent.java @@ -12,7 +12,7 @@ import lombok.EqualsAndHashCode; import lombok.NonNull; import lombok.extern.java.Log; -import nostr.base.Profile; +import nostr.base.UserProfile; import nostr.base.annotation.Event; import nostr.event.list.TagList; import nostr.event.util.Nip05Validator; @@ -28,38 +28,25 @@ @Event(name = "Internet Identifier Metadata Event", nip = 5) public final class InternetIdentifierMetadataEvent extends GenericEvent { - private final String name; - private final String nip05; - - public InternetIdentifierMetadataEvent(PublicKey pubKey, TagList tags, @NonNull Profile profile) { + public InternetIdentifierMetadataEvent(PublicKey pubKey, TagList tags, @NonNull UserProfile profile) throws NostrException { super(pubKey, Kind.SET_METADATA, tags); - this.name = profile.getName(); - this.nip05 = profile.getNip05(); + this.init(profile); } - @Override - public void update() throws NostrException { - - try { - // NIP-05 validator - Nip05Validator.builder().nip05(nip05).publicKey(getPubKey()).build().validate(); - - setContent(); + public InternetIdentifierMetadataEvent(PublicKey pubKey, @NonNull UserProfile profile) throws NostrException { + this(pubKey, new TagList(), profile); + } - super.update(); - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException ex) { - log.log(Level.SEVERE, null, ex); - throw new NostrException(ex); - } + private void init(UserProfile profile) throws NostrException { + // NIP-05 validator + Nip05Validator.builder().nip05(profile.getNip05()).publicKey(getPubKey()).build().validate(); + setContent(profile); } - - // TODO #30 - Use jackson - private void setContent() { + + private void setContent(UserProfile profile) { try { - Profile profile = Profile.builder().name(name).nip05(nip05).build(); - ObjectMapper objectMapper = new ObjectMapper(); String jsonString = objectMapper.writeValueAsString(profile); @@ -71,14 +58,4 @@ private void setContent() { throw new RuntimeException(ex); } } - - private static String escapeJsonString(String jsonString) { - return jsonString.replace("\\", "\\\\") - .replace("\"", "\\\"") - .replace("\b", "\\b") - .replace("\f", "\\f") - .replace("\n", "\\n") - .replace("\r", "\\r") - .replace("\t", "\\t"); - } } 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 new file mode 100644 index 00000000..288411c8 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/impl/MentionsEvent.java @@ -0,0 +1,40 @@ +package nostr.event.impl; + +import nostr.event.tag.PubKeyTag; +import nostr.event.Kind; +import nostr.base.PublicKey; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.extern.java.Log; +import nostr.base.ITag; +import nostr.base.annotation.Event; +import nostr.event.list.TagList; + +/** + * + * @author squirrel + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Event(name = "Handling Mentions", nip = 8) +@Log +public final class MentionsEvent extends GenericEvent { + + public MentionsEvent(PublicKey pubKey, TagList tags, String content) { + super(pubKey, Kind.TEXT_NOTE, tags, content); + } + + @SuppressWarnings("unchecked") + @Override + public void update() { + super.update(); + + int index = 0; + + while (getTags().getList().iterator().hasNext()) { + ITag tag = (ITag) getTags().getList().iterator().next(); + String replacement = "#[" + index++ + "]"; + setContent(this.getContent().replace(((PubKeyTag) tag).getStringPubKey(), 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 new file mode 100644 index 00000000..1a590261 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/impl/MetadataEvent.java @@ -0,0 +1,71 @@ +package nostr.event.impl; + +import java.util.logging.Level; + +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 lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.extern.java.Log; +import nostr.base.IMarshaller; +import nostr.base.UserProfile; +import nostr.base.PublicKey; +import nostr.base.annotation.Event; +import nostr.event.Kind; +import nostr.event.list.TagList; +import nostr.util.NostrException; + +/** + * + * @author squirrel + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Event(name = "Metadata") +@Log +public final class MetadataEvent extends GenericEvent { + + private static final String NAME_PATTERN = "\\w[\\w\\-]+\\w"; + + @JsonIgnore + private UserProfile profile; + + public MetadataEvent(PublicKey pubKey, UserProfile profile) throws NostrException { + super(pubKey, Kind.SET_METADATA, new TagList()); + this.profile = profile; + } + + @Override + protected void validate() { + var valid = this.profile.getName().matches(NAME_PATTERN); + if (!valid) { + throw new AssertionError("Invalid profile name: " + this.profile, null); + } + } + + @Override + public void update() { + setContent(); + + super.update(); + } + + private void setContent() { + var mapper = IMarshaller.MAPPER; + try { + ObjectNode objNode = JsonNodeFactory.instance.objectNode(); + objNode.set("name", mapper.valueToTree(this.getProfile().getName())); + objNode.set("about", mapper.valueToTree(this.getProfile().getAbout())); + objNode.set("picture", mapper.valueToTree(this.getProfile().getPicture().toString())); + + setContent(mapper.writeValueAsString(objNode)); + } catch (JsonProcessingException | IllegalArgumentException e) { + log.log(Level.SEVERE, null, e); + throw new RuntimeException(e); + } + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/impl/MuteUserEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/MuteUserEvent.java new file mode 100644 index 00000000..bcf6869e --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/impl/MuteUserEvent.java @@ -0,0 +1,26 @@ +package nostr.event.impl; + +import lombok.NonNull; +import nostr.base.PublicKey; +import nostr.base.annotation.Event; +import nostr.event.Kind; +import nostr.event.list.TagList; +import nostr.event.tag.PubKeyTag; + +/** + * @author guilhermegps + * + */ +@Event(name = "Mute User on Channel", nip = 28) +public class MuteUserEvent extends GenericEvent { + + public MuteUserEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { + super(pubKey, Kind.MUTE_USER, tags, content); + } + + public MuteUserEvent(@NonNull PublicKey pubKey, @NonNull PublicKey mutedUser, String content) { + super(pubKey, Kind.MUTE_USER); + this.addTag(PubKeyTag.builder().publicKey(mutedUser).build()); + this.setContent(content); + } +} diff --git a/nostr-event/src/main/java/nostr/event/impl/OtsEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/OtsEvent.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/impl/OtsEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/OtsEvent.java diff --git a/nostr-event/src/main/java/nostr/event/impl/ReactionEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ReactionEvent.java similarity index 59% rename from nostr-event/src/main/java/nostr/event/impl/ReactionEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/ReactionEvent.java index 5de168fa..8dcef0cc 100644 --- a/nostr-event/src/main/java/nostr/event/impl/ReactionEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ReactionEvent.java @@ -8,6 +8,8 @@ import lombok.extern.java.Log; import nostr.base.annotation.Event; import nostr.event.list.TagList; +import nostr.event.tag.EventTag; +import nostr.event.tag.PubKeyTag; /** * @@ -19,11 +21,14 @@ @Event(name = "Reactions", nip = 25) public class ReactionEvent extends GenericEvent { - private final GenericEvent sourceEvent; - public ReactionEvent(PublicKey pubKey, TagList tags, Reaction content, GenericEvent sourceEvent) { super(pubKey, Kind.REACTION, tags, content.getEmoji()); - this.sourceEvent = sourceEvent; } + public ReactionEvent(PublicKey pubKey, GenericEvent event, Reaction content, GenericEvent sourceEvent) { + super(pubKey, Kind.REACTION); + this.setContent(content.getEmoji()); + this.addTag(EventTag.builder().idEvent(event.getId()).build()); + this.addTag(PubKeyTag.builder().publicKey(event.getPubKey()).build()); + } } diff --git a/nostr-event/src/main/java/nostr/event/impl/ReplaceableEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ReplaceableEvent.java similarity index 50% rename from nostr-event/src/main/java/nostr/event/impl/ReplaceableEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/ReplaceableEvent.java index 780a2770..9fccde10 100644 --- a/nostr-event/src/main/java/nostr/event/impl/ReplaceableEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ReplaceableEvent.java @@ -1,6 +1,5 @@ package nostr.event.impl; -import nostr.event.Kind; import nostr.base.PublicKey; import lombok.Data; import lombok.EqualsAndHashCode; @@ -18,11 +17,15 @@ @Event(name = "Replaceable Events", nip = 16) public class ReplaceableEvent extends GenericEvent { - private final GenericEvent original; - - public ReplaceableEvent(PublicKey pubKey, TagList tags, String content, GenericEvent original) { - super(pubKey, Kind.DELETION, tags, content); - this.original = original; + public ReplaceableEvent(PublicKey sender, Integer kind, TagList tags, String content) { + super(sender, kind, tags, content); } + @Override + protected void validate() { + if (this.getKind() >= 10_000 && this.getKind() < 20_000) { + return; + } + throw new AssertionError("Invalid kind value. Must be between 10000 and 20000 (excl)", null); + } } diff --git a/nostr-event/src/main/java/nostr/event/impl/TextNoteEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/TextNoteEvent.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/impl/TextNoteEvent.java rename to nostr-java-event/src/main/java/nostr/event/impl/TextNoteEvent.java diff --git a/nostr-event/src/main/java/nostr/event/list/BaseList.java b/nostr-java-event/src/main/java/nostr/event/list/BaseList.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/list/BaseList.java rename to nostr-java-event/src/main/java/nostr/event/list/BaseList.java diff --git a/nostr-event/src/main/java/nostr/event/list/EventList.java b/nostr-java-event/src/main/java/nostr/event/list/EventList.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/list/EventList.java rename to nostr-java-event/src/main/java/nostr/event/list/EventList.java diff --git a/nostr-event/src/main/java/nostr/event/list/FiltersList.java b/nostr-java-event/src/main/java/nostr/event/list/FiltersList.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/list/FiltersList.java rename to nostr-java-event/src/main/java/nostr/event/list/FiltersList.java diff --git a/nostr-event/src/main/java/nostr/event/list/GenericTagQueryList.java b/nostr-java-event/src/main/java/nostr/event/list/GenericTagQueryList.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/list/GenericTagQueryList.java rename to nostr-java-event/src/main/java/nostr/event/list/GenericTagQueryList.java diff --git a/nostr-event/src/main/java/nostr/event/list/KindList.java b/nostr-java-event/src/main/java/nostr/event/list/KindList.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/list/KindList.java rename to nostr-java-event/src/main/java/nostr/event/list/KindList.java diff --git a/nostr-event/src/main/java/nostr/event/list/PubKeyTagList.java b/nostr-java-event/src/main/java/nostr/event/list/PubKeyTagList.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/list/PubKeyTagList.java rename to nostr-java-event/src/main/java/nostr/event/list/PubKeyTagList.java diff --git a/nostr-event/src/main/java/nostr/event/list/PublicKeyList.java b/nostr-java-event/src/main/java/nostr/event/list/PublicKeyList.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/list/PublicKeyList.java rename to nostr-java-event/src/main/java/nostr/event/list/PublicKeyList.java diff --git a/nostr-event/src/main/java/nostr/event/list/TagList.java b/nostr-java-event/src/main/java/nostr/event/list/TagList.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/list/TagList.java rename to nostr-java-event/src/main/java/nostr/event/list/TagList.java diff --git a/nostr-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java similarity index 78% rename from nostr-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java index b02a7c21..03d5375e 100644 --- a/nostr-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java @@ -1,5 +1,6 @@ package nostr.event.marshaller.impl; +import com.fasterxml.jackson.core.JsonProcessingException; import java.lang.reflect.Field; import java.util.logging.Level; @@ -27,36 +28,32 @@ public class ElementMarshaller implements IMarshaller { @Override public String marshall() throws UnsupportedNIPException, NostrException { - Relay relay = getRelay(); - if (!nipEventSupport()) { throw new UnsupportedNIPException("NIP is not supported by relay: \"" + relay.getName() + "\" - List of supported NIP(s): " + relay.printSupportedNips()); } try { - return toJson(); - } catch (NostrException e) { - log.log(Level.SEVERE, null, e); + return toJson(); + } catch (NostrException e) { + log.log(Level.SEVERE, null, e); throw new RuntimeException(e); - } + } } private boolean nipEventSupport() { - Relay relay = getRelay(); - return (relay != null) ? NipUtil.checkSupport(relay, getElement()) : true; } protected boolean nipFieldSupport(Field field) { return (relay != null) ? NipUtil.checkSupport(relay, field) : true; } - + @Override public String toJson() throws NostrException { - try { - return MAPPER.writeValueAsString(element); - } catch (Exception e) { - throw new NostrException(e); - } + try { + return MAPPER.writeValueAsString(element); + } catch (JsonProcessingException e) { + throw new NostrException(e); + } } } diff --git a/nostr-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java similarity index 92% rename from nostr-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java index 753682d2..f0f2d1cb 100644 --- a/nostr-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java @@ -1,5 +1,6 @@ package nostr.event.marshaller.impl; +import com.fasterxml.jackson.core.JsonProcessingException; import java.util.Spliterator; import java.util.Spliterators; import java.util.stream.StreamSupport; @@ -51,7 +52,7 @@ public String toJson() throws NostrException { objNode.remove("genericTagQueryList"); return MAPPER.writeValueAsString(node); - } catch (Exception e) { + } catch (JsonProcessingException | IllegalArgumentException e) { throw new NostrException(e); } } diff --git a/nostr-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java similarity index 62% rename from nostr-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java index 551747ec..2d453e10 100644 --- a/nostr-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java @@ -1,6 +1,7 @@ package nostr.event.marshaller.impl; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -29,20 +30,20 @@ public class GenericTagMarshaller implements IMarshaller { public String marshall() throws NostrException { return toJson(); } - + @Override public String toJson() throws NostrException { - try { - SimpleModule module = new SimpleModule(); - module.addSerializer(new CustomGenericTagSerializer()); - var mappe = (new ObjectMapper()) - .setSerializationInclusion(Include.NON_NULL) - .registerModule(module); - - return mappe.writeValueAsString(tag); - } catch (Exception e) { - throw new NostrException(e); - } + try { + SimpleModule module = new SimpleModule(); + module.addSerializer(new CustomGenericTagSerializer()); + var mappe = (new ObjectMapper()) + .setSerializationInclusion(Include.NON_NULL) + .registerModule(module); + + return mappe.writeValueAsString(tag); + } catch (JsonProcessingException e) { + throw new NostrException(e); + } } } diff --git a/nostr-event/src/main/java/nostr/event/marshaller/impl/MessageMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/MessageMarshaller.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/marshaller/impl/MessageMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/marshaller/impl/MessageMarshaller.java diff --git a/nostr-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java diff --git a/nostr-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java similarity index 62% rename from nostr-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java index 958d11eb..6d8b2bef 100644 --- a/nostr-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java @@ -1,6 +1,7 @@ package nostr.event.marshaller.impl; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -29,20 +30,20 @@ public class TagMarshaller implements IMarshaller { public String marshall() throws NostrException { return toJson(); } - + @Override public String toJson() throws NostrException { - try { - SimpleModule module = new SimpleModule(); - module.addSerializer(new CustomTagSerializer()); - var mappe = (new ObjectMapper()) - .setSerializationInclusion(Include.NON_NULL) - .registerModule(module); - - return mappe.writeValueAsString(tag); - } catch (Exception e) { - throw new NostrException(e); - } + try { + SimpleModule module = new SimpleModule(); + module.addSerializer(new CustomTagSerializer()); + var mappe = (new ObjectMapper()) + .setSerializationInclusion(Include.NON_NULL) + .registerModule(module); + + return mappe.writeValueAsString(tag); + } catch (JsonProcessingException e) { + throw new NostrException(e); + } } } diff --git a/nostr-event/src/main/java/nostr/event/message/AuthMessage.java b/nostr-java-event/src/main/java/nostr/event/message/AuthMessage.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/message/AuthMessage.java rename to nostr-java-event/src/main/java/nostr/event/message/AuthMessage.java diff --git a/nostr-event/src/main/java/nostr/event/message/CloseMessage.java b/nostr-java-event/src/main/java/nostr/event/message/CloseMessage.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/message/CloseMessage.java rename to nostr-java-event/src/main/java/nostr/event/message/CloseMessage.java diff --git a/nostr-event/src/main/java/nostr/event/message/ContactListMessage.java b/nostr-java-event/src/main/java/nostr/event/message/ContactListMessage.java similarity index 92% rename from nostr-event/src/main/java/nostr/event/message/ContactListMessage.java rename to nostr-java-event/src/main/java/nostr/event/message/ContactListMessage.java index 027ca15e..03bfb46e 100644 --- a/nostr-event/src/main/java/nostr/event/message/ContactListMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/ContactListMessage.java @@ -1,5 +1,6 @@ package nostr.event.message; +import lombok.ToString; import nostr.event.Kind; import nostr.base.PublicKey; import nostr.event.impl.GenericEvent; @@ -9,6 +10,7 @@ * * @author squirrel */ +@ToString public class ContactListMessage extends EventMessage { public ContactListMessage(PubKeyTagList contactList, PublicKey publicKey) { diff --git a/nostr-event/src/main/java/nostr/event/message/EoseMessage.java b/nostr-java-event/src/main/java/nostr/event/message/EoseMessage.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/message/EoseMessage.java rename to nostr-java-event/src/main/java/nostr/event/message/EoseMessage.java diff --git a/nostr-event/src/main/java/nostr/event/message/EventMessage.java b/nostr-java-event/src/main/java/nostr/event/message/EventMessage.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/message/EventMessage.java rename to nostr-java-event/src/main/java/nostr/event/message/EventMessage.java diff --git a/nostr-event/src/main/java/nostr/event/message/NoticeMessage.java b/nostr-java-event/src/main/java/nostr/event/message/NoticeMessage.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/message/NoticeMessage.java rename to nostr-java-event/src/main/java/nostr/event/message/NoticeMessage.java diff --git a/nostr-event/src/main/java/nostr/event/message/OkMessage.java b/nostr-java-event/src/main/java/nostr/event/message/OkMessage.java similarity index 78% rename from nostr-event/src/main/java/nostr/event/message/OkMessage.java rename to nostr-java-event/src/main/java/nostr/event/message/OkMessage.java index df1753db..4f9446e2 100644 --- a/nostr-event/src/main/java/nostr/event/message/OkMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/OkMessage.java @@ -1,6 +1,9 @@ package nostr.event.message; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; import nostr.base.Command; import nostr.event.impl.GenericMessage; @@ -8,6 +11,9 @@ * * @author squirrel */ +@Data +@EqualsAndHashCode(callSuper = false) +@ToString public class OkMessage extends GenericMessage { private final String eventId; diff --git a/nostr-event/src/main/java/nostr/event/message/ReqMessage.java b/nostr-java-event/src/main/java/nostr/event/message/ReqMessage.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/message/ReqMessage.java rename to nostr-java-event/src/main/java/nostr/event/message/ReqMessage.java diff --git a/nostr-java-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java b/nostr-java-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java new file mode 100644 index 00000000..9c4dc039 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java @@ -0,0 +1,64 @@ +package nostr.event.serializer; + +import java.io.IOException; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import lombok.extern.java.Log; +import nostr.base.IMarshaller; +import nostr.event.list.BaseList; + +/** + * @author guilhermegps + * + */ +@Log +public class CustomBaseListSerializer extends JsonSerializer { + + @Override + public void serialize(BaseList value, JsonGenerator gen, SerializerProvider serializers) { + try { + var list = value.getList().parallelStream().map(obj -> toJson(obj)) + .collect(Collectors.toList()); + + gen.writePOJO(list); + } catch (IOException e) { + log.log(Level.SEVERE, null, e); + throw new RuntimeException(e); + } + } + + protected JsonNode toJson(Object obj) { + var mapper = IMarshaller.MAPPER; + try { + JsonNode node = mapper.valueToTree(obj); + + if (node.isObject()) { + Iterator> fields = node.fields(); + + var list = StreamSupport.stream( + Spliterators.spliteratorUnknownSize(fields, Spliterator.ORDERED), false) + .map(f -> f.getValue().asText().toLowerCase()) + .collect(Collectors.toList()); + + return mapper.valueToTree(list); + } + + return node; + } catch (IllegalArgumentException e) { + log.log(Level.SEVERE, null, e); + throw new RuntimeException(e); + } + } + +} diff --git a/nostr-event/src/main/java/nostr/event/serializer/CustomGenericTagListSerializer.java b/nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagListSerializer.java similarity index 54% rename from nostr-event/src/main/java/nostr/event/serializer/CustomGenericTagListSerializer.java rename to nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagListSerializer.java index fcbfd7f7..884b3d44 100644 --- a/nostr-event/src/main/java/nostr/event/serializer/CustomGenericTagListSerializer.java +++ b/nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagListSerializer.java @@ -15,7 +15,6 @@ import nostr.base.IMarshaller; import nostr.event.list.GenericTagQueryList; - /** * @author guilhermegps * @@ -23,33 +22,33 @@ @Log public class CustomGenericTagListSerializer extends JsonSerializer { - @Override - public void serialize(GenericTagQueryList value, JsonGenerator gen, SerializerProvider serializers) { - try { - var list = value.getList().parallelStream().map(gtq -> toJson(gtq)) - .collect(Collectors.toList()); - - gen.writePOJO(list); - } catch (IOException e) { + @Override + public void serialize(GenericTagQueryList value, JsonGenerator gen, SerializerProvider serializers) { + try { + var list = value.getList().parallelStream().map(gtq -> toJson(gtq)) + .collect(Collectors.toList()); + + gen.writePOJO(list); + } catch (IOException e) { log.log(Level.SEVERE, null, e); throw new RuntimeException(e); - } - } - + } + } + protected JsonNode toJson(GenericTagQuery gtq) { - var mapper = IMarshaller.MAPPER; - try { - JsonNode node = mapper.valueToTree(gtq); - ObjectNode objNode = (ObjectNode) node; - objNode.set("#" + node.get("tagName").textValue(), node.get("value")); - objNode.remove("tagName"); - objNode.remove("value"); - - return node; - } catch (Exception e) { + var mapper = IMarshaller.MAPPER; + try { + JsonNode node = mapper.valueToTree(gtq); + ObjectNode objNode = (ObjectNode) node; + objNode.set("#" + node.get("tagName").textValue(), node.get("value")); + objNode.remove("tagName"); + objNode.remove("value"); + + return node; + } catch (IllegalArgumentException e) { log.log(Level.SEVERE, null, e); throw new RuntimeException(e); - } + } } } diff --git a/nostr-event/src/main/java/nostr/event/serializer/CustomGenericTagSerializer.java b/nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagSerializer.java similarity index 51% rename from nostr-event/src/main/java/nostr/event/serializer/CustomGenericTagSerializer.java rename to nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagSerializer.java index 0d3d384c..5c99e952 100644 --- a/nostr-event/src/main/java/nostr/event/serializer/CustomGenericTagSerializer.java +++ b/nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagSerializer.java @@ -13,7 +13,6 @@ import nostr.base.GenericTagQuery; import nostr.base.IMarshaller; - /** * @author guilhermegps * @@ -21,36 +20,36 @@ @Log public class CustomGenericTagSerializer extends StdSerializer { - private static final long serialVersionUID = 6803478463890319884L; + private static final long serialVersionUID = 6803478463890319884L; - public CustomGenericTagSerializer() { - super(GenericTagQuery.class); - } + public CustomGenericTagSerializer() { + super(GenericTagQuery.class); + } - @Override - public void serialize(GenericTagQuery value, JsonGenerator gen, SerializerProvider serializers) { - try { - gen.writePOJO(toJson(value)); - } catch (IOException e) { + @Override + public void serialize(GenericTagQuery value, JsonGenerator gen, SerializerProvider serializers) { + try { + gen.writePOJO(toJson(value)); + } catch (IOException e) { log.log(Level.SEVERE, null, e); throw new RuntimeException(e); - } - } - + } + } + public static JsonNode toJson(GenericTagQuery gtq) { - var mapper = IMarshaller.MAPPER; - try { - JsonNode node = mapper.valueToTree(gtq); - ObjectNode objNode = (ObjectNode) node; - objNode.set("#" + node.get("tagName").textValue(), node.get("value")); - objNode.remove("tagName"); - objNode.remove("value"); - - return node; - } catch (Exception e) { + var mapper = IMarshaller.MAPPER; + try { + JsonNode node = mapper.valueToTree(gtq); + ObjectNode objNode = (ObjectNode) node; + objNode.set("#" + node.get("tagName").textValue(), node.get("value")); + objNode.remove("tagName"); + objNode.remove("value"); + + return node; + } catch (IllegalArgumentException e) { log.log(Level.SEVERE, null, e); throw new RuntimeException(e); - } + } } } diff --git a/nostr-event/src/main/java/nostr/event/serializer/CustomIdEventListSerializer.java b/nostr-java-event/src/main/java/nostr/event/serializer/CustomIdEventListSerializer.java similarity index 65% rename from nostr-event/src/main/java/nostr/event/serializer/CustomIdEventListSerializer.java rename to nostr-java-event/src/main/java/nostr/event/serializer/CustomIdEventListSerializer.java index 8a1f8bba..ddf534af 100644 --- a/nostr-event/src/main/java/nostr/event/serializer/CustomIdEventListSerializer.java +++ b/nostr-java-event/src/main/java/nostr/event/serializer/CustomIdEventListSerializer.java @@ -12,7 +12,6 @@ import nostr.event.impl.GenericEvent; import nostr.event.list.EventList; - /** * @author guilhermegps * @@ -20,16 +19,16 @@ @Log public class CustomIdEventListSerializer extends JsonSerializer { - @Override - public void serialize(EventList value, JsonGenerator gen, SerializerProvider serializers) { - try { - var list = value.getList().parallelStream().map(GenericEvent::getId).collect(Collectors.toList()); - - gen.writePOJO(list); - } catch (IOException e) { + @Override + public void serialize(EventList value, JsonGenerator gen, SerializerProvider serializers) { + try { + var list = value.getList().parallelStream().map(GenericEvent::getId).collect(Collectors.toList()); + + gen.writePOJO(list); + } catch (IOException e) { log.log(Level.SEVERE, null, e); throw new RuntimeException(e); - } - } + } + } } diff --git a/nostr-event/src/main/java/nostr/event/serializer/CustomTagSerializer.java b/nostr-java-event/src/main/java/nostr/event/serializer/CustomTagSerializer.java similarity index 50% rename from nostr-event/src/main/java/nostr/event/serializer/CustomTagSerializer.java rename to nostr-java-event/src/main/java/nostr/event/serializer/CustomTagSerializer.java index 7d198158..12473ef1 100644 --- a/nostr-event/src/main/java/nostr/event/serializer/CustomTagSerializer.java +++ b/nostr-java-event/src/main/java/nostr/event/serializer/CustomTagSerializer.java @@ -25,29 +25,29 @@ @Log public class CustomTagSerializer extends StdSerializer { - private static final long serialVersionUID = -3877972991082754068L; - - public CustomTagSerializer() { - super(ITag.class); - } - - @Override - public void serialize(ITag value, JsonGenerator gen, SerializerProvider serializers) { - try { - var mapper = IMarshaller.MAPPER; - JsonNode node = mapper.valueToTree(value); - - Iterator> fields = node.fields(); - var list = StreamSupport.stream( - Spliterators.spliteratorUnknownSize(fields, Spliterator.ORDERED), false) - .map(f -> f.getValue().asText().toLowerCase() ) - .collect(Collectors.toList()); - - gen.writePOJO(list); - } catch (IOException e) { + private static final long serialVersionUID = -3877972991082754068L; + + public CustomTagSerializer() { + super(ITag.class); + } + + @Override + public void serialize(ITag value, JsonGenerator gen, SerializerProvider serializers) { + try { + var mapper = IMarshaller.MAPPER; + JsonNode node = mapper.valueToTree(value); + + Iterator> fields = node.fields(); + var list = StreamSupport.stream( + Spliterators.spliteratorUnknownSize(fields, Spliterator.ORDERED), false) + .map(f -> f.getValue().asText().toLowerCase()) + .collect(Collectors.toList()); + + gen.writePOJO(list); + } catch (IOException e) { log.log(Level.SEVERE, null, e); throw new RuntimeException(e); - } - } + } + } -} \ No newline at end of file +} diff --git a/nostr-event/src/main/java/nostr/event/tag/DelegationTag.java b/nostr-java-event/src/main/java/nostr/event/tag/DelegationTag.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/tag/DelegationTag.java rename to nostr-java-event/src/main/java/nostr/event/tag/DelegationTag.java diff --git a/nostr-event/src/main/java/nostr/event/tag/EventTag.java b/nostr-java-event/src/main/java/nostr/event/tag/EventTag.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/tag/EventTag.java rename to nostr-java-event/src/main/java/nostr/event/tag/EventTag.java diff --git a/nostr-event/src/main/java/nostr/event/tag/NonceTag.java b/nostr-java-event/src/main/java/nostr/event/tag/NonceTag.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/tag/NonceTag.java rename to nostr-java-event/src/main/java/nostr/event/tag/NonceTag.java diff --git a/nostr-event/src/main/java/nostr/event/tag/PubKeyTag.java b/nostr-java-event/src/main/java/nostr/event/tag/PubKeyTag.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/tag/PubKeyTag.java rename to nostr-java-event/src/main/java/nostr/event/tag/PubKeyTag.java diff --git a/nostr-event/src/main/java/nostr/event/tag/SubjectTag.java b/nostr-java-event/src/main/java/nostr/event/tag/SubjectTag.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/tag/SubjectTag.java rename to nostr-java-event/src/main/java/nostr/event/tag/SubjectTag.java diff --git a/nostr-event/src/main/java/nostr/event/util/Nip05Validator.java b/nostr-java-event/src/main/java/nostr/event/util/Nip05Validator.java similarity index 100% rename from nostr-event/src/main/java/nostr/event/util/Nip05Validator.java rename to nostr-java-event/src/main/java/nostr/event/util/Nip05Validator.java diff --git a/nostr-examples/nb-configuration.xml b/nostr-java-examples/nb-configuration.xml similarity index 100% rename from nostr-examples/nb-configuration.xml rename to nostr-java-examples/nb-configuration.xml diff --git a/nostr-examples/nbactions.xml b/nostr-java-examples/nbactions.xml similarity index 100% rename from nostr-examples/nbactions.xml rename to nostr-java-examples/nbactions.xml diff --git a/nostr-examples/pom.xml b/nostr-java-examples/pom.xml similarity index 71% rename from nostr-examples/pom.xml rename to nostr-java-examples/pom.xml index 16e1ff35..1f9f428b 100644 --- a/nostr-examples/pom.xml +++ b/nostr-java-examples/pom.xml @@ -6,10 +6,10 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-examples + nostr-java-examples jar @@ -20,28 +20,22 @@ ${project.groupId} - nostr-event + nostr-java-event ${project.version} - - - ${project.groupId} - nostr-util - - ${project.groupId} - nostr-ws + nostr-java-ws ${project.version} ${project.groupId} - nostr-base + nostr-java-base ${project.version} ${project.groupId} - nostr-id + nostr-java-id ${project.version} diff --git a/nostr-examples/src/main/java/module-info.java b/nostr-java-examples/src/main/java/module-info.java similarity index 100% rename from nostr-examples/src/main/java/module-info.java rename to nostr-java-examples/src/main/java/module-info.java diff --git a/nostr-examples/src/main/java/nostr/examples/FilterRelays.java b/nostr-java-examples/src/main/java/nostr/examples/FilterRelays.java similarity index 100% rename from nostr-examples/src/main/java/nostr/examples/FilterRelays.java rename to nostr-java-examples/src/main/java/nostr/examples/FilterRelays.java diff --git a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java new file mode 100644 index 00000000..eeedda9f --- /dev/null +++ b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java @@ -0,0 +1,651 @@ +package nostr.examples; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +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.base.Channel; +import nostr.base.ContentReason; +import nostr.base.ITag; +import nostr.base.UserProfile; +import nostr.base.PublicKey; +import nostr.event.Kind; +import nostr.event.Marker; +import nostr.event.Reaction; +import nostr.event.impl.ChannelCreateEvent; +import nostr.event.impl.ChannelMessageEvent; +import nostr.event.impl.ChannelMetadataEvent; +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.GenericMessage; +import nostr.event.impl.HideMessageEvent; +import nostr.event.impl.InternetIdentifierMetadataEvent; +import nostr.event.impl.MentionsEvent; +import nostr.event.impl.MetadataEvent; +import nostr.event.impl.MuteUserEvent; +import nostr.event.impl.ReactionEvent; +import nostr.event.impl.ReplaceableEvent; +import nostr.event.impl.TextNoteEvent; +import nostr.event.list.KindList; +import nostr.event.list.TagList; +import nostr.event.message.EventMessage; +import nostr.event.message.ReqMessage; +import nostr.event.tag.EventTag; +import nostr.event.tag.PubKeyTag; +import nostr.id.Client; +import nostr.id.Identity; +import nostr.util.NostrException; +import nostr.util.UnsupportedNIPException; + +/** + * + * @author squirrel + */ +@Log +public class NostrExamples { + + private static final Identity RECEIVER = Identity.generateRandomIdentity(); + private static final Identity SENDER = Identity.generateRandomIdentity(); + + private static final UserProfile PROFILE = new UserProfile(SENDER.getPublicKey(), "erict875@nostr-java.io", "eric t", "It's me!", null); + + private final static Map RELAYS = Map.of("brb", "brb.io", "damus", "relay.damus.io", "ZBD", "nostr.zebedee.cloud", "taxi", "relay.taxi", "vision", "relay.nostr.vision"); + + private final static Client CLIENT = Client.getInstance(RELAYS); + + static { + final LogManager logManager = LogManager.getLogManager(); + try (final InputStream is = NostrExamples.class + .getResourceAsStream("/logging.properties")) { + logManager.readConfiguration(is); + } catch (IOException ex) { + System.exit(-1000); + } + + try { + PROFILE.setPicture(new URL("https://images.unsplash.com/photo-1462888210965-cdf193fb74de")); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) throws IOException, Exception { + try { +// Wait it until tried to connect to a half of relays + while (CLIENT.getThreadPool().getCompletedTaskCount() < (RELAYS.size() / 2)) { + Thread.sleep(5000); + } + + log.log(Level.FINE, "================= The Beginning"); + logAccountsData(); + + ExecutorService executor = Executors.newFixedThreadPool(10); + + executor.submit(() -> { + try { + sendTextNoteEvent(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + sendEncryptedDirectMessage(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + mentionsEvent(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + deletionEvent(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + metaDataEvent(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + ephemerealEvent(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + reactionEvent(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + replaceableEvent(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + internetIdMetadata(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + filters(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + createChannel(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + updateChannelMetadata(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + sendChannelMessage(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + hideMessage(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + executor.submit(() -> { + try { + muteUser(); + } catch (NostrException ex) { + log.log(Level.SEVERE, null, ex); + } + }); + + stop(executor); + + if (executor.isTerminated()) { + log.log(Level.FINE, "================== The End"); + } + + } catch (IllegalArgumentException ex) { + log.log(Level.SEVERE, null, ex); + throw new NostrException(ex); + } + } + + private static void sendTextNoteEvent() throws NostrException { + logHeader("sendTextNoteEvent"); + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build(); + TagList tagList = new TagList(); + tagList.add(rcptTag); + + GenericEvent event = new TextNoteEvent(publicKeySender, tagList, + "Hello world, I'm here on nostr-java API!"); + + SENDER.sign(event); + GenericMessage message = new EventMessage(event); + + CLIENT.send(message); + } catch (UnsupportedNIPException ex) { + log.log(Level.WARNING, null, ex); + } + } + + private static void sendEncryptedDirectMessage() throws NostrException { + logHeader("sendEncryptedDirectMessage"); + + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build(); + TagList tagList = new TagList(); + tagList.add(rcptTag); + + var event2 = new DirectMessageEvent(publicKeySender, tagList, "Hello Nakamoto!"); + + SENDER.encryptDirectMessage(event2); + SENDER.sign(event2); + + GenericMessage message = new EventMessage(event2); + + CLIENT.send(message); + + } catch (UnsupportedNIPException ex) { + log.log(Level.WARNING, null, ex); + } + } + + private static void mentionsEvent() throws NostrException { + logHeader("mentionsEvent"); + + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + TagList tagList = new TagList(); + tagList.add(rcptTag); + + GenericEvent event = new MentionsEvent(publicKeySender, tagList, "Hello " + RECEIVER.getPublicKey().toString()); + SENDER.sign(event); + + GenericMessage message = new EventMessage(event); + + CLIENT.send(message); + + } catch (UnsupportedNIPException ex) { + log.log(Level.WARNING, null, ex); + } + } + + private static void deletionEvent() throws NostrException { + logHeader("deletionEvent"); + + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + TagList tagList = new TagList(); + tagList.add(rcptTag); + + GenericEvent event = new TextNoteEvent(publicKeySender, tagList, "Hello Astral, Please delete me!"); + + SENDER.sign(event); + GenericMessage message = new EventMessage(event); + + CLIENT.send(message); + + tagList = new TagList(); + tagList.add(EventTag.builder().idEvent(event.getId()).build()); + GenericEvent delEvent = new DeletionEvent(publicKeySender, tagList); + + SENDER.sign(delEvent); + message = new EventMessage(delEvent); + + CLIENT.send(message); + + } catch (UnsupportedNIPException ex) { + log.log(Level.WARNING, null, ex); + } + } + + private static void metaDataEvent() throws NostrException { + logHeader("metaDataEvent"); + + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + var event = new MetadataEvent(publicKeySender, PROFILE); + + SENDER.sign(event); + GenericMessage message = new EventMessage(event); + + CLIENT.send(message); + + } catch (UnsupportedNIPException ex) { + log.log(Level.WARNING, null, ex); + } + } + + private static void ephemerealEvent() throws NostrException { + logHeader("ephemerealEvent"); + + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + TagList tagList = new TagList(); + tagList.add(rcptTag); + + GenericEvent event = new EphemeralEvent(publicKeySender, tagList); + + SENDER.sign(event); + GenericMessage message = new EventMessage(event); + + CLIENT.send(message); + } catch (UnsupportedNIPException ex) { + log.log(Level.WARNING, null, ex); + } + } + + private static void reactionEvent() throws NostrException { + logHeader("reactionEvent"); + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + TagList tagList = new TagList(); + tagList.add(rcptTag); + + GenericEvent event = new TextNoteEvent(publicKeySender, tagList, "Hello Astral, Please like me!"); + + SENDER.sign(event); + GenericMessage message = new EventMessage(event); + + CLIENT.send(message); + + tagList = new TagList(); + tagList.add(EventTag.builder().idEvent(event.getId()).build()); + tagList.add(PubKeyTag.builder().publicKey(publicKeySender).build()); + GenericEvent reactionEvent = new ReactionEvent(publicKeySender, tagList, Reaction.LIKE, event); + + SENDER.sign(reactionEvent); + message = new EventMessage(reactionEvent); + + CLIENT.send(message); + + } catch (UnsupportedNIPException ex) { + log.log(Level.WARNING, null, ex); + } + } + + private static void replaceableEvent() throws NostrException { + logHeader("replaceableEvent"); + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + TagList tagList = new TagList(); + tagList.add(rcptTag); + + GenericEvent event = new TextNoteEvent(publicKeySender, tagList, "Hello Astral, Please replace me!"); + + SENDER.sign(event); + GenericMessage message = new EventMessage(event); + + CLIENT.send(message); + + tagList = new TagList(); + tagList.add(EventTag.builder().idEvent(event.getId()).build()); + GenericEvent replaceableEvent = new ReplaceableEvent(publicKeySender, 15000, tagList, "Content"); + + SENDER.sign(replaceableEvent); + message = new EventMessage(replaceableEvent); + + CLIENT.send(message); + + replaceableEvent = new ReplaceableEvent(publicKeySender, 15000, tagList, "New Content"); + + SENDER.sign(replaceableEvent); + message = new EventMessage(replaceableEvent); + + CLIENT.send(message); + } catch (UnsupportedNIPException ex) { + log.log(Level.WARNING, null, ex); + } + } + + private static void internetIdMetadata() throws NostrException { + logHeader("internetIdMetadata"); + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + TagList tagList = new TagList(); + tagList.add(rcptTag); + + GenericEvent event = new InternetIdentifierMetadataEvent(publicKeySender, tagList, PROFILE); + + SENDER.sign(event); + GenericMessage message = new EventMessage(event); + + CLIENT.send(message); + + } catch (UnsupportedNIPException ex) { + log.log(Level.WARNING, null, ex); + } + } + + // FIXME + public static void filters() throws NostrException { + logHeader("filters"); + try { + KindList kindList = new KindList(); + kindList.add(Kind.EPHEMEREAL_EVENT); + kindList.add(Kind.TEXT_NOTE); + + Filters filters = Filters.builder().kinds(kindList).limit(10).build(); + + String subId = "subId" + System.currentTimeMillis(); + GenericMessage message = new ReqMessage(subId, filters); + + CLIENT.send(message); + } catch (Exception ex) { + throw new NostrException(ex); + } + } + + private static GenericEvent createChannel() throws NostrException { + logHeader("createChannel"); + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + var channel = Channel.builder().name("JNostr Channel") + .about("This is a channel to test NIP28 in nostr-java") + .picture("https://cdn.pixabay.com/photo/2020/05/19/13/48/cartoon-5190942_960_720.jpg").build(); + GenericEvent event = new ChannelCreateEvent(publicKeySender, new TagList(), channel.toString()); + + SENDER.sign(event); + GenericMessage message = new EventMessage(event); + + CLIENT.send(message); + + return event; + } catch (Exception ex) { + throw new NostrException(ex); + } + } + + private static void updateChannelMetadata() throws NostrException { + logHeader("updateChannelMetadata"); + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + var channelCreateEvent = createChannel(); + + var tagList = new TagList(); + tagList.add(EventTag.builder().idEvent(channelCreateEvent.getId()) + .recommendedRelayUrl(CLIENT.getRelays().stream().findFirst().get().getUri()).build()); + + var channel = Channel.builder().name("test change name") + .about("This is a channel to test NIP28 in nostr-java | changed") + .picture("https://cdn.pixabay.com/photo/2020/05/19/13/48/cartoon-5190942_960_720.jpg").build(); + GenericEvent event = new ChannelMetadataEvent(publicKeySender, tagList, channel.toString()); + + SENDER.sign(event); + var message = new EventMessage(event); + + CLIENT.send(message); + } catch (Exception ex) { + throw new NostrException(ex); + } + } + + private static GenericEvent sendChannelMessage() throws NostrException { + logHeader("sendChannelMessage"); + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + var channelCreateEvent = createChannel(); + + var tagList = new TagList(); + tagList.add(EventTag.builder().idEvent(channelCreateEvent.getId()) + .recommendedRelayUrl(CLIENT.getRelays().stream().findFirst().get().getUri()) + .marker(Marker.ROOT) + .build()); + + GenericEvent event = new ChannelMessageEvent(publicKeySender, tagList, "Hello everybody!"); + + SENDER.sign(event); + var message = new EventMessage(event); + + CLIENT.send(message); + + return event; + } catch (Exception ex) { + throw new NostrException(ex); + } + } + + private static GenericEvent hideMessage() throws NostrException { + logHeader("hideMessage"); + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + var channelMessageEvent = sendChannelMessage(); + + var tagList = new TagList(); + tagList.add(EventTag.builder().idEvent(channelMessageEvent.getId()).build()); + + GenericEvent event = new HideMessageEvent(publicKeySender, tagList, + ContentReason.builder().reason("Dick pic").build().toString()); + + SENDER.sign(event); + var message = new EventMessage(event); + + CLIENT.send(message); + + return event; + } catch (Exception ex) { + throw new NostrException(ex); + } + } + + private static GenericEvent muteUser() throws NostrException { + logHeader("muteUser"); + try { + final PublicKey publicKeySender = SENDER.getPublicKey(); + + var tagList = new TagList(); + tagList.add(PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build()); + + GenericEvent event = new MuteUserEvent(publicKeySender, tagList, + ContentReason.builder().reason("Posting dick pics").build().toString()); + + SENDER.sign(event); + var message = new EventMessage(event); + + CLIENT.send(message); + + return event; + } catch (Exception ex) { + throw new NostrException(ex); + } + } + +// public static void sensitiveContentNote(Identity wallet, Client cliepublicKeySendernt) throws NostrException { +// logHeader("sensitiveContentNote"); +// try { +// // Create the attribute value list +// List values = new ArrayList<>(); +// values.add("sensitive content"); +// +// // Create the attributes +// final ElementAttribute attr = ElementAttribute.builder().nip(36).isString(true).name("reason").valueList(values).build(); +// Set attributes = new HashSet<>(); +// attributes.add(attr); +// +// GenericTag sensitiveContentTag = new GenericTag(1, "", attributes); +// } catch (UnsupportedNIPException ex) { +// log.log(Level.WARNING, null, ex); +// } catch (Exception ex) { +// throw new NostrException(ex); +// } +// +// } + private static void logAccountsData() throws NostrException { + StringBuilder msg = new StringBuilder("################################ ACCOUNTS BEGINNING ################################") + .append('\n').append("*** RECEIVER ***").append('\n') + .append('\n').append("* PrivateKey: ").append(RECEIVER.getPrivateKey().getBech32()) + .append('\n').append("* PrivateKey HEX: ").append(RECEIVER.getPrivateKey().toString()) + .append('\n').append("* PublicKey: ").append(RECEIVER.getPublicKey().getBech32()) + .append('\n').append("* PublicKey HEX: ").append(RECEIVER.getPublicKey().toString()) + .append('\n').append('\n').append("*** SENDER ***").append('\n') + .append('\n').append("* PrivateKey: ").append(SENDER.getPrivateKey().getBech32()) + .append('\n').append("* PrivateKey HEX: ").append(SENDER.getPrivateKey().toString()) + .append('\n').append("* PublicKey: ").append(SENDER.getPublicKey().getBech32()) + .append('\n').append("* PublicKey HEX: ").append(SENDER.getPublicKey().toString()) + .append('\n').append('\n').append("################################ ACCOUNTS END ################################"); + + log.log(Level.INFO, msg.toString()); + } + + private static void logHeader(String header) { + for (int i = 0; i < 30; i++) { + System.out.print("#"); + } + System.out.println(); + System.out.println("\t" + header); + for (int i = 0; i < 30; i++) { + System.out.print("#"); + } + System.out.println(); + } + + private static void stop(ExecutorService executor) { + try { + executor.shutdown(); + executor.awaitTermination(60, TimeUnit.SECONDS); + } catch (InterruptedException e) { + log.log(Level.SEVERE, "termination interrupted"); + } finally { + if (!executor.isTerminated()) { + log.log(Level.SEVERE, "killing non-finished tasks"); + } + executor.shutdownNow(); + } + } +} diff --git a/nostr-examples/src/main/resources/logging.properties b/nostr-java-examples/src/main/resources/logging.properties similarity index 100% rename from nostr-examples/src/main/resources/logging.properties rename to nostr-java-examples/src/main/resources/logging.properties diff --git a/nostr-id/nb-configuration.xml b/nostr-java-id/nb-configuration.xml similarity index 100% rename from nostr-id/nb-configuration.xml rename to nostr-java-id/nb-configuration.xml diff --git a/nostr-id/pom.xml b/nostr-java-id/pom.xml similarity index 51% rename from nostr-id/pom.xml rename to nostr-java-id/pom.xml index 1b7cac3c..bf7ae1c6 100644 --- a/nostr-id/pom.xml +++ b/nostr-java-id/pom.xml @@ -6,10 +6,10 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-id + nostr-java-id jar @@ -26,23 +26,49 @@ ${project.groupId} - nostr-base + nostr-java-base ${project.version} ${project.groupId} - nostr-event + nostr-java-event ${project.version} ${project.groupId} - nostr-util + nostr-java-util ${project.version} ${project.groupId} - nostr-ws + nostr-java-ws ${project.version} + + + nostr-java + nostr-base + + + nostr-java + nostr-event + + + nostr-java + nostr-util + + + nostr-java + nostr-ws-handler-command-provider + + + nostr-java + nostr-ws-handler-interface + + + nostr-java + nostr-ws-response-handler-provider + + org.bouncycastle @@ -51,13 +77,19 @@ ${project.groupId} - nostr-ws-handler-interface + nostr-java-ws-handler-interface ${project.version} ${project.groupId} - nostr-ws-request-handler-provider + nostr-java-ws-request-handler-provider ${project.version} + + + nostr-java + nostr-ws-handler-interface + + \ No newline at end of file diff --git a/nostr-id/src/main/java/module-info.java b/nostr-java-id/src/main/java/module-info.java similarity index 100% rename from nostr-id/src/main/java/module-info.java rename to nostr-java-id/src/main/java/module-info.java diff --git a/nostr-id/src/main/java/nostr/id/Client.java b/nostr-java-id/src/main/java/nostr/id/Client.java similarity index 82% rename from nostr-id/src/main/java/nostr/id/Client.java rename to nostr-java-id/src/main/java/nostr/id/Client.java index f63ec723..07f6cced 100644 --- a/nostr-id/src/main/java/nostr/id/Client.java +++ b/nostr-java-id/src/main/java/nostr/id/Client.java @@ -13,13 +13,12 @@ import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Collectors; import lombok.Data; import lombok.NonNull; import lombok.extern.java.Log; -import nostr.base.BaseConfiguration; +import nostr.util.AbstractBaseConfiguration; import nostr.base.Relay; import nostr.event.impl.ClientAuthenticationEvent; import nostr.event.impl.GenericEvent; @@ -44,11 +43,11 @@ public class Client { private final ThreadPoolExecutor threadPool; private IRequestHandler requestHandler; - private Client(String relayConfFile) throws IOException { + private Client() throws IOException { this.futureRelays = new HashSet<>(); this.requestHandler = new DefaultRequestHandler(); this.threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool(); - this.init(relayConfFile); + this.init(); } private Client(Map relays) { @@ -58,10 +57,10 @@ private Client(Map relays) { this.init(relays); } - public static Client getInstance(String relayConfFile) { + public static Client getInstance() { if (INSTANCE == null) { try { - INSTANCE = new Client(relayConfFile); + INSTANCE = new Client(); } catch (IOException ex) { log.log(Level.SEVERE, null, ex); throw new RuntimeException(ex); @@ -131,6 +130,16 @@ public void auth(Identity identity, String challenge) throws NostrException { this.send(authMsg); } + public void auth(Identity identity, String challenge, Relay relay) throws NostrException { + + log.log(Level.INFO, "Authenticating..."); + GenericEvent event = new ClientAuthenticationEvent(identity.getPublicKey(), challenge, relay); + GenericMessage authMsg = new AuthMessage(event); + + identity.sign(event); + this.send(authMsg); + } + private Set getRelaySet() { Set result = new HashSet<>(); @@ -138,7 +147,7 @@ private Set getRelaySet() { try { result.add(fr.get()); } catch (InterruptedException | ExecutionException ex) { - log.log(Level.SEVERE, null, ex); + throw new RuntimeException(ex); } }); @@ -168,13 +177,13 @@ private void init(Map mapRelays) { }); } - private void init(String file) throws IOException { - this.init(toMapRelays(file)); + private void init() throws IOException { + this.init(toMapRelays()); } - private Map toMapRelays(String file) throws IOException { + private Map toMapRelays() throws IOException { Map relays = new HashMap<>(); - List relayList = new RelayConfiguration(file).getRelays(); + List relayList = new RelayConfiguration().getRelays(); relayList.stream().forEach(r -> relays.put(r.getName(), r.getUri())); return relays; } @@ -189,14 +198,13 @@ private void updateRelayInformation(@NonNull Relay relay) { } @Log - static class RelayConfiguration extends BaseConfiguration { - + static class RelayConfiguration extends AbstractBaseConfiguration { + RelayConfiguration() throws IOException { - this("/relays.properties"); - } - - RelayConfiguration(String file) throws IOException { - super(file); + super(); + var configFile = appConfig.getRelaysProperties(); + configFile = configFile.startsWith("/") ? configFile : "/" + configFile; + load(configFile); } List getRelays() { diff --git a/nostr-id/src/main/java/nostr/id/Identity.java b/nostr-java-id/src/main/java/nostr/id/Identity.java similarity index 92% rename from nostr-id/src/main/java/nostr/id/Identity.java rename to nostr-java-id/src/main/java/nostr/id/Identity.java index 8c31d1ad..6500f9a4 100644 --- a/nostr-id/src/main/java/nostr/id/Identity.java +++ b/nostr-java-id/src/main/java/nostr/id/Identity.java @@ -27,7 +27,7 @@ import lombok.NonNull; import lombok.ToString; import lombok.extern.java.Log; -import nostr.base.BaseConfiguration; +import nostr.util.AbstractBaseConfiguration; import nostr.base.ISignable; import nostr.base.ITag; import nostr.base.PrivateKey; @@ -53,19 +53,23 @@ public class Identity { private static Identity INSTANCE; - + @ToString.Exclude private final PrivateKey privateKey; - private Identity(String profileFile) throws IOException, NostrException { - this.privateKey = new IdentityConfiguration(profileFile).getPrivateKey(); + private Identity() throws IOException, NostrException { + this.privateKey = new IdentityConfiguration().getPrivateKey(); } - - public static Identity getInstance() throws IOException, NostrException { - if(INSTANCE == null) { - INSTANCE = new Identity("/profile.properties"); + + public static Identity getInstance() { + if (INSTANCE == null) { + try { + INSTANCE = new Identity(); + } catch (IOException | NostrException ex) { + throw new RuntimeException(ex); + } } - + return INSTANCE; } @@ -227,16 +231,22 @@ private static PublicKey generatePublicKey(PrivateKey privateKey) throws Excepti } @Log - static class IdentityConfiguration extends BaseConfiguration { + static class IdentityConfiguration extends AbstractBaseConfiguration { - IdentityConfiguration(String propertyFile) throws IOException { - super(propertyFile); + IdentityConfiguration() throws IOException { + super(); + var configFile = appConfig.getIdentityProperties(); + configFile = configFile.startsWith("/") ? configFile : "/" + configFile; + load(configFile); } PrivateKey getPrivateKey() throws IOException, NostrException { String privKey = getProperty("privateKey"); log.log(Level.FINE, "Reading the private key..."); + if (privKey == null) { + throw new RuntimeException("Missing private key. Aborting...."); + } String hex = privKey.startsWith(Bech32Prefix.NSEC.getCode()) ? Bech32.fromBech32(privKey) : privKey; return new PrivateKey(hex); } diff --git a/nostr-id/src/main/resources/profile.properties b/nostr-java-id/src/main/resources/profile.properties similarity index 100% rename from nostr-id/src/main/resources/profile.properties rename to nostr-java-id/src/main/resources/profile.properties diff --git a/nostr-id/src/main/resources/relays.properties b/nostr-java-id/src/main/resources/relays.properties similarity index 100% rename from nostr-id/src/main/resources/relays.properties rename to nostr-java-id/src/main/resources/relays.properties diff --git a/nostr-test/nb-configuration.xml b/nostr-java-test/nb-configuration.xml similarity index 100% rename from nostr-test/nb-configuration.xml rename to nostr-java-test/nb-configuration.xml diff --git a/nostr-test/pom.xml b/nostr-java-test/pom.xml similarity index 85% rename from nostr-test/pom.xml rename to nostr-java-test/pom.xml index fb751e52..d1fc86b3 100644 --- a/nostr-test/pom.xml +++ b/nostr-java-test/pom.xml @@ -6,16 +6,12 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-test + nostr-java-test jar - - com.tcheeric.nostr.test.NostrTest - - @@ -26,23 +22,23 @@ ${project.groupId} - nostr-event + nostr-java-event ${project.version} ${project.groupId} - nostr-base + nostr-java-base ${project.version} ${project.groupId} - nostr-id + nostr-java-id ${project.version} test ${project.groupId} - nostr-util + nostr-java-util ${project.version} diff --git a/nostr-java-test/src/main/java/nostr/test/EntityFactory.java b/nostr-java-test/src/main/java/nostr/test/EntityFactory.java new file mode 100644 index 00000000..fbee2bf4 --- /dev/null +++ b/nostr-java-test/src/main/java/nostr/test/EntityFactory.java @@ -0,0 +1,219 @@ +package nostr.test; + +import java.beans.IntrospectionException; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import lombok.extern.java.Log; +import nostr.base.ElementAttribute; +import nostr.base.GenericTagQuery; +import nostr.base.IEvent; +import nostr.base.UserProfile; +import nostr.base.PublicKey; +import nostr.event.Reaction; +import nostr.event.impl.DirectMessageEvent; +import nostr.event.impl.EphemeralEvent; +import nostr.event.impl.Filters; +import nostr.event.impl.GenericEvent; +import nostr.event.impl.GenericTag; +import nostr.event.impl.InternetIdentifierMetadataEvent; +import nostr.event.impl.MentionsEvent; +import nostr.event.impl.MetadataEvent; +import nostr.event.impl.OtsEvent; +import nostr.event.impl.ReactionEvent; +import nostr.event.impl.ReplaceableEvent; +import nostr.event.impl.TextNoteEvent; +import nostr.event.list.EventList; +import nostr.event.list.GenericTagQueryList; +import nostr.event.list.KindList; +import nostr.event.list.PublicKeyList; +import nostr.event.list.TagList; +import nostr.event.tag.PubKeyTag; +import nostr.util.NostrException; + +/** + * + * @author squirrel + */ +@Log +//TODO - Add the sender PK to all createEvents. +public class EntityFactory { + + @Log + public static class Events { + + @SuppressWarnings("unchecked") + public static EphemeralEvent createEphemeralEvent(PublicKey publicKey) { + TagList tagList = new TagList(); + tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("eric").build()); + GenericEvent event = new EphemeralEvent(publicKey, tagList); + event.update(); + return (EphemeralEvent) event; + } + + public static DirectMessageEvent createDirectMessageEvent(PublicKey senderPublicKey, PublicKey rcptPublicKey, String content) { + TagList tagList = new TagList(); + tagList.add(PubKeyTag.builder().publicKey(rcptPublicKey).petName("uq7yfx3l").build()); + GenericEvent event = new DirectMessageEvent(senderPublicKey, tagList, content); + event.update(); + return (DirectMessageEvent) event; + } + + public static Filters createFilters(PublicKeyList authors, KindList kindList, Long since) { + return Filters.builder().authors(authors).kinds(kindList).since(since).build(); + } + + @SuppressWarnings("unchecked") + public static InternetIdentifierMetadataEvent createInternetIdentifierMetadataEvent(UserProfile profile) throws NostrException { + final PublicKey publicKey = profile.getPublicKey(); + TagList tagList = new TagList(); + tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("daniel").build()); + GenericEvent event = new InternetIdentifierMetadataEvent(publicKey, tagList, profile); + event.update(); + return (InternetIdentifierMetadataEvent) event; + } + + @SuppressWarnings("unchecked") + public static MentionsEvent createMentionsEvent(PublicKey publicKey) { + TagList tagList = new TagList(); + tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("charlie").build()); + String content = generateRamdomAlpha(32); + StringBuilder sbContent = new StringBuilder(content); + + int len = tagList.getList().size(); + for (int i = 0; i < len; i++) { + sbContent.append(", ").append(((PubKeyTag) tagList.getList().get(i)).getPublicKey().toString()); + + } + GenericEvent event = new MentionsEvent(publicKey, tagList, sbContent.toString()); + event.update(); + return (MentionsEvent) event; + } + + @SuppressWarnings("unchecked") + public static MetadataEvent createMetadataEvent(UserProfile profile) throws NostrException { + final PublicKey publicKey = profile.getPublicKey(); + GenericEvent event = new MetadataEvent(publicKey, profile); + return (MetadataEvent) event; + } + + @SuppressWarnings("unchecked") + public static ReactionEvent createReactionEvent(PublicKey publicKey, GenericEvent original) { + TagList tagList = new TagList(); + tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("charlie").build()); + GenericEvent event = new ReactionEvent(publicKey, tagList, Reaction.LIKE, original); + return (ReactionEvent) event; + } + + public static ReplaceableEvent createReplaceableEvent(PublicKey publicKey) { + String content = generateRamdomAlpha(32); + GenericEvent event = new ReplaceableEvent(publicKey, 15000, new TagList(), content); + return (ReplaceableEvent) event; + } + + public static TextNoteEvent createTextNoteEvent(PublicKey publicKey) { + String content = generateRamdomAlpha(32); + return createTextNoteEvent(publicKey, content); + } + + @SuppressWarnings("unchecked") + public static TextNoteEvent createTextNoteEvent(PublicKey publicKey, String content) { + TagList tagList = new TagList(); + tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("alice").build()); + GenericEvent event = new TextNoteEvent(publicKey, tagList, content); + return (TextNoteEvent) event; + } + + public static OtsEvent createOtsEvent(PublicKey publicKey) { + TagList tagList = new TagList(); + final PubKeyTag pkTag = PubKeyTag.builder().publicKey(publicKey).petName("bob").build(); + tagList.add(pkTag); + OtsEvent event = new OtsEvent(publicKey, tagList, generateRamdomAlpha(32), generateRamdomAlpha(32)); + return event; + } + + public static GenericTag createGenericTag(PublicKey publicKey) { + IEvent event = createTextNoteEvent(publicKey); + return createGenericTag(publicKey, event); + } + + public static GenericTag createGenericTag(PublicKey publicKey, IEvent event) { + GenericTag tag = new GenericTag("devil"); + tag.addAttribute(ElementAttribute.builder().value("Lucifer").nip(666).build()); + ((GenericEvent) event).addTag(tag); + return tag; + } + + public static GenericTag createGenericTag(PublicKey publicKey, IEvent event, Integer tagNip) { + GenericTag tag = new GenericTag(tagNip, "devil"); + tag.addAttribute(ElementAttribute.builder().value("Lucifer").nip(666).build()); + ((GenericEvent) event).addTag(tag); + return tag; + } + + public static Filters createFilters(PublicKey publicKey) { + EventList eventList = new EventList(); + eventList.add(createTextNoteEvent(publicKey)); + eventList.add(createEphemeralEvent(publicKey)); + + EventList refEvents = new EventList(); + refEvents.add(createTextNoteEvent(publicKey)); + + GenericTagQueryList gtqList = new GenericTagQueryList(); + gtqList.add(createGenericTagQuery()); + + return Filters.builder().events(eventList).referencedEvents(refEvents).genericTagQueryList(gtqList).build(); + } + + public static GenericTagQuery createGenericTagQuery() { + Character c = generateRamdomAlpha(1).charAt(0); + String v1 = generateRamdomAlpha(5); + String v2 = generateRamdomAlpha(6); + String v3 = generateRamdomAlpha(7); + + List list = new ArrayList<>(); + list.add(v3); + list.add(v2); + list.add(v1); + return GenericTagQuery.builder().tagName(c).value(list).build(); + } + } + + public static UserProfile createProfile(PublicKey pubKey) { + try { + String number = EntityFactory.generateRandomNumber(4); + String about = "about_" + number; + String name = "name_" + number; + String nip05 = name + "@tcheeric.com"; + String url = "http://assets.tcheeric.com/" + number + ".PNG"; + + return new UserProfile(pubKey, nip05, name, about, new URL(url)); + + } catch (MalformedURLException ex) { + throw new RuntimeException(ex); + } + } + + public static String generateRamdomAlpha(int len) { + return generateRandom(58, 122, len); + } + + public static String generateRandomNumber(int len) { + return generateRandom(48, 57, len); + } + + private static String generateRandom(int leftLimit, int rightLimit, int len) { + + return new Random().ints(leftLimit, rightLimit + 1) + .filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97)) + .limit(len) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) + .toString(); + } + +} diff --git a/nostr-test/src/test/java/nostr/test/base/NostrUtilTest.java b/nostr-java-test/src/test/java/nostr/test/base/NostrUtilTest.java similarity index 100% rename from nostr-test/src/test/java/nostr/test/base/NostrUtilTest.java rename to nostr-java-test/src/test/java/nostr/test/base/NostrUtilTest.java diff --git a/nostr-test/src/test/java/nostr/test/crypto/CryptoTest.java b/nostr-java-test/src/test/java/nostr/test/crypto/CryptoTest.java similarity index 100% rename from nostr-test/src/test/java/nostr/test/crypto/CryptoTest.java rename to nostr-java-test/src/test/java/nostr/test/crypto/CryptoTest.java diff --git a/nostr-test/src/test/java/nostr/test/event/EventTest.java b/nostr-java-test/src/test/java/nostr/test/event/EventTest.java similarity index 86% rename from nostr-test/src/test/java/nostr/test/event/EventTest.java rename to nostr-java-test/src/test/java/nostr/test/event/EventTest.java index 62a163fb..aa25acbc 100644 --- a/nostr-test/src/test/java/nostr/test/event/EventTest.java +++ b/nostr-java-test/src/test/java/nostr/test/event/EventTest.java @@ -1,6 +1,11 @@ package nostr.test.event; +import java.beans.IntrospectionException; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.security.NoSuchAlgorithmException; +import java.util.logging.Level; +import java.util.logging.Logger; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -30,25 +35,20 @@ public class EventTest { //private final Identity identity; public EventTest() throws IOException, NostrException { - //this.identity = new Identity("/profile.properties"); } @Test - public void testCreateTextNoteEvent() { - try { - System.out.println("testCreateTextNoteEvent"); - //PublicKey publicKey = this.identity.getPublicKey(); - PublicKey publicKey = Identity.getInstance().getPublicKey(); - GenericEvent instance = EntityFactory.Events.createTextNoteEvent(publicKey); - Assertions.assertNotNull(instance.getId()); - Assertions.assertNotNull(instance.getCreatedAt()); - Assertions.assertNull(instance.getSignature()); - final String bech32 = instance.toBech32(); - Assertions.assertNotNull(bech32); - Assertions.assertEquals(Bech32Prefix.NOTE.getCode(), Bech32.decode(bech32).hrp); - } catch (NostrException | IOException ex) { - Assertions.fail(ex); - } + public void testCreateTextNoteEvent() throws NostrException { + System.out.println("testCreateTextNoteEvent"); + PublicKey publicKey = Identity.getInstance().getPublicKey(); + GenericEvent instance = EntityFactory.Events.createTextNoteEvent(publicKey); + instance.update(); + Assertions.assertNotNull(instance.getId()); + Assertions.assertNotNull(instance.getCreatedAt()); + Assertions.assertNull(instance.getSignature()); + final String bech32 = instance.toBech32(); + Assertions.assertNotNull(bech32); + Assertions.assertEquals(Bech32Prefix.NOTE.getCode(), Bech32.decode(bech32).hrp); } @Test diff --git a/nostr-test/src/test/java/nostr/test/id/ClientTest.java b/nostr-java-test/src/test/java/nostr/test/id/ClientTest.java similarity index 67% rename from nostr-test/src/test/java/nostr/test/id/ClientTest.java rename to nostr-java-test/src/test/java/nostr/test/id/ClientTest.java index 3b90ba8e..63ff09a7 100644 --- a/nostr-test/src/test/java/nostr/test/id/ClientTest.java +++ b/nostr-java-test/src/test/java/nostr/test/id/ClientTest.java @@ -21,25 +21,16 @@ */ class ClientTest { -// private final Client client; -// private final Identity identity; - public ClientTest() throws IOException, NostrException { -// this.client = new Client("/relays.properties"); -// this.identity = new Identity("/profile.properties"); } @Test public void testSend() { - try { - System.out.println("testSend"); - PublicKey publicKey = Identity.getInstance().getPublicKey(); - GenericMessage msg = new EventMessage(EntityFactory.Events.createTextNoteEvent(publicKey)); - Client.getInstance("/relays.properties").send(msg); - assertTrue(true); - } catch (IOException | NostrException ex) { - fail(ex); - } + System.out.println("testSend"); + PublicKey publicKey = Identity.getInstance().getPublicKey(); + GenericMessage msg = new EventMessage(EntityFactory.Events.createTextNoteEvent(publicKey)); + Client.getInstance().send(msg); + assertTrue(true); } // @Test diff --git a/nostr-test/src/test/java/nostr/test/id/IdentityTest.java b/nostr-java-test/src/test/java/nostr/test/id/IdentityTest.java similarity index 97% rename from nostr-test/src/test/java/nostr/test/id/IdentityTest.java rename to nostr-java-test/src/test/java/nostr/test/id/IdentityTest.java index 83d4a5f8..137f8e93 100644 --- a/nostr-test/src/test/java/nostr/test/id/IdentityTest.java +++ b/nostr-java-test/src/test/java/nostr/test/id/IdentityTest.java @@ -23,7 +23,6 @@ public class IdentityTest { //private final Identity identity; public IdentityTest() throws IOException, NostrException { - //Identity.getInstance() = new Identity("/profile.properties"); } @Test diff --git a/nostr-java-test/src/test/resources/app.properties b/nostr-java-test/src/test/resources/app.properties new file mode 100644 index 00000000..4ff8e632 --- /dev/null +++ b/nostr-java-test/src/test/resources/app.properties @@ -0,0 +1,3 @@ +profile=profile.properties +client=client.properties +relays=relays.properties \ No newline at end of file diff --git a/nostr-test/src/test/resources/profile.properties b/nostr-java-test/src/test/resources/profile.properties similarity index 100% rename from nostr-test/src/test/resources/profile.properties rename to nostr-java-test/src/test/resources/profile.properties diff --git a/nostr-util/nb-configuration.xml b/nostr-java-util/nb-configuration.xml similarity index 100% rename from nostr-util/nb-configuration.xml rename to nostr-java-util/nb-configuration.xml diff --git a/nostr-util/pom.xml b/nostr-java-util/pom.xml similarity index 89% rename from nostr-util/pom.xml rename to nostr-java-util/pom.xml index f94355a4..fdf629f0 100644 --- a/nostr-util/pom.xml +++ b/nostr-java-util/pom.xml @@ -6,10 +6,10 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-util + nostr-java-util jar diff --git a/nostr-util/src/main/java/module-info.java b/nostr-java-util/src/main/java/module-info.java similarity index 91% rename from nostr-util/src/main/java/module-info.java rename to nostr-java-util/src/main/java/module-info.java index 9ea7b537..c7dcf4d4 100644 --- a/nostr-util/src/main/java/module-info.java +++ b/nostr-java-util/src/main/java/module-info.java @@ -5,6 +5,7 @@ module nostr.util { requires static lombok; + requires java.logging; exports nostr.util; } diff --git a/nostr-base/src/main/java/nostr/base/BaseConfiguration.java b/nostr-java-util/src/main/java/nostr/util/AbstractBaseConfiguration.java similarity index 75% rename from nostr-base/src/main/java/nostr/base/BaseConfiguration.java rename to nostr-java-util/src/main/java/nostr/util/AbstractBaseConfiguration.java index 19f27b2e..8774e570 100644 --- a/nostr-base/src/main/java/nostr/base/BaseConfiguration.java +++ b/nostr-java-util/src/main/java/nostr/util/AbstractBaseConfiguration.java @@ -1,4 +1,4 @@ -package nostr.base; +package nostr.util; import java.io.File; import java.io.FileInputStream; @@ -9,7 +9,6 @@ import java.util.logging.Level; import lombok.Data; -import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.extern.java.Log; @@ -19,16 +18,20 @@ */ @Data @Log -@NoArgsConstructor -public class BaseConfiguration { +public abstract class AbstractBaseConfiguration { protected final Properties properties = new Properties(); + protected final ApplicationConfiguration appConfig; private static final String PREFIX_FILE = "file."; private static final String CONFIG_DIR = "config.folder"; - protected BaseConfiguration(@NonNull String file) throws IOException { - load(file); + protected AbstractBaseConfiguration() throws IOException { + this.appConfig = new ApplicationConfiguration(); + } + + protected AbstractBaseConfiguration(ApplicationConfiguration appConfig) { + this.appConfig = appConfig; } protected String getFileLocation(String key) throws FileNotFoundException { @@ -79,13 +82,16 @@ private String getPrefix(String key) { return null; } - private void load(@NonNull String filename) throws FileNotFoundException, IOException { - - var configFolder = System.getProperty(CONFIG_DIR); + protected final void load(@NonNull String filename) throws FileNotFoundException, IOException { - log.log(Level.FINER, "Configuration location: {0}", configFolder); + //var configFolder = System.getProperty(CONFIG_DIR); + var configFolder = this.appConfig.getDefaultConfigFolder(); + log.log(Level.INFO, "loading configuration file: {0}", filename); + log.log(Level.FINE, "Configuration location: {0}", configFolder); if (configFolder != null) { - loadFromConfigDir(filename, configFolder); + final var baseConfigFolder = appConfig.getDefaultBaseConfigFolder(); + final var configLocationFolder = new File(baseConfigFolder, configFolder);//(baseConfigFolder + configFolder).replace("//", "/"); + loadFromConfigDir(filename, configLocationFolder); return; } @@ -117,11 +123,11 @@ private void loadFromResourceStream(String filename) throws IOException { } } - private void loadFromConfigDir(String filename, String configFolder) throws IOException { + private void loadFromConfigDir(String filename, File configFolder) throws IOException { log.log(Level.FINER, "loadFromConfigDir({0}, {1})", new Object[]{filename, configFolder}); final String fname = filename.substring(1); var tmpFile = filename.startsWith("/") ? fname : filename; - final File file = new File(new File(configFolder), tmpFile); + final File file = new File(configFolder, tmpFile); log.log(Level.FINER, "Configuration file {0}", file.getName()); if (file.exists()) { var inputStream = new FileInputStream(file); diff --git a/nostr-java-util/src/main/java/nostr/util/ApplicationConfiguration.java b/nostr-java-util/src/main/java/nostr/util/ApplicationConfiguration.java new file mode 100644 index 00000000..b28a1361 --- /dev/null +++ b/nostr-java-util/src/main/java/nostr/util/ApplicationConfiguration.java @@ -0,0 +1,85 @@ +package nostr.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.Level; +import java.util.Properties; +import lombok.extern.java.Log; + +/** + * + * @author eric + */ +@Log +public class ApplicationConfiguration { + + private final String DEFAULT_APP_CONFIG = "config"; + private final String DEFAULT_ID_CONFIG = "/profile.properties"; + private final String DEFAULT_RELAYS_CONFIG = "/relays.properties"; + //private final String DEFAULT_CLIENT_CONFIG = "/client.properties"; + private final String DEFAULT_CONFIG_FOLDER = ".nostr-java"; + + private final Properties properties; + + public ApplicationConfiguration() throws IOException { + InputStream appConfig = getAppConfig(); + this.properties = new Properties(); + + log.log(Level.INFO, "Loading the application configuration file..."); + this.properties.load(appConfig); + } + + public String getIdentityProperties() { + var id = getProperty("profile"); + return id == null ? DEFAULT_ID_CONFIG : id; + } + +// public String getClientProperties() { +// var client = getProperty("client"); +// return client == null ? DEFAULT_CLIENT_CONFIG : client; +// } + + public String getRelaysProperties() { + var client = getProperty("relays"); + return client == null ? DEFAULT_RELAYS_CONFIG : client; + } + + public String getDefaultConfigFolder() { + return getProperty("config.folder"); + } + + public String getDefaultBaseConfigFolder() { + var dcf = getProperty("config.base"); + return dcf == null ? System.getProperty("user.home") : dcf; + } + + private InputStream getAppConfig() throws FileNotFoundException { + var configFile = System.getProperty(DEFAULT_APP_CONFIG); + return configFile == null ? getAppProperties() : new FileInputStream(configFile); + } + + protected String getProperty(String key) { + return this.properties.getProperty(key); + } + + private InputStream getAppProperties() throws FileNotFoundException { + + if (new File("app.properties").exists()) { + return new FileInputStream("app.properties"); + } + + ClassLoader classLoader = getClass().getClassLoader(); + InputStream resource = classLoader.getResourceAsStream("/app.properties"); + resource = resource == null ? classLoader.getResourceAsStream("app.properties") : resource; + + if (resource == null) { + throw new IllegalStateException("app.properties file not found in resources folder."); + } + + return resource; + } + +} diff --git a/nostr-util/src/main/java/nostr/util/NostrException.java b/nostr-java-util/src/main/java/nostr/util/NostrException.java similarity index 100% rename from nostr-util/src/main/java/nostr/util/NostrException.java rename to nostr-java-util/src/main/java/nostr/util/NostrException.java diff --git a/nostr-util/src/main/java/nostr/util/NostrUtil.java b/nostr-java-util/src/main/java/nostr/util/NostrUtil.java similarity index 100% rename from nostr-util/src/main/java/nostr/util/NostrUtil.java rename to nostr-java-util/src/main/java/nostr/util/NostrUtil.java diff --git a/nostr-util/src/main/java/nostr/util/UnsupportedNIPException.java b/nostr-java-util/src/main/java/nostr/util/UnsupportedNIPException.java similarity index 100% rename from nostr-util/src/main/java/nostr/util/UnsupportedNIPException.java rename to nostr-java-util/src/main/java/nostr/util/UnsupportedNIPException.java diff --git a/nostr-ws-response-handler-provider/pom.xml b/nostr-java-ws-handler-default-command/pom.xml similarity index 76% rename from nostr-ws-response-handler-provider/pom.xml rename to nostr-java-ws-handler-default-command/pom.xml index 6427c7be..8a119c0e 100644 --- a/nostr-ws-response-handler-provider/pom.xml +++ b/nostr-java-ws-handler-default-command/pom.xml @@ -1,25 +1,30 @@ 4.0.0 + nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-ws-response-handler-provider + + nostr-java-ws-handler-command-provider jar + ${project.groupId} - nostr-ws-handler-interface + nostr-java-ws-handler-interface ${project.version} ${project.groupId} - nostr-ws-handler-command-provider + nostr-java-id ${project.version} + + \ No newline at end of file diff --git a/nostr-ws-handler-default-command/src/main/java/module-info.java b/nostr-java-ws-handler-default-command/src/main/java/module-info.java similarity index 93% rename from nostr-ws-handler-default-command/src/main/java/module-info.java rename to nostr-java-ws-handler-default-command/src/main/java/module-info.java index 542ab7b2..1ca27409 100644 --- a/nostr-ws-handler-default-command/src/main/java/module-info.java +++ b/nostr-java-ws-handler-default-command/src/main/java/module-info.java @@ -7,6 +7,8 @@ requires nostr.ws.handler; requires nostr.util; requires nostr.base; + requires nostr.id; + requires nostr.event; requires com.fasterxml.jackson.databind; requires com.fasterxml.jackson.annotation; requires com.fasterxml.jackson.core; diff --git a/nostr-ws-handler-default-command/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java b/nostr-java-ws-handler-default-command/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java similarity index 78% rename from nostr-ws-handler-default-command/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java rename to nostr-java-ws-handler-default-command/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java index ac20df8b..b025c818 100644 --- a/nostr-ws-handler-default-command/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java +++ b/nostr-java-ws-handler-default-command/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java @@ -9,6 +9,9 @@ import nostr.base.Command; import nostr.base.Relay; import nostr.base.annotation.DefaultHandler; +import nostr.id.Client; +import nostr.id.Identity; +import nostr.util.NostrException; import nostr.ws.handler.command.spi.ICommandHandler; import nostr.ws.handler.command.spi.ICommandHandler.Reason; @@ -41,7 +44,16 @@ public void onEvent(String jsonEvent, String subId, Relay relay) { } @Override - public void onAuth(String challenge, Relay relay) { + public void onAuth(String challenge, Relay relay) throws NostrException { log.log(Level.INFO, "Command: {0} - Challenge: {1} - Relay {3}", new Object[]{Command.AUTH, challenge, relay}); + + var client = Client.getInstance(); + var identity = Identity.getInstance(); + + client.auth(identity, challenge, relay); + } + + public static void auth(String challenge, Relay relay) throws NostrException { + new DefaultCommandHandler().onAuth(challenge, relay); } } diff --git a/nostr-ws-handler-default-command/src/main/resources/META-INF/services/nostr.ws.handler.command.spi.ICommandHandler b/nostr-java-ws-handler-default-command/src/main/resources/META-INF/services/nostr.ws.handler.command.spi.ICommandHandler similarity index 100% rename from nostr-ws-handler-default-command/src/main/resources/META-INF/services/nostr.ws.handler.command.spi.ICommandHandler rename to nostr-java-ws-handler-default-command/src/main/resources/META-INF/services/nostr.ws.handler.command.spi.ICommandHandler diff --git a/nostr-ws-handler/pom.xml b/nostr-java-ws-handler-interface/pom.xml similarity index 77% rename from nostr-ws-handler/pom.xml rename to nostr-java-ws-handler-interface/pom.xml index 36af202d..479f80cb 100644 --- a/nostr-ws-handler/pom.xml +++ b/nostr-java-ws-handler-interface/pom.xml @@ -5,25 +5,25 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-ws-handler-interface + nostr-java-ws-handler-interface jar nostr-java - nostr-util + nostr-java-util ${project.version} nostr-java - nostr-base + nostr-java-base ${project.version} ${project.groupId} - nostr-event + nostr-java-event ${project.version} diff --git a/nostr-ws-handler/src/main/java/module-info.java b/nostr-java-ws-handler-interface/src/main/java/module-info.java similarity index 100% rename from nostr-ws-handler/src/main/java/module-info.java rename to nostr-java-ws-handler-interface/src/main/java/module-info.java diff --git a/nostr-ws-handler/src/main/java/nostr/ws/handler/command/spi/ICommandHandler.java b/nostr-java-ws-handler-interface/src/main/java/nostr/ws/handler/command/spi/ICommandHandler.java similarity index 92% rename from nostr-ws-handler/src/main/java/nostr/ws/handler/command/spi/ICommandHandler.java rename to nostr-java-ws-handler-interface/src/main/java/nostr/ws/handler/command/spi/ICommandHandler.java index ba1d81d0..ffaa2113 100644 --- a/nostr-ws-handler/src/main/java/nostr/ws/handler/command/spi/ICommandHandler.java +++ b/nostr-java-ws-handler-interface/src/main/java/nostr/ws/handler/command/spi/ICommandHandler.java @@ -8,6 +8,7 @@ import java.util.Optional; import nostr.base.IHandler; import nostr.base.Relay; +import nostr.util.NostrException; /** * @@ -23,7 +24,7 @@ public interface ICommandHandler extends IHandler { public abstract void onEvent(String jsonEvent, String subId, Relay relay); - public abstract void onAuth(String challenge, Relay relay); + public abstract void onAuth(String challenge, Relay relay) throws NostrException; public enum Reason { UNDEFINED(""), diff --git a/nostr-ws-handler/src/main/java/nostr/ws/handler/spi/IRequestHandler.java b/nostr-java-ws-handler-interface/src/main/java/nostr/ws/handler/spi/IRequestHandler.java similarity index 100% rename from nostr-ws-handler/src/main/java/nostr/ws/handler/spi/IRequestHandler.java rename to nostr-java-ws-handler-interface/src/main/java/nostr/ws/handler/spi/IRequestHandler.java diff --git a/nostr-ws-handler/src/main/java/nostr/ws/handler/spi/IResponseHandler.java b/nostr-java-ws-handler-interface/src/main/java/nostr/ws/handler/spi/IResponseHandler.java similarity index 100% rename from nostr-ws-handler/src/main/java/nostr/ws/handler/spi/IResponseHandler.java rename to nostr-java-ws-handler-interface/src/main/java/nostr/ws/handler/spi/IResponseHandler.java diff --git a/nostr-ws-request-handler-provider/pom.xml b/nostr-java-ws-request-handler-provider/pom.xml similarity index 77% rename from nostr-ws-request-handler-provider/pom.xml rename to nostr-java-ws-request-handler-provider/pom.xml index 5f75d809..caf2d3fb 100644 --- a/nostr-ws-request-handler-provider/pom.xml +++ b/nostr-java-ws-request-handler-provider/pom.xml @@ -4,19 +4,19 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-ws-request-handler-provider + nostr-java-ws-request-handler-provider jar ${project.groupId} - nostr-ws + nostr-java-ws ${project.version} ${project.groupId} - nostr-ws-handler-interface + nostr-java-ws-handler-interface ${project.version} diff --git a/nostr-ws-request-handler-provider/src/main/java/module-info.java b/nostr-java-ws-request-handler-provider/src/main/java/module-info.java similarity index 100% rename from nostr-ws-request-handler-provider/src/main/java/module-info.java rename to nostr-java-ws-request-handler-provider/src/main/java/module-info.java diff --git a/nostr-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java b/nostr-java-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java similarity index 100% rename from nostr-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java rename to nostr-java-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java diff --git a/nostr-ws-request-handler-provider/src/main/resources/META-INF/services/nostr.ws.handler.spi.IRequestHandler b/nostr-java-ws-request-handler-provider/src/test/resources/META-INF/services/nostr.ws.handler.spi.IRequestHandler similarity index 100% rename from nostr-ws-request-handler-provider/src/main/resources/META-INF/services/nostr.ws.handler.spi.IRequestHandler rename to nostr-java-ws-request-handler-provider/src/test/resources/META-INF/services/nostr.ws.handler.spi.IRequestHandler diff --git a/nostr-ws-handler-default-command/pom.xml b/nostr-java-ws-response-handler-provider/pom.xml similarity index 78% rename from nostr-ws-handler-default-command/pom.xml rename to nostr-java-ws-response-handler-provider/pom.xml index 59f9090d..12cbf164 100644 --- a/nostr-ws-handler-default-command/pom.xml +++ b/nostr-java-ws-response-handler-provider/pom.xml @@ -1,25 +1,20 @@ 4.0.0 - nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - - nostr-ws-handler-command-provider + nostr-java-ws-response-handler-provider jar - ${project.groupId} - nostr-ws-handler-interface + nostr-java-ws-handler-interface ${project.version} - - \ No newline at end of file diff --git a/nostr-ws-response-handler-provider/src/main/java/module-info.java b/nostr-java-ws-response-handler-provider/src/main/java/module-info.java similarity index 100% rename from nostr-ws-response-handler-provider/src/main/java/module-info.java rename to nostr-java-ws-response-handler-provider/src/main/java/module-info.java diff --git a/nostr-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java similarity index 100% rename from nostr-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java rename to nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java diff --git a/nostr-ws-response-handler-provider/src/main/resources/META-INF/services/nostr.ws.handler.spi.IResponseHandler b/nostr-java-ws-response-handler-provider/src/main/resources/META-INF/services/nostr.ws.handler.spi.IResponseHandler similarity index 100% rename from nostr-ws-response-handler-provider/src/main/resources/META-INF/services/nostr.ws.handler.spi.IResponseHandler rename to nostr-java-ws-response-handler-provider/src/main/resources/META-INF/services/nostr.ws.handler.spi.IResponseHandler diff --git a/nostr-ws/nb-configuration.xml b/nostr-java-ws/nb-configuration.xml similarity index 100% rename from nostr-ws/nb-configuration.xml rename to nostr-java-ws/nb-configuration.xml diff --git a/nostr-ws/pom.xml b/nostr-java-ws/pom.xml similarity index 84% rename from nostr-ws/pom.xml rename to nostr-java-ws/pom.xml index 3e6ac286..8d4cf430 100644 --- a/nostr-ws/pom.xml +++ b/nostr-java-ws/pom.xml @@ -6,10 +6,10 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT - nostr-ws + nostr-java-ws jar @@ -37,22 +37,22 @@ ${project.groupId} - nostr-event + nostr-java-event ${project.version} ${project.groupId} - nostr-util + nostr-java-util ${project.version} ${project.groupId} - nostr-ws-handler-interface + nostr-java-ws-handler-interface ${project.version} ${project.groupId} - nostr-ws-response-handler-provider + nostr-java-ws-response-handler-provider ${project.version} diff --git a/nostr-ws/src/main/java/module-info.java b/nostr-java-ws/src/main/java/module-info.java similarity index 100% rename from nostr-ws/src/main/java/module-info.java rename to nostr-java-ws/src/main/java/module-info.java diff --git a/nostr-ws/src/main/java/nostr/ws/ClientListenerEndPoint.java b/nostr-java-ws/src/main/java/nostr/ws/ClientListenerEndPoint.java similarity index 87% rename from nostr-ws/src/main/java/nostr/ws/ClientListenerEndPoint.java rename to nostr-java-ws/src/main/java/nostr/ws/ClientListenerEndPoint.java index 23e7ff79..b0e9edb7 100644 --- a/nostr-ws/src/main/java/nostr/ws/ClientListenerEndPoint.java +++ b/nostr-java-ws/src/main/java/nostr/ws/ClientListenerEndPoint.java @@ -1,12 +1,8 @@ package nostr.ws; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.util.Arrays; -import java.util.List; import java.util.logging.Level; import lombok.NonNull; @@ -102,15 +98,6 @@ private void disposeResources() { log.log(Level.FINE, "disposeResources"); } - private List unmarshall(String message) { - try { - ObjectMapper objectMapper = new ObjectMapper(); - return Arrays.asList(objectMapper.readValue(message, String[].class)); - } catch (JsonProcessingException ex) { - throw new RuntimeException(ex); - } - } - private void savePNGImage(byte[] payload, int offset, int length) { log.log(Level.FINE, "savePNGImage"); } diff --git a/nostr-ws/src/main/java/nostr/ws/Connection.java b/nostr-java-ws/src/main/java/nostr/ws/Connection.java similarity index 96% rename from nostr-ws/src/main/java/nostr/ws/Connection.java rename to nostr-java-ws/src/main/java/nostr/ws/Connection.java index c82a0747..0f205ccb 100644 --- a/nostr-ws/src/main/java/nostr/ws/Connection.java +++ b/nostr-java-ws/src/main/java/nostr/ws/Connection.java @@ -183,7 +183,7 @@ public String getRelayInformation() throws InterruptedException, TimeoutExceptio public void updateRelayMetadata() throws Exception { String strInfo = getRelayInformation(); - log.log(Level.FINE, "Relay information: {0}", strInfo); + log.log(Level.INFO, "Relay information: {0}", strInfo); ObjectMapper objectMapper = new ObjectMapper(); var relayInfoDoc = objectMapper.readValue(strInfo, Relay.RelayInformationDocument.class); diff --git a/nostr-ws/src/main/resources/logging.properties b/nostr-java-ws/src/main/resources/logging.properties similarity index 100% rename from nostr-ws/src/main/resources/logging.properties rename to nostr-java-ws/src/main/resources/logging.properties diff --git a/nostr-test/src/main/java/nostr/test/EntityFactory.java b/nostr-test/src/main/java/nostr/test/EntityFactory.java deleted file mode 100644 index 265bbfc9..00000000 --- a/nostr-test/src/main/java/nostr/test/EntityFactory.java +++ /dev/null @@ -1,265 +0,0 @@ -package nostr.test; - -import java.beans.IntrospectionException; -import java.lang.reflect.InvocationTargetException; -import java.net.MalformedURLException; -import java.net.URL; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import lombok.extern.java.Log; -import nostr.base.ElementAttribute; -import nostr.base.GenericTagQuery; -import nostr.base.IEvent; -import nostr.base.Profile; -import nostr.base.PublicKey; -import nostr.event.Reaction; -import nostr.event.impl.DirectMessageEvent; -import nostr.event.impl.EphemeralEvent; -import nostr.event.impl.Filters; -import nostr.event.impl.GenericEvent; -import nostr.event.impl.GenericTag; -import nostr.event.impl.InternetIdentifierMetadataEvent; -import nostr.event.impl.MentionsEvent; -import nostr.event.impl.MetadataEvent; -import nostr.event.impl.OtsEvent; -import nostr.event.impl.ReactionEvent; -import nostr.event.impl.ReplaceableEvent; -import nostr.event.impl.TextNoteEvent; -import nostr.event.list.EventList; -import nostr.event.list.GenericTagQueryList; -import nostr.event.list.KindList; -import nostr.event.list.PubKeyTagList; -import nostr.event.list.PublicKeyList; -import nostr.event.list.TagList; -import nostr.event.tag.PubKeyTag; -import nostr.util.NostrException; - -/** - * - * @author squirrel - */ -@Log -//TODO - Add the sender PK to all createEvents. -public class EntityFactory { - - @Log - public static class Events { - - @SuppressWarnings("unchecked") - public static EphemeralEvent createEphemeralEvent(PublicKey publicKey) { - try { - TagList tagList = new TagList(); - tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("eric").build()); - GenericEvent event = new EphemeralEvent(publicKey, tagList); - event.update(); - return (EphemeralEvent) event; - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException | NostrException ex) { - throw new RuntimeException(ex); - } - } - - public static DirectMessageEvent createDirectMessageEvent(PublicKey senderPublicKey,PublicKey rcptPublicKey, String content) { - try { - TagList tagList = new TagList(); - tagList.add(PubKeyTag.builder().publicKey(rcptPublicKey).petName("uq7yfx3l").build()); - GenericEvent event = new DirectMessageEvent(senderPublicKey, tagList, content); - event.update(); - return (DirectMessageEvent) event; - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException | NostrException ex) { - throw new RuntimeException(ex); - } - } - - public static Filters createFilters(PublicKeyList authors, KindList kindList, Long since) { - return Filters.builder().authors(authors).kinds(kindList).since(since).build(); - } - - @SuppressWarnings("unchecked") - public static InternetIdentifierMetadataEvent createInternetIdentifierMetadataEvent(Profile profile) { - try { - final PublicKey publicKey = profile.getPublicKey(); - TagList tagList = new TagList(); - tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("daniel").build()); - GenericEvent event = new InternetIdentifierMetadataEvent(publicKey, tagList, profile); - event.update(); - return (InternetIdentifierMetadataEvent) event; - } catch (NostrException | NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException ex) { - throw new RuntimeException(ex); - } - } - - @SuppressWarnings("unchecked") - public static MentionsEvent createMentionsEvent(PublicKey publicKey, PubKeyTagList mentionees) { - try { - TagList tagList = new TagList(); - tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("charlie").build()); - String content = generateRamdomAlpha(32); - StringBuilder sbContent = new StringBuilder(content); - - int len = mentionees.size(); - for (int i = 0; i < len; i++) { - sbContent.append(", ").append(((PubKeyTag) mentionees.getList().get(i)).getPublicKey().toString()); - - } - GenericEvent event = new MentionsEvent(publicKey, tagList, sbContent.toString(), mentionees); - event.update(); - return (MentionsEvent) event; - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException | NostrException ex) { - throw new RuntimeException(ex); - } - } - - @SuppressWarnings("unchecked") - public static MetadataEvent createMetadataEvent(Profile profile) { - try { - final PublicKey publicKey = profile.getPublicKey(); - TagList tagList = new TagList(); - tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("charlie").build()); - GenericEvent event = new MetadataEvent(publicKey, tagList, profile); - event.update(); - return (MetadataEvent) event; - } catch (NostrException | NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException ex) { - throw new RuntimeException(ex); - } - } - - @SuppressWarnings("unchecked") - public static ReactionEvent createReactionEvent(PublicKey publicKey, GenericEvent original) { - try { - TagList tagList = new TagList(); - tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("charlie").build()); - GenericEvent event = new ReactionEvent(publicKey, tagList, Reaction.LIKE, original); - event.update(); - return (ReactionEvent) event; - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException | NostrException ex) { - throw new RuntimeException(ex); - } - } - - public static ReplaceableEvent createReplaceableEvent(GenericEvent original) { - try { - String content = generateRamdomAlpha(32); - TagList tagList = original.getTags(); - PublicKey publicKey = original.getPubKey(); - GenericEvent event = new ReplaceableEvent(publicKey, tagList, content, original); - event.update(); - return (ReplaceableEvent) event; - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException | NostrException ex) { - throw new RuntimeException(ex); - } - } - - public static TextNoteEvent createTextNoteEvent(PublicKey publicKey) { - String content = generateRamdomAlpha(32); - return createTextNoteEvent(publicKey, content); - } - - @SuppressWarnings("unchecked") - public static TextNoteEvent createTextNoteEvent(PublicKey publicKey, String content) { - try { - TagList tagList = new TagList(); - tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("alice").build()); - GenericEvent event = new TextNoteEvent(publicKey, tagList, content); - event.update(); - return (TextNoteEvent) event; - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException | NostrException ex) { - throw new RuntimeException(ex); - } - } - - public static OtsEvent createOtsEvent(PublicKey publicKey) { - try { - TagList tagList = new TagList(); - final PubKeyTag pkTag = PubKeyTag.builder().publicKey(publicKey).petName("bob").build(); - tagList.add(pkTag); - OtsEvent event = new OtsEvent(publicKey, tagList, generateRamdomAlpha(32), generateRamdomAlpha(32)); - event.update(); - return event; - } catch (NoSuchAlgorithmException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException | NostrException ex) { - throw new RuntimeException(ex); - } - } - - public static GenericTag createGenericTag(PublicKey publicKey) { - IEvent event = createTextNoteEvent(publicKey); - return createGenericTag(publicKey, event); - } - - public static GenericTag createGenericTag(PublicKey publicKey, IEvent event) { - GenericTag tag = new GenericTag("devil"); - tag.addAttribute(ElementAttribute.builder().value("Lucifer").nip(666).build()); - ((GenericEvent) event).addTag(tag); - return tag; - } - - public static GenericTag createGenericTag(PublicKey publicKey, IEvent event, Integer tagNip) { - GenericTag tag = new GenericTag(tagNip, "devil"); - tag.addAttribute(ElementAttribute.builder().value("Lucifer").nip(666).build()); - ((GenericEvent) event).addTag(tag); - return tag; - } - - public static Filters createFilters(PublicKey publicKey) { - EventList eventList = new EventList(); - eventList.add(createTextNoteEvent(publicKey)); - eventList.add(createEphemeralEvent(publicKey)); - - EventList refEvents = new EventList(); - refEvents.add(createTextNoteEvent(publicKey)); - - GenericTagQueryList gtqList = new GenericTagQueryList(); - gtqList.add(createGenericTagQuery()); - - return Filters.builder().events(eventList).referencedEvents(refEvents).genericTagQueryList(gtqList).build(); - } - - public static GenericTagQuery createGenericTagQuery() { - Character c = generateRamdomAlpha(1).charAt(0); - String v1 = generateRamdomAlpha(5); - String v2 = generateRamdomAlpha(6); - String v3 = generateRamdomAlpha(7); - - List list = new ArrayList<>(); - list.add(v3); - list.add(v2); - list.add(v1); - return GenericTagQuery.builder().tagName(c).value(list).build(); - } - } - - public static Profile createProfile(PublicKey pubKey) { - try { - String number = EntityFactory.generateRandomNumber(4); - String about = "about_" + number; - String name = "name_" + number; - String nip05 = name + "@tcheeric.com"; - String url = "http://assets.tcheeric.com/" + number + ".PNG"; - - return Profile.builder().about(about).name(name).nip05(nip05).picture(new URL(url)).publicKey(pubKey).build(); - - } catch (MalformedURLException ex) { - throw new RuntimeException(ex); - } - } - - public static String generateRamdomAlpha(int len) { - return generateRandom(58, 122, len); - } - - public static String generateRandomNumber(int len) { - return generateRandom(48, 57, len); - } - - private static String generateRandom(int leftLimit, int rightLimit, int len) { - - return new Random().ints(leftLimit, rightLimit + 1) - .filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97)) - .limit(len) - .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) - .toString(); - } - -} diff --git a/pom.xml b/pom.xml index b0288e8c..d6f6ffb8 100644 --- a/pom.xml +++ b/pom.xml @@ -5,22 +5,22 @@ nostr-java nostr-java - 0.1 + 0.2-SNAPSHOT pom - nostr-event - nostr-base - nostr-id - nostr-test - nostr-examples - nostr-util - nostr-crypto - nostr-ws - nostr-ws-handler - nostr-ws-response-handler-provider - nostr-ws-handler-default-command - nostr-ws-request-handler-provider + nostr-java-base + nostr-java-crypto + nostr-java-event + nostr-java-examples + nostr-java-id + nostr-java-test + nostr-java-util + nostr-java-ws + nostr-java-ws-handler-interface + nostr-java-ws-handler-default-command + nostr-java-ws-request-handler-provider + nostr-java-ws-response-handler-provider From f810a0308e71ec07eaa2203d936288b5c0f5f31d Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 1 Jun 2023 08:30:11 +0100 Subject: [PATCH 02/37] Minimal text --- README.md | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/README.md b/README.md index 4a69431d..e0c97406 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,2 @@ # nostr-java A nostr client library written in java, for generating, signing and publishing events to relays. -1. Unsupported events will not be published to the relay. -2. Unsupported tags will be discarded from the event before being published. - -## Usage -Have a look at [NostrExamples.java](https://github.com/tcheeric/nostr-java/blob/main/nostr-examples/src/main/java/nostr/examples/NostrExamples.java) in the [nostr-examples](https://github.com/tcheeric/nostr-java/tree/main/nostr-examples) folder for more details. - -## Currently Supported NIPS: - 1. NIP-01 - 2. NIP-02 - 3. NIP-03 - 4. NIP-04 - 5. NIP-05 - 6. NIP-08 - 7. NIP-09 - 8. NIP-10 - 9. NIP-12 - 10. NIP-14 - 11. NIP-16 - 12. NIP-19 (Partial: Bare keys and ids) - 13. NIP-25 - 14. NIP-26 - 15. NIP-28 \ No newline at end of file From 5c1c7009cc78b33f7886e88ba0b2c260dcd9cef5 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 1 Jun 2023 08:57:33 +0100 Subject: [PATCH 03/37] Typo --- nostr-java-base/src/main/java/nostr/base/Relay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nostr-java-base/src/main/java/nostr/base/Relay.java b/nostr-java-base/src/main/java/nostr/base/Relay.java index 96e2cd8b..3c3a99ff 100644 --- a/nostr-java-base/src/main/java/nostr/base/Relay.java +++ b/nostr-java-base/src/main/java/nostr/base/Relay.java @@ -79,7 +79,7 @@ public static class RelayInformationDocument { private String contact; @Builder.Default - @JsonProperty("supported_nipd") + @JsonProperty("supported_nips") @JsonIgnoreProperties(ignoreUnknown = true) private List supportedNips = new ArrayList<>(); From dad5cd905ed17830b7812c0ad7ce44e5f4fafe17 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Sun, 11 Jun 2023 23:21:51 +0100 Subject: [PATCH 04/37] Refactoring. Completed json codec with Jackson json library --- .../src/main/java/nostr/base/IMarshaller.java | 2 +- .../src/main/java/nostr/base/ITag.java | 4 +- .../src/main/java/nostr/base/PublicKey.java | 6 +- .../src/main/java/nostr/base/Signature.java | 22 ++-- .../base/util/PublicKeyDeserializer.java | 20 +++ .../base/util/SignatureDeserializer.java | 28 ++++ .../src/main/java/module-info.java | 2 +- .../src/main/java/nostr/event/BaseTag.java | 69 +++------- .../CustomBaseListEncoder.java} | 4 +- .../CustomGenericTagEncoder.java} | 6 +- .../CustomGenericTagListEncoder.java} | 4 +- .../CustomIdEventListEncoder.java} | 4 +- .../nostr/event/codec/CustomTagEncoder.java | 64 +++++++++ .../java/nostr/event/codec/ITagDecoder.java | 102 ++++++++++++++ .../nostr/event/impl/ChannelCreateEvent.java | 8 +- .../nostr/event/impl/ChannelMessageEvent.java | 5 +- .../event/impl/ChannelMetadataEvent.java | 7 +- .../event/impl/ClientAuthenticationEvent.java | 20 +-- .../java/nostr/event/impl/DeletionEvent.java | 19 ++- .../nostr/event/impl/DirectMessageEvent.java | 5 +- .../java/nostr/event/impl/EphemeralEvent.java | 7 +- .../main/java/nostr/event/impl/Filters.java | 10 +- .../java/nostr/event/impl/GenericEvent.java | 38 +++--- .../java/nostr/event/impl/GenericTag.java | 8 +- .../nostr/event/impl/HideMessageEvent.java | 5 +- .../impl/InternetIdentifierMetadataEvent.java | 13 +- .../java/nostr/event/impl/MentionsEvent.java | 11 +- .../java/nostr/event/impl/MetadataEvent.java | 5 +- .../java/nostr/event/impl/MuteUserEvent.java | 5 +- .../main/java/nostr/event/impl/OtsEvent.java | 5 +- .../java/nostr/event/impl/ReactionEvent.java | 5 +- .../nostr/event/impl/ReplaceableEvent.java | 5 +- .../java/nostr/event/impl/TextNoteEvent.java | 5 +- .../main/java/nostr/event/list/BaseList.java | 8 +- .../java/nostr/event/list/PubKeyTagList.java | 24 ---- .../main/java/nostr/event/list/TagList.java | 29 ---- .../marshaller/impl/ElementMarshaller.java | 12 +- .../marshaller/impl/FilterMarshaller.java | 3 +- .../marshaller/impl/GenericTagMarshaller.java | 19 +-- .../marshaller/impl/OstEventMarshaller.java | 5 +- .../event/marshaller/impl/TagMarshaller.java | 15 +-- .../event/message/ContactListMessage.java | 5 +- .../event/serializer/CustomTagSerializer.java | 53 -------- .../java/nostr/event/tag/DelegationTag.java | 18 ++- .../main/java/nostr/event/tag/EventTag.java | 11 ++ .../main/java/nostr/event/tag/NonceTag.java | 7 + .../main/java/nostr/event/tag/PubKeyTag.java | 21 +-- .../main/java/nostr/event/tag/SubjectTag.java | 12 +- .../java/nostr/examples/NostrExamples.java | 124 +++++++++--------- .../src/main/java/nostr/id/Identity.java | 10 +- .../main/java/nostr/test/EntityFactory.java | 26 ++-- .../nostr/util/AbstractBaseConfiguration.java | 10 +- .../nostr/util/ApplicationConfiguration.java | 5 - .../handler/provider/ResponseHandlerImpl.java | 46 ++++--- .../java/nostr/ws/ClientListenerEndPoint.java | 4 +- 55 files changed, 550 insertions(+), 440 deletions(-) create mode 100644 nostr-java-base/src/main/java/nostr/base/util/PublicKeyDeserializer.java create mode 100644 nostr-java-base/src/main/java/nostr/base/util/SignatureDeserializer.java rename nostr-java-event/src/main/java/nostr/event/{serializer/CustomBaseListSerializer.java => codec/CustomBaseListEncoder.java} (94%) rename nostr-java-event/src/main/java/nostr/event/{serializer/CustomGenericTagSerializer.java => codec/CustomGenericTagEncoder.java} (90%) rename nostr-java-event/src/main/java/nostr/event/{serializer/CustomGenericTagListSerializer.java => codec/CustomGenericTagListEncoder.java} (92%) rename nostr-java-event/src/main/java/nostr/event/{serializer/CustomIdEventListSerializer.java => codec/CustomIdEventListEncoder.java} (88%) create mode 100644 nostr-java-event/src/main/java/nostr/event/codec/CustomTagEncoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/codec/ITagDecoder.java delete mode 100644 nostr-java-event/src/main/java/nostr/event/list/PubKeyTagList.java delete mode 100644 nostr-java-event/src/main/java/nostr/event/list/TagList.java delete mode 100644 nostr-java-event/src/main/java/nostr/event/serializer/CustomTagSerializer.java diff --git a/nostr-java-base/src/main/java/nostr/base/IMarshaller.java b/nostr-java-base/src/main/java/nostr/base/IMarshaller.java index e76fb83e..b8bd36e9 100644 --- a/nostr-java-base/src/main/java/nostr/base/IMarshaller.java +++ b/nostr-java-base/src/main/java/nostr/base/IMarshaller.java @@ -15,5 +15,5 @@ public interface IMarshaller { public abstract String marshall() throws NostrException; - public String toJson() throws NostrException; +// public String toJson() throws NostrException; } diff --git a/nostr-java-base/src/main/java/nostr/base/ITag.java b/nostr-java-base/src/main/java/nostr/base/ITag.java index 42861e72..eb7a4f53 100644 --- a/nostr-java-base/src/main/java/nostr/base/ITag.java +++ b/nostr-java-base/src/main/java/nostr/base/ITag.java @@ -1,8 +1,6 @@ package nostr.base; -import nostr.util.NostrException; - /** * * @author squirrel @@ -13,5 +11,5 @@ public interface ITag extends IElement { public abstract String getCode(); - public abstract String printAttributes(Relay relay, boolean escape) throws NostrException; +// public abstract String printAttributes(Relay relay, boolean escape) throws NostrException; } diff --git a/nostr-java-base/src/main/java/nostr/base/PublicKey.java b/nostr-java-base/src/main/java/nostr/base/PublicKey.java index 8ceaa0a5..df417b1b 100644 --- a/nostr-java-base/src/main/java/nostr/base/PublicKey.java +++ b/nostr-java-base/src/main/java/nostr/base/PublicKey.java @@ -1,6 +1,8 @@ package nostr.base; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import lombok.EqualsAndHashCode; +import nostr.base.util.PublicKeyDeserializer; import nostr.crypto.bech32.Bech32Prefix; import nostr.util.NostrUtil; @@ -9,6 +11,7 @@ * @author squirrel */ @EqualsAndHashCode(callSuper = true) +@JsonDeserialize(using = PublicKeyDeserializer.class) public class PublicKey extends BaseKey { public PublicKey(byte[] rawData) { @@ -17,6 +20,5 @@ public PublicKey(byte[] rawData) { public PublicKey(String hexPubKey) { super(KeyType.PUBLIC, NostrUtil.hexToBytes(hexPubKey), Bech32Prefix.NPUB); - } - + } } diff --git a/nostr-java-base/src/main/java/nostr/base/Signature.java b/nostr-java-base/src/main/java/nostr/base/Signature.java index f0b2c8fa..e96f9964 100644 --- a/nostr-java-base/src/main/java/nostr/base/Signature.java +++ b/nostr-java-base/src/main/java/nostr/base/Signature.java @@ -1,28 +1,30 @@ package nostr.base; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import nostr.util.NostrUtil; import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; -import lombok.NonNull; +import lombok.NoArgsConstructor; +import nostr.base.util.SignatureDeserializer; /** * * @author squirrel */ @Data -@Builder -@AllArgsConstructor +@NoArgsConstructor +@JsonDeserialize(using = SignatureDeserializer.class) public class Signature { - @NonNull - private final byte[] rawData; - - @NonNull - private final PublicKey pubKey; + @JsonProperty("rawData") + private byte[] rawData; + + @JsonIgnore + private PublicKey pubKey; @JsonValue @Override diff --git a/nostr-java-base/src/main/java/nostr/base/util/PublicKeyDeserializer.java b/nostr-java-base/src/main/java/nostr/base/util/PublicKeyDeserializer.java new file mode 100644 index 00000000..74bf47b0 --- /dev/null +++ b/nostr-java-base/src/main/java/nostr/base/util/PublicKeyDeserializer.java @@ -0,0 +1,20 @@ + +package nostr.base.util; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import java.io.IOException; +import nostr.base.PublicKey; + +public class PublicKeyDeserializer extends JsonDeserializer { + + @Override + public PublicKey deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + JsonNode node = jsonParser.readValueAsTree(); + String hexPubKey = node.asText(); + + return new PublicKey(hexPubKey); + } +} diff --git a/nostr-java-base/src/main/java/nostr/base/util/SignatureDeserializer.java b/nostr-java-base/src/main/java/nostr/base/util/SignatureDeserializer.java new file mode 100644 index 00000000..7e294044 --- /dev/null +++ b/nostr-java-base/src/main/java/nostr/base/util/SignatureDeserializer.java @@ -0,0 +1,28 @@ +package nostr.base.util; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import nostr.base.Signature; +import nostr.util.NostrUtil; + +public class SignatureDeserializer extends JsonDeserializer { + + @Override + public Signature deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + ObjectMapper objectMapper = (ObjectMapper) jsonParser.getCodec(); + JsonNode node = objectMapper.readTree(jsonParser); + + String sigValue = node.asText(); + byte[] rawData = NostrUtil.hexToBytes(sigValue); + + Signature signature = new Signature(); + signature.setRawData(rawData); + + return signature; + } +} diff --git a/nostr-java-event/src/main/java/module-info.java b/nostr-java-event/src/main/java/module-info.java index bc5de80d..95a2694a 100644 --- a/nostr-java-event/src/main/java/module-info.java +++ b/nostr-java-event/src/main/java/module-info.java @@ -15,7 +15,7 @@ exports nostr.event.list; exports nostr.event.marshaller.impl; exports nostr.event.message; - exports nostr.event.serializer; + exports nostr.event.codec; exports nostr.event.tag; exports nostr.event.util; } diff --git a/nostr-java-event/src/main/java/nostr/event/BaseTag.java b/nostr-java-event/src/main/java/nostr/event/BaseTag.java index 127fe420..d3500f7c 100644 --- a/nostr-java-event/src/main/java/nostr/event/BaseTag.java +++ b/nostr-java-event/src/main/java/nostr/event/BaseTag.java @@ -1,6 +1,9 @@ - package nostr.event; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; @@ -9,11 +12,9 @@ import java.util.List; import java.util.logging.Level; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import lombok.ToString; import lombok.extern.java.Log; import nostr.base.IEvent; @@ -22,20 +23,24 @@ import nostr.base.Relay; import nostr.base.annotation.Key; import nostr.base.annotation.Tag; +import nostr.event.codec.CustomTagEncoder; +import nostr.event.codec.ITagDecoder; import nostr.util.NostrException; /** * * @author squirrel */ -@JsonPropertyOrder({"code"}) @Data @ToString @EqualsAndHashCode(callSuper = false) +@NoArgsConstructor @Log +@JsonDeserialize(using = ITagDecoder.class) +@JsonSerialize(using = CustomTagEncoder.class) public abstract class BaseTag implements ITag { - @JsonIgnore + @JsonIgnore private IEvent parent; @Override @@ -49,44 +54,17 @@ public String getCode() { return tag.code(); } - @Override - public String printAttributes(Relay relay, boolean escape) throws NostrException { - - var fields = this.getClass().getDeclaredFields(); - var index = 0; - var result = new StringBuilder(); - var fieldList = getSupportedFields(fields, relay); - - if (fieldList.size() >= 1) { - result.append(","); - - for (Field f : fieldList) { - final String fieldValue = getFieldValue(f); - - if (!escape) { - result.append("\""); - } else { - result.append("\\\""); - } - - result.append(fieldValue); - - if (!escape) { - result.append("\""); - } else { - result.append("\\\""); - } - - if (++index < fieldList.size()) { - result.append(","); - } - } + public String getFieldValue(Field field) throws NostrException { + try { + Object f = new PropertyDescriptor(field.getName(), this.getClass()).getReadMethod().invoke(this); + return f != null ? f.toString() : null; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | IntrospectionException ex) { + throw new NostrException(ex); } - - return result.toString(); } - private List getSupportedFields(Field[] fields, Relay relay) throws NostrException { + public List getSupportedFields(Relay relay) throws NostrException { + var fields = this.getClass().getDeclaredFields(); List fieldList = new ArrayList<>(); for (Field f : fields) { if (nipSupport(f, relay) && null != getFieldValue(f)) { @@ -110,13 +88,4 @@ private boolean nipSupport(Field field, Relay relay) { return NipUtil.checkSupport(relay, field); } - - private String getFieldValue(Field field) throws NostrException { - try { - Object f = new PropertyDescriptor(field.getName(), this.getClass()).getReadMethod().invoke(this); - return f != null ? f.toString() : null; - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | IntrospectionException ex) { - throw new NostrException(ex); - } - } } diff --git a/nostr-java-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java b/nostr-java-event/src/main/java/nostr/event/codec/CustomBaseListEncoder.java similarity index 94% rename from nostr-java-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java rename to nostr-java-event/src/main/java/nostr/event/codec/CustomBaseListEncoder.java index 9c4dc039..535a737d 100644 --- a/nostr-java-event/src/main/java/nostr/event/serializer/CustomBaseListSerializer.java +++ b/nostr-java-event/src/main/java/nostr/event/codec/CustomBaseListEncoder.java @@ -1,4 +1,4 @@ -package nostr.event.serializer; +package nostr.event.codec; import java.io.IOException; import java.util.Iterator; @@ -23,7 +23,7 @@ * */ @Log -public class CustomBaseListSerializer extends JsonSerializer { +public class CustomBaseListEncoder extends JsonSerializer { @Override public void serialize(BaseList value, JsonGenerator gen, SerializerProvider serializers) { diff --git a/nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagSerializer.java b/nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagEncoder.java similarity index 90% rename from nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagSerializer.java rename to nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagEncoder.java index 5c99e952..0215dfac 100644 --- a/nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagSerializer.java +++ b/nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagEncoder.java @@ -1,4 +1,4 @@ -package nostr.event.serializer; +package nostr.event.codec; import java.io.IOException; import java.util.logging.Level; @@ -18,11 +18,11 @@ * */ @Log -public class CustomGenericTagSerializer extends StdSerializer { +public class CustomGenericTagEncoder extends StdSerializer { private static final long serialVersionUID = 6803478463890319884L; - public CustomGenericTagSerializer() { + public CustomGenericTagEncoder() { super(GenericTagQuery.class); } diff --git a/nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagListSerializer.java b/nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagListEncoder.java similarity index 92% rename from nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagListSerializer.java rename to nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagListEncoder.java index 884b3d44..c5a6d0f2 100644 --- a/nostr-java-event/src/main/java/nostr/event/serializer/CustomGenericTagListSerializer.java +++ b/nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagListEncoder.java @@ -1,4 +1,4 @@ -package nostr.event.serializer; +package nostr.event.codec; import java.io.IOException; import java.util.logging.Level; @@ -20,7 +20,7 @@ * */ @Log -public class CustomGenericTagListSerializer extends JsonSerializer { +public class CustomGenericTagListEncoder extends JsonSerializer { @Override public void serialize(GenericTagQueryList value, JsonGenerator gen, SerializerProvider serializers) { diff --git a/nostr-java-event/src/main/java/nostr/event/serializer/CustomIdEventListSerializer.java b/nostr-java-event/src/main/java/nostr/event/codec/CustomIdEventListEncoder.java similarity index 88% rename from nostr-java-event/src/main/java/nostr/event/serializer/CustomIdEventListSerializer.java rename to nostr-java-event/src/main/java/nostr/event/codec/CustomIdEventListEncoder.java index ddf534af..1bd7c272 100644 --- a/nostr-java-event/src/main/java/nostr/event/serializer/CustomIdEventListSerializer.java +++ b/nostr-java-event/src/main/java/nostr/event/codec/CustomIdEventListEncoder.java @@ -1,4 +1,4 @@ -package nostr.event.serializer; +package nostr.event.codec; import java.io.IOException; import java.util.logging.Level; @@ -17,7 +17,7 @@ * */ @Log -public class CustomIdEventListSerializer extends JsonSerializer { +public class CustomIdEventListEncoder extends JsonSerializer { @Override public void serialize(EventList value, JsonGenerator gen, SerializerProvider serializers) { diff --git a/nostr-java-event/src/main/java/nostr/event/codec/CustomTagEncoder.java b/nostr-java-event/src/main/java/nostr/event/codec/CustomTagEncoder.java new file mode 100644 index 00000000..ec06b2a9 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/codec/CustomTagEncoder.java @@ -0,0 +1,64 @@ +package nostr.event.codec; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import java.lang.reflect.Field; +import java.util.List; + +import lombok.extern.java.Log; +import nostr.event.BaseTag; +import nostr.util.NostrException; + +/** + * @author guilhermegps + * + */ +@Log +public class CustomTagEncoder extends StdSerializer { + + private static final long serialVersionUID = -3877972991082754068L; + + public CustomTagEncoder() { + super(BaseTag.class); + } + + @Override + public void serialize(BaseTag value, JsonGenerator gen, SerializerProvider serializers) { + try { + // -- Create the node + final ObjectNode node = new ObjectNode(JsonNodeFactory.instance); + List fields = value.getSupportedFields(null); + + fields.stream().forEach((Field f) -> { + try { + node.put(f.getName(), value.getFieldValue(f)); + } catch (NostrException ex) { + throw new RuntimeException(ex); + } + }); + + // Extract the property values from the node and serialize them as an array + if (node.isObject()) { + ArrayNode arrayNode = node.objectNode().putArray("values"); + + // Add the tag code as the first element + arrayNode.add(value.getCode()); + node.fields().forEachRemaining(entry -> arrayNode.add(entry.getValue().asText())); + + gen.writePOJO(arrayNode); + } else { + throw new AssertionError("node.isObject()", new RuntimeException()); + } + + } catch (IOException | NostrException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/codec/ITagDecoder.java b/nostr-java-event/src/main/java/nostr/event/codec/ITagDecoder.java new file mode 100644 index 00000000..667212c1 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/codec/ITagDecoder.java @@ -0,0 +1,102 @@ +package nostr.event.codec; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; +import nostr.base.ITag; +import nostr.base.PublicKey; +import nostr.event.Marker; +import nostr.event.tag.EventTag; +import nostr.event.tag.NonceTag; +import nostr.event.tag.PubKeyTag; +import nostr.event.tag.SubjectTag; + +public class ITagDecoder extends JsonDeserializer { + + @Override + public T deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + JsonNode node = jsonParser.getCodec().readTree(jsonParser); + + // Extract relevant data from the JSON node + String code = node.get(0).asText(); + + if (null == code) { + throw new IOException("Unknown tag code: " + code); + } else // Perform custom deserialization logic based on the concrete class + { + switch (code) { + case "p" -> { + // Deserialization logic for ConcreteTag1 + PubKeyTag tag = new PubKeyTag(); + + final JsonNode nodePubKey = node.get(1); + if (nodePubKey != null) { + tag.setPublicKey(new PublicKey(nodePubKey.asText())); + } + + final JsonNode nodeMainUrl = node.get(2); + if (nodeMainUrl != null) { + tag.setMainRelayUrl(nodeMainUrl.asText()); + } + + final JsonNode nodePetName = node.get(3); + if (nodePetName != null) { + tag.setPetName(nodePetName.asText()); + } + + return (T) tag; + } + + case "nonce" -> { + // Deserialization logic for ConcreteTag2 + NonceTag tag = new NonceTag(); + + final JsonNode nodeNonce = node.get(1); + if (nodeNonce != null) { + tag.setNonce(Integer.valueOf(nodeNonce.asText())); + } + + final JsonNode nodeDifficulty = node.get(1); + if (nodeDifficulty != null) { + tag.setDifficulty(Integer.valueOf(nodeDifficulty.asText())); + } + return (T) tag; + } + case "e" -> { + // Deserialization logic for ConcreteTag2 + EventTag tag = new EventTag(); + + final JsonNode nodeIdEvent = node.get(1); + if (nodeIdEvent != null) { + tag.setIdEvent(nodeIdEvent.asText()); + } + + final JsonNode nodeRelay = node.get(2); + if (nodeRelay != null) { + tag.setRecommendedRelayUrl(nodeRelay.asText()); + } + + final JsonNode nodeMarker = node.get(3); + if (nodeMarker != null) { + tag.setMarker(Marker.valueOf(nodeMarker.asText())); + } + return (T) tag; + } + case "subject" -> { + SubjectTag tag = new SubjectTag(); + + final JsonNode nodeSubject = node.get(1); + if (nodeSubject != null) { + tag.setSubject(nodeSubject.asText()); + } + return (T) tag; + } + default -> + throw new IOException("Unknown tag type: " + code); + } + } + } +} diff --git a/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java index 817bfb17..0aa644c6 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java @@ -2,13 +2,15 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; import lombok.NonNull; import nostr.base.ChannelProfile; +import nostr.base.ITag; import nostr.base.PublicKey; import nostr.base.annotation.Event; +import nostr.event.BaseTag; import nostr.event.Kind; import static nostr.event.impl.GenericEvent.escapeJsonString; -import nostr.event.list.TagList; /** * @author guilhermegps @@ -17,11 +19,11 @@ @Event(name = "Create Channel", nip = 28) public class ChannelCreateEvent extends GenericEvent { - public ChannelCreateEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { + public ChannelCreateEvent(@NonNull PublicKey pubKey, @NonNull List tags, String content) { super(pubKey, Kind.CHANNEL_CREATE, tags, content); } - public ChannelCreateEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, ChannelProfile profile) { + public ChannelCreateEvent(@NonNull PublicKey pubKey, @NonNull List tags, ChannelProfile profile) { super(pubKey, Kind.CHANNEL_CREATE, tags); this.setContent(profile); } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/ChannelMessageEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ChannelMessageEvent.java index 9122fb0c..db56d494 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/ChannelMessageEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ChannelMessageEvent.java @@ -1,10 +1,11 @@ package nostr.event.impl; +import java.util.List; import lombok.NonNull; import nostr.base.PublicKey; import nostr.base.annotation.Event; +import nostr.event.BaseTag; import nostr.event.Kind; -import nostr.event.list.TagList; /** * @author guilhermegps @@ -13,7 +14,7 @@ @Event(name = "Channel Message", nip = 28) public class ChannelMessageEvent extends GenericEvent { - public ChannelMessageEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { + public ChannelMessageEvent(@NonNull PublicKey pubKey, @NonNull List tags, String content) { super(pubKey, Kind.CHANNEL_MESSAGE, tags, content); } } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java index c98871a7..b1940581 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ChannelMetadataEvent.java @@ -2,12 +2,13 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; import lombok.NonNull; import nostr.base.ChannelProfile; import nostr.base.PublicKey; import nostr.base.annotation.Event; +import nostr.event.BaseTag; import nostr.event.Kind; -import nostr.event.list.TagList; /** * @author guilhermegps @@ -16,11 +17,11 @@ @Event(name = "Channel Metadata", nip = 28) public class ChannelMetadataEvent extends GenericEvent { - public ChannelMetadataEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { + public ChannelMetadataEvent(@NonNull PublicKey pubKey, @NonNull List tags, String content) { super(pubKey, Kind.CHANNEL_METADATA, tags, content); } - public ChannelMetadataEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, ChannelProfile profile) { + public ChannelMetadataEvent(@NonNull PublicKey pubKey, @NonNull List tags, ChannelProfile profile) { super(pubKey, Kind.CHANNEL_METADATA, tags); this.setContent(profile); } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java index a79f2109..7a006a0e 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ClientAuthenticationEvent.java @@ -1,18 +1,18 @@ package nostr.event.impl; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.concurrent.ExecutionException; -import java.util.logging.Level; -import java.util.logging.Logger; import lombok.NonNull; import nostr.base.ElementAttribute; import nostr.base.ITag; import nostr.base.PublicKey; import nostr.base.Relay; import nostr.base.annotation.Event; +import nostr.event.BaseTag; import nostr.event.Kind; -import nostr.event.list.TagList; /** * @@ -21,7 +21,7 @@ @Event(name = "Authentication of clients to relays", nip = 42) public class ClientAuthenticationEvent extends GenericEvent { - public ClientAuthenticationEvent(@NonNull PublicKey pubKey, @NonNull TagList tags) { + public ClientAuthenticationEvent(@NonNull PublicKey pubKey, @NonNull List tags) { super(pubKey, Kind.CLIENT_AUTH, tags); } @@ -32,10 +32,10 @@ public ClientAuthenticationEvent(@NonNull PublicKey pubKey, String challenge, @N var attribute = ElementAttribute.builder().nip(42).name("challenge").value(challenge).build(); chAttributes.add(attribute); - this.setTags(new TagList()); + this.setTags(new ArrayList<>()); ITag chTag = new GenericTag(42, "challenge", chAttributes); - this.addTag(chTag); + this.addTag((GenericTag) chTag); relays.stream().forEach(r -> { try { @@ -43,7 +43,7 @@ public ClientAuthenticationEvent(@NonNull PublicKey pubKey, String challenge, @N final ElementAttribute relayAttribute = getRelayAttribute(r); relayAttributes.add(relayAttribute); final ITag relayTag = new GenericTag(42, "relay", relayAttributes); - this.addTag(relayTag); + this.addTag((BaseTag) relayTag); } catch (InterruptedException | ExecutionException ex) { throw new RuntimeException(ex); } @@ -60,16 +60,16 @@ public ClientAuthenticationEvent(@NonNull PublicKey pubKey, String challenge, @N var attribute = ElementAttribute.builder().nip(42).name("challenge").value(challenge).build(); chAttributes.add(attribute); - this.setTags(new TagList()); + this.setTags(new ArrayList<>()); ITag chTag = new GenericTag(42, "challenge", chAttributes); - this.addTag(chTag); + this.addTag((BaseTag) chTag); final Set relayAttributes = new HashSet<>(); final ElementAttribute relayAttribute = getRelayAttribute(relay); relayAttributes.add(relayAttribute); final ITag relayTag = new GenericTag(42, "relay", relayAttributes); - this.addTag(relayTag); + this.addTag((BaseTag) relayTag); this.setNip(42); } catch (ExecutionException | InterruptedException ex) { 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 139ff7bf..9bb7cb32 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 @@ -7,8 +7,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import nostr.base.annotation.Event; -import nostr.event.list.TagList; -import nostr.event.tag.EventTag; +import nostr.event.BaseTag; /** * @@ -19,16 +18,16 @@ @Event(name = "Event Deletion", nip = 9) public class DeletionEvent extends GenericEvent { - public DeletionEvent(PublicKey pubKey, TagList tagList, String content) { - super(pubKey, Kind.DELETION, tagList, content); + public DeletionEvent(PublicKey pubKey, List tags, String content) { + super(pubKey, Kind.DELETION, tags, content); } - public DeletionEvent(PublicKey pubKey, TagList tagList) { - this(pubKey, tagList, "Deletion request"); + public DeletionEvent(PublicKey pubKey, List tags) { + this(pubKey, tags, "Deletion request"); } - public DeletionEvent(PublicKey pubKey, List eventsToDelete) { - super(pubKey, Kind.DELETION); - eventsToDelete.stream().map(e -> e.getId()).forEach(eId -> addTag(EventTag.builder().idEvent(eId).build())); - } +// public DeletionEvent(PublicKey pubKey, List eventsToDelete) { +// super(pubKey, Kind.DELETION); +// eventsToDelete.stream().map(e -> e.getId()).forEach(eId -> addTag(EventTag.builder().idEvent(eId).build())); +// } } 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 ad9281c8..44670475 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,9 +1,10 @@ package nostr.event.impl; +import java.util.List; import nostr.base.PublicKey; import nostr.event.Kind; import nostr.base.annotation.Event; -import nostr.event.list.TagList; +import nostr.event.BaseTag; import nostr.event.tag.PubKeyTag; /** @@ -13,7 +14,7 @@ @Event(name = "Encrypted Direct Message", nip = 4) public class DirectMessageEvent extends GenericEvent { - public DirectMessageEvent(PublicKey sender, TagList tags, String content) { + 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 468c64c3..7b51fbb2 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 @@ -1,12 +1,13 @@ package nostr.event.impl; +import java.util.List; import nostr.event.Kind; import nostr.base.PublicKey; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.java.Log; import nostr.base.annotation.Event; -import nostr.event.list.TagList; +import nostr.event.BaseTag; import nostr.event.tag.PubKeyTag; /** @@ -19,11 +20,11 @@ @Event(name = "Ephemeral Events", nip = 16) public class EphemeralEvent extends GenericEvent { - public EphemeralEvent(PublicKey pubKey, TagList tags, String content) { + public EphemeralEvent(PublicKey pubKey, List tags, String content) { super(pubKey, Kind.EPHEMEREAL_EVENT, tags, content); } - public EphemeralEvent(PublicKey pubKey, TagList tags) { + public EphemeralEvent(PublicKey pubKey, List tags) { this(pubKey, tags, "..."); } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/Filters.java b/nostr-java-event/src/main/java/nostr/event/impl/Filters.java index 40a3bf7a..9d3278d5 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/Filters.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/Filters.java @@ -10,12 +10,12 @@ import lombok.EqualsAndHashCode; import nostr.base.annotation.Key; import nostr.event.BaseEvent; +import nostr.event.codec.CustomGenericTagListEncoder; +import nostr.event.codec.CustomIdEventListEncoder; import nostr.event.list.EventList; import nostr.event.list.GenericTagQueryList; import nostr.event.list.KindList; import nostr.event.list.PublicKeyList; -import nostr.event.serializer.CustomGenericTagListSerializer; -import nostr.event.serializer.CustomIdEventListSerializer; /** * @@ -28,7 +28,7 @@ public class Filters extends BaseEvent { @Key @JsonProperty("ids") - @JsonSerialize(using=CustomIdEventListSerializer.class) + @JsonSerialize(using=CustomIdEventListEncoder.class) private EventList events; @Key @@ -40,7 +40,7 @@ public class Filters extends BaseEvent { @Key @JsonProperty("#e") - @JsonSerialize(using=CustomIdEventListSerializer.class) + @JsonSerialize(using=CustomIdEventListEncoder.class) private EventList referencedEvents; @Key @@ -57,7 +57,7 @@ public class Filters extends BaseEvent { private Integer limit; @Key(nip = 12) - @JsonSerialize(using=CustomGenericTagListSerializer.class) + @JsonSerialize(using=CustomGenericTagListEncoder.class) private GenericTagQueryList genericTagQueryList; @Override 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 ad7a13ae..1f1dd0ef 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 @@ -1,20 +1,18 @@ package nostr.event.impl; -import java.beans.IntrospectionException; import java.beans.Transient; -import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.util.HashSet; import java.util.List; import java.util.Set; -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.node.JsonNodeFactory; +import java.util.ArrayList; import lombok.Data; import lombok.EqualsAndHashCode; @@ -32,8 +30,8 @@ import nostr.crypto.bech32.Bech32; import nostr.crypto.bech32.Bech32Prefix; import nostr.event.BaseEvent; +import nostr.event.BaseTag; import nostr.event.Kind; -import nostr.event.list.TagList; import nostr.util.NostrException; import nostr.util.NostrUtil; @@ -67,7 +65,8 @@ public class GenericEvent extends BaseEvent implements ISignable, IGenericElemen @Key @EqualsAndHashCode.Exclude - private TagList tags; + @JsonProperty("tags") + private List tags; @Key @EqualsAndHashCode.Exclude @@ -96,18 +95,18 @@ public GenericEvent() { } public GenericEvent(@NonNull PublicKey pubKey, @NonNull Kind kind) { - this(pubKey, kind, new TagList(), null); + this(pubKey, kind, new ArrayList<>(), null); } - public GenericEvent(@NonNull PublicKey pubKey, @NonNull Kind kind, @NonNull TagList tags) { + public GenericEvent(@NonNull PublicKey pubKey, @NonNull Kind kind, @NonNull List tags) { this(pubKey, kind, tags, null); } - public GenericEvent(@NonNull PublicKey pubKey, @NonNull Kind kind, @NonNull TagList tags, String content) { + public GenericEvent(@NonNull PublicKey pubKey, @NonNull Kind kind, @NonNull List tags, String content) { this(pubKey, kind.getValue(), tags, content); } - public GenericEvent(@NonNull PublicKey pubKey, @NonNull Integer kind, @NonNull TagList tags, String content) { + public GenericEvent(@NonNull PublicKey pubKey, @NonNull Integer kind, @NonNull List tags, String content) { this.pubKey = pubKey; this.kind = kind; this.tags = tags; @@ -131,25 +130,20 @@ public String toBech32() { } } - public void setTags(TagList tags) { + public void setTags(List tags) { this.tags = tags; - for (Object o : tags.getList()) { + for (Object o : tags) { ((ITag) o).setParent(this); } } - public void addTag(ITag tag) { - if (this.tags == null) { - this.tags = new TagList(); - } - - List list = tags.getList(); + public void addTag(BaseTag tag) { - if (!list.contains(tag)) { + if (!tags.contains(tag)) { tag.setParent(this); - list.add(tag); + ((List) tags).add(tag); } } @@ -211,9 +205,9 @@ private String serialize() throws NostrException { } } - protected final void updateTagsParents(TagList tagList) { - if (tagList != null && !tagList.getList().isEmpty()) { - for (Object t : tagList.getList()) { + protected final void updateTagsParents(List tagList) { + if (tagList != null && !tagList.isEmpty()) { + for (Object t : tagList) { ITag tag = (ITag) t; tag.setParent(this); } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java b/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java index 0cf0794e..9a5cdb59 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java @@ -2,9 +2,9 @@ import java.util.HashSet; import java.util.Set; -import java.util.logging.Level; import com.fasterxml.jackson.annotation.JsonIgnore; +import java.util.logging.Level; import lombok.Data; import lombok.EqualsAndHashCode; @@ -24,10 +24,10 @@ @Log public class GenericTag extends BaseTag implements IGenericElement { - private final String code; - @JsonIgnore + private final String code; + @JsonIgnore private final Integer nip; - @JsonIgnore + @JsonIgnore private final Set attributes; public GenericTag(String code) { diff --git a/nostr-java-event/src/main/java/nostr/event/impl/HideMessageEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/HideMessageEvent.java index f7bf5e79..c505044a 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/HideMessageEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/HideMessageEvent.java @@ -1,10 +1,11 @@ package nostr.event.impl; +import java.util.List; import lombok.NonNull; import nostr.base.PublicKey; import nostr.base.annotation.Event; +import nostr.event.BaseTag; import nostr.event.Kind; -import nostr.event.list.TagList; import nostr.event.tag.EventTag; /** @@ -14,7 +15,7 @@ @Event(name = "Hide Message on Channel", nip = 28) public class HideMessageEvent extends GenericEvent { - public HideMessageEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { + public HideMessageEvent(@NonNull PublicKey pubKey, @NonNull List tags, String content) { super(pubKey, Kind.HIDE_MESSAGE, tags, content); } 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 43ac2785..d1f3912e 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 @@ -4,17 +4,16 @@ import com.fasterxml.jackson.databind.ObjectMapper; import nostr.event.Kind; import nostr.base.PublicKey; -import java.beans.IntrospectionException; -import java.lang.reflect.InvocationTargetException; -import java.security.NoSuchAlgorithmException; -import java.util.logging.Level; +import java.util.ArrayList; +import java.util.List; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NonNull; import lombok.extern.java.Log; +import nostr.base.ITag; import nostr.base.UserProfile; import nostr.base.annotation.Event; -import nostr.event.list.TagList; +import nostr.event.BaseTag; import nostr.event.util.Nip05Validator; import nostr.util.NostrException; @@ -28,13 +27,13 @@ @Event(name = "Internet Identifier Metadata Event", nip = 5) public final class InternetIdentifierMetadataEvent extends GenericEvent { - public InternetIdentifierMetadataEvent(PublicKey pubKey, TagList tags, @NonNull UserProfile profile) throws NostrException { + public InternetIdentifierMetadataEvent(PublicKey pubKey, List tags, @NonNull UserProfile profile) throws NostrException { super(pubKey, Kind.SET_METADATA, tags); this.init(profile); } public InternetIdentifierMetadataEvent(PublicKey pubKey, @NonNull UserProfile profile) throws NostrException { - this(pubKey, new TagList(), profile); + this(pubKey, new ArrayList(), profile); } private void init(UserProfile profile) throws NostrException { 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 288411c8..20f1a212 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,5 +1,6 @@ package nostr.event.impl; +import java.util.List; import nostr.event.tag.PubKeyTag; import nostr.event.Kind; import nostr.base.PublicKey; @@ -8,7 +9,7 @@ import lombok.extern.java.Log; import nostr.base.ITag; import nostr.base.annotation.Event; -import nostr.event.list.TagList; +import nostr.event.BaseTag; /** * @@ -20,7 +21,7 @@ @Log public final class MentionsEvent extends GenericEvent { - public MentionsEvent(PublicKey pubKey, TagList tags, String content) { + public MentionsEvent(PublicKey pubKey, List tags, String content) { super(pubKey, Kind.TEXT_NOTE, tags, content); } @@ -31,10 +32,10 @@ public void update() { int index = 0; - while (getTags().getList().iterator().hasNext()) { - ITag tag = (ITag) getTags().getList().iterator().next(); + while (getTags().iterator().hasNext()) { + ITag tag = (ITag) getTags().iterator().next(); String replacement = "#[" + index++ + "]"; - setContent(this.getContent().replace(((PubKeyTag) tag).getStringPubKey(), replacement)); + 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 1a590261..8577cc25 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 @@ -6,6 +6,7 @@ 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; @@ -14,8 +15,8 @@ import nostr.base.UserProfile; import nostr.base.PublicKey; import nostr.base.annotation.Event; +import nostr.event.BaseTag; import nostr.event.Kind; -import nostr.event.list.TagList; import nostr.util.NostrException; /** @@ -34,7 +35,7 @@ public final class MetadataEvent extends GenericEvent { private UserProfile profile; public MetadataEvent(PublicKey pubKey, UserProfile profile) throws NostrException { - super(pubKey, Kind.SET_METADATA, new TagList()); + super(pubKey, Kind.SET_METADATA, new ArrayList()); this.profile = profile; } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/MuteUserEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/MuteUserEvent.java index bcf6869e..5392968f 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/MuteUserEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/MuteUserEvent.java @@ -1,10 +1,11 @@ package nostr.event.impl; +import java.util.List; import lombok.NonNull; import nostr.base.PublicKey; import nostr.base.annotation.Event; +import nostr.event.BaseTag; import nostr.event.Kind; -import nostr.event.list.TagList; import nostr.event.tag.PubKeyTag; /** @@ -14,7 +15,7 @@ @Event(name = "Mute User on Channel", nip = 28) public class MuteUserEvent extends GenericEvent { - public MuteUserEvent(@NonNull PublicKey pubKey, @NonNull TagList tags, String content) { + public MuteUserEvent(@NonNull PublicKey pubKey, @NonNull List tags, String content) { super(pubKey, Kind.MUTE_USER, tags, content); } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/OtsEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/OtsEvent.java index 6385c9cd..ba61ab7a 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/OtsEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/OtsEvent.java @@ -1,11 +1,12 @@ package nostr.event.impl; +import java.util.List; import java.util.Map; import nostr.base.ElementAttribute; import nostr.base.PublicKey; import nostr.base.annotation.Event; -import nostr.event.list.TagList; +import nostr.event.BaseTag; /** * @@ -14,7 +15,7 @@ @Event(name = "OpenTimestamps Attestations for Events", nip = 1) public class OtsEvent extends TextNoteEvent { - public OtsEvent(PublicKey pubKey, TagList tags, String content, String ots) { + public OtsEvent(PublicKey pubKey, List tags, String content, String ots) { super(pubKey, tags, content); var attribute = ElementAttribute.builder().nip(3).value(Map.of("ots", ots)).build(); this.addAttribute(attribute); 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 8dcef0cc..fe3380a8 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,5 +1,6 @@ package nostr.event.impl; +import java.util.List; import nostr.event.Kind; import nostr.base.PublicKey; import nostr.event.Reaction; @@ -7,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.extern.java.Log; import nostr.base.annotation.Event; -import nostr.event.list.TagList; +import nostr.event.BaseTag; import nostr.event.tag.EventTag; import nostr.event.tag.PubKeyTag; @@ -21,7 +22,7 @@ @Event(name = "Reactions", nip = 25) public class ReactionEvent extends GenericEvent { - public ReactionEvent(PublicKey pubKey, TagList tags, Reaction content, GenericEvent sourceEvent) { + public ReactionEvent(PublicKey pubKey, List tags, Reaction content, GenericEvent sourceEvent) { super(pubKey, Kind.REACTION, tags, content.getEmoji()); } 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 9fccde10..2efa9cd6 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,11 +1,12 @@ 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.annotation.Event; -import nostr.event.list.TagList; +import nostr.event.BaseTag; /** * @@ -17,7 +18,7 @@ @Event(name = "Replaceable Events", nip = 16) public class ReplaceableEvent extends GenericEvent { - public ReplaceableEvent(PublicKey sender, Integer kind, TagList tags, String content) { + public ReplaceableEvent(PublicKey sender, Integer kind, List tags, String content) { super(sender, kind, tags, content); } 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 c8e50f0e..bc100875 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 @@ -1,10 +1,11 @@ package nostr.event.impl; +import java.util.List; import nostr.base.PublicKey; import nostr.event.Kind; import nostr.base.annotation.Event; -import nostr.event.list.TagList; +import nostr.event.BaseTag; /** * @@ -13,7 +14,7 @@ @Event(name = "Text Note") public class TextNoteEvent extends GenericEvent { - public TextNoteEvent(PublicKey pubKey, TagList tags, String content) { + 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/list/BaseList.java b/nostr-java-event/src/main/java/nostr/event/list/BaseList.java index f59b7bf0..7a0f8466 100644 --- a/nostr-java-event/src/main/java/nostr/event/list/BaseList.java +++ b/nostr-java-event/src/main/java/nostr/event/list/BaseList.java @@ -10,7 +10,7 @@ import lombok.NonNull; import nostr.base.INostrList; import nostr.base.annotation.JsonList; -import nostr.event.serializer.CustomBaseListSerializer; +import nostr.event.codec.CustomBaseListEncoder; /** * @@ -20,7 +20,7 @@ @AllArgsConstructor @Data @JsonList -@JsonSerialize(using=CustomBaseListSerializer.class) +@JsonSerialize(using=CustomBaseListEncoder.class) public abstract class BaseList implements INostrList { @NonNull @@ -38,6 +38,10 @@ public void addAll(@NonNull INostrList aList) { this.list.addAll(aList.getList()); } + public void addAll(@NonNull List aList) { + aList.stream().forEach(e -> this.list.add(e)); + } + @Override public int size() { return this.list.size(); diff --git a/nostr-java-event/src/main/java/nostr/event/list/PubKeyTagList.java b/nostr-java-event/src/main/java/nostr/event/list/PubKeyTagList.java deleted file mode 100644 index ccc94531..00000000 --- a/nostr-java-event/src/main/java/nostr/event/list/PubKeyTagList.java +++ /dev/null @@ -1,24 +0,0 @@ -package nostr.event.list; - -import nostr.event.tag.PubKeyTag; -import java.util.ArrayList; -import java.util.List; -import lombok.extern.java.Log; -import nostr.base.annotation.JsonList; - -/** - * - * @author squirrel - */ -@Log -@JsonList -public class PubKeyTagList extends TagList { - - public PubKeyTagList() { - this(new ArrayList<>()); - } - - private PubKeyTagList(List list) { - super(list); - } -} diff --git a/nostr-java-event/src/main/java/nostr/event/list/TagList.java b/nostr-java-event/src/main/java/nostr/event/list/TagList.java deleted file mode 100644 index 11ffa0e5..00000000 --- a/nostr-java-event/src/main/java/nostr/event/list/TagList.java +++ /dev/null @@ -1,29 +0,0 @@ - -package nostr.event.list; - -import java.util.ArrayList; -import java.util.List; - -import lombok.NonNull; -import nostr.base.ITag; -import nostr.base.annotation.JsonList; - -/** - * - * @author squirrel - */ -@SuppressWarnings("rawtypes") -@JsonList -public class TagList extends BaseList { - - @SuppressWarnings("unchecked") - public TagList() { - this(new ArrayList<>()); - } - - @SuppressWarnings("unchecked") - protected TagList(@NonNull List list) { - super(list); - } - -} diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java index 03d5375e..52b235b9 100644 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java @@ -2,13 +2,13 @@ import com.fasterxml.jackson.core.JsonProcessingException; import java.lang.reflect.Field; -import java.util.logging.Level; import lombok.AllArgsConstructor; import lombok.Data; import lombok.extern.java.Log; import nostr.base.IElement; import nostr.base.IMarshaller; +import static nostr.base.IMarshaller.MAPPER; import nostr.base.NipUtil; import nostr.base.Relay; import nostr.util.NostrException; @@ -32,12 +32,7 @@ public String marshall() throws UnsupportedNIPException, NostrException { throw new UnsupportedNIPException("NIP is not supported by relay: \"" + relay.getName() + "\" - List of supported NIP(s): " + relay.printSupportedNips()); } - try { - return toJson(); - } catch (NostrException e) { - log.log(Level.SEVERE, null, e); - throw new RuntimeException(e); - } + return toJson(); } private boolean nipEventSupport() { @@ -48,8 +43,7 @@ protected boolean nipFieldSupport(Field field) { return (relay != null) ? NipUtil.checkSupport(relay, field) : true; } - @Override - public String toJson() throws NostrException { + private String toJson() throws NostrException { try { return MAPPER.writeValueAsString(element); } catch (JsonProcessingException e) { diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java index f0f2d1cb..c9bc1397 100644 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java @@ -34,8 +34,7 @@ public String marshall() throws NostrException { return toJson(); } - @Override - public String toJson() throws NostrException { + private String toJson() throws NostrException { try { JsonNode node = MAPPER.valueToTree(filters); ObjectNode objNode = (ObjectNode) node; diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java index 2d453e10..c5a900f8 100644 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java @@ -1,9 +1,6 @@ package nostr.event.marshaller.impl; -import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; import lombok.AllArgsConstructor; import lombok.Builder; @@ -11,7 +8,6 @@ import nostr.base.GenericTagQuery; import nostr.base.IMarshaller; import nostr.base.Relay; -import nostr.event.serializer.CustomGenericTagSerializer; import nostr.util.NostrException; /** @@ -31,16 +27,15 @@ public String marshall() throws NostrException { return toJson(); } - @Override - public String toJson() throws NostrException { + private String toJson() throws NostrException { try { - SimpleModule module = new SimpleModule(); - module.addSerializer(new CustomGenericTagSerializer()); - var mappe = (new ObjectMapper()) - .setSerializationInclusion(Include.NON_NULL) - .registerModule(module); +// SimpleModule module = new SimpleModule(); +// module.addSerializer(new CustomGenericTagSerializer()); +// var mapper = (new ObjectMapper()) +// .setSerializationInclusion(Include.NON_NULL) +// MAPPER.registerModule(module); - return mappe.writeValueAsString(tag); + return MAPPER.writeValueAsString(tag); } catch (JsonProcessingException e) { throw new NostrException(e); } diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java index 78aed934..cd73c4db 100644 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java @@ -30,9 +30,8 @@ public class OstEventMarshaller implements IMarshaller { public String marshall() throws NostrException { return toJson(); } - - @Override - public String toJson() throws NostrException { + + private String toJson() throws NostrException { try { JsonNode node = MAPPER.valueToTree(event); ObjectNode objNode = (ObjectNode) node; diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java index 6d8b2bef..abc72909 100644 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java @@ -9,9 +9,9 @@ import lombok.Builder; import lombok.Data; import nostr.base.IMarshaller; -import nostr.base.ITag; import nostr.base.Relay; -import nostr.event.serializer.CustomTagSerializer; +import nostr.event.BaseTag; +import nostr.event.codec.CustomTagEncoder; import nostr.util.NostrException; /** @@ -23,7 +23,7 @@ @Builder public class TagMarshaller implements IMarshaller { - private final ITag tag; + private final BaseTag tag; private final Relay relay; @Override @@ -31,16 +31,15 @@ public String marshall() throws NostrException { return toJson(); } - @Override - public String toJson() throws NostrException { + private String toJson() throws NostrException { try { SimpleModule module = new SimpleModule(); - module.addSerializer(new CustomTagSerializer()); - var mappe = (new ObjectMapper()) + module.addSerializer(new CustomTagEncoder()); + var mapper = (new ObjectMapper()) .setSerializationInclusion(Include.NON_NULL) .registerModule(module); - return mappe.writeValueAsString(tag); + return mapper.writeValueAsString(tag); } catch (JsonProcessingException e) { throw new NostrException(e); } diff --git a/nostr-java-event/src/main/java/nostr/event/message/ContactListMessage.java b/nostr-java-event/src/main/java/nostr/event/message/ContactListMessage.java index 03bfb46e..9b5b7062 100644 --- a/nostr-java-event/src/main/java/nostr/event/message/ContactListMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/ContactListMessage.java @@ -1,10 +1,11 @@ package nostr.event.message; +import java.util.List; import lombok.ToString; import nostr.event.Kind; import nostr.base.PublicKey; +import nostr.event.BaseTag; import nostr.event.impl.GenericEvent; -import nostr.event.list.PubKeyTagList; /** * @@ -13,7 +14,7 @@ @ToString public class ContactListMessage extends EventMessage { - public ContactListMessage(PubKeyTagList contactList, PublicKey publicKey) { + public ContactListMessage(List contactList, PublicKey publicKey) { super(new GenericEvent(publicKey, Kind.CONTACT_LIST, contactList)); } diff --git a/nostr-java-event/src/main/java/nostr/event/serializer/CustomTagSerializer.java b/nostr-java-event/src/main/java/nostr/event/serializer/CustomTagSerializer.java deleted file mode 100644 index 12473ef1..00000000 --- a/nostr-java-event/src/main/java/nostr/event/serializer/CustomTagSerializer.java +++ /dev/null @@ -1,53 +0,0 @@ -package nostr.event.serializer; - -import java.io.IOException; -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.logging.Level; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; - -import lombok.extern.java.Log; -import nostr.base.IMarshaller; -import nostr.base.ITag; - -/** - * @author guilhermegps - * - */ -@Log -public class CustomTagSerializer extends StdSerializer { - - private static final long serialVersionUID = -3877972991082754068L; - - public CustomTagSerializer() { - super(ITag.class); - } - - @Override - public void serialize(ITag value, JsonGenerator gen, SerializerProvider serializers) { - try { - var mapper = IMarshaller.MAPPER; - JsonNode node = mapper.valueToTree(value); - - Iterator> fields = node.fields(); - var list = StreamSupport.stream( - Spliterators.spliteratorUnknownSize(fields, Spliterator.ORDERED), false) - .map(f -> f.getValue().asText().toLowerCase()) - .collect(Collectors.toList()); - - gen.writePOJO(list); - } catch (IOException e) { - log.log(Level.SEVERE, null, e); - throw new RuntimeException(e); - } - } - -} diff --git a/nostr-java-event/src/main/java/nostr/event/tag/DelegationTag.java b/nostr-java-event/src/main/java/nostr/event/tag/DelegationTag.java index a97a3777..11657b87 100644 --- a/nostr-java-event/src/main/java/nostr/event/tag/DelegationTag.java +++ b/nostr-java-event/src/main/java/nostr/event/tag/DelegationTag.java @@ -1,13 +1,17 @@ package nostr.event.tag; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import nostr.base.ISignable; import nostr.base.annotation.Key; import nostr.event.BaseTag; import nostr.base.PublicKey; import nostr.base.Signature; import java.beans.Transient; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import lombok.extern.java.Log; import nostr.base.annotation.Tag; @@ -19,26 +23,32 @@ @Log @EqualsAndHashCode(callSuper = false) @Tag(code = "delegation", nip = 26) +@AllArgsConstructor +@NoArgsConstructor +@JsonPropertyOrder({"pubkey", "conditions", "signature"}) public class DelegationTag extends BaseTag implements ISignable { @Key - private PublicKey delegatee; + @JsonProperty("delegator") + private PublicKey delegator; @Key + @JsonProperty("conditions") private String conditions; @Key + @JsonProperty("token") private Signature signature; - public DelegationTag(PublicKey delegatee, String conditions) { - this.delegatee = delegatee; + public DelegationTag(PublicKey delegator, String conditions) { + this.delegator = delegator; this.conditions = conditions == null ? "" : conditions; } @Transient public String getToken() { StringBuilder strToken = new StringBuilder(); - strToken.append("nostr:").append(getCode()).append(":").append(delegatee.toString()).append(":").append(conditions); + strToken.append("nostr:").append(getCode()).append(":").append(delegator.toString()).append(":").append(conditions); return strToken.toString(); } } diff --git a/nostr-java-event/src/main/java/nostr/event/tag/EventTag.java b/nostr-java-event/src/main/java/nostr/event/tag/EventTag.java index 15d7ebd5..106b3e17 100644 --- a/nostr-java-event/src/main/java/nostr/event/tag/EventTag.java +++ b/nostr-java-event/src/main/java/nostr/event/tag/EventTag.java @@ -5,10 +5,14 @@ */ package nostr.event.tag; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import nostr.base.annotation.Key; import nostr.base.annotation.Tag; import nostr.event.BaseTag; @@ -23,15 +27,22 @@ @EqualsAndHashCode(callSuper = true) @AllArgsConstructor @Tag(code = "e", name = "event") +@JsonPropertyOrder({"idEvent", "recommendedRelayUrl", "marker"}) +@NoArgsConstructor public class EventTag extends BaseTag { @Key + @JsonProperty("idEvent") private String idEvent; @Key + @JsonProperty("recommendedRelayUrl") + @JsonInclude(JsonInclude.Include.NON_NULL) private String recommendedRelayUrl; @Key(nip = 10) + @JsonProperty("marker") + @JsonInclude(JsonInclude.Include.NON_NULL) private Marker marker; public EventTag(String idEvent) { diff --git a/nostr-java-event/src/main/java/nostr/event/tag/NonceTag.java b/nostr-java-event/src/main/java/nostr/event/tag/NonceTag.java index 723c0882..814443b6 100644 --- a/nostr-java-event/src/main/java/nostr/event/tag/NonceTag.java +++ b/nostr-java-event/src/main/java/nostr/event/tag/NonceTag.java @@ -1,11 +1,14 @@ package nostr.event.tag; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import nostr.base.annotation.Key; import nostr.event.BaseTag; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import lombok.NonNull; import nostr.base.annotation.Tag; @@ -17,12 +20,16 @@ @Data @EqualsAndHashCode(callSuper = true) @Tag(code = "nonce", nip = 13) +@JsonPropertyOrder({"nonce", "difficulty"}) +@NoArgsConstructor public class NonceTag extends BaseTag { @Key + @JsonProperty("nonce") private Integer nonce; @Key + @JsonProperty("difficulty") private Integer difficulty; public NonceTag(@NonNull Integer nonce, @NonNull Integer difficulty) { 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 fc628b11..8ed32e9e 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 @@ -5,13 +5,14 @@ */ package nostr.event.tag; -import com.fasterxml.jackson.annotation.JsonGetter; -import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import lombok.NonNull; import nostr.base.PublicKey; import nostr.base.annotation.Key; @@ -22,31 +23,31 @@ * * @author squirrel */ -@JsonPropertyOrder({"code", "pubKey"}) +@JsonPropertyOrder({"pubKey", "mainRelayUrl", "petName"}) @Builder @Data @EqualsAndHashCode(callSuper = true) @Tag(code = "p") +@NoArgsConstructor public class PubKeyTag extends BaseTag { - @JsonIgnore @Key + @JsonProperty("publicKey") private PublicKey publicKey; @Key + @JsonProperty("mainRelayUrl") + @JsonInclude(JsonInclude.Include.NON_NULL) private String mainRelayUrl; @Key(nip = 2) + @JsonProperty("petName") + @JsonInclude(JsonInclude.Include.NON_NULL) private String petName; - private PubKeyTag(@NonNull PublicKey publicKey, String mainRelayUrl, String petName) { + public PubKeyTag(@NonNull PublicKey publicKey, String mainRelayUrl, String petName) { this.publicKey = publicKey; this.mainRelayUrl = mainRelayUrl; this.petName = petName; } - - @JsonGetter("pubKey") - public String getStringPubKey() { - return publicKey.toString(); - } } diff --git a/nostr-java-event/src/main/java/nostr/event/tag/SubjectTag.java b/nostr-java-event/src/main/java/nostr/event/tag/SubjectTag.java index cedf2b59..45022e93 100644 --- a/nostr-java-event/src/main/java/nostr/event/tag/SubjectTag.java +++ b/nostr-java-event/src/main/java/nostr/event/tag/SubjectTag.java @@ -1,9 +1,13 @@ package nostr.event.tag; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import lombok.NonNull; import nostr.base.annotation.Key; import nostr.base.annotation.Tag; @@ -15,14 +19,14 @@ */ @Builder @Data +@NoArgsConstructor +@AllArgsConstructor @EqualsAndHashCode(callSuper = true) @Tag(code = "subject", nip = 14) +@JsonPropertyOrder({"subject"}) public final class SubjectTag extends BaseTag { @Key + @JsonProperty("subject") private String subject; - - public SubjectTag(@NonNull String subject) { - this.subject = subject; - } } diff --git a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java index eeedda9f..c935fe41 100644 --- a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java +++ b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java @@ -4,6 +4,8 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -17,6 +19,7 @@ import nostr.base.ITag; import nostr.base.UserProfile; import nostr.base.PublicKey; +import nostr.event.BaseTag; import nostr.event.Kind; import nostr.event.Marker; import nostr.event.Reaction; @@ -38,7 +41,6 @@ import nostr.event.impl.ReplaceableEvent; import nostr.event.impl.TextNoteEvent; import nostr.event.list.KindList; -import nostr.event.list.TagList; import nostr.event.message.EventMessage; import nostr.event.message.ReqMessage; import nostr.event.tag.EventTag; @@ -229,11 +231,11 @@ private static void sendTextNoteEvent() throws NostrException { try { final PublicKey publicKeySender = SENDER.getPublicKey(); - ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build(); - TagList tagList = new TagList(); - tagList.add(rcptTag); + PubKeyTag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build(); + List tags = new ArrayList<>(); + tags.add(rcptTag); - GenericEvent event = new TextNoteEvent(publicKeySender, tagList, + GenericEvent event = new TextNoteEvent(publicKeySender, tags, "Hello world, I'm here on nostr-java API!"); SENDER.sign(event); @@ -251,11 +253,11 @@ private static void sendEncryptedDirectMessage() throws NostrException { try { final PublicKey publicKeySender = SENDER.getPublicKey(); - ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build(); - TagList tagList = new TagList(); - tagList.add(rcptTag); + PubKeyTag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build(); + List tags = new ArrayList<>(); + tags.add(rcptTag); - var event2 = new DirectMessageEvent(publicKeySender, tagList, "Hello Nakamoto!"); + var event2 = new DirectMessageEvent(publicKeySender, tags, "Hello Nakamoto!"); SENDER.encryptDirectMessage(event2); SENDER.sign(event2); @@ -275,11 +277,11 @@ private static void mentionsEvent() throws NostrException { try { final PublicKey publicKeySender = SENDER.getPublicKey(); - ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(rcptTag); + PubKeyTag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + List tags = new ArrayList<>(); + tags.add(rcptTag); - GenericEvent event = new MentionsEvent(publicKeySender, tagList, "Hello " + RECEIVER.getPublicKey().toString()); + GenericEvent event = new MentionsEvent(publicKeySender, tags, "Hello " + RECEIVER.getPublicKey().toString()); SENDER.sign(event); GenericMessage message = new EventMessage(event); @@ -297,20 +299,20 @@ private static void deletionEvent() throws NostrException { try { final PublicKey publicKeySender = SENDER.getPublicKey(); - ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(rcptTag); + PubKeyTag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + List tags = new ArrayList<>(); + tags.add((PubKeyTag) rcptTag); - GenericEvent event = new TextNoteEvent(publicKeySender, tagList, "Hello Astral, Please delete me!"); + GenericEvent event = new TextNoteEvent(publicKeySender, tags, "Hello Astral, Please delete me!"); SENDER.sign(event); GenericMessage message = new EventMessage(event); CLIENT.send(message); - tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(event.getId()).build()); - GenericEvent delEvent = new DeletionEvent(publicKeySender, tagList); + tags = new ArrayList<>(); + tags.add(EventTag.builder().idEvent(event.getId()).build()); + GenericEvent delEvent = new DeletionEvent(publicKeySender, tags); SENDER.sign(delEvent); message = new EventMessage(delEvent); @@ -346,11 +348,11 @@ private static void ephemerealEvent() throws NostrException { try { final PublicKey publicKeySender = SENDER.getPublicKey(); - ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(rcptTag); + PubKeyTag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + List tags = new ArrayList<>(); + tags.add(rcptTag); - GenericEvent event = new EphemeralEvent(publicKeySender, tagList); + GenericEvent event = new EphemeralEvent(publicKeySender, tags); SENDER.sign(event); GenericMessage message = new EventMessage(event); @@ -366,21 +368,21 @@ private static void reactionEvent() throws NostrException { try { final PublicKey publicKeySender = SENDER.getPublicKey(); - ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(rcptTag); + PubKeyTag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + List tags = new ArrayList<>(); + tags.add(rcptTag); - GenericEvent event = new TextNoteEvent(publicKeySender, tagList, "Hello Astral, Please like me!"); + GenericEvent event = new TextNoteEvent(publicKeySender, tags, "Hello Astral, Please like me!"); SENDER.sign(event); GenericMessage message = new EventMessage(event); CLIENT.send(message); - tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(event.getId()).build()); - tagList.add(PubKeyTag.builder().publicKey(publicKeySender).build()); - GenericEvent reactionEvent = new ReactionEvent(publicKeySender, tagList, Reaction.LIKE, event); + tags = new ArrayList<>(); + tags.add(EventTag.builder().idEvent(event.getId()).build()); + tags.add(PubKeyTag.builder().publicKey(publicKeySender).build()); + GenericEvent reactionEvent = new ReactionEvent(publicKeySender, tags, Reaction.LIKE, event); SENDER.sign(reactionEvent); message = new EventMessage(reactionEvent); @@ -397,27 +399,27 @@ private static void replaceableEvent() throws NostrException { try { final PublicKey publicKeySender = SENDER.getPublicKey(); - ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(rcptTag); + PubKeyTag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + List tags = new ArrayList<>(); + tags.add(rcptTag); - GenericEvent event = new TextNoteEvent(publicKeySender, tagList, "Hello Astral, Please replace me!"); + GenericEvent event = new TextNoteEvent(publicKeySender, tags, "Hello Astral, Please replace me!"); SENDER.sign(event); GenericMessage message = new EventMessage(event); CLIENT.send(message); - tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(event.getId()).build()); - GenericEvent replaceableEvent = new ReplaceableEvent(publicKeySender, 15000, tagList, "Content"); + tags = new ArrayList<>(); + tags.add(EventTag.builder().idEvent(event.getId()).build()); + GenericEvent replaceableEvent = new ReplaceableEvent(publicKeySender, 15000, tags, "Content"); SENDER.sign(replaceableEvent); message = new EventMessage(replaceableEvent); CLIENT.send(message); - replaceableEvent = new ReplaceableEvent(publicKeySender, 15000, tagList, "New Content"); + replaceableEvent = new ReplaceableEvent(publicKeySender, 15000, tags, "New Content"); SENDER.sign(replaceableEvent); message = new EventMessage(replaceableEvent); @@ -433,11 +435,11 @@ private static void internetIdMetadata() throws NostrException { try { final PublicKey publicKeySender = SENDER.getPublicKey(); - ITag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); - TagList tagList = new TagList(); - tagList.add(rcptTag); + PubKeyTag rcptTag = PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).petName("nostr-java").build(); + List tags = new ArrayList<>(); + tags.add(rcptTag); - GenericEvent event = new InternetIdentifierMetadataEvent(publicKeySender, tagList, PROFILE); + GenericEvent event = new InternetIdentifierMetadataEvent(publicKeySender, tags, PROFILE); SENDER.sign(event); GenericMessage message = new EventMessage(event); @@ -476,7 +478,7 @@ private static GenericEvent createChannel() throws NostrException { var channel = Channel.builder().name("JNostr Channel") .about("This is a channel to test NIP28 in nostr-java") .picture("https://cdn.pixabay.com/photo/2020/05/19/13/48/cartoon-5190942_960_720.jpg").build(); - GenericEvent event = new ChannelCreateEvent(publicKeySender, new TagList(), channel.toString()); + GenericEvent event = new ChannelCreateEvent(publicKeySender, new ArrayList(), channel.toString()); SENDER.sign(event); GenericMessage message = new EventMessage(event); @@ -484,7 +486,7 @@ private static GenericEvent createChannel() throws NostrException { CLIENT.send(message); return event; - } catch (Exception ex) { + } catch (NostrException ex) { throw new NostrException(ex); } } @@ -496,14 +498,14 @@ private static void updateChannelMetadata() throws NostrException { var channelCreateEvent = createChannel(); - var tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(channelCreateEvent.getId()) + var tags = new ArrayList(); + tags.add(EventTag.builder().idEvent(channelCreateEvent.getId()) .recommendedRelayUrl(CLIENT.getRelays().stream().findFirst().get().getUri()).build()); var channel = Channel.builder().name("test change name") .about("This is a channel to test NIP28 in nostr-java | changed") .picture("https://cdn.pixabay.com/photo/2020/05/19/13/48/cartoon-5190942_960_720.jpg").build(); - GenericEvent event = new ChannelMetadataEvent(publicKeySender, tagList, channel.toString()); + GenericEvent event = new ChannelMetadataEvent(publicKeySender, tags, channel.toString()); SENDER.sign(event); var message = new EventMessage(event); @@ -521,13 +523,13 @@ private static GenericEvent sendChannelMessage() throws NostrException { var channelCreateEvent = createChannel(); - var tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(channelCreateEvent.getId()) + var tags = new ArrayList(); + tags.add(EventTag.builder().idEvent(channelCreateEvent.getId()) .recommendedRelayUrl(CLIENT.getRelays().stream().findFirst().get().getUri()) .marker(Marker.ROOT) .build()); - GenericEvent event = new ChannelMessageEvent(publicKeySender, tagList, "Hello everybody!"); + GenericEvent event = new ChannelMessageEvent(publicKeySender, tags, "Hello everybody!"); SENDER.sign(event); var message = new EventMessage(event); @@ -535,7 +537,7 @@ private static GenericEvent sendChannelMessage() throws NostrException { CLIENT.send(message); return event; - } catch (Exception ex) { + } catch (NostrException ex) { throw new NostrException(ex); } } @@ -547,10 +549,10 @@ private static GenericEvent hideMessage() throws NostrException { var channelMessageEvent = sendChannelMessage(); - var tagList = new TagList(); - tagList.add(EventTag.builder().idEvent(channelMessageEvent.getId()).build()); + var tags = new ArrayList(); + tags.add(EventTag.builder().idEvent(channelMessageEvent.getId()).build()); - GenericEvent event = new HideMessageEvent(publicKeySender, tagList, + GenericEvent event = new HideMessageEvent(publicKeySender, tags, ContentReason.builder().reason("Dick pic").build().toString()); SENDER.sign(event); @@ -559,7 +561,7 @@ private static GenericEvent hideMessage() throws NostrException { CLIENT.send(message); return event; - } catch (Exception ex) { + } catch (NostrException ex) { throw new NostrException(ex); } } @@ -569,10 +571,10 @@ private static GenericEvent muteUser() throws NostrException { try { final PublicKey publicKeySender = SENDER.getPublicKey(); - var tagList = new TagList(); - tagList.add(PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build()); + var tags = new ArrayList(); + tags.add(PubKeyTag.builder().publicKey(RECEIVER.getPublicKey()).build()); - GenericEvent event = new MuteUserEvent(publicKeySender, tagList, + GenericEvent event = new MuteUserEvent(publicKeySender, tags, ContentReason.builder().reason("Posting dick pics").build().toString()); SENDER.sign(event); @@ -581,7 +583,7 @@ private static GenericEvent muteUser() throws NostrException { CLIENT.send(message); return event; - } catch (Exception ex) { + } catch (NostrException ex) { throw new NostrException(ex); } } 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 6500f9a4..106c5d02 100644 --- a/nostr-java-id/src/main/java/nostr/id/Identity.java +++ b/nostr-java-id/src/main/java/nostr/id/Identity.java @@ -82,7 +82,7 @@ public PublicKey getPublicKey() { } public void encryptDirectMessage(@NonNull DirectMessageEvent dmEvent) throws NostrException { - ITag pkTag = (ITag) dmEvent.getTags().getList().get(0); + ITag pkTag = (ITag) dmEvent.getTags().get(0); if (pkTag instanceof PubKeyTag pubKeyTag) { try { var rcptPublicKey = pubKeyTag.getPublicKey(); @@ -142,14 +142,18 @@ private Signature signEvent(@NonNull GenericEvent event) throws NoSuchAlgorithmE event.update(); log.log(Level.FINER, "Serialized event: {0}", new String(event.get_serializedEvent())); final var signedHashedSerializedEvent = Schnorr.sign(NostrUtil.sha256(event.get_serializedEvent()), privateKey.getRawData(), generateAuxRand()); - final Signature signature = Signature.builder().rawData(signedHashedSerializedEvent).pubKey(this.getPublicKey()).build(); + final Signature signature = new Signature(); + signature.setRawData(signedHashedSerializedEvent); + signature.setPubKey(getPublicKey()); event.setSignature(signature); return signature; } private Signature signDelegationTag(@NonNull DelegationTag delegationTag) throws NoSuchAlgorithmException, IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException, Exception { final var signedHashedToken = Schnorr.sign(NostrUtil.sha256(delegationTag.getToken().getBytes(StandardCharsets.UTF_8)), privateKey.getRawData(), generateAuxRand()); - final Signature signature = Signature.builder().rawData(signedHashedToken).pubKey(this.getPublicKey()).build(); + final Signature signature = new Signature(); + signature.setRawData(signedHashedToken); + signature.setPubKey(getPublicKey()); delegationTag.setSignature(signature); return signature; } diff --git a/nostr-java-test/src/main/java/nostr/test/EntityFactory.java b/nostr-java-test/src/main/java/nostr/test/EntityFactory.java index fbee2bf4..6b8409f7 100644 --- a/nostr-java-test/src/main/java/nostr/test/EntityFactory.java +++ b/nostr-java-test/src/main/java/nostr/test/EntityFactory.java @@ -1,10 +1,7 @@ package nostr.test; -import java.beans.IntrospectionException; -import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -15,6 +12,7 @@ import nostr.base.IEvent; import nostr.base.UserProfile; import nostr.base.PublicKey; +import nostr.event.BaseTag; import nostr.event.Reaction; import nostr.event.impl.DirectMessageEvent; import nostr.event.impl.EphemeralEvent; @@ -32,7 +30,6 @@ import nostr.event.list.GenericTagQueryList; import nostr.event.list.KindList; import nostr.event.list.PublicKeyList; -import nostr.event.list.TagList; import nostr.event.tag.PubKeyTag; import nostr.util.NostrException; @@ -49,7 +46,7 @@ public static class Events { @SuppressWarnings("unchecked") public static EphemeralEvent createEphemeralEvent(PublicKey publicKey) { - TagList tagList = new TagList(); + List tagList = new ArrayList<>(); tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("eric").build()); GenericEvent event = new EphemeralEvent(publicKey, tagList); event.update(); @@ -57,7 +54,7 @@ public static EphemeralEvent createEphemeralEvent(PublicKey publicKey) { } public static DirectMessageEvent createDirectMessageEvent(PublicKey senderPublicKey, PublicKey rcptPublicKey, String content) { - TagList tagList = new TagList(); + List tagList = new ArrayList<>(); tagList.add(PubKeyTag.builder().publicKey(rcptPublicKey).petName("uq7yfx3l").build()); GenericEvent event = new DirectMessageEvent(senderPublicKey, tagList, content); event.update(); @@ -71,7 +68,7 @@ public static Filters createFilters(PublicKeyList authors, KindList kindList, Lo @SuppressWarnings("unchecked") public static InternetIdentifierMetadataEvent createInternetIdentifierMetadataEvent(UserProfile profile) throws NostrException { final PublicKey publicKey = profile.getPublicKey(); - TagList tagList = new TagList(); + List tagList = new ArrayList<>(); tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("daniel").build()); GenericEvent event = new InternetIdentifierMetadataEvent(publicKey, tagList, profile); event.update(); @@ -80,14 +77,14 @@ public static InternetIdentifierMetadataEvent createInternetIdentifierMetadataEv @SuppressWarnings("unchecked") public static MentionsEvent createMentionsEvent(PublicKey publicKey) { - TagList tagList = new TagList(); + List tagList = new ArrayList<>(); tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("charlie").build()); String content = generateRamdomAlpha(32); StringBuilder sbContent = new StringBuilder(content); - int len = tagList.getList().size(); + int len = tagList.size(); for (int i = 0; i < len; i++) { - sbContent.append(", ").append(((PubKeyTag) tagList.getList().get(i)).getPublicKey().toString()); + sbContent.append(", ").append(((PubKeyTag) tagList.get(i)).getPublicKey().toString()); } GenericEvent event = new MentionsEvent(publicKey, tagList, sbContent.toString()); @@ -104,7 +101,7 @@ public static MetadataEvent createMetadataEvent(UserProfile profile) throws Nost @SuppressWarnings("unchecked") public static ReactionEvent createReactionEvent(PublicKey publicKey, GenericEvent original) { - TagList tagList = new TagList(); + List tagList = new ArrayList<>(); tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("charlie").build()); GenericEvent event = new ReactionEvent(publicKey, tagList, Reaction.LIKE, original); return (ReactionEvent) event; @@ -112,7 +109,7 @@ public static ReactionEvent createReactionEvent(PublicKey publicKey, GenericEven public static ReplaceableEvent createReplaceableEvent(PublicKey publicKey) { String content = generateRamdomAlpha(32); - GenericEvent event = new ReplaceableEvent(publicKey, 15000, new TagList(), content); + GenericEvent event = new ReplaceableEvent(publicKey, 15000, new ArrayList<>(), content); return (ReplaceableEvent) event; } @@ -121,16 +118,15 @@ public static TextNoteEvent createTextNoteEvent(PublicKey publicKey) { return createTextNoteEvent(publicKey, content); } - @SuppressWarnings("unchecked") public static TextNoteEvent createTextNoteEvent(PublicKey publicKey, String content) { - TagList tagList = new TagList(); + List tagList = new ArrayList<>(); tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("alice").build()); GenericEvent event = new TextNoteEvent(publicKey, tagList, content); return (TextNoteEvent) event; } public static OtsEvent createOtsEvent(PublicKey publicKey) { - TagList tagList = new TagList(); + List tagList = new ArrayList<>(); final PubKeyTag pkTag = PubKeyTag.builder().publicKey(publicKey).petName("bob").build(); tagList.add(pkTag); OtsEvent event = new OtsEvent(publicKey, tagList, generateRamdomAlpha(32), generateRamdomAlpha(32)); diff --git a/nostr-java-util/src/main/java/nostr/util/AbstractBaseConfiguration.java b/nostr-java-util/src/main/java/nostr/util/AbstractBaseConfiguration.java index 8774e570..20163aea 100644 --- a/nostr-java-util/src/main/java/nostr/util/AbstractBaseConfiguration.java +++ b/nostr-java-util/src/main/java/nostr/util/AbstractBaseConfiguration.java @@ -87,10 +87,10 @@ protected final void load(@NonNull String filename) throws FileNotFoundException //var configFolder = System.getProperty(CONFIG_DIR); var configFolder = this.appConfig.getDefaultConfigFolder(); log.log(Level.INFO, "loading configuration file: {0}", filename); - log.log(Level.FINE, "Configuration location: {0}", configFolder); + log.log(Level.INFO, "Configuration folder location: {0}", configFolder); if (configFolder != null) { final var baseConfigFolder = appConfig.getDefaultBaseConfigFolder(); - final var configLocationFolder = new File(baseConfigFolder, configFolder);//(baseConfigFolder + configFolder).replace("//", "/"); + final var configLocationFolder = new File(baseConfigFolder, configFolder); loadFromConfigDir(filename, configLocationFolder); return; } @@ -128,11 +128,13 @@ private void loadFromConfigDir(String filename, File configFolder) throws IOExce final String fname = filename.substring(1); var tmpFile = filename.startsWith("/") ? fname : filename; final File file = new File(configFolder, tmpFile); - log.log(Level.FINER, "Configuration file {0}", file.getName()); + log.log(Level.INFO, "Configuration file {0}", file.getAbsoluteFile()); if (file.exists()) { var inputStream = new FileInputStream(file); - log.log(Level.FINER, "Loading configuration file from {0}", file.getParent()); + log.log(Level.INFO, "Loading configuration file from {0}", file.getParent()); properties.load(inputStream); + } else { + log.log(Level.WARNING, "The file {0} does not exist", file.getAbsoluteFile()); } } diff --git a/nostr-java-util/src/main/java/nostr/util/ApplicationConfiguration.java b/nostr-java-util/src/main/java/nostr/util/ApplicationConfiguration.java index b28a1361..0da73f12 100644 --- a/nostr-java-util/src/main/java/nostr/util/ApplicationConfiguration.java +++ b/nostr-java-util/src/main/java/nostr/util/ApplicationConfiguration.java @@ -37,11 +37,6 @@ public String getIdentityProperties() { return id == null ? DEFAULT_ID_CONFIG : id; } -// public String getClientProperties() { -// var client = getProperty("client"); -// return client == null ? DEFAULT_CLIENT_CONFIG : client; -// } - public String getRelaysProperties() { var client = getProperty("relays"); return client == null ? DEFAULT_RELAYS_CONFIG : client; diff --git a/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java index 4d009b2e..7c59466e 100644 --- a/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java +++ b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java @@ -5,8 +5,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.Arrays; -import java.util.List; import java.util.ServiceLoader; import java.util.logging.Level; import lombok.Data; @@ -43,25 +41,18 @@ public void process(String message, Relay relay) throws NostrException { log.log(Level.INFO, "Process Message: {0} from relay: {1}", new Object[]{message, relay}); - ObjectMapper objectMapper = new ObjectMapper(); - List items; - try { - items = Arrays.asList(objectMapper.readValue(message, String[].class)); - } catch (JsonProcessingException ex) { - throw new NostrException(ex); - } - - final String command = items.get(0); + Object[] items = unmarshall(message); + final String command = items[0].toString(); switch (command) { case "EOSE" -> { - var subId = items.get(1); + var subId = items[1].toString(); commandHandler.onEose(subId, relay); } case "OK" -> { - String eventId = items.get(1); - boolean result = Boolean.parseBoolean(items.get(2)); - String msg = items.get(3); + String eventId = items[1].toString(); + boolean result = Boolean.parseBoolean(items[2].toString()); + String msg = items[3].toString(); final var msgSplit = msg.split(":", 2); Reason reason; String reasonMessage = msg; @@ -75,17 +66,21 @@ public void process(String message, Relay relay) throws NostrException { commandHandler.onOk(eventId, reasonMessage, reason, result, relay); } case "NOTICE" -> { - var param = items.get(1); + var param = items[1].toString(); commandHandler.onNotice(param); } case "EVENT" -> { - var subId = items.get(1); - var jsonEvent = items.get(2); - - commandHandler.onEvent(jsonEvent, subId, relay); + try { + var subId = items[1].toString(); + var jsonEvent = new ObjectMapper().writeValueAsString(items[2]); + commandHandler.onEvent(jsonEvent, subId, relay); + } catch (JsonProcessingException ex) { + throw new RuntimeException(ex); + } } + case "AUTH" -> { - var challenge = items.get(1); + var challenge = items[1].toString(); commandHandler.onAuth(challenge, relay); } @@ -94,4 +89,13 @@ public void process(String message, Relay relay) throws NostrException { } } } + + private Object[] unmarshall(String jsonString) { + try { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(jsonString, Object[].class); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } } diff --git a/nostr-java-ws/src/main/java/nostr/ws/ClientListenerEndPoint.java b/nostr-java-ws/src/main/java/nostr/ws/ClientListenerEndPoint.java index b0e9edb7..3409fe21 100644 --- a/nostr-java-ws/src/main/java/nostr/ws/ClientListenerEndPoint.java +++ b/nostr-java-ws/src/main/java/nostr/ws/ClientListenerEndPoint.java @@ -67,9 +67,7 @@ public void onTextMessage(Session session, @NonNull String message) throws IOExc session.close(StatusCode.NORMAL, "bye"); return; } - - log.log(Level.FINE, "onTextMessage Relay {0}: Message: {1}", new Object[]{session.getRemoteAddress(), message}); - + responseHandler.process(message, getRelay(session)); } From c0e646bc1364716cd01a0739d91cf6e8f26381c1 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 15 Jun 2023 10:51:57 +0100 Subject: [PATCH 05/37] Correcting typos --- nostr-java-id/src/main/java/nostr/id/Identity.java | 2 +- nostr-java-id/src/main/resources/profile.properties | 2 +- nostr-java-test/src/test/resources/profile.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 106c5d02..41c3ab26 100644 --- a/nostr-java-id/src/main/java/nostr/id/Identity.java +++ b/nostr-java-id/src/main/java/nostr/id/Identity.java @@ -256,7 +256,7 @@ PrivateKey getPrivateKey() throws IOException, NostrException { } PublicKey getPublicKey() throws NostrException, IOException { - String pubKey = getProperty("publickKey"); + String pubKey = getProperty("publicKey"); if (pubKey == null || "".equals(pubKey.trim())) { log.log(Level.FINE, "Generating new public key"); try { diff --git a/nostr-java-id/src/main/resources/profile.properties b/nostr-java-id/src/main/resources/profile.properties index e44cfe66..56448368 100644 --- a/nostr-java-id/src/main/resources/profile.properties +++ b/nostr-java-id/src/main/resources/profile.properties @@ -1,3 +1,3 @@ privateKey=7b94cef920b07392577940df7181935189e85e0a90bbe474e137770671473ce7 -publickKey=f6a04a16b1fb3b4bf40838dacc7f8bd4d46b60d3c9e2a4915877f9a2eac8e323 \ No newline at end of file +publicKey=f6a04a16b1fb3b4bf40838dacc7f8bd4d46b60d3c9e2a4915877f9a2eac8e323 \ No newline at end of file diff --git a/nostr-java-test/src/test/resources/profile.properties b/nostr-java-test/src/test/resources/profile.properties index 976a5d15..44f2c68c 100644 --- a/nostr-java-test/src/test/resources/profile.properties +++ b/nostr-java-test/src/test/resources/profile.properties @@ -1,3 +1,3 @@ privateKey=519672a628310117110bfa93798eb03566f99b47d75b3998a1d65366aff97988 -publickKey= \ No newline at end of file +publicKey= \ No newline at end of file From c9d0af5caa63244f5e900167fbb0b78d548de982 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 15 Jun 2023 11:40:24 +0100 Subject: [PATCH 06/37] The java.util.NoSuchElementException occurs in the constructor of ResponseHandlerImpl. #35 --- .../handler/provider/ResponseHandlerImpl.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java index 7c59466e..575e91a7 100644 --- a/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java +++ b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.NoSuchElementException; import java.util.ServiceLoader; import java.util.logging.Level; import lombok.Data; @@ -25,15 +26,24 @@ @Log public class ResponseHandlerImpl implements IResponseHandler { - private final ICommandHandler commandHandler; + private ICommandHandler commandHandler; public ResponseHandlerImpl() { - this.commandHandler = ServiceLoader - .load(ICommandHandler.class).stream().map(p -> p.get()) - .filter(ch -> !ch.getClass().isAnnotationPresent(DefaultHandler.class)) - .findFirst() - .get(); + try { + this.commandHandler = ServiceLoader + .load(ICommandHandler.class).stream().map(p -> p.get()) + .filter(ch -> !ch.getClass().isAnnotationPresent(DefaultHandler.class)) + .findFirst() + .get(); + } catch (NoSuchElementException ex) { + log.log(Level.WARNING, "No custom command handler provided. Using default command handler"); + this.commandHandler = ServiceLoader + .load(ICommandHandler.class).stream().map(p -> p.get()) + .filter(ch -> ch.getClass().isAnnotationPresent(DefaultHandler.class)) + .findFirst() + .get(); + } } @Override From ab0ee63e13cd83d4dbd1c8b7acceb90194ead91f Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 15 Jun 2023 11:46:24 +0100 Subject: [PATCH 07/37] When connecting to certain relays, there is a failure in converting to RelayInformationDocument. #41 --- nostr-java-base/src/main/java/nostr/base/Relay.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nostr-java-base/src/main/java/nostr/base/Relay.java b/nostr-java-base/src/main/java/nostr/base/Relay.java index 3c3a99ff..b49781b6 100644 --- a/nostr-java-base/src/main/java/nostr/base/Relay.java +++ b/nostr-java-base/src/main/java/nostr/base/Relay.java @@ -73,6 +73,10 @@ public static class RelayInformationDocument { @JsonProperty private String pubkey; + + @JsonProperty + @JsonIgnoreProperties(ignoreUnknown = true) + private String id; @JsonProperty @JsonIgnoreProperties(ignoreUnknown = true) From 70fbcb8f7e98f8e5c87481ee1908b6d888324d4d Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 15 Jun 2023 22:18:10 +0100 Subject: [PATCH 08/37] The java.util.NoSuchElementException occurs in the constructor of ResponseHandlerImpl. #35 --- nostr-java-examples/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nostr-java-examples/pom.xml b/nostr-java-examples/pom.xml index 1f9f428b..75e8a988 100644 --- a/nostr-java-examples/pom.xml +++ b/nostr-java-examples/pom.xml @@ -38,5 +38,10 @@ nostr-java-id ${project.version} + + ${project.groupId} + nostr-java-ws-handler-command-provider + ${project.version} + \ No newline at end of file From 5488f62c8aaa661605bc573cf1786abc9d98834c Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 15 Jun 2023 22:18:28 +0100 Subject: [PATCH 09/37] The java.util.NoSuchElementException occurs in the constructor of ResponseHandlerImpl. #35 --- .../handler/provider/ResponseHandlerImpl.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java index 575e91a7..2f47429a 100644 --- a/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java +++ b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java @@ -37,12 +37,16 @@ public ResponseHandlerImpl() { .findFirst() .get(); } catch (NoSuchElementException ex) { - log.log(Level.WARNING, "No custom command handler provided. Using default command handler"); - this.commandHandler = ServiceLoader - .load(ICommandHandler.class).stream().map(p -> p.get()) - .filter(ch -> ch.getClass().isAnnotationPresent(DefaultHandler.class)) - .findFirst() - .get(); + log.log(Level.WARNING, "No custom command handler provided. Using default command handler..."); + try { + this.commandHandler = ServiceLoader + .load(ICommandHandler.class).stream().map(p -> p.get()) + .filter(ch -> ch.getClass().isAnnotationPresent(DefaultHandler.class)) + .findFirst() + .get(); + } catch (NoSuchElementException e) { + throw new AssertionError("Could not load the default handler", e); + } } } From 07ba9f045a531788b9b03112f8207a12dbc73391 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 20 Jun 2023 01:34:37 +0100 Subject: [PATCH 10/37] Tag de/serializer using jackson. Refacotoring --- .../src/main/java/nostr/base/Channel.java | 16 ++-- .../java/nostr/base/ElementAttribute.java | 12 +++ .../main/java/nostr/base/GenericTagQuery.java | 2 +- .../src/main/java/nostr/base/IDecoder.java | 14 ++++ .../base/{IMarshaller.java => IEncoder.java} | 6 +- .../src/main/java/nostr/base/PublicKey.java | 3 - .../src/main/java/nostr/base/Signature.java | 3 - .../src/main/java/module-info.java | 5 +- .../src/main/java/nostr/event/BaseTag.java | 8 +- .../nostr/event/impl/ChannelCreateEvent.java | 1 - .../java/nostr/event/impl/DeletionEvent.java | 5 -- .../java/nostr/event/impl/EphemeralEvent.java | 15 ++-- .../main/java/nostr/event/impl/Filters.java | 10 +-- .../java/nostr/event/impl/GenericEvent.java | 9 ++- .../java/nostr/event/impl/GenericMessage.java | 7 +- .../java/nostr/event/impl/GenericTag.java | 11 ++- .../impl/InternetIdentifierMetadataEvent.java | 1 - .../java/nostr/event/impl/MetadataEvent.java | 4 +- .../codec/ElementEncoder.java} | 25 +++--- .../codec/FilterEncoder.java} | 26 ++++--- .../event/json/codec/GenericTagDecoder.java | 39 ++++++++++ .../event/json/codec/GenericTagEncoder.java | 42 ++++++++++ .../codec/MessageEncoder.java} | 12 +-- .../codec/OstEventEncoder.java} | 29 ++++--- .../codec/TagEncoder.java} | 32 ++++---- .../deserializer}/PublicKeyDeserializer.java | 2 +- .../deserializer}/SignatureDeserializer.java | 2 +- .../deserializer/TagDeserializer.java} | 19 +++-- .../serializer/CustomBaseListSerializer.java} | 8 +- .../CustomGenericTagListSerializer.java} | 8 +- .../CustomGenericTagSerializer.java} | 10 +-- .../CustomIdEventListSerializer.java} | 4 +- .../serializer/TagSerializer.java} | 20 +++-- .../main/java/nostr/event/list/BaseList.java | 4 +- .../marshaller/impl/GenericTagMarshaller.java | 44 ----------- .../main/java/nostr/event/tag/SubjectTag.java | 1 - .../java/nostr/examples/NostrExamples.java | 3 +- .../main/java/nostr/test/EntityFactory.java | 3 +- .../test/java/nostr/test/event/EventTest.java | 78 ++++++++----------- .../provider/DefaultRequestHandler.java | 4 +- 40 files changed, 312 insertions(+), 235 deletions(-) create mode 100644 nostr-java-base/src/main/java/nostr/base/IDecoder.java rename nostr-java-base/src/main/java/nostr/base/{IMarshaller.java => IEncoder.java} (68%) rename nostr-java-event/src/main/java/nostr/event/{marshaller/impl/ElementMarshaller.java => json/codec/ElementEncoder.java} (71%) rename nostr-java-event/src/main/java/nostr/event/{marshaller/impl/FilterMarshaller.java => json/codec/FilterEncoder.java} (72%) create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagDecoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagEncoder.java rename nostr-java-event/src/main/java/nostr/event/{marshaller/impl/MessageMarshaller.java => json/codec/MessageEncoder.java} (79%) rename nostr-java-event/src/main/java/nostr/event/{marshaller/impl/OstEventMarshaller.java => json/codec/OstEventEncoder.java} (65%) rename nostr-java-event/src/main/java/nostr/event/{marshaller/impl/TagMarshaller.java => json/codec/TagEncoder.java} (57%) rename {nostr-java-base/src/main/java/nostr/base/util => nostr-java-event/src/main/java/nostr/event/json/deserializer}/PublicKeyDeserializer.java (94%) rename {nostr-java-base/src/main/java/nostr/base/util => nostr-java-event/src/main/java/nostr/event/json/deserializer}/SignatureDeserializer.java (95%) rename nostr-java-event/src/main/java/nostr/event/{codec/ITagDecoder.java => json/deserializer/TagDeserializer.java} (86%) rename nostr-java-event/src/main/java/nostr/event/{codec/CustomBaseListEncoder.java => json/serializer/CustomBaseListSerializer.java} (90%) rename nostr-java-event/src/main/java/nostr/event/{codec/CustomGenericTagListEncoder.java => json/serializer/CustomGenericTagListSerializer.java} (88%) rename nostr-java-event/src/main/java/nostr/event/{codec/CustomGenericTagEncoder.java => json/serializer/CustomGenericTagSerializer.java} (85%) rename nostr-java-event/src/main/java/nostr/event/{codec/CustomIdEventListEncoder.java => json/serializer/CustomIdEventListSerializer.java} (87%) rename nostr-java-event/src/main/java/nostr/event/{codec/CustomTagEncoder.java => json/serializer/TagSerializer.java} (75%) delete mode 100644 nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java diff --git a/nostr-java-base/src/main/java/nostr/base/Channel.java b/nostr-java-base/src/main/java/nostr/base/Channel.java index 80fabfa6..3e678ce5 100644 --- a/nostr-java-base/src/main/java/nostr/base/Channel.java +++ b/nostr-java-base/src/main/java/nostr/base/Channel.java @@ -21,16 +21,16 @@ public class Channel { private String about; private String picture; - + @Override public String toString() { - ObjectMapper mapper = new ObjectMapper(); - - try { - return mapper.writeValueAsString(this); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } + ObjectMapper mapper = new ObjectMapper(); + + try { + return mapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } } } diff --git a/nostr-java-base/src/main/java/nostr/base/ElementAttribute.java b/nostr-java-base/src/main/java/nostr/base/ElementAttribute.java index e9994fd4..e15e9201 100644 --- a/nostr-java-base/src/main/java/nostr/base/ElementAttribute.java +++ b/nostr-java-base/src/main/java/nostr/base/ElementAttribute.java @@ -1,5 +1,7 @@ package nostr.base; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -17,8 +19,18 @@ @AllArgsConstructor public class ElementAttribute { + @JsonProperty + @JsonInclude(JsonInclude.Include.NON_NULL) + @EqualsAndHashCode.Exclude private final String name; + + @JsonProperty + @EqualsAndHashCode.Include private final Object value; + + @JsonProperty + @JsonInclude(JsonInclude.Include.NON_NULL) + @EqualsAndHashCode.Exclude private final Integer nip; } diff --git a/nostr-java-base/src/main/java/nostr/base/GenericTagQuery.java b/nostr-java-base/src/main/java/nostr/base/GenericTagQuery.java index 657a6097..3dd051a5 100644 --- a/nostr-java-base/src/main/java/nostr/base/GenericTagQuery.java +++ b/nostr-java-base/src/main/java/nostr/base/GenericTagQuery.java @@ -11,7 +11,7 @@ */ @Data @Builder -public class GenericTagQuery { +public class GenericTagQuery implements IElement { private final Character tagName; private final List value; diff --git a/nostr-java-base/src/main/java/nostr/base/IDecoder.java b/nostr-java-base/src/main/java/nostr/base/IDecoder.java new file mode 100644 index 00000000..4b087119 --- /dev/null +++ b/nostr-java-base/src/main/java/nostr/base/IDecoder.java @@ -0,0 +1,14 @@ +package nostr.base; + +import nostr.util.NostrException; + +/** + * + * @author eric + * @param + */ +public interface IDecoder { + + public abstract T decode() throws NostrException; + +} diff --git a/nostr-java-base/src/main/java/nostr/base/IMarshaller.java b/nostr-java-base/src/main/java/nostr/base/IEncoder.java similarity index 68% rename from nostr-java-base/src/main/java/nostr/base/IMarshaller.java rename to nostr-java-base/src/main/java/nostr/base/IEncoder.java index b8bd36e9..6267a0b4 100644 --- a/nostr-java-base/src/main/java/nostr/base/IMarshaller.java +++ b/nostr-java-base/src/main/java/nostr/base/IEncoder.java @@ -10,10 +10,8 @@ * * @author squirrel */ -public interface IMarshaller { +public interface IEncoder { public static final ObjectMapper MAPPER = new ObjectMapper().setSerializationInclusion(Include.NON_NULL); - public abstract String marshall() throws NostrException; - -// public String toJson() throws NostrException; + public abstract String encode() throws NostrException; } diff --git a/nostr-java-base/src/main/java/nostr/base/PublicKey.java b/nostr-java-base/src/main/java/nostr/base/PublicKey.java index df417b1b..3472d0d6 100644 --- a/nostr-java-base/src/main/java/nostr/base/PublicKey.java +++ b/nostr-java-base/src/main/java/nostr/base/PublicKey.java @@ -1,8 +1,6 @@ package nostr.base; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import lombok.EqualsAndHashCode; -import nostr.base.util.PublicKeyDeserializer; import nostr.crypto.bech32.Bech32Prefix; import nostr.util.NostrUtil; @@ -11,7 +9,6 @@ * @author squirrel */ @EqualsAndHashCode(callSuper = true) -@JsonDeserialize(using = PublicKeyDeserializer.class) public class PublicKey extends BaseKey { public PublicKey(byte[] rawData) { diff --git a/nostr-java-base/src/main/java/nostr/base/Signature.java b/nostr-java-base/src/main/java/nostr/base/Signature.java index e96f9964..c8c8dfa5 100644 --- a/nostr-java-base/src/main/java/nostr/base/Signature.java +++ b/nostr-java-base/src/main/java/nostr/base/Signature.java @@ -5,11 +5,9 @@ import nostr.util.NostrUtil; import com.fasterxml.jackson.annotation.JsonValue; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import lombok.Data; import lombok.NoArgsConstructor; -import nostr.base.util.SignatureDeserializer; /** * @@ -17,7 +15,6 @@ */ @Data @NoArgsConstructor -@JsonDeserialize(using = SignatureDeserializer.class) public class Signature { @JsonProperty("rawData") diff --git a/nostr-java-event/src/main/java/module-info.java b/nostr-java-event/src/main/java/module-info.java index 95a2694a..c8ed2e4b 100644 --- a/nostr-java-event/src/main/java/module-info.java +++ b/nostr-java-event/src/main/java/module-info.java @@ -13,9 +13,10 @@ exports nostr.event; exports nostr.event.impl; exports nostr.event.list; - exports nostr.event.marshaller.impl; exports nostr.event.message; - exports nostr.event.codec; + exports nostr.event.json.codec; + exports nostr.event.json.deserializer; + exports nostr.event.json.serializer; exports nostr.event.tag; exports nostr.event.util; } diff --git a/nostr-java-event/src/main/java/nostr/event/BaseTag.java b/nostr-java-event/src/main/java/nostr/event/BaseTag.java index d3500f7c..2b1e0a7d 100644 --- a/nostr-java-event/src/main/java/nostr/event/BaseTag.java +++ b/nostr-java-event/src/main/java/nostr/event/BaseTag.java @@ -23,8 +23,8 @@ import nostr.base.Relay; import nostr.base.annotation.Key; import nostr.base.annotation.Tag; -import nostr.event.codec.CustomTagEncoder; -import nostr.event.codec.ITagDecoder; +import nostr.event.json.deserializer.TagDeserializer; +import nostr.event.json.serializer.TagSerializer; import nostr.util.NostrException; /** @@ -36,8 +36,8 @@ @EqualsAndHashCode(callSuper = false) @NoArgsConstructor @Log -@JsonDeserialize(using = ITagDecoder.class) -@JsonSerialize(using = CustomTagEncoder.class) +@JsonDeserialize(using = TagDeserializer.class) +@JsonSerialize(using = TagSerializer.class) public abstract class BaseTag implements ITag { @JsonIgnore diff --git a/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java b/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java index 0aa644c6..cff851d6 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/ChannelCreateEvent.java @@ -5,7 +5,6 @@ import java.util.List; import lombok.NonNull; import nostr.base.ChannelProfile; -import nostr.base.ITag; import nostr.base.PublicKey; import nostr.base.annotation.Event; import nostr.event.BaseTag; 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 9bb7cb32..56d0f363 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 @@ -25,9 +25,4 @@ public DeletionEvent(PublicKey pubKey, List tags, String cont public DeletionEvent(PublicKey pubKey, List tags) { this(pubKey, tags, "Deletion request"); } - -// public DeletionEvent(PublicKey pubKey, List eventsToDelete) { -// super(pubKey, Kind.DELETION); -// eventsToDelete.stream().map(e -> e.getId()).forEach(eId -> addTag(EventTag.builder().idEvent(eId).build())); -// } } 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 7b51fbb2..f25242ed 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 @@ -1,5 +1,6 @@ package nostr.event.impl; +import java.util.ArrayList; import java.util.List; import nostr.event.Kind; import nostr.base.PublicKey; @@ -20,16 +21,18 @@ @Event(name = "Ephemeral Events", nip = 16) public class EphemeralEvent extends GenericEvent { - public EphemeralEvent(PublicKey pubKey, List tags, String content) { - super(pubKey, Kind.EPHEMEREAL_EVENT, tags, content); + public EphemeralEvent(PublicKey pubKey, Integer kind, List tags, String content) { + super(pubKey, kind, tags, content); } - public EphemeralEvent(PublicKey pubKey, List tags) { - this(pubKey, tags, "..."); + public EphemeralEvent(PublicKey pubKey, Integer kind, List tags) { + this(pubKey, kind, tags, "..."); } - public EphemeralEvent(PublicKey sender, PublicKey recipient) { - super(sender, Kind.EPHEMEREAL_EVENT); + public EphemeralEvent(PublicKey sender, Integer kind, PublicKey recipient) { + this(sender, kind, new ArrayList<>()); this.addTag(PubKeyTag.builder().publicKey(recipient).build()); } + + // TODO - Validate the kind. } diff --git a/nostr-java-event/src/main/java/nostr/event/impl/Filters.java b/nostr-java-event/src/main/java/nostr/event/impl/Filters.java index 9d3278d5..d3419a4c 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/Filters.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/Filters.java @@ -10,8 +10,8 @@ import lombok.EqualsAndHashCode; import nostr.base.annotation.Key; import nostr.event.BaseEvent; -import nostr.event.codec.CustomGenericTagListEncoder; -import nostr.event.codec.CustomIdEventListEncoder; +import nostr.event.json.serializer.CustomGenericTagListSerializer; +import nostr.event.json.serializer.CustomIdEventListSerializer; import nostr.event.list.EventList; import nostr.event.list.GenericTagQueryList; import nostr.event.list.KindList; @@ -28,7 +28,7 @@ public class Filters extends BaseEvent { @Key @JsonProperty("ids") - @JsonSerialize(using=CustomIdEventListEncoder.class) + @JsonSerialize(using=CustomIdEventListSerializer.class) private EventList events; @Key @@ -40,7 +40,7 @@ public class Filters extends BaseEvent { @Key @JsonProperty("#e") - @JsonSerialize(using=CustomIdEventListEncoder.class) + @JsonSerialize(using=CustomIdEventListSerializer.class) private EventList referencedEvents; @Key @@ -57,7 +57,7 @@ public class Filters extends BaseEvent { private Integer limit; @Key(nip = 12) - @JsonSerialize(using=CustomGenericTagListEncoder.class) + @JsonSerialize(using=CustomGenericTagListSerializer.class) private GenericTagQueryList genericTagQueryList; @Override 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 1f1dd0ef..26039eaf 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 @@ -11,6 +11,7 @@ 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; @@ -19,8 +20,8 @@ import lombok.NonNull; import lombok.extern.java.Log; import nostr.base.ElementAttribute; +import nostr.base.IEncoder; import nostr.base.IGenericElement; -import nostr.base.IMarshaller; import nostr.base.ISignable; import nostr.base.ITag; import nostr.base.PublicKey; @@ -32,6 +33,8 @@ import nostr.event.BaseEvent; import nostr.event.BaseTag; import nostr.event.Kind; +import nostr.event.json.deserializer.PublicKeyDeserializer; +import nostr.event.json.deserializer.SignatureDeserializer; import nostr.util.NostrException; import nostr.util.NostrUtil; @@ -52,6 +55,7 @@ public class GenericEvent extends BaseEvent implements ISignable, IGenericElemen @JsonProperty("pubkey") @EqualsAndHashCode.Include @JsonString + @JsonDeserialize(using = PublicKeyDeserializer.class) private PublicKey pubKey; @Key @@ -76,6 +80,7 @@ public class GenericEvent extends BaseEvent implements ISignable, IGenericElemen @JsonProperty("sig") @EqualsAndHashCode.Exclude @JsonString + @JsonDeserialize(using = SignatureDeserializer.class) private Signature signature; @JsonIgnore @@ -188,7 +193,7 @@ protected static String escapeJsonString(String jsonString) { @SuppressWarnings("unchecked") private String serialize() throws NostrException { - var mapper = IMarshaller.MAPPER; + var mapper = IEncoder.MAPPER; var arrayNode = JsonNodeFactory.instance.arrayNode(); try { diff --git a/nostr-java-event/src/main/java/nostr/event/impl/GenericMessage.java b/nostr-java-event/src/main/java/nostr/event/impl/GenericMessage.java index e8e85c7a..c0dfa62c 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/GenericMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/GenericMessage.java @@ -1,5 +1,6 @@ package nostr.event.impl; +import com.fasterxml.jackson.annotation.JsonIgnore; import java.util.HashSet; import java.util.Set; import lombok.Data; @@ -14,8 +15,12 @@ @Data public class GenericMessage implements IGenericElement, IElement { - private final String command; + private final String command; + + @JsonIgnore private final Set attributes; + + @JsonIgnore private final Integer nip; public GenericMessage(String command) { diff --git a/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java b/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java index 9a5cdb59..5354aec9 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java @@ -12,7 +12,7 @@ import nostr.base.ElementAttribute; import nostr.base.IGenericElement; import nostr.event.BaseTag; -import nostr.event.marshaller.impl.ElementMarshaller; +import nostr.event.json.codec.ElementEncoder; import nostr.util.NostrException; /** @@ -23,11 +23,14 @@ @EqualsAndHashCode(callSuper = false) @Log public class GenericTag extends BaseTag implements IGenericElement { - + private final String code; + @JsonIgnore + @EqualsAndHashCode.Exclude private final Integer nip; - @JsonIgnore + + //@JsonIgnore private final Set attributes; public GenericTag(String code) { @@ -52,7 +55,7 @@ public void addAttribute(ElementAttribute attribute) { @Override public String toString() { try { - return new ElementMarshaller(this, null).marshall(); + return new ElementEncoder(this).encode(); } catch (NostrException ex) { log.log(Level.SEVERE, null, ex); 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 d1f3912e..d8779470 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 @@ -10,7 +10,6 @@ import lombok.EqualsAndHashCode; import lombok.NonNull; import lombok.extern.java.Log; -import nostr.base.ITag; import nostr.base.UserProfile; import nostr.base.annotation.Event; import nostr.event.BaseTag; 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 8577cc25..c7298136 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 @@ -11,7 +11,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.java.Log; -import nostr.base.IMarshaller; +import nostr.base.IEncoder; import nostr.base.UserProfile; import nostr.base.PublicKey; import nostr.base.annotation.Event; @@ -55,7 +55,7 @@ public void update() { } private void setContent() { - var mapper = IMarshaller.MAPPER; + var mapper = IEncoder.MAPPER; try { ObjectNode objNode = JsonNodeFactory.instance.objectNode(); objNode.set("name", mapper.valueToTree(this.getProfile().getName())); diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java b/nostr-java-event/src/main/java/nostr/event/json/codec/ElementEncoder.java similarity index 71% rename from nostr-java-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/json/codec/ElementEncoder.java index 52b235b9..8f1f3a83 100644 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/ElementMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/ElementEncoder.java @@ -1,4 +1,4 @@ -package nostr.event.marshaller.impl; +package nostr.event.json.codec; import com.fasterxml.jackson.core.JsonProcessingException; import java.lang.reflect.Field; @@ -7,8 +7,8 @@ import lombok.Data; import lombok.extern.java.Log; import nostr.base.IElement; -import nostr.base.IMarshaller; -import static nostr.base.IMarshaller.MAPPER; +import nostr.base.IEncoder; +import static nostr.base.IEncoder.MAPPER; import nostr.base.NipUtil; import nostr.base.Relay; import nostr.util.NostrException; @@ -21,13 +21,17 @@ @AllArgsConstructor @Log @Data -public class ElementMarshaller implements IMarshaller { +public class ElementEncoder implements IEncoder { private final IElement element; private final Relay relay; + public ElementEncoder(IElement element) { + this(element, null); + } + @Override - public String marshall() throws UnsupportedNIPException, NostrException { + public String encode() throws UnsupportedNIPException, NostrException { if (!nipEventSupport()) { throw new UnsupportedNIPException("NIP is not supported by relay: \"" + relay.getName() + "\" - List of supported NIP(s): " + relay.printSupportedNips()); } @@ -35,19 +39,20 @@ public String marshall() throws UnsupportedNIPException, NostrException { return toJson(); } - private boolean nipEventSupport() { - return (relay != null) ? NipUtil.checkSupport(relay, getElement()) : true; - } - protected boolean nipFieldSupport(Field field) { return (relay != null) ? NipUtil.checkSupport(relay, field) : true; } - private String toJson() throws NostrException { + protected String toJson() throws NostrException { try { return MAPPER.writeValueAsString(element); } catch (JsonProcessingException e) { throw new NostrException(e); } } + + private boolean nipEventSupport() { + return (relay != null) ? NipUtil.checkSupport(relay, element) : true; + } + } diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java b/nostr-java-event/src/main/java/nostr/event/json/codec/FilterEncoder.java similarity index 72% rename from nostr-java-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/json/codec/FilterEncoder.java index c9bc1397..c5f5ad2f 100644 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/FilterMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/FilterEncoder.java @@ -1,4 +1,4 @@ -package nostr.event.marshaller.impl; +package nostr.event.json.codec; import com.fasterxml.jackson.core.JsonProcessingException; import java.util.Spliterator; @@ -12,7 +12,9 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; -import nostr.base.IMarshaller; +import lombok.EqualsAndHashCode; +import nostr.base.GenericTagQuery; +import nostr.base.IEncoder; import nostr.base.Relay; import nostr.event.impl.Filters; import nostr.util.NostrException; @@ -21,22 +23,22 @@ * @author guilhermegps * */ -@AllArgsConstructor @Data -@Builder -public class FilterMarshaller implements IMarshaller { +@EqualsAndHashCode(callSuper = false) +public class FilterEncoder extends ElementEncoder { - private final Filters filters; - private final Relay relay; + public FilterEncoder(Filters filters, Relay relay) { + super(filters, relay); + } - @Override - public String marshall() throws NostrException { - return toJson(); + public FilterEncoder(Filters filters) { + super(filters); } - private String toJson() throws NostrException { + @Override + protected String toJson() throws NostrException { try { - JsonNode node = MAPPER.valueToTree(filters); + JsonNode node = MAPPER.valueToTree((Filters) getElement()); ObjectNode objNode = (ObjectNode) node; var arrayNode = (ArrayNode) node.get("genericTagQueryList"); if (arrayNode != null && !arrayNode.isNull()) { diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagDecoder.java new file mode 100644 index 00000000..a2ea16af --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagDecoder.java @@ -0,0 +1,39 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.HashSet; +import java.util.Set; +import lombok.AllArgsConstructor; +import lombok.Data; +import nostr.base.ElementAttribute; +import nostr.base.IDecoder; +import nostr.event.impl.GenericTag; +import nostr.util.NostrException; + +@Data +@AllArgsConstructor +public class GenericTagDecoder implements IDecoder { + + private final String json; + + @Override + public GenericTag decode() throws NostrException { + try { + ObjectMapper objectMapper = new ObjectMapper(); + String[] jsonElements = objectMapper.readValue(this.json, String[].class); + + String code = jsonElements[0]; + + Set attributes = new HashSet<>(); + for (int i = 1; i < jsonElements.length; i++) { + ElementAttribute attribute = new ElementAttribute(null, jsonElements[i], null); + attributes.add(attribute); + } + + return new GenericTag(null, code, attributes); + } catch (JsonProcessingException ex) { + throw new NostrException(ex); + } + } +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagEncoder.java new file mode 100644 index 00000000..b081749b --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagEncoder.java @@ -0,0 +1,42 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonProcessingException; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import nostr.base.GenericTagQuery; +import static nostr.base.IEncoder.MAPPER; +import nostr.base.Relay; +import nostr.util.NostrException; + +/** + * @author guilhermegps + * + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class GenericTagEncoder extends ElementEncoder { + + public GenericTagEncoder(GenericTagQuery tag, Relay relay) { + super(tag, relay); + } + + public GenericTagEncoder(GenericTagQuery tag) { + super(tag); + } + + @Override + public String encode() throws NostrException { + return toJson(); + } + + @Override + protected String toJson() throws NostrException { + try { + return MAPPER.writeValueAsString((GenericTagQuery) getElement()); + } catch (JsonProcessingException e) { + throw new NostrException(e); + } + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/MessageMarshaller.java b/nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java similarity index 79% rename from nostr-java-event/src/main/java/nostr/event/marshaller/impl/MessageMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java index ef016718..d43e318b 100644 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/MessageMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java @@ -1,4 +1,4 @@ -package nostr.event.marshaller.impl; +package nostr.event.json.codec; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; @@ -17,25 +17,25 @@ * * @author squirrel */ -public class MessageMarshaller extends ElementMarshaller { +public class MessageEncoder extends ElementEncoder { - public MessageMarshaller(GenericMessage baseMessage, Relay relay) { + public MessageEncoder(GenericMessage baseMessage, Relay relay) { super(baseMessage, relay); } @Override - public String marshall() throws NostrException { + public String encode() throws NostrException { GenericMessage message = (GenericMessage) getElement(); Relay relay = getRelay(); var arrayNode = JsonNodeFactory.instance.arrayNode(); try { arrayNode.add(message.getCommand()); if (message instanceof EventMessage msg) { - JsonNode tree = MAPPER.readTree(new ElementMarshaller(msg.getEvent(), relay).marshall()); + JsonNode tree = MAPPER.readTree(new ElementEncoder(msg.getEvent(), relay).encode()); arrayNode.add(tree); } else if (message instanceof ReqMessage msg) { arrayNode.add(msg.getSubscriptionId()); - JsonNode tree = MAPPER.readTree(new ElementMarshaller(msg.getFilters(), relay).marshall()); + JsonNode tree = MAPPER.readTree(new ElementEncoder(msg.getFilters(), relay).encode()); arrayNode.add(tree); } else if (message instanceof NoticeMessage msg) { arrayNode.add(msg.getMessage()); diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java b/nostr-java-event/src/main/java/nostr/event/json/codec/OstEventEncoder.java similarity index 65% rename from nostr-java-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/json/codec/OstEventEncoder.java index cd73c4db..3291fa36 100644 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/OstEventMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/OstEventEncoder.java @@ -1,15 +1,14 @@ -package nostr.event.marshaller.impl; +package nostr.event.json.codec; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import java.util.HashMap; -import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; +import lombok.EqualsAndHashCode; import nostr.base.ElementAttribute; -import nostr.base.IMarshaller; +import static nostr.base.IEncoder.MAPPER; import nostr.base.Relay; import nostr.event.impl.OtsEvent; import nostr.util.NostrException; @@ -18,21 +17,27 @@ * @author guilhermegps * */ -@AllArgsConstructor @Data -@Builder -public class OstEventMarshaller implements IMarshaller { +@EqualsAndHashCode(callSuper = false) +public class OstEventEncoder extends ElementEncoder { - private final OtsEvent event; - private final Relay relay; + public OstEventEncoder(OtsEvent event, Relay relay) { + super(event, relay); + } + + public OstEventEncoder(OtsEvent event) { + super(event); + } @Override - public String marshall() throws NostrException { + public String encode() throws NostrException { return toJson(); } - - private String toJson() throws NostrException { + + @Override + protected String toJson() throws NostrException { try { + final OtsEvent event = (OtsEvent) getElement(); JsonNode node = MAPPER.valueToTree(event); ObjectNode objNode = (ObjectNode) node; event.getAttributes().parallelStream() diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java b/nostr-java-event/src/main/java/nostr/event/json/codec/TagEncoder.java similarity index 57% rename from nostr-java-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java rename to nostr-java-event/src/main/java/nostr/event/json/codec/TagEncoder.java index abc72909..7f0cd25b 100644 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/TagMarshaller.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/TagEncoder.java @@ -1,45 +1,43 @@ -package nostr.event.marshaller.impl; +package nostr.event.json.codec; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; -import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; -import nostr.base.IMarshaller; +import lombok.EqualsAndHashCode; import nostr.base.Relay; import nostr.event.BaseTag; -import nostr.event.codec.CustomTagEncoder; +import nostr.event.json.serializer.TagSerializer; import nostr.util.NostrException; /** * @author guilhermegps * */ -@AllArgsConstructor @Data -@Builder -public class TagMarshaller implements IMarshaller { +@EqualsAndHashCode(callSuper = false) +public class TagEncoder extends ElementEncoder { - private final BaseTag tag; - private final Relay relay; - - @Override - public String marshall() throws NostrException { - return toJson(); + public TagEncoder(BaseTag tag, Relay relay) { + super(tag, relay); } - private String toJson() throws NostrException { + public TagEncoder(BaseTag tag) { + super(tag); + } + + @Override + protected String toJson() throws NostrException { try { SimpleModule module = new SimpleModule(); - module.addSerializer(new CustomTagEncoder()); + module.addSerializer(new TagSerializer()); var mapper = (new ObjectMapper()) .setSerializationInclusion(Include.NON_NULL) .registerModule(module); - return mapper.writeValueAsString(tag); + return mapper.writeValueAsString((BaseTag) getElement()); } catch (JsonProcessingException e) { throw new NostrException(e); } diff --git a/nostr-java-base/src/main/java/nostr/base/util/PublicKeyDeserializer.java b/nostr-java-event/src/main/java/nostr/event/json/deserializer/PublicKeyDeserializer.java similarity index 94% rename from nostr-java-base/src/main/java/nostr/base/util/PublicKeyDeserializer.java rename to nostr-java-event/src/main/java/nostr/event/json/deserializer/PublicKeyDeserializer.java index 74bf47b0..cf12c1a7 100644 --- a/nostr-java-base/src/main/java/nostr/base/util/PublicKeyDeserializer.java +++ b/nostr-java-event/src/main/java/nostr/event/json/deserializer/PublicKeyDeserializer.java @@ -1,5 +1,5 @@ -package nostr.base.util; +package nostr.event.json.deserializer; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; diff --git a/nostr-java-base/src/main/java/nostr/base/util/SignatureDeserializer.java b/nostr-java-event/src/main/java/nostr/event/json/deserializer/SignatureDeserializer.java similarity index 95% rename from nostr-java-base/src/main/java/nostr/base/util/SignatureDeserializer.java rename to nostr-java-event/src/main/java/nostr/event/json/deserializer/SignatureDeserializer.java index 7e294044..f6917ba2 100644 --- a/nostr-java-base/src/main/java/nostr/base/util/SignatureDeserializer.java +++ b/nostr-java-event/src/main/java/nostr/event/json/deserializer/SignatureDeserializer.java @@ -1,4 +1,4 @@ -package nostr.base.util; +package nostr.event.json.deserializer; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; diff --git a/nostr-java-event/src/main/java/nostr/event/codec/ITagDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java similarity index 86% rename from nostr-java-event/src/main/java/nostr/event/codec/ITagDecoder.java rename to nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java index 667212c1..ba3a321b 100644 --- a/nostr-java-event/src/main/java/nostr/event/codec/ITagDecoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java @@ -1,20 +1,22 @@ -package nostr.event.codec; +package nostr.event.json.deserializer; +import nostr.event.json.codec.GenericTagDecoder; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import java.io.IOException; -import nostr.base.ITag; import nostr.base.PublicKey; +import nostr.event.BaseTag; import nostr.event.Marker; import nostr.event.tag.EventTag; import nostr.event.tag.NonceTag; import nostr.event.tag.PubKeyTag; import nostr.event.tag.SubjectTag; +import nostr.util.NostrException; -public class ITagDecoder extends JsonDeserializer { +public class TagDeserializer extends JsonDeserializer { @Override public T deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { @@ -94,8 +96,15 @@ public T deserialize(JsonParser jsonParser, DeserializationContext deserializati } return (T) tag; } - default -> - throw new IOException("Unknown tag type: " + code); + default -> { + try { + var tag = new GenericTagDecoder(node.toString()).decode(); + return (T) tag; + } catch (NostrException ex) { + throw new IOException(ex); + } + } + } } } diff --git a/nostr-java-event/src/main/java/nostr/event/codec/CustomBaseListEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomBaseListSerializer.java similarity index 90% rename from nostr-java-event/src/main/java/nostr/event/codec/CustomBaseListEncoder.java rename to nostr-java-event/src/main/java/nostr/event/json/serializer/CustomBaseListSerializer.java index 535a737d..188565d2 100644 --- a/nostr-java-event/src/main/java/nostr/event/codec/CustomBaseListEncoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomBaseListSerializer.java @@ -1,4 +1,4 @@ -package nostr.event.codec; +package nostr.event.json.serializer; import java.io.IOException; import java.util.Iterator; @@ -15,7 +15,7 @@ import com.fasterxml.jackson.databind.SerializerProvider; import lombok.extern.java.Log; -import nostr.base.IMarshaller; +import nostr.base.IEncoder; import nostr.event.list.BaseList; /** @@ -23,7 +23,7 @@ * */ @Log -public class CustomBaseListEncoder extends JsonSerializer { +public class CustomBaseListSerializer extends JsonSerializer { @Override public void serialize(BaseList value, JsonGenerator gen, SerializerProvider serializers) { @@ -39,7 +39,7 @@ public void serialize(BaseList value, JsonGenerator gen, SerializerProvider seri } protected JsonNode toJson(Object obj) { - var mapper = IMarshaller.MAPPER; + var mapper = IEncoder.MAPPER; try { JsonNode node = mapper.valueToTree(obj); diff --git a/nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagListEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagListSerializer.java similarity index 88% rename from nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagListEncoder.java rename to nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagListSerializer.java index c5a6d0f2..6aa9d2be 100644 --- a/nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagListEncoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagListSerializer.java @@ -1,4 +1,4 @@ -package nostr.event.codec; +package nostr.event.json.serializer; import java.io.IOException; import java.util.logging.Level; @@ -12,7 +12,7 @@ import lombok.extern.java.Log; import nostr.base.GenericTagQuery; -import nostr.base.IMarshaller; +import nostr.base.IEncoder; import nostr.event.list.GenericTagQueryList; /** @@ -20,7 +20,7 @@ * */ @Log -public class CustomGenericTagListEncoder extends JsonSerializer { +public class CustomGenericTagListSerializer extends JsonSerializer { @Override public void serialize(GenericTagQueryList value, JsonGenerator gen, SerializerProvider serializers) { @@ -36,7 +36,7 @@ public void serialize(GenericTagQueryList value, JsonGenerator gen, SerializerPr } protected JsonNode toJson(GenericTagQuery gtq) { - var mapper = IMarshaller.MAPPER; + var mapper = IEncoder.MAPPER; try { JsonNode node = mapper.valueToTree(gtq); ObjectNode objNode = (ObjectNode) node; diff --git a/nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagSerializer.java similarity index 85% rename from nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagEncoder.java rename to nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagSerializer.java index 0215dfac..af133653 100644 --- a/nostr-java-event/src/main/java/nostr/event/codec/CustomGenericTagEncoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagSerializer.java @@ -1,4 +1,4 @@ -package nostr.event.codec; +package nostr.event.json.serializer; import java.io.IOException; import java.util.logging.Level; @@ -11,18 +11,18 @@ import lombok.extern.java.Log; import nostr.base.GenericTagQuery; -import nostr.base.IMarshaller; +import nostr.base.IEncoder; /** * @author guilhermegps * */ @Log -public class CustomGenericTagEncoder extends StdSerializer { +public class CustomGenericTagSerializer extends StdSerializer { private static final long serialVersionUID = 6803478463890319884L; - public CustomGenericTagEncoder() { + public CustomGenericTagSerializer() { super(GenericTagQuery.class); } @@ -37,7 +37,7 @@ public void serialize(GenericTagQuery value, JsonGenerator gen, SerializerProvid } public static JsonNode toJson(GenericTagQuery gtq) { - var mapper = IMarshaller.MAPPER; + var mapper = IEncoder.MAPPER; try { JsonNode node = mapper.valueToTree(gtq); ObjectNode objNode = (ObjectNode) node; diff --git a/nostr-java-event/src/main/java/nostr/event/codec/CustomIdEventListEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomIdEventListSerializer.java similarity index 87% rename from nostr-java-event/src/main/java/nostr/event/codec/CustomIdEventListEncoder.java rename to nostr-java-event/src/main/java/nostr/event/json/serializer/CustomIdEventListSerializer.java index 1bd7c272..f95e7216 100644 --- a/nostr-java-event/src/main/java/nostr/event/codec/CustomIdEventListEncoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomIdEventListSerializer.java @@ -1,4 +1,4 @@ -package nostr.event.codec; +package nostr.event.json.serializer; import java.io.IOException; import java.util.logging.Level; @@ -17,7 +17,7 @@ * */ @Log -public class CustomIdEventListEncoder extends JsonSerializer { +public class CustomIdEventListSerializer extends JsonSerializer { @Override public void serialize(EventList value, JsonGenerator gen, SerializerProvider serializers) { diff --git a/nostr-java-event/src/main/java/nostr/event/codec/CustomTagEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/serializer/TagSerializer.java similarity index 75% rename from nostr-java-event/src/main/java/nostr/event/codec/CustomTagEncoder.java rename to nostr-java-event/src/main/java/nostr/event/json/serializer/TagSerializer.java index ec06b2a9..008f1d30 100644 --- a/nostr-java-event/src/main/java/nostr/event/codec/CustomTagEncoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/serializer/TagSerializer.java @@ -1,4 +1,4 @@ -package nostr.event.codec; +package nostr.event.json.serializer; import java.io.IOException; @@ -10,9 +10,12 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.lang.reflect.Field; import java.util.List; +import java.util.Set; import lombok.extern.java.Log; +import nostr.base.ElementAttribute; import nostr.event.BaseTag; +import nostr.event.impl.GenericTag; import nostr.util.NostrException; /** @@ -20,11 +23,11 @@ * */ @Log -public class CustomTagEncoder extends StdSerializer { +public class TagSerializer extends StdSerializer { private static final long serialVersionUID = -3877972991082754068L; - public CustomTagEncoder() { + public TagSerializer() { super(BaseTag.class); } @@ -35,6 +38,7 @@ public void serialize(BaseTag value, JsonGenerator gen, SerializerProvider seria final ObjectNode node = new ObjectNode(JsonNodeFactory.instance); List fields = value.getSupportedFields(null); + // Populate the node with the fields data fields.stream().forEach((Field f) -> { try { node.put(f.getName(), value.getFieldValue(f)); @@ -43,12 +47,18 @@ public void serialize(BaseTag value, JsonGenerator gen, SerializerProvider seria } }); + // Populate the node with the attributes data + if (value instanceof GenericTag genericTag) { + Set attrs = genericTag.getAttributes(); + attrs.stream().forEach(a -> node.put(a.getName(), a.getValue().toString())); + } + // Extract the property values from the node and serialize them as an array if (node.isObject()) { ArrayNode arrayNode = node.objectNode().putArray("values"); - + // Add the tag code as the first element - arrayNode.add(value.getCode()); + arrayNode.add(value.getCode()); node.fields().forEachRemaining(entry -> arrayNode.add(entry.getValue().asText())); gen.writePOJO(arrayNode); diff --git a/nostr-java-event/src/main/java/nostr/event/list/BaseList.java b/nostr-java-event/src/main/java/nostr/event/list/BaseList.java index 7a0f8466..770750dd 100644 --- a/nostr-java-event/src/main/java/nostr/event/list/BaseList.java +++ b/nostr-java-event/src/main/java/nostr/event/list/BaseList.java @@ -10,7 +10,7 @@ import lombok.NonNull; import nostr.base.INostrList; import nostr.base.annotation.JsonList; -import nostr.event.codec.CustomBaseListEncoder; +import nostr.event.json.serializer.CustomBaseListSerializer; /** * @@ -20,7 +20,7 @@ @AllArgsConstructor @Data @JsonList -@JsonSerialize(using=CustomBaseListEncoder.class) +@JsonSerialize(using=CustomBaseListSerializer.class) public abstract class BaseList implements INostrList { @NonNull diff --git a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java b/nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java deleted file mode 100644 index c5a900f8..00000000 --- a/nostr-java-event/src/main/java/nostr/event/marshaller/impl/GenericTagMarshaller.java +++ /dev/null @@ -1,44 +0,0 @@ -package nostr.event.marshaller.impl; - -import com.fasterxml.jackson.core.JsonProcessingException; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import nostr.base.GenericTagQuery; -import nostr.base.IMarshaller; -import nostr.base.Relay; -import nostr.util.NostrException; - -/** - * @author guilhermegps - * - */ -@AllArgsConstructor -@Data -@Builder -public class GenericTagMarshaller implements IMarshaller { - - private final GenericTagQuery tag; - private final Relay relay; - - @Override - public String marshall() throws NostrException { - return toJson(); - } - - private String toJson() throws NostrException { - try { -// SimpleModule module = new SimpleModule(); -// module.addSerializer(new CustomGenericTagSerializer()); -// var mapper = (new ObjectMapper()) -// .setSerializationInclusion(Include.NON_NULL) -// MAPPER.registerModule(module); - - return MAPPER.writeValueAsString(tag); - } catch (JsonProcessingException e) { - throw new NostrException(e); - } - } - -} diff --git a/nostr-java-event/src/main/java/nostr/event/tag/SubjectTag.java b/nostr-java-event/src/main/java/nostr/event/tag/SubjectTag.java index 45022e93..8fd7466b 100644 --- a/nostr-java-event/src/main/java/nostr/event/tag/SubjectTag.java +++ b/nostr-java-event/src/main/java/nostr/event/tag/SubjectTag.java @@ -8,7 +8,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import lombok.NonNull; import nostr.base.annotation.Key; import nostr.base.annotation.Tag; import nostr.event.BaseTag; diff --git a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java index c935fe41..3fd37cc6 100644 --- a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java +++ b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java @@ -16,7 +16,6 @@ import lombok.extern.java.Log; import nostr.base.Channel; import nostr.base.ContentReason; -import nostr.base.ITag; import nostr.base.UserProfile; import nostr.base.PublicKey; import nostr.event.BaseTag; @@ -352,7 +351,7 @@ private static void ephemerealEvent() throws NostrException { List tags = new ArrayList<>(); tags.add(rcptTag); - GenericEvent event = new EphemeralEvent(publicKeySender, tags); + GenericEvent event = new EphemeralEvent(publicKeySender, Kind.EPHEMEREAL_EVENT.getValue(), tags); SENDER.sign(event); GenericMessage message = new EventMessage(event); diff --git a/nostr-java-test/src/main/java/nostr/test/EntityFactory.java b/nostr-java-test/src/main/java/nostr/test/EntityFactory.java index 6b8409f7..2036212b 100644 --- a/nostr-java-test/src/main/java/nostr/test/EntityFactory.java +++ b/nostr-java-test/src/main/java/nostr/test/EntityFactory.java @@ -13,6 +13,7 @@ import nostr.base.UserProfile; import nostr.base.PublicKey; import nostr.event.BaseTag; +import nostr.event.Kind; import nostr.event.Reaction; import nostr.event.impl.DirectMessageEvent; import nostr.event.impl.EphemeralEvent; @@ -48,7 +49,7 @@ public static class Events { public static EphemeralEvent createEphemeralEvent(PublicKey publicKey) { List tagList = new ArrayList<>(); tagList.add(PubKeyTag.builder().publicKey(publicKey).petName("eric").build()); - GenericEvent event = new EphemeralEvent(publicKey, tagList); + GenericEvent event = new EphemeralEvent(publicKey, Kind.EPHEMEREAL_EVENT.getValue(), tagList); event.update(); return (EphemeralEvent) event; } diff --git a/nostr-java-test/src/test/java/nostr/test/event/EventTest.java b/nostr-java-test/src/test/java/nostr/test/event/EventTest.java index aa25acbc..5dac09ad 100644 --- a/nostr-java-test/src/test/java/nostr/test/event/EventTest.java +++ b/nostr-java-test/src/test/java/nostr/test/event/EventTest.java @@ -1,25 +1,23 @@ package nostr.test.event; -import java.beans.IntrospectionException; +import com.fasterxml.jackson.core.JsonProcessingException; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.security.NoSuchAlgorithmException; -import java.util.logging.Level; -import java.util.logging.Logger; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import nostr.base.ElementAttribute; +import nostr.base.IEncoder; import nostr.base.IEvent; import nostr.base.PublicKey; import nostr.base.Relay; import nostr.crypto.bech32.Bech32; import nostr.crypto.bech32.Bech32Prefix; +import nostr.event.BaseTag; +import nostr.event.json.codec.ElementEncoder; import nostr.event.impl.GenericEvent; import nostr.event.impl.GenericMessage; import nostr.event.impl.GenericTag; -import nostr.event.marshaller.impl.ElementMarshaller; import nostr.event.util.Nip05Validator; import nostr.id.Identity; import nostr.test.EntityFactory; @@ -32,8 +30,7 @@ * @author squirrel */ public class EventTest { - - //private final Identity identity; + public EventTest() throws IOException, NostrException { } @@ -52,42 +49,29 @@ public void testCreateTextNoteEvent() throws NostrException { } @Test - public void testCreateGenericTag() { -// try { -// System.out.println("testCreateGenericTag"); -// PublicKey publicKey = this.identity.getPublicKey(); -// GenericTag genericTag = EntityFactory.Events.createGenericTag(publicKey); -// -// Relay relay = Relay.builder().uri("wss://secret.relay.com").build(); -// relay.addNipSupport(1); -// relay.addNipSupport(genericTag.getNip()); -// var attrs = genericTag.getAttributes(); -// for (var a : attrs) { -// relay.addNipSupport(a.getNip()); -// } -// -// ElementMarshaller marshaller = new ElementMarshaller(genericTag.getParent(), relay); -// var strJsonEvent = marshaller.marshall(); -// -// var jsonValue = new JsonObjectUnmarshaller(strJsonEvent).unmarshall(); -// -// IValue tags = ((ObjectValue) jsonValue).get("tags").get(); -// -// Assertions.assertEquals(2, ((ArrayValue) tags).length()); -// -// IValue tag = ((ArrayValue) tags).get(1).get(); -// -// Assertions.assertTrue(tag instanceof ArrayValue); -// -// IValue code = ((ArrayValue) tag).get(0).get(); -// -// Assertions.assertTrue(code instanceof StringValue); -// -// Assertions.assertEquals("devil", code.getValue()); -// -// } catch (NostrException ex) { -// Assertions.fail(ex); -// } + public void testCreateGenericTag() throws JsonProcessingException { + try { + System.out.println("testCreateGenericTag"); + PublicKey publicKey = Identity.getInstance().getPublicKey(); + GenericTag genericTag = EntityFactory.Events.createGenericTag(publicKey); + + Relay relay = Relay.builder().uri("wss://secret.relay.com").build(); + relay.addNipSupport(1); + relay.addNipSupport(genericTag.getNip()); + var attrs = genericTag.getAttributes(); + for (var a : attrs) { + relay.addNipSupport(a.getNip()); + } + + ElementEncoder encoder = new ElementEncoder((BaseTag)genericTag, relay); + var strJsonEvent = encoder.encode(); + + var tag = IEncoder.MAPPER.readValue(strJsonEvent, BaseTag.class); + Assertions.assertEquals(genericTag, tag); + + } catch (NostrException ex) { + Assertions.fail(ex); + } } @Test @@ -101,7 +85,7 @@ public void testCreateUnsupportedGenericTagAttribute() { // relay.addNipSupport(1); // relay.addNipSupport(genericTag.getNip()); // -// ElementMarshaller marshaller = new ElementMarshaller(genericTag.getParent(), relay); +// ElementEncoder marshaller = new ElementEncoder(genericTag.getParent(), relay); // var strJsonEvent = marshaller.marshall(); // // var jsonValue = new JsonObjectUnmarshaller(strJsonEvent).unmarshall(); @@ -137,11 +121,11 @@ public void testCreateUnsupportedGenericTag() throws IOException, NostrException Relay relay = Relay.builder().uri("wss://secret.relay.com").build(); relay.addNipSupport(0); - ElementMarshaller marshaller = new ElementMarshaller(genericTag.getParent(), relay); + ElementEncoder marshaller = new ElementEncoder(genericTag.getParent(), relay); UnsupportedNIPException thrown = Assertions.assertThrows(UnsupportedNIPException.class, () -> { - marshaller.marshall(); + marshaller.encode(); }, "This event is not supported. List of relay supported NIP(s): " + relay.printSupportedNips() ); diff --git a/nostr-java-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java b/nostr-java-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java index 882b01f6..632d68c9 100644 --- a/nostr-java-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java +++ b/nostr-java-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java @@ -11,8 +11,8 @@ import lombok.extern.java.Log; import nostr.base.Relay; import nostr.base.annotation.DefaultHandler; +import nostr.event.json.codec.MessageEncoder; import nostr.event.impl.GenericMessage; -import nostr.event.marshaller.impl.MessageMarshaller; import nostr.util.NostrException; import nostr.util.UnsupportedNIPException; import nostr.ws.Connection; @@ -58,7 +58,7 @@ private void sendMessage(GenericMessage message) throws IOException, NostrExcept if (session != null) { RemoteEndpoint remote = session.getRemote(); - final String msg = new MessageMarshaller(message, relay).marshall(); + final String msg = new MessageEncoder(message, relay).encode(); log.log(Level.INFO, ">>> Sending Message: {0}", msg); From 221475608da7b12b824e4888fa114f198385a4c1 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Wed, 21 Jun 2023 07:53:14 +0100 Subject: [PATCH 11/37] Added wrapper class for decoding events --- .../event/json/codec/BaseEventDecoder.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventDecoder.java diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventDecoder.java new file mode 100644 index 00000000..ca802b13 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventDecoder.java @@ -0,0 +1,31 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import nostr.base.IDecoder; +import nostr.event.BaseEvent; +import nostr.util.NostrException; + +/** + * + * @author eric + */ +@Data +@AllArgsConstructor +public class BaseEventDecoder implements IDecoder { + + private final String jsonEvent; + + @Override + public BaseEvent decode() throws NostrException { + try { + ObjectMapper objectMapper = new ObjectMapper(); + BaseEvent event = objectMapper.readValue(jsonEvent, BaseEvent.class); + return event; + } catch (JsonProcessingException ex) { + throw new NostrException(ex); + } + } +} From b79bfd09d6cf1136f8ab5c3d4746633a38fd401d Mon Sep 17 00:00:00 2001 From: tcheeric Date: Wed, 21 Jun 2023 23:46:56 +0100 Subject: [PATCH 12/37] Fixed issue #45 --- .../src/main/java/nostr/base/UserProfile.java | 7 ++----- .../event/impl/InternetIdentifierMetadataEvent.java | 2 +- .../src/main/java/nostr/event/impl/MetadataEvent.java | 9 ++++++++- .../src/main/java/nostr/examples/NostrExamples.java | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/nostr-java-base/src/main/java/nostr/base/UserProfile.java b/nostr-java-base/src/main/java/nostr/base/UserProfile.java index 0be4aea1..1f659517 100644 --- a/nostr-java-base/src/main/java/nostr/base/UserProfile.java +++ b/nostr-java-base/src/main/java/nostr/base/UserProfile.java @@ -23,12 +23,9 @@ public final class UserProfile extends Profile implements IBech32Encodable { private final PublicKey publicKey; - private String nip05; - - public UserProfile(PublicKey publicKey, String nip05, String name, String about, URL picture) { - super(name, about, picture); + public UserProfile(PublicKey publicKey, String nip05, String about, URL picture) { + super(nip05, about, picture); this.publicKey = publicKey; - this.nip05 = nip05; } @Override 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 d8779470..d5450f9e 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 @@ -37,7 +37,7 @@ public InternetIdentifierMetadataEvent(PublicKey pubKey, @NonNull UserProfile pr private void init(UserProfile profile) throws NostrException { // NIP-05 validator - Nip05Validator.builder().nip05(profile.getNip05()).publicKey(getPubKey()).build().validate(); + Nip05Validator.builder().nip05(profile.getName()).publicKey(getPubKey()).build().validate(); setContent(profile); } 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 c7298136..c38e093d 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 @@ -41,7 +41,14 @@ public MetadataEvent(PublicKey pubKey, UserProfile profile) throws NostrExceptio @Override protected void validate() { - var valid = this.profile.getName().matches(NAME_PATTERN); + boolean valid = true; + + var strNameArr = this.profile.getName().split("@"); + if (strNameArr.length == 2) { + var localPart = strNameArr[0]; + valid = localPart.matches(NAME_PATTERN); + } + if (!valid) { throw new AssertionError("Invalid profile name: " + this.profile, null); } diff --git a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java index 3fd37cc6..5f7c3306 100644 --- a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java +++ b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java @@ -59,7 +59,7 @@ public class NostrExamples { private static final Identity RECEIVER = Identity.generateRandomIdentity(); private static final Identity SENDER = Identity.generateRandomIdentity(); - private static final UserProfile PROFILE = new UserProfile(SENDER.getPublicKey(), "erict875@nostr-java.io", "eric t", "It's me!", null); + private static final UserProfile PROFILE = new UserProfile(SENDER.getPublicKey(), "erict875@nostr-java.io", "It's me!", null); private final static Map RELAYS = Map.of("brb", "brb.io", "damus", "relay.damus.io", "ZBD", "nostr.zebedee.cloud", "taxi", "relay.taxi", "vision", "relay.nostr.vision"); From 49038216847513a30267652550e7c9d277c6c5bd Mon Sep 17 00:00:00 2001 From: tcheeric Date: Wed, 21 Jun 2023 23:50:25 +0100 Subject: [PATCH 13/37] Fixed issue #45 --- nostr-java-test/src/main/java/nostr/test/EntityFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nostr-java-test/src/main/java/nostr/test/EntityFactory.java b/nostr-java-test/src/main/java/nostr/test/EntityFactory.java index 2036212b..a27054db 100644 --- a/nostr-java-test/src/main/java/nostr/test/EntityFactory.java +++ b/nostr-java-test/src/main/java/nostr/test/EntityFactory.java @@ -189,7 +189,7 @@ public static UserProfile createProfile(PublicKey pubKey) { String nip05 = name + "@tcheeric.com"; String url = "http://assets.tcheeric.com/" + number + ".PNG"; - return new UserProfile(pubKey, nip05, name, about, new URL(url)); + return new UserProfile(pubKey, nip05, about, new URL(url)); } catch (MalformedURLException ex) { throw new RuntimeException(ex); From 37c26cf8fbb01a60beed1531728676de0d2980f7 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 22 Jun 2023 02:38:26 +0100 Subject: [PATCH 14/37] Fixed issue #39 --- .../java/nostr/event/impl/GenericMessage.java | 2 + .../event/json/codec/BaseEventDecoder.java | 15 +-- .../event/json/codec/BaseMessageDecoder.java | 109 ++++++++++++++++++ .../nostr/event/json/codec/FilterEncoder.java | 4 - .../event/json/codec/FiltersDecoder.java | 31 +++++ .../event/json/codec/MessageEncoder.java | 7 +- .../nostr/event/message/BaseAuthMessage.java | 15 +++ .../message/ClientAuthenticationMessage.java | 30 +++++ .../nostr/event/message/CloseMessage.java | 2 + .../java/nostr/event/message/EoseMessage.java | 2 + .../nostr/event/message/EventMessage.java | 2 + .../nostr/event/message/NoticeMessage.java | 2 + .../java/nostr/event/message/OkMessage.java | 6 + ...AuthMessage.java => RelayAuthMessage.java} | 18 +-- .../java/nostr/event/message/ReqMessage.java | 4 + .../src/main/java/nostr/id/Client.java | 11 +- .../test/java/nostr/test/id/ClientTest.java | 1 - .../java/nostr/test/json/JsonParseTest.java | 42 +++++++ 18 files changed, 274 insertions(+), 29 deletions(-) create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageDecoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/FiltersDecoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/message/BaseAuthMessage.java create mode 100644 nostr-java-event/src/main/java/nostr/event/message/ClientAuthenticationMessage.java rename nostr-java-event/src/main/java/nostr/event/message/{AuthMessage.java => RelayAuthMessage.java} (55%) create mode 100644 nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java diff --git a/nostr-java-event/src/main/java/nostr/event/impl/GenericMessage.java b/nostr-java-event/src/main/java/nostr/event/impl/GenericMessage.java index c0dfa62c..0cfe96f5 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/GenericMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/GenericMessage.java @@ -1,6 +1,7 @@ package nostr.event.impl; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.HashSet; import java.util.Set; import lombok.Data; @@ -15,6 +16,7 @@ @Data public class GenericMessage implements IGenericElement, IElement { + @JsonProperty private final String command; @JsonIgnore diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventDecoder.java index ca802b13..5d9aeb6a 100644 --- a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventDecoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventDecoder.java @@ -1,11 +1,12 @@ package nostr.event.json.codec; +import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; import lombok.Data; import nostr.base.IDecoder; -import nostr.event.BaseEvent; +import nostr.event.impl.GenericEvent; import nostr.util.NostrException; /** @@ -14,16 +15,16 @@ */ @Data @AllArgsConstructor -public class BaseEventDecoder implements IDecoder { +public class BaseEventDecoder implements IDecoder { private final String jsonEvent; - + @Override - public BaseEvent decode() throws NostrException { + public GenericEvent decode() throws NostrException { try { - ObjectMapper objectMapper = new ObjectMapper(); - BaseEvent event = objectMapper.readValue(jsonEvent, BaseEvent.class); - return event; + var mapper = new ObjectMapper(); + mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + return mapper.readValue(jsonEvent, GenericEvent.class); } catch (JsonProcessingException ex) { throw new NostrException(ex); } diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageDecoder.java new file mode 100644 index 00000000..2627dca8 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageDecoder.java @@ -0,0 +1,109 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Data; +import nostr.base.Command; +import nostr.base.IDecoder; +import nostr.event.impl.ClientAuthenticationEvent; +import nostr.event.impl.Filters; +import nostr.event.impl.GenericEvent; +import nostr.event.impl.GenericMessage; +import nostr.event.message.BaseAuthMessage; +import nostr.event.message.ClientAuthenticationMessage; +import nostr.event.message.CloseMessage; +import nostr.event.message.EoseMessage; +import nostr.event.message.EventMessage; +import nostr.event.message.NoticeMessage; +import nostr.event.message.OkMessage; +import nostr.event.message.RelayAuthMessage; +import nostr.event.message.ReqMessage; +import nostr.util.NostrException; + +/** + * + * @author eric + */ +@Data +@AllArgsConstructor +public class BaseMessageDecoder implements IDecoder { + + private final String jsonString; + + @Override + public GenericMessage decode() throws NostrException { + try { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + var msgArr = mapper.readValue(jsonString, Object[].class); + final String strCmd = msgArr[0].toString(); + final Command command = Command.valueOf(strCmd); + final Object arg = msgArr[1]; + GenericMessage message = null; + + if (arg == null) { + throw new AssertionError("arg == null"); + } + + switch (command) { + case AUTH -> { + final BaseAuthMessage authMsg; + // Client Auth + if (arg instanceof Map map) { + var event = mapper.convertValue(map, new TypeReference() { + }); + authMsg = new ClientAuthenticationMessage(event); + } else { + // Relay Auth + final var challenge = arg.toString(); + authMsg = new RelayAuthMessage(challenge); + } + message = authMsg; + } + case CLOSE -> + message = new CloseMessage(arg.toString()); + case EOSE -> + message = new EoseMessage(arg.toString()); + case EVENT -> { + if (arg instanceof Map map) { + var event = mapper.convertValue(map, new TypeReference() { + }); + message = new EventMessage(event); + } else { + throw new AssertionError("Invalid argument: " + arg); + } + } + case NOTICE -> + message = new NoticeMessage(arg.toString()); + case OK -> { + //Boolean duplicate = (Boolean) msgArr[2]; + if (msgArr[2] instanceof Boolean duplicate) { + String msgArg = msgArr[3].toString(); + message = new OkMessage(arg.toString(), duplicate, msgArg); + } else { + throw new AssertionError("Invalid argument: " + msgArr[2]); + } + } + case REQ -> { + if (arg instanceof Map map) { + var filters = mapper.convertValue(map, new TypeReference() { + }); + message = new ReqMessage(arg.toString(), filters); + } else { + throw new AssertionError("Invalid argument: " + msgArr[2]); + } + } + default -> + throw new AssertionError("Invalid command " + strCmd); + } + return message; + } catch (JsonProcessingException ex) { + throw new NostrException(ex); + } + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/FilterEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/FilterEncoder.java index c5f5ad2f..c221f868 100644 --- a/nostr-java-event/src/main/java/nostr/event/json/codec/FilterEncoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/FilterEncoder.java @@ -9,12 +9,8 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; -import nostr.base.GenericTagQuery; -import nostr.base.IEncoder; import nostr.base.Relay; import nostr.event.impl.Filters; import nostr.util.NostrException; diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/FiltersDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/FiltersDecoder.java new file mode 100644 index 00000000..1ad09859 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/FiltersDecoder.java @@ -0,0 +1,31 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import nostr.base.IDecoder; +import nostr.event.impl.Filters; +import nostr.util.NostrException; + +/** + * + * @author eric + */ +@Data +@AllArgsConstructor +public class FiltersDecoder implements IDecoder { + + private final String jsonString; + + @Override + public Filters decode() throws NostrException { + try { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(jsonString, Filters.class); + } catch (JsonProcessingException ex) { + throw new NostrException(ex); + } + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java index d43e318b..1873b258 100644 --- a/nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java @@ -6,10 +6,11 @@ import nostr.base.Relay; import nostr.event.impl.GenericMessage; -import nostr.event.message.AuthMessage; +import nostr.event.message.ClientAuthenticationMessage; import nostr.event.message.CloseMessage; import nostr.event.message.EventMessage; import nostr.event.message.NoticeMessage; +import nostr.event.message.RelayAuthMessage; import nostr.event.message.ReqMessage; import nostr.util.NostrException; @@ -41,8 +42,10 @@ public String encode() throws NostrException { arrayNode.add(msg.getMessage()); } else if (message instanceof CloseMessage msg) { arrayNode.add(msg.getSubscriptionId()); - } else if (message instanceof AuthMessage msg) { + } else if (message instanceof ClientAuthenticationMessage msg) { arrayNode.add(msg.getEvent().toString()); + } else if (message instanceof RelayAuthMessage msg){ + arrayNode.add(msg.getChallenge()); } else { throw new NostrException(String.format("Invalid message type %s", message)); } diff --git a/nostr-java-event/src/main/java/nostr/event/message/BaseAuthMessage.java b/nostr-java-event/src/main/java/nostr/event/message/BaseAuthMessage.java new file mode 100644 index 00000000..3fd87891 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/message/BaseAuthMessage.java @@ -0,0 +1,15 @@ +package nostr.event.message; + +import nostr.event.impl.GenericMessage; + +/** + * + * @author eric + */ +public abstract class BaseAuthMessage extends GenericMessage { + + public BaseAuthMessage(String command) { + super(command); + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/message/ClientAuthenticationMessage.java b/nostr-java-event/src/main/java/nostr/event/message/ClientAuthenticationMessage.java new file mode 100644 index 00000000..de086748 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/message/ClientAuthenticationMessage.java @@ -0,0 +1,30 @@ + +package nostr.event.message; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import nostr.base.Command; +import nostr.base.IEvent; +import nostr.event.impl.ClientAuthenticationEvent; +import nostr.event.impl.GenericMessage; + +/** + * + * @author eric + */ +@Data +@EqualsAndHashCode(callSuper = false) +@ToString(callSuper = true) +public class ClientAuthenticationMessage extends BaseAuthMessage { + + @JsonProperty + private final ClientAuthenticationEvent event; + + public ClientAuthenticationMessage(ClientAuthenticationEvent event) { + super(Command.AUTH.name()); + this.event = event; + } + +} \ No newline at end of file diff --git a/nostr-java-event/src/main/java/nostr/event/message/CloseMessage.java b/nostr-java-event/src/main/java/nostr/event/message/CloseMessage.java index b4f5682a..a476a1df 100644 --- a/nostr-java-event/src/main/java/nostr/event/message/CloseMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/CloseMessage.java @@ -5,6 +5,7 @@ */ package nostr.event.message; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -20,6 +21,7 @@ @ToString(callSuper = true) public class CloseMessage extends GenericMessage { + @JsonProperty private final String subscriptionId; public CloseMessage(String subscriptionId) { diff --git a/nostr-java-event/src/main/java/nostr/event/message/EoseMessage.java b/nostr-java-event/src/main/java/nostr/event/message/EoseMessage.java index 37ea2665..154b6e09 100644 --- a/nostr-java-event/src/main/java/nostr/event/message/EoseMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/EoseMessage.java @@ -1,6 +1,7 @@ package nostr.event.message; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -16,6 +17,7 @@ @ToString(callSuper = true) public class EoseMessage extends GenericMessage { + @JsonProperty private final String subscriptionId; public EoseMessage(String subId) { diff --git a/nostr-java-event/src/main/java/nostr/event/message/EventMessage.java b/nostr-java-event/src/main/java/nostr/event/message/EventMessage.java index 1e3d64d2..7d9474d5 100644 --- a/nostr-java-event/src/main/java/nostr/event/message/EventMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/EventMessage.java @@ -1,6 +1,7 @@ package nostr.event.message; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NonNull; @@ -18,6 +19,7 @@ @ToString(callSuper = true) public class EventMessage extends GenericMessage { + @JsonProperty private final IEvent event; public EventMessage(@NonNull IEvent event) { diff --git a/nostr-java-event/src/main/java/nostr/event/message/NoticeMessage.java b/nostr-java-event/src/main/java/nostr/event/message/NoticeMessage.java index 7af544db..908904cf 100644 --- a/nostr-java-event/src/main/java/nostr/event/message/NoticeMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/NoticeMessage.java @@ -1,6 +1,7 @@ package nostr.event.message; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -16,6 +17,7 @@ @ToString(callSuper = true) public class NoticeMessage extends GenericMessage { + @JsonProperty private final String message; public NoticeMessage(String message) { diff --git a/nostr-java-event/src/main/java/nostr/event/message/OkMessage.java b/nostr-java-event/src/main/java/nostr/event/message/OkMessage.java index 4f9446e2..acf1b0a2 100644 --- a/nostr-java-event/src/main/java/nostr/event/message/OkMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/OkMessage.java @@ -1,6 +1,7 @@ package nostr.event.message; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -16,8 +17,13 @@ @ToString public class OkMessage extends GenericMessage { + @JsonProperty private final String eventId; + + @JsonProperty private final Boolean flag; + + @JsonProperty private final String message; public OkMessage(String eventId, Boolean flag, String message) { diff --git a/nostr-java-event/src/main/java/nostr/event/message/AuthMessage.java b/nostr-java-event/src/main/java/nostr/event/message/RelayAuthMessage.java similarity index 55% rename from nostr-java-event/src/main/java/nostr/event/message/AuthMessage.java rename to nostr-java-event/src/main/java/nostr/event/message/RelayAuthMessage.java index 548e6971..47fd1cfd 100644 --- a/nostr-java-event/src/main/java/nostr/event/message/AuthMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/RelayAuthMessage.java @@ -1,11 +1,10 @@ - package nostr.event.message; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; import nostr.base.Command; -import nostr.base.IEvent; import nostr.event.impl.GenericMessage; /** @@ -15,13 +14,14 @@ @Data @EqualsAndHashCode(callSuper = false) @ToString(callSuper = true) -public class AuthMessage extends GenericMessage { +public class RelayAuthMessage extends BaseAuthMessage { + + @JsonProperty + private final String challenge; - private final IEvent event; - - public AuthMessage(IEvent event) { + public RelayAuthMessage(String challenge) { super(Command.AUTH.name()); - this.event = event; + this.challenge = challenge; } - -} \ No newline at end of file + +} diff --git a/nostr-java-event/src/main/java/nostr/event/message/ReqMessage.java b/nostr-java-event/src/main/java/nostr/event/message/ReqMessage.java index 148cc9cb..83a501f1 100644 --- a/nostr-java-event/src/main/java/nostr/event/message/ReqMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/ReqMessage.java @@ -1,6 +1,7 @@ package nostr.event.message; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -17,7 +18,10 @@ @ToString(callSuper = true) public class ReqMessage extends GenericMessage { + @JsonProperty private final String subscriptionId; + + @JsonProperty private final Filters filters; public ReqMessage(String subscriptionId, Filters filters) { diff --git a/nostr-java-id/src/main/java/nostr/id/Client.java b/nostr-java-id/src/main/java/nostr/id/Client.java index 07f6cced..7a3de33d 100644 --- a/nostr-java-id/src/main/java/nostr/id/Client.java +++ b/nostr-java-id/src/main/java/nostr/id/Client.java @@ -21,9 +21,8 @@ import nostr.util.AbstractBaseConfiguration; import nostr.base.Relay; import nostr.event.impl.ClientAuthenticationEvent; -import nostr.event.impl.GenericEvent; import nostr.event.impl.GenericMessage; -import nostr.event.message.AuthMessage; +import nostr.event.message.ClientAuthenticationMessage; import nostr.util.NostrException; import nostr.ws.Connection; import nostr.ws.handler.spi.IRequestHandler; @@ -123,8 +122,8 @@ public void auth(Identity identity, String challenge) throws NostrException { log.log(Level.INFO, "Authenticating..."); Set relays = getRelaySet(); - GenericEvent event = new ClientAuthenticationEvent(identity.getPublicKey(), challenge, relays); - GenericMessage authMsg = new AuthMessage(event); + var event = new ClientAuthenticationEvent(identity.getPublicKey(), challenge, relays); + GenericMessage authMsg = new ClientAuthenticationMessage(event); identity.sign(event); this.send(authMsg); @@ -133,8 +132,8 @@ public void auth(Identity identity, String challenge) throws NostrException { public void auth(Identity identity, String challenge, Relay relay) throws NostrException { log.log(Level.INFO, "Authenticating..."); - GenericEvent event = new ClientAuthenticationEvent(identity.getPublicKey(), challenge, relay); - GenericMessage authMsg = new AuthMessage(event); + var event = new ClientAuthenticationEvent(identity.getPublicKey(), challenge, relay); + GenericMessage authMsg = new ClientAuthenticationMessage(event); identity.sign(event); this.send(authMsg); diff --git a/nostr-java-test/src/test/java/nostr/test/id/ClientTest.java b/nostr-java-test/src/test/java/nostr/test/id/ClientTest.java index 63ff09a7..05dee8f2 100644 --- a/nostr-java-test/src/test/java/nostr/test/id/ClientTest.java +++ b/nostr-java-test/src/test/java/nostr/test/id/ClientTest.java @@ -1,7 +1,6 @@ package nostr.test.id; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; diff --git a/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java b/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java new file mode 100644 index 00000000..67dd4e1f --- /dev/null +++ b/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java @@ -0,0 +1,42 @@ +package nostr.test.json; + +import nostr.base.Command; +import nostr.event.impl.GenericEvent; +import nostr.event.json.codec.BaseMessageDecoder; +import nostr.event.message.EventMessage; +import nostr.util.NostrException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * + * @author eric + */ +public class JsonParseTest { + + @Test + public void issue39() throws NostrException { + System.out.println("issue39"); + + final String parseTarget + = "[\"EVENT\"," + + "{" + + "\"content\":\"直んないわ。まあええか\"," + + "\"created_at\":1686199583," + + "\"id\":\"fc7f200c5bed175702bd06c7ca5dba90d3497e827350b42fc99c3a4fa276a712\"," + + "\"kind\":1," + + "\"pubkey\":\"8c59239319637f97e007dad0d681e65ce35b1ace333b629e2d33f9465c132608\"," + + "\"sig\":\"9584afd231c52fcbcec6ce668a2cc4b6dc9b4d9da20510dcb9005c6844679b4844edb7a2e1e0591958b0295241567c774dbf7d39a73932877542de1a5f963f4b\"," + + "\"tags\":[]" + + "}]"; + + final var message = new BaseMessageDecoder(parseTarget).decode(); + + Assertions.assertEquals(Command.EVENT.toString(), message.getCommand()); + + final var event = (GenericEvent) (((EventMessage) message).getEvent()); + Assertions.assertEquals(1, event.getKind().intValue()); + Assertions.assertEquals(1686199583, event.getCreatedAt().longValue()); + Assertions.assertEquals("fc7f200c5bed175702bd06c7ca5dba90d3497e827350b42fc99c3a4fa276a712", event.getId()); + } +} From 63f1a2c20712cac324e7d17e054b1e94fd0aeb5b Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 22 Jun 2023 03:54:59 +0100 Subject: [PATCH 15/37] Fixed issue #39 --- .../event/json/codec/BaseMessageDecoder.java | 17 ++-- .../event/json/codec/MessageEncoder.java | 4 +- .../nostr/event/message/EventMessage.java | 8 ++ ...e.java => RelayAuthenticationMessage.java} | 5 +- .../java/nostr/test/json/JsonParseTest.java | 2 + .../src/main/java/module-info.java | 1 + .../handler/provider/ResponseHandlerImpl.java | 84 +++++++++++-------- 7 files changed, 77 insertions(+), 44 deletions(-) rename nostr-java-event/src/main/java/nostr/event/message/{RelayAuthMessage.java => RelayAuthenticationMessage.java} (74%) diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageDecoder.java index 2627dca8..83ae0126 100644 --- a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageDecoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageDecoder.java @@ -20,7 +20,7 @@ import nostr.event.message.EventMessage; import nostr.event.message.NoticeMessage; import nostr.event.message.OkMessage; -import nostr.event.message.RelayAuthMessage; +import nostr.event.message.RelayAuthenticationMessage; import nostr.event.message.ReqMessage; import nostr.util.NostrException; @@ -60,7 +60,7 @@ public GenericMessage decode() throws NostrException { } else { // Relay Auth final var challenge = arg.toString(); - authMsg = new RelayAuthMessage(challenge); + authMsg = new RelayAuthenticationMessage(challenge); } message = authMsg; } @@ -69,10 +69,17 @@ public GenericMessage decode() throws NostrException { case EOSE -> message = new EoseMessage(arg.toString()); case EVENT -> { - if (arg instanceof Map map) { + if (msgArr.length == 2 && arg instanceof Map map) { var event = mapper.convertValue(map, new TypeReference() { }); message = new EventMessage(event); + } else if (msgArr.length == 3 && arg instanceof String) { + var subId = arg.toString(); + if (msgArr[2] instanceof Map map) { + var event = mapper.convertValue(map, new TypeReference() { + }); + message = new EventMessage(event, subId); + } } else { throw new AssertionError("Invalid argument: " + arg); } @@ -80,14 +87,14 @@ public GenericMessage decode() throws NostrException { case NOTICE -> message = new NoticeMessage(arg.toString()); case OK -> { - //Boolean duplicate = (Boolean) msgArr[2]; - if (msgArr[2] instanceof Boolean duplicate) { + if (msgArr.length == 4 && msgArr[2] instanceof Boolean duplicate) { String msgArg = msgArr[3].toString(); message = new OkMessage(arg.toString(), duplicate, msgArg); } else { throw new AssertionError("Invalid argument: " + msgArr[2]); } } + // TODO - Cater for more than one filters. Create issue in Github case REQ -> { if (arg instanceof Map map) { var filters = mapper.convertValue(map, new TypeReference() { diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java index 1873b258..3d22b01a 100644 --- a/nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/MessageEncoder.java @@ -10,7 +10,7 @@ import nostr.event.message.CloseMessage; import nostr.event.message.EventMessage; import nostr.event.message.NoticeMessage; -import nostr.event.message.RelayAuthMessage; +import nostr.event.message.RelayAuthenticationMessage; import nostr.event.message.ReqMessage; import nostr.util.NostrException; @@ -44,7 +44,7 @@ public String encode() throws NostrException { arrayNode.add(msg.getSubscriptionId()); } else if (message instanceof ClientAuthenticationMessage msg) { arrayNode.add(msg.getEvent().toString()); - } else if (message instanceof RelayAuthMessage msg){ + } else if (message instanceof RelayAuthenticationMessage msg){ arrayNode.add(msg.getChallenge()); } else { throw new NostrException(String.format("Invalid message type %s", message)); diff --git a/nostr-java-event/src/main/java/nostr/event/message/EventMessage.java b/nostr-java-event/src/main/java/nostr/event/message/EventMessage.java index 7d9474d5..22af0644 100644 --- a/nostr-java-event/src/main/java/nostr/event/message/EventMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/EventMessage.java @@ -21,9 +21,17 @@ public class EventMessage extends GenericMessage { @JsonProperty private final IEvent event; + + @JsonProperty + private String subscriptionId; public EventMessage(@NonNull IEvent event) { + this(event, null); + } + + public EventMessage(@NonNull IEvent event, String subscriptionId) { super(Command.EVENT.name()); this.event = event; + this.subscriptionId = subscriptionId; } } diff --git a/nostr-java-event/src/main/java/nostr/event/message/RelayAuthMessage.java b/nostr-java-event/src/main/java/nostr/event/message/RelayAuthenticationMessage.java similarity index 74% rename from nostr-java-event/src/main/java/nostr/event/message/RelayAuthMessage.java rename to nostr-java-event/src/main/java/nostr/event/message/RelayAuthenticationMessage.java index 47fd1cfd..8ffb0fca 100644 --- a/nostr-java-event/src/main/java/nostr/event/message/RelayAuthMessage.java +++ b/nostr-java-event/src/main/java/nostr/event/message/RelayAuthenticationMessage.java @@ -5,7 +5,6 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import nostr.base.Command; -import nostr.event.impl.GenericMessage; /** * @@ -14,12 +13,12 @@ @Data @EqualsAndHashCode(callSuper = false) @ToString(callSuper = true) -public class RelayAuthMessage extends BaseAuthMessage { +public class RelayAuthenticationMessage extends BaseAuthMessage { @JsonProperty private final String challenge; - public RelayAuthMessage(String challenge) { + public RelayAuthenticationMessage(String challenge) { super(Command.AUTH.name()); this.challenge = challenge; } diff --git a/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java b/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java index 67dd4e1f..ca58156c 100644 --- a/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java +++ b/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java @@ -20,6 +20,7 @@ public void issue39() throws NostrException { final String parseTarget = "[\"EVENT\"," + + "\"npub17x6pn22ukq3n5yw5x9prksdyyu6ww9jle2ckpqwdprh3ey8qhe6stnpujh\"," + "{" + "\"content\":\"直んないわ。まあええか\"," + "\"created_at\":1686199583," @@ -35,6 +36,7 @@ public void issue39() throws NostrException { Assertions.assertEquals(Command.EVENT.toString(), message.getCommand()); final var event = (GenericEvent) (((EventMessage) message).getEvent()); + Assertions.assertEquals("npub17x6pn22ukq3n5yw5x9prksdyyu6ww9jle2ckpqwdprh3ey8qhe6stnpujh", ((EventMessage) message).getSubscriptionId()); Assertions.assertEquals(1, event.getKind().intValue()); Assertions.assertEquals(1686199583, event.getCreatedAt().longValue()); Assertions.assertEquals("fc7f200c5bed175702bd06c7ca5dba90d3497e827350b42fc99c3a4fa276a712", event.getId()); diff --git a/nostr-java-ws-response-handler-provider/src/main/java/module-info.java b/nostr-java-ws-response-handler-provider/src/main/java/module-info.java index 514d2794..3e27b5bc 100644 --- a/nostr-java-ws-response-handler-provider/src/main/java/module-info.java +++ b/nostr-java-ws-response-handler-provider/src/main/java/module-info.java @@ -8,6 +8,7 @@ requires nostr.util; requires nostr.base; requires nostr.crypto; + requires nostr.event; requires com.fasterxml.jackson.databind; requires com.fasterxml.jackson.annotation; diff --git a/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java index 2f47429a..2afe41ab 100644 --- a/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java +++ b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java @@ -8,10 +8,19 @@ import java.util.NoSuchElementException; import java.util.ServiceLoader; import java.util.logging.Level; +import java.util.logging.Logger; import lombok.Data; import lombok.extern.java.Log; import nostr.base.Relay; import nostr.base.annotation.DefaultHandler; +import nostr.event.impl.GenericMessage; +import nostr.event.json.codec.BaseMessageDecoder; +import nostr.event.message.ClientAuthenticationMessage; +import nostr.event.message.EoseMessage; +import nostr.event.message.EventMessage; +import nostr.event.message.NoticeMessage; +import nostr.event.message.OkMessage; +import nostr.event.message.RelayAuthenticationMessage; import nostr.util.NostrException; import nostr.ws.handler.command.spi.ICommandHandler; import nostr.ws.handler.command.spi.ICommandHandler.Reason; @@ -55,61 +64,68 @@ public void process(String message, Relay relay) throws NostrException { log.log(Level.INFO, "Process Message: {0} from relay: {1}", new Object[]{message, relay}); - Object[] items = unmarshall(message); - final String command = items[0].toString(); + var oMsg = new BaseMessageDecoder(message).decode(); + final String command = oMsg.getCommand(); switch (command) { case "EOSE" -> { - var subId = items[1].toString(); - commandHandler.onEose(subId, relay); + if (oMsg instanceof EoseMessage msg) { + commandHandler.onEose(msg.getSubscriptionId(), relay); + } else { + throw new AssertionError(); + } } case "OK" -> { - String eventId = items[1].toString(); - boolean result = Boolean.parseBoolean(items[2].toString()); - String msg = items[3].toString(); - final var msgSplit = msg.split(":", 2); - Reason reason; - String reasonMessage = msg; - if (msgSplit.length < 2) { - reason = Reason.UNDEFINED; + if (oMsg instanceof OkMessage msg) { + String eventId = msg.getEventId(); + boolean result = msg.getFlag(); + String strMsg = msg.getMessage(); + final var msgSplit = strMsg.split(":", 2); + Reason reason; + String reasonMessage = strMsg; + if (msgSplit.length < 2) { + reason = Reason.UNDEFINED; + } else { + reason = Reason.fromCode(msgSplit[0]).orElseThrow(RuntimeException::new); + reasonMessage = msgSplit[1]; + } + + commandHandler.onOk(eventId, reasonMessage, reason, result, relay); } else { - reason = Reason.fromCode(msgSplit[0]).orElseThrow(RuntimeException::new); - reasonMessage = msgSplit[1]; + throw new AssertionError(); } - - commandHandler.onOk(eventId, reasonMessage, reason, result, relay); } case "NOTICE" -> { - var param = items[1].toString(); - commandHandler.onNotice(param); + if (oMsg instanceof NoticeMessage msg) { + commandHandler.onNotice(msg.getMessage()); + } else { + throw new AssertionError(); + } } case "EVENT" -> { - try { - var subId = items[1].toString(); - var jsonEvent = new ObjectMapper().writeValueAsString(items[2]); + if (oMsg instanceof EventMessage msg) { + var subId = msg.getSubscriptionId(); + var jsonEvent = msg.getEvent().toString(); commandHandler.onEvent(jsonEvent, subId, relay); - } catch (JsonProcessingException ex) { - throw new RuntimeException(ex); + } else { + throw new AssertionError(); } } case "AUTH" -> { - var challenge = items[1].toString(); + if (oMsg instanceof RelayAuthenticationMessage msg) { + var challenge = msg.getChallenge(); + commandHandler.onAuth(challenge, relay); + } else if (oMsg instanceof ClientAuthenticationMessage msg) { + // Actually, do nothing! + } else { + throw new AssertionError(); + } - commandHandler.onAuth(challenge, relay); } default -> { throw new AssertionError(); } } } - - private Object[] unmarshall(String jsonString) { - try { - ObjectMapper mapper = new ObjectMapper(); - return mapper.readValue(jsonString, Object[].class); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } } From b09a7fbdcee038617077a944906b5df4aa43b22a Mon Sep 17 00:00:00 2001 From: tcheeric Date: Thu, 22 Jun 2023 03:59:59 +0100 Subject: [PATCH 16/37] Fixed issue #39 --- .../handler/provider/ResponseHandlerImpl.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java index 2afe41ab..1ff2d1ba 100644 --- a/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java +++ b/nostr-java-ws-response-handler-provider/src/main/java/nostr/ws/response/handler/provider/ResponseHandlerImpl.java @@ -3,17 +3,13 @@ */ package nostr.ws.response.handler.provider; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.NoSuchElementException; import java.util.ServiceLoader; import java.util.logging.Level; -import java.util.logging.Logger; import lombok.Data; import lombok.extern.java.Log; import nostr.base.Relay; import nostr.base.annotation.DefaultHandler; -import nostr.event.impl.GenericMessage; import nostr.event.json.codec.BaseMessageDecoder; import nostr.event.message.ClientAuthenticationMessage; import nostr.event.message.EoseMessage; @@ -72,7 +68,7 @@ public void process(String message, Relay relay) throws NostrException { if (oMsg instanceof EoseMessage msg) { commandHandler.onEose(msg.getSubscriptionId(), relay); } else { - throw new AssertionError(); + throw new AssertionError("EOSE"); } } case "OK" -> { @@ -92,14 +88,14 @@ public void process(String message, Relay relay) throws NostrException { commandHandler.onOk(eventId, reasonMessage, reason, result, relay); } else { - throw new AssertionError(); + throw new AssertionError("OK"); } } case "NOTICE" -> { if (oMsg instanceof NoticeMessage msg) { commandHandler.onNotice(msg.getMessage()); } else { - throw new AssertionError(); + throw new AssertionError("NOTICE"); } } case "EVENT" -> { @@ -108,7 +104,7 @@ public void process(String message, Relay relay) throws NostrException { var jsonEvent = msg.getEvent().toString(); commandHandler.onEvent(jsonEvent, subId, relay); } else { - throw new AssertionError(); + throw new AssertionError("EVENT"); } } @@ -119,12 +115,12 @@ public void process(String message, Relay relay) throws NostrException { } else if (oMsg instanceof ClientAuthenticationMessage msg) { // Actually, do nothing! } else { - throw new AssertionError(); + throw new AssertionError("AUTH"); } } default -> { - throw new AssertionError(); + throw new AssertionError("Unknown command " + command); } } } From aa219e72ebc338988aadbe5ec4d7f64fd9a56fab Mon Sep 17 00:00:00 2001 From: tcheeric Date: Fri, 23 Jun 2023 00:50:42 +0100 Subject: [PATCH 17/37] Fixed issue #45 - Take two. --- .../src/main/java/nostr/base/UserProfile.java | 7 +- .../main/java/nostr/event/Nip05Content.java | 24 ++++++ .../event/json/codec/Nip05ContentDecoder.java | 29 +++++++ .../json/deserializer/TagDeserializer.java | 2 +- .../java/nostr/event/util/Nip05Validator.java | 75 ++++--------------- .../java/nostr/examples/NostrExamples.java | 4 +- .../main/java/nostr/test/EntityFactory.java | 2 +- .../test/java/nostr/test/event/EventTest.java | 2 +- .../provider/DefaultRequestHandler.java | 2 +- 9 files changed, 79 insertions(+), 68 deletions(-) create mode 100644 nostr-java-event/src/main/java/nostr/event/Nip05Content.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/Nip05ContentDecoder.java diff --git a/nostr-java-base/src/main/java/nostr/base/UserProfile.java b/nostr-java-base/src/main/java/nostr/base/UserProfile.java index 1f659517..caac4f1d 100644 --- a/nostr-java-base/src/main/java/nostr/base/UserProfile.java +++ b/nostr-java-base/src/main/java/nostr/base/UserProfile.java @@ -7,6 +7,7 @@ import java.util.logging.Level; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NonNull; import lombok.ToString; import lombok.extern.java.Log; import nostr.util.NostrException; @@ -22,10 +23,12 @@ public final class UserProfile extends Profile implements IBech32Encodable { private final PublicKey publicKey; + private final String nip05; - public UserProfile(PublicKey publicKey, String nip05, String about, URL picture) { - super(nip05, about, picture); + public UserProfile(@NonNull PublicKey publicKey, String name, String nip05, String about, URL picture) { + super(name, about, picture); this.publicKey = publicKey; + this.nip05 = nip05; } @Override diff --git a/nostr-java-event/src/main/java/nostr/event/Nip05Content.java b/nostr-java-event/src/main/java/nostr/event/Nip05Content.java new file mode 100644 index 00000000..21a65634 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/Nip05Content.java @@ -0,0 +1,24 @@ +package nostr.event; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import java.util.Map; +import lombok.Data; +import lombok.NoArgsConstructor; +import nostr.base.IElement; + +/** + * + * @author eric + */ +@Data +@NoArgsConstructor +public class Nip05Content implements IElement { + + @JsonProperty("names") + private Map names; + + @JsonProperty("relays") + private Map> relays; + +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/Nip05ContentDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/Nip05ContentDecoder.java new file mode 100644 index 00000000..8ce941b6 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/Nip05ContentDecoder.java @@ -0,0 +1,29 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import nostr.base.IDecoder; +import nostr.event.Nip05Content; +import nostr.util.NostrException; + +/** + * + * @author eric + */ +@Data +@AllArgsConstructor +public class Nip05ContentDecoder implements IDecoder { + + private final String jsonContent; + + @Override + public Nip05Content decode() throws NostrException { + try { + return new ObjectMapper().readValue(this.jsonContent, Nip05Content.class); + } catch (JsonProcessingException ex) { + throw new NostrException(ex); + } + } +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java b/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java index ba3a321b..9463c2c0 100644 --- a/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java +++ b/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java @@ -1,6 +1,5 @@ package nostr.event.json.deserializer; -import nostr.event.json.codec.GenericTagDecoder; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; @@ -10,6 +9,7 @@ import nostr.base.PublicKey; import nostr.event.BaseTag; import nostr.event.Marker; +import nostr.event.json.codec.GenericTagDecoder; import nostr.event.tag.EventTag; import nostr.event.tag.NonceTag; import nostr.event.tag.PubKeyTag; 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 6f7bdcf5..5ffce4f8 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 @@ -1,8 +1,5 @@ package nostr.event.util; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -10,13 +7,14 @@ import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; -import java.util.List; import java.util.Map; import java.util.logging.Level; import lombok.Builder; import lombok.Data; import lombok.extern.java.Log; import nostr.base.PublicKey; +import nostr.event.Nip05Content; +import nostr.event.json.codec.Nip05ContentDecoder; import nostr.util.NostrException; /** @@ -30,13 +28,15 @@ public class Nip05Validator { private final String nip05; private final PublicKey publicKey; + + private static final String LOCAL_PART_PATTERN = "^[a-zA-Z0-9-_\\.]+$"; public void validate() throws NostrException { if (this.nip05 != null) { var localPart = nip05.split("@")[0]; var domain = nip05.split("@")[1]; - if (!localPart.matches("^[-\\w.]+$")) { + if (!localPart.matches(LOCAL_PART_PATTERN)) { throw new NostrException("Invalid syntax in nip05 attribute."); } @@ -81,64 +81,19 @@ private void validatePublicKey(String domain, String localPart) throws Malformed throw new NostrException(String.format("Failed to connect to {0}. Error message: {1)", new Object[]{strUrl, connection.getResponseMessage()})); } - // TODO #30 - Use jackson - private String getPublicKey(StringBuilder content, String localPart) { - return Nip05Decoder.builder().jsonContent(content.toString()).build().getPublicKey(localPart).toString(); - } - - @Builder - private static class Nip05Decoder { + private String getPublicKey(StringBuilder content, String localPart) throws NostrException { - private final String jsonContent; + Nip05Content nip05Content = new Nip05ContentDecoder(content.toString()).decode(); - PublicKey getPublicKey(String localPart) { - try { - ObjectMapper objectMapper = new ObjectMapper(); - Content content = objectMapper.readValue(this.jsonContent, Content.class); - - // Access the decoded data - Map names = content.getNames(); - for (Map.Entry entry : names.entrySet()) { - String name = entry.getKey(); - String hash = entry.getValue(); - if (name.equals(localPart)) { - return new PublicKey(hash); - } - } - } catch (JsonProcessingException ex) { - throw new RuntimeException(ex); + // Access the decoded data + Map names = nip05Content.getNames(); + for (Map.Entry entry : names.entrySet()) { + String name = entry.getKey(); + String hash = entry.getValue(); + if (name.equals(localPart)) { + return hash; } - - return null; } - - List getRelays(String localPart) { - try { - ObjectMapper objectMapper = new ObjectMapper(); - Content content = objectMapper.readValue(this.jsonContent, Content.class); - - PublicKey pk = getPublicKey(localPart); - if (pk == null) { - return null; - } - - return content.getRelays().get(pk.toString()); - } catch (JsonProcessingException ex) { - throw new RuntimeException(ex); - } - } - - @Data - private static class Content { - - @JsonProperty("names") - private Map names; - - @JsonProperty("relays") - private Map> relays; - - } - + return null; } - } diff --git a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java index 5f7c3306..beebcafa 100644 --- a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java +++ b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java @@ -59,7 +59,7 @@ public class NostrExamples { private static final Identity RECEIVER = Identity.generateRandomIdentity(); private static final Identity SENDER = Identity.generateRandomIdentity(); - private static final UserProfile PROFILE = new UserProfile(SENDER.getPublicKey(), "erict875@nostr-java.io", "It's me!", null); + private static final UserProfile PROFILE = new UserProfile(SENDER.getPublicKey(), "erict875", "erict875@nostr-java.io", "It's me!", null); private final static Map RELAYS = Map.of("brb", "brb.io", "damus", "relay.damus.io", "ZBD", "nostr.zebedee.cloud", "taxi", "relay.taxi", "vision", "relay.nostr.vision"); @@ -77,7 +77,7 @@ public class NostrExamples { try { PROFILE.setPicture(new URL("https://images.unsplash.com/photo-1462888210965-cdf193fb74de")); } catch (MalformedURLException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } diff --git a/nostr-java-test/src/main/java/nostr/test/EntityFactory.java b/nostr-java-test/src/main/java/nostr/test/EntityFactory.java index a27054db..24c7d156 100644 --- a/nostr-java-test/src/main/java/nostr/test/EntityFactory.java +++ b/nostr-java-test/src/main/java/nostr/test/EntityFactory.java @@ -189,7 +189,7 @@ public static UserProfile createProfile(PublicKey pubKey) { String nip05 = name + "@tcheeric.com"; String url = "http://assets.tcheeric.com/" + number + ".PNG"; - return new UserProfile(pubKey, nip05, about, new URL(url)); + return new UserProfile(pubKey, name, nip05, about, new URL(url)); } catch (MalformedURLException ex) { throw new RuntimeException(ex); diff --git a/nostr-java-test/src/test/java/nostr/test/event/EventTest.java b/nostr-java-test/src/test/java/nostr/test/event/EventTest.java index 5dac09ad..4d78d0ac 100644 --- a/nostr-java-test/src/test/java/nostr/test/event/EventTest.java +++ b/nostr-java-test/src/test/java/nostr/test/event/EventTest.java @@ -14,10 +14,10 @@ import nostr.crypto.bech32.Bech32; import nostr.crypto.bech32.Bech32Prefix; import nostr.event.BaseTag; -import nostr.event.json.codec.ElementEncoder; import nostr.event.impl.GenericEvent; import nostr.event.impl.GenericMessage; import nostr.event.impl.GenericTag; +import nostr.event.json.codec.ElementEncoder; import nostr.event.util.Nip05Validator; import nostr.id.Identity; import nostr.test.EntityFactory; diff --git a/nostr-java-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java b/nostr-java-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java index 632d68c9..759fc228 100644 --- a/nostr-java-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java +++ b/nostr-java-ws-request-handler-provider/src/main/java/nostr/ws/request/handler/provider/DefaultRequestHandler.java @@ -11,8 +11,8 @@ import lombok.extern.java.Log; import nostr.base.Relay; import nostr.base.annotation.DefaultHandler; -import nostr.event.json.codec.MessageEncoder; import nostr.event.impl.GenericMessage; +import nostr.event.json.codec.MessageEncoder; import nostr.util.NostrException; import nostr.util.UnsupportedNIPException; import nostr.ws.Connection; From 01487b0a7d5f34700a7a07eb962e3ed3e772b357 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Sat, 24 Jun 2023 00:39:09 +0100 Subject: [PATCH 18/37] Unit tests --- .../java/nostr/event/impl/GenericTag.java | 1 - .../nostr/event/json/codec/TagDecoder.java | 31 +++++++++++ .../java/nostr/test/json/JsonParseTest.java | 52 ++++++++++++++++++- 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/TagDecoder.java diff --git a/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java b/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java index 5354aec9..3ebba7d6 100644 --- a/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java +++ b/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java @@ -30,7 +30,6 @@ public class GenericTag extends BaseTag implements IGenericElement { @EqualsAndHashCode.Exclude private final Integer nip; - //@JsonIgnore private final Set attributes; public GenericTag(String code) { diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/TagDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/TagDecoder.java new file mode 100644 index 00000000..febee513 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/TagDecoder.java @@ -0,0 +1,31 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import nostr.base.IDecoder; +import nostr.event.BaseTag; +import nostr.util.NostrException; + +/** + * + * @author eric + */ +@Data +@AllArgsConstructor +public class TagDecoder implements IDecoder { + + private final String jsonString; + + @Override + public BaseTag decode() throws NostrException { + try { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(jsonString, BaseTag.class); + } catch (JsonProcessingException ex) { + throw new NostrException(ex); + } + } + +} diff --git a/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java b/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java index ca58156c..a81386f6 100644 --- a/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java +++ b/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java @@ -1,9 +1,16 @@ package nostr.test.json; import nostr.base.Command; +import nostr.base.ElementAttribute; +import nostr.base.PublicKey; +import nostr.crypto.bech32.Bech32; import nostr.event.impl.GenericEvent; +import nostr.event.impl.GenericTag; import nostr.event.json.codec.BaseMessageDecoder; +import nostr.event.json.codec.GenericTagDecoder; +import nostr.event.json.codec.TagDecoder; import nostr.event.message.EventMessage; +import nostr.event.tag.PubKeyTag; import nostr.util.NostrException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -30,7 +37,7 @@ public void issue39() throws NostrException { + "\"sig\":\"9584afd231c52fcbcec6ce668a2cc4b6dc9b4d9da20510dcb9005c6844679b4844edb7a2e1e0591958b0295241567c774dbf7d39a73932877542de1a5f963f4b\"," + "\"tags\":[]" + "}]"; - + final var message = new BaseMessageDecoder(parseTarget).decode(); Assertions.assertEquals(Command.EVENT.toString(), message.getCommand()); @@ -41,4 +48,47 @@ public void issue39() throws NostrException { Assertions.assertEquals(1686199583, event.getCreatedAt().longValue()); Assertions.assertEquals("fc7f200c5bed175702bd06c7ca5dba90d3497e827350b42fc99c3a4fa276a712", event.getId()); } + + @Test + public void testGenericTagDecoder() throws NostrException { + System.out.println("testGenericTagDecoder"); + final String jsonString = "[\"saturn\", \"jetpack\", false]"; + + var tag = new GenericTagDecoder(jsonString).decode(); + + Assertions.assertEquals("saturn", tag.getCode()); + Assertions.assertEquals(2, tag.getAttributes().size()); + Assertions.assertEquals("jetpack", ((ElementAttribute) (tag.getAttributes().toArray())[1]).getValue()); + Assertions.assertEquals(false, Boolean.valueOf(((ElementAttribute) (tag.getAttributes().toArray())[1]).getValue().toString())); + } + + @Test + public void testDeserializeTag() throws NostrException { + System.out.println("testDeserializeTag"); + + String npubHex = new PublicKey(Bech32.decode("npub1clk6vc9xhjp8q5cws262wuf2eh4zuvwupft03hy4ttqqnm7e0jrq3upup9").data).toString(); + final String jsonString = "[\"p\", \"" + npubHex + "\", \"wss://nostr.java\", \"alice\"]"; + var tag = new TagDecoder(jsonString).decode(); + + Assertions.assertTrue(tag instanceof PubKeyTag); + + PubKeyTag pTag = (PubKeyTag) tag; + Assertions.assertEquals("wss://nostr.java", pTag.getMainRelayUrl()); + Assertions.assertEquals(npubHex, pTag.getPublicKey().toString()); + Assertions.assertEquals("alice", pTag.getPetName()); + } + + @Test + public void testDeserializeGenericTag() throws NostrException { + System.out.println("testDeserializeGenericTag"); + + String npubHex = new PublicKey(Bech32.decode("npub1clk6vc9xhjp8q5cws262wuf2eh4zuvwupft03hy4ttqqnm7e0jrq3upup9").data).toString(); + final String jsonString = "[\"gt\", \"" + npubHex + "\", \"wss://nostr.java\", \"alice\"]"; + var tag = new TagDecoder(jsonString).decode(); + + Assertions.assertTrue(tag instanceof GenericTag); + + GenericTag gTag = (GenericTag) tag; + Assertions.assertEquals("gt", gTag.getCode()); + } } From 41e7c7a5bdf9da722ae506a4862923c0bfdc0dc1 Mon Sep 17 00:00:00 2001 From: Memory-of-Snow Date: Tue, 27 Jun 2023 19:35:29 +0900 Subject: [PATCH 19/37] Make DecodeTest --- .../java/nostr/test/event/DecodeTest.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 nostr-java-test/src/test/java/nostr/test/event/DecodeTest.java diff --git a/nostr-java-test/src/test/java/nostr/test/event/DecodeTest.java b/nostr-java-test/src/test/java/nostr/test/event/DecodeTest.java new file mode 100644 index 00000000..52903ce7 --- /dev/null +++ b/nostr-java-test/src/test/java/nostr/test/event/DecodeTest.java @@ -0,0 +1,85 @@ +package nostr.test.event; + +import nostr.base.PublicKey; +import nostr.event.BaseTag; +import nostr.event.Marker; +import nostr.event.impl.GenericEvent; +import nostr.event.impl.GenericMessage; +import nostr.event.json.codec.BaseMessageDecoder; +import nostr.event.message.EventMessage; +import nostr.event.tag.EventTag; +import nostr.event.tag.PubKeyTag; +import nostr.util.NostrException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +public class DecodeTest { + @Test + public void decodeTest() throws NostrException { + + String json = "[" + + "\"EVENT\"," + + "\"temp20230627\"," + + "{" + + "\"id\":\"28f2fc030e335d061f0b9d03ce0e2c7d1253e6fadb15d89bd47379a96b2c861a\"," + + "\"kind\":1," + + "\"pubkey\":\"2bed79f81439ff794cf5ac5f7bff9121e257f399829e472c7a14d3e86fe76984\"," + + "\"created_at\":1687765220," + + "\"content\":\"手順書が間違ってたら作業者は無理だな\"," + + "\"tags\":[" + + "[\"e\",\"494001ac0c8af2a10f60f23538e5b35d3cdacb8e1cc956fe7a16dfa5cbfc4346\",\"\",\"root\"]," + + "[\"p\",\"2bed79f81439ff794cf5ac5f7bff9121e257f399829e472c7a14d3e86fe76984\"]" + + "]," + + "\"sig\":\"86f25c161fec51b9e441bdb2c09095d5f8b92fdce66cb80d9ef09fad6ce53eaa14c5e16787c42f5404905536e43ebec0e463aee819378a4acbe412c533e60546\"" + + "}]"; + + BaseMessageDecoder decoder = new BaseMessageDecoder(json); + GenericMessage message = decoder.decode(); + + Assertions.assertEquals("EVENT",message.getCommand()); + EventMessage eventMessage = (EventMessage) message; + + Assertions.assertEquals("temp20230627",eventMessage.getSubscriptionId()); + GenericEvent eventImpl = (GenericEvent)eventMessage.getEvent(); + + Assertions.assertEquals("28f2fc030e335d061f0b9d03ce0e2c7d1253e6fadb15d89bd47379a96b2c861a", eventImpl.getId()); + Assertions.assertEquals(1, eventImpl.getKind()); + Assertions.assertEquals("2bed79f81439ff794cf5ac5f7bff9121e257f399829e472c7a14d3e86fe76984", eventImpl.getPubKey().toString()); + Assertions.assertEquals(1687765220, eventImpl.getCreatedAt()); + Assertions.assertEquals("手順書が間違ってたら作業者は無理だな", eventImpl.getContent()); + Assertions.assertEquals("86f25c161fec51b9e441bdb2c09095d5f8b92fdce66cb80d9ef09fad6ce53eaa14c5e16787c42f5404905536e43ebec0e463aee819378a4acbe412c533e60546", + eventImpl.getSignature().toString()); + + + List expectedTags = new ArrayList<>(); + EventTag eventTag = new EventTag("494001ac0c8af2a10f60f23538e5b35d3cdacb8e1cc956fe7a16dfa5cbfc4346"); + eventTag.setRecommendedRelayUrl(""); + eventTag.setMarker(Marker.ROOT); + expectedTags.add(eventTag); + PubKeyTag pubKeyTag = new PubKeyTag(); + pubKeyTag.setPublicKey(new PublicKey("2bed79f81439ff794cf5ac5f7bff9121e257f399829e472c7a14d3e86fe76984")); + expectedTags.add(pubKeyTag); + + List actualTags = eventImpl.getTags(); + + for(int i =0; i < expectedTags.size();i++){ + BaseTag expected = expectedTags.get(i); + if (expected instanceof EventTag expetedEventTag){ + EventTag actualEventTag = (EventTag) actualTags.get(i); + Assertions.assertEquals(expetedEventTag.getIdEvent(),actualEventTag.getIdEvent()); + Assertions.assertEquals(expetedEventTag.getRecommendedRelayUrl(),actualEventTag.getRecommendedRelayUrl()); + Assertions.assertEquals(expetedEventTag.getMarker(),actualEventTag.getMarker()); + }else if (expected instanceof PubKeyTag expectedPublicKeyTag){ + PubKeyTag actualPublicKeyTag = (PubKeyTag) actualTags.get(i); + Assertions.assertEquals(expectedPublicKeyTag.getPublicKey().toString(),actualPublicKeyTag.getPublicKey().toString()); + }else{ + Assertions.fail(); + } + + } + + } + +} From c3edf3e4912963093bcefd5f3b835c9c9f84febb Mon Sep 17 00:00:00 2001 From: Memory-of-Snow Date: Tue, 27 Jun 2023 19:35:56 +0900 Subject: [PATCH 20/37] Change to setting the marker after converting the marker string to uppercase. --- .../java/nostr/event/json/deserializer/TagDeserializer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java b/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java index 9463c2c0..359fd6fa 100644 --- a/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java +++ b/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java @@ -83,7 +83,7 @@ public T deserialize(JsonParser jsonParser, DeserializationContext deserializati final JsonNode nodeMarker = node.get(3); if (nodeMarker != null) { - tag.setMarker(Marker.valueOf(nodeMarker.asText())); + tag.setMarker(Marker.valueOf(nodeMarker.asText().toUpperCase())); } return (T) tag; } From 6a89956294f6cfe23cc299f7e1b225f4bb4c1303 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Wed, 28 Jun 2023 00:26:48 +0100 Subject: [PATCH 21/37] When using the "e" tag on the "feature/feature_bug_fixes" branch, an exception occurs if the marker string is in lowercase. #49 --- .../java/nostr/event/json/deserializer/TagDeserializer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java b/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java index 9463c2c0..43c0a279 100644 --- a/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java +++ b/nostr-java-event/src/main/java/nostr/event/json/deserializer/TagDeserializer.java @@ -83,7 +83,7 @@ public T deserialize(JsonParser jsonParser, DeserializationContext deserializati final JsonNode nodeMarker = node.get(3); if (nodeMarker != null) { - tag.setMarker(Marker.valueOf(nodeMarker.asText())); + tag.setMarker(nodeMarker.asText()); } return (T) tag; } From a3f1a90305582b77f36b96a2735b9013f0787d00 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Wed, 28 Jun 2023 00:26:57 +0100 Subject: [PATCH 22/37] When using the "e" tag on the "feature/feature_bug_fixes" branch, an exception occurs if the marker string is in lowercase. #49 --- .../src/main/java/nostr/event/Marker.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/nostr-java-event/src/main/java/nostr/event/Marker.java b/nostr-java-event/src/main/java/nostr/event/Marker.java index 4c6e1a3a..9e334023 100644 --- a/nostr-java-event/src/main/java/nostr/event/Marker.java +++ b/nostr-java-event/src/main/java/nostr/event/Marker.java @@ -1,4 +1,3 @@ - package nostr.event; /** @@ -8,14 +7,27 @@ public enum Marker { ROOT("root"), REPLY("reply"); - + private final String value; Marker(String value) { this.value = value; } - + public String getValue() { return value; } + + public static Marker fromValue(String value) { + if (value == null) { + return null; + } + if (value.equalsIgnoreCase("root")) { + return ROOT; + } else if (value.equalsIgnoreCase("reply")) { + return REPLY; + } else { + throw new IllegalArgumentException("Invalid marker value: " + value); + } + } } From 5cc2dd31ed15105a30d86d8ace65f83a0f89ad8c Mon Sep 17 00:00:00 2001 From: tcheeric Date: Wed, 28 Jun 2023 00:27:09 +0100 Subject: [PATCH 23/37] When using the "e" tag on the "feature/feature_bug_fixes" branch, an exception occurs if the marker string is in lowercase. #49 --- .../src/main/java/nostr/event/tag/EventTag.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nostr-java-event/src/main/java/nostr/event/tag/EventTag.java b/nostr-java-event/src/main/java/nostr/event/tag/EventTag.java index 106b3e17..dbb63bf1 100644 --- a/nostr-java-event/src/main/java/nostr/event/tag/EventTag.java +++ b/nostr-java-event/src/main/java/nostr/event/tag/EventTag.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonSetter; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -50,4 +51,9 @@ public EventTag(String idEvent) { this.idEvent = idEvent; this.marker = this.idEvent == null ? Marker.ROOT : Marker.REPLY; } + + @JsonSetter("marker") + public void setMarker(String marker) { + this.marker = Marker.fromValue(marker); + } } From b904f27234f87051d40ee866a352f11b77acbf47 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Wed, 28 Jun 2023 00:27:37 +0100 Subject: [PATCH 24/37] When using the "e" tag on the "feature/feature_bug_fixes" branch, an exception occurs if the marker string is in lowercase. #49 --- .../java/nostr/test/json/JsonParseTest.java | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java b/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java index a81386f6..867d9ed0 100644 --- a/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java +++ b/nostr-java-test/src/test/java/nostr/test/json/JsonParseTest.java @@ -4,12 +4,16 @@ import nostr.base.ElementAttribute; import nostr.base.PublicKey; import nostr.crypto.bech32.Bech32; +import nostr.event.BaseMessage; +import nostr.event.BaseTag; +import nostr.event.Marker; import nostr.event.impl.GenericEvent; import nostr.event.impl.GenericTag; import nostr.event.json.codec.BaseMessageDecoder; import nostr.event.json.codec.GenericTagDecoder; -import nostr.event.json.codec.TagDecoder; +import nostr.event.json.codec.BaseTagDecoder; import nostr.event.message.EventMessage; +import nostr.event.tag.EventTag; import nostr.event.tag.PubKeyTag; import nostr.util.NostrException; import org.junit.jupiter.api.Assertions; @@ -22,8 +26,8 @@ public class JsonParseTest { @Test - public void issue39() throws NostrException { - System.out.println("issue39"); + public void testBaseMessageDecoder() throws NostrException { + System.out.println("testBaseMessageDecoder"); final String parseTarget = "[\"EVENT\"," @@ -49,6 +53,39 @@ public void issue39() throws NostrException { Assertions.assertEquals("fc7f200c5bed175702bd06c7ca5dba90d3497e827350b42fc99c3a4fa276a712", event.getId()); } + @Test + public void testBaseMessageMarkerDecoder() throws NostrException { + System.out.println("testBaseMessageMarkerDecoder"); + + String json = "[" + + "\"EVENT\"," + + "\"temp20230627\"," + + "{" + + "\"id\":\"28f2fc030e335d061f0b9d03ce0e2c7d1253e6fadb15d89bd47379a96b2c861a\"," + + "\"kind\":1," + + "\"pubkey\":\"2bed79f81439ff794cf5ac5f7bff9121e257f399829e472c7a14d3e86fe76984\"," + + "\"created_at\":1687765220," + + "\"content\":\"手順書が間違ってたら作業者は無理だな\"," + + "\"tags\":[" + + "[\"e\",\"494001ac0c8af2a10f60f23538e5b35d3cdacb8e1cc956fe7a16dfa5cbfc4346\",\"\",\"root\"]," + + "[\"p\",\"2bed79f81439ff794cf5ac5f7bff9121e257f399829e472c7a14d3e86fe76984\"]" + + "]," + + "\"sig\":\"86f25c161fec51b9e441bdb2c09095d5f8b92fdce66cb80d9ef09fad6ce53eaa14c5e16787c42f5404905536e43ebec0e463aee819378a4acbe412c533e60546\"" + + "}]"; + + BaseMessageDecoder decoder = new BaseMessageDecoder(json); + BaseMessage message = decoder.decode(); + + final var event = (GenericEvent) (((EventMessage) message).getEvent()); + var tags = event.getTags(); + for (BaseTag t : tags) { + if (t.getCode().equalsIgnoreCase("e")) { + EventTag et = (EventTag) t; + Assertions.assertEquals(Marker.ROOT, et.getMarker()); + } + } + } + @Test public void testGenericTagDecoder() throws NostrException { System.out.println("testGenericTagDecoder"); @@ -68,7 +105,7 @@ public void testDeserializeTag() throws NostrException { String npubHex = new PublicKey(Bech32.decode("npub1clk6vc9xhjp8q5cws262wuf2eh4zuvwupft03hy4ttqqnm7e0jrq3upup9").data).toString(); final String jsonString = "[\"p\", \"" + npubHex + "\", \"wss://nostr.java\", \"alice\"]"; - var tag = new TagDecoder(jsonString).decode(); + var tag = new BaseTagDecoder(jsonString).decode(); Assertions.assertTrue(tag instanceof PubKeyTag); @@ -84,7 +121,7 @@ public void testDeserializeGenericTag() throws NostrException { String npubHex = new PublicKey(Bech32.decode("npub1clk6vc9xhjp8q5cws262wuf2eh4zuvwupft03hy4ttqqnm7e0jrq3upup9").data).toString(); final String jsonString = "[\"gt\", \"" + npubHex + "\", \"wss://nostr.java\", \"alice\"]"; - var tag = new TagDecoder(jsonString).decode(); + var tag = new BaseTagDecoder(jsonString).decode(); Assertions.assertTrue(tag instanceof GenericTag); From a6ee219d095f6e35c599f7f6b74476d4f57bb17c Mon Sep 17 00:00:00 2001 From: tcheeric Date: Wed, 28 Jun 2023 01:05:06 +0100 Subject: [PATCH 25/37] jackson json lib integration (cont'd) --- .../event/json/codec/BaseEventEncoder.java | 59 +++++++++++++++++ .../event/json/codec/BaseMessageEncoder.java | 66 +++++++++++++++++++ .../event/json/codec/BaseTagDecoder.java | 31 +++++++++ .../event/json/codec/BaseTagEncoder.java | 46 +++++++++++++ .../event/json/codec/FiltersEncoder.java | 57 ++++++++++++++++ .../json/codec/GenericTagQueryDecoder.java | 24 +++++++ .../json/codec/GenericTagQueryEncoder.java | 38 +++++++++++ .../CustomGenericTagQueryDeserializer.java | 37 +++++++++++ ...CustomGenericTagQueryListDeserializer.java | 21 ++++++ .../CustomGenericTagQueryListSerializer.java | 54 +++++++++++++++ .../CustomGenericTagQuerySerializer.java | 55 ++++++++++++++++ 11 files changed, 488 insertions(+) create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventEncoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageEncoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/BaseTagDecoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/BaseTagEncoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/FiltersEncoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagQueryDecoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagQueryEncoder.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/deserializer/CustomGenericTagQueryDeserializer.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/deserializer/CustomGenericTagQueryListDeserializer.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagQueryListSerializer.java create mode 100644 nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagQuerySerializer.java 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 new file mode 100644 index 00000000..0d8655b2 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseEventEncoder.java @@ -0,0 +1,59 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.lang.reflect.Field; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.extern.java.Log; +import nostr.base.IElement; +import nostr.base.IEncoder; +import static nostr.base.IEncoder.MAPPER; +import nostr.base.NipUtil; +import nostr.base.Relay; +import nostr.event.BaseEvent; +import nostr.util.NostrException; +import nostr.util.UnsupportedNIPException; + +/** + * @author guilhermegps + * + */ +@AllArgsConstructor +@Log +@Data + public class BaseEventEncoder implements IEncoder { + + private final BaseEvent event; + private final Relay relay; + + public BaseEventEncoder(BaseEvent event) { + this(event, null); + } + + @Override + public String encode() throws UnsupportedNIPException, NostrException { + if (!nipEventSupport()) { + throw new UnsupportedNIPException("NIP is not supported by relay: \"" + relay.getName() + "\" - List of supported NIP(s): " + relay.printSupportedNips()); + } + + return toJson(); + } + + protected boolean nipFieldSupport(Field field) { + return (relay != null) ? NipUtil.checkSupport(relay, field) : true; + } + + protected String toJson() throws NostrException { + try { + return MAPPER.writeValueAsString(event); + } catch (JsonProcessingException e) { + throw new NostrException(e); + } + } + + private boolean nipEventSupport() { + return (relay != null) ? NipUtil.checkSupport(relay, event) : true; + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageEncoder.java new file mode 100644 index 00000000..7bab4a1f --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseMessageEncoder.java @@ -0,0 +1,66 @@ +package nostr.event.json.codec; + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import lombok.AllArgsConstructor; +import lombok.Data; +import nostr.base.IEncoder; +import static nostr.base.IEncoder.MAPPER; +import nostr.base.Relay; +import nostr.event.BaseEvent; +import nostr.event.BaseMessage; +import nostr.event.impl.GenericMessage; +import nostr.event.message.ClientAuthenticationMessage; +import nostr.event.message.CloseMessage; +import nostr.event.message.EventMessage; +import nostr.event.message.NoticeMessage; +import nostr.event.message.RelayAuthenticationMessage; +import nostr.event.message.ReqMessage; +import nostr.util.NostrException; + +/** + * + * @author squirrel + */ +@Data +@AllArgsConstructor +public class BaseMessageEncoder implements IEncoder { + + private final BaseMessage message; + private final Relay relay; + + @Override + public String encode() throws NostrException { + var arrayNode = JsonNodeFactory.instance.arrayNode(); + try { + arrayNode.add(message.getCommand()); + if (message instanceof EventMessage msg) { + JsonNode tree = MAPPER.readTree(new BaseEventEncoder((BaseEvent) msg.getEvent(), relay).encode()); + arrayNode.add(tree); + } else if (message instanceof ReqMessage msg) { + arrayNode.add(msg.getSubscriptionId()); + JsonNode tree = MAPPER.readTree(new BaseEventEncoder(msg.getFilters(), relay).encode()); + arrayNode.add(tree); + } else if (message instanceof NoticeMessage msg) { + arrayNode.add(msg.getMessage()); + } else if (message instanceof CloseMessage msg) { + arrayNode.add(msg.getSubscriptionId()); + } else if (message instanceof ClientAuthenticationMessage msg) { + arrayNode.add(msg.getEvent().toString()); + } else if (message instanceof RelayAuthenticationMessage msg){ + arrayNode.add(msg.getChallenge()); + } else if (message instanceof GenericMessage msg) { + arrayNode.add(msg.getCommand()); + msg.getAttributes().stream().map(a -> a.getValue()).forEach(v -> arrayNode.add(v.toString())); + } else { + throw new NostrException(String.format("Invalid message type %s", message)); + } + + return MAPPER.writeValueAsString(arrayNode); + } catch (JsonProcessingException e) { + throw new NostrException(e); + } + } +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseTagDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseTagDecoder.java new file mode 100644 index 00000000..ff60f76d --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseTagDecoder.java @@ -0,0 +1,31 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import nostr.base.IDecoder; +import nostr.event.BaseTag; +import nostr.util.NostrException; + +/** + * + * @author eric + */ +@Data +@AllArgsConstructor +public class BaseTagDecoder implements IDecoder { + + private final String jsonString; + + @Override + public BaseTag decode() throws NostrException { + try { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(jsonString, BaseTag.class); + } catch (JsonProcessingException ex) { + throw new NostrException(ex); + } + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/BaseTagEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseTagEncoder.java new file mode 100644 index 00000000..d517ac49 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/BaseTagEncoder.java @@ -0,0 +1,46 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import lombok.AllArgsConstructor; + +import lombok.Data; +import lombok.NonNull; +import nostr.base.IEncoder; +import nostr.base.Relay; +import nostr.event.BaseTag; +import nostr.event.json.serializer.TagSerializer; +import nostr.util.NostrException; + +/** + * @author guilhermegps + * + */ +@Data +@AllArgsConstructor +public class BaseTagEncoder implements IEncoder { + + private final BaseTag tag; + private final Relay relay; + + public BaseTagEncoder(@NonNull BaseTag tag) { + this(tag, null); + } + + @Override + public String encode() throws NostrException { + try { + SimpleModule module = new SimpleModule(); + module.addSerializer(new TagSerializer()); + var mapper = (new ObjectMapper()) + .setSerializationInclusion(Include.NON_NULL) + .registerModule(module); + + return mapper.writeValueAsString(tag); + } catch (JsonProcessingException e) { + throw new NostrException(e); + } + } +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/FiltersEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/FiltersEncoder.java new file mode 100644 index 00000000..0ef02a0f --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/FiltersEncoder.java @@ -0,0 +1,57 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.StreamSupport; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import nostr.base.Relay; +import nostr.event.impl.Filters; +import nostr.util.NostrException; + +/** + * @author guilhermegps + * + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class FiltersEncoder extends BaseEventEncoder { + + public FiltersEncoder(Filters filters, Relay relay) { + super(filters, relay); + } + + public FiltersEncoder(Filters filters) { + super(filters); + } + + @Override + protected String toJson() throws NostrException { + try { + JsonNode node = MAPPER.valueToTree((Filters) getEvent()); + ObjectNode objNode = (ObjectNode) node; + var arrayNode = (ArrayNode) node.get("genericTagQueryList"); + if (arrayNode != null && !arrayNode.isNull()) { + for (JsonNode jn : arrayNode) { + StreamSupport.stream( + Spliterators.spliteratorUnknownSize(jn.fields(), Spliterator.ORDERED), false) + .forEach(f -> { + objNode.set(f.getKey(), f.getValue()); + }); + } + } + objNode.remove("genericTagQueryList"); + + return MAPPER.writeValueAsString(node); + } catch (JsonProcessingException | IllegalArgumentException e) { + throw new NostrException(e); + } + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagQueryDecoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagQueryDecoder.java new file mode 100644 index 00000000..1748430d --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagQueryDecoder.java @@ -0,0 +1,24 @@ +package nostr.event.json.codec; + +import lombok.AllArgsConstructor; +import lombok.Data; +import nostr.base.GenericTagQuery; +import nostr.base.IDecoder; +import nostr.util.NostrException; + +/** + * + * @author eric + */ +@AllArgsConstructor +@Data +public class GenericTagQueryDecoder implements IDecoder { + + private final String json; + + @Override + public GenericTagQuery decode() throws NostrException { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagQueryEncoder.java b/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagQueryEncoder.java new file mode 100644 index 00000000..32522e98 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/codec/GenericTagQueryEncoder.java @@ -0,0 +1,38 @@ +package nostr.event.json.codec; + +import com.fasterxml.jackson.core.JsonProcessingException; +import lombok.AllArgsConstructor; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import nostr.base.IEncoder; +import static nostr.base.IEncoder.MAPPER; +import nostr.base.Relay; +import nostr.base.GenericTagQuery; +import nostr.util.NostrException; + +/** + * @author guilhermegps + * + */ +@Data +@EqualsAndHashCode(callSuper = false) +@AllArgsConstructor +public class GenericTagQueryEncoder implements IEncoder { + + private final GenericTagQuery genericTagQuery; + private final Relay relay; + + public GenericTagQueryEncoder(GenericTagQuery tag) { + this(tag, null); + } + + @Override + public String encode() throws NostrException { + try { + return MAPPER.writeValueAsString(genericTagQuery); + } catch (JsonProcessingException e) { + throw new NostrException(e); + } + } +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/deserializer/CustomGenericTagQueryDeserializer.java b/nostr-java-event/src/main/java/nostr/event/json/deserializer/CustomGenericTagQueryDeserializer.java new file mode 100644 index 00000000..f69c365c --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/deserializer/CustomGenericTagQueryDeserializer.java @@ -0,0 +1,37 @@ +package nostr.event.json.deserializer; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import nostr.base.GenericTagQuery; + +public class CustomGenericTagQueryDeserializer extends JsonDeserializer { + + @Override + public GenericTagQuery deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); + + var genericTagQuery = new GenericTagQuery(); + + Iterator> fields = rootNode.fields(); + if (fields.hasNext()) { + Map.Entry field = fields.next(); + String tagName = field.getKey(); + JsonNode valuesNode = field.getValue(); + List values = objectMapper.convertValue(valuesNode, ArrayList.class); + genericTagQuery.setTagName(tagName.charAt(1)); // Assuming tagName is always a single character preceded by '#' + genericTagQuery.setValue(values); + } + + return genericTagQuery; + } +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/deserializer/CustomGenericTagQueryListDeserializer.java b/nostr-java-event/src/main/java/nostr/event/json/deserializer/CustomGenericTagQueryListDeserializer.java new file mode 100644 index 00000000..e6b434bb --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/deserializer/CustomGenericTagQueryListDeserializer.java @@ -0,0 +1,21 @@ +package nostr.event.json.deserializer; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import java.io.IOException; +import nostr.event.list.GenericTagQueryList; + +/** + * + * @author eric + */ +public class CustomGenericTagQueryListDeserializer extends JsonDeserializer { + + @Override + public GenericTagQueryList deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagQueryListSerializer.java b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagQueryListSerializer.java new file mode 100644 index 00000000..6716a925 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagQueryListSerializer.java @@ -0,0 +1,54 @@ +package nostr.event.json.serializer; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import lombok.extern.java.Log; +import nostr.base.GenericTagQuery; +import nostr.base.IEncoder; +import nostr.event.list.GenericTagQueryList; + +/** + * @author guilhermegps + * + */ +@Log +public class CustomGenericTagQueryListSerializer extends JsonSerializer { + + @Override + public void serialize(GenericTagQueryList value, JsonGenerator gen, SerializerProvider serializers) { + try { + var list = value.getList().parallelStream().map(gtq -> toJson(gtq)) + .collect(Collectors.toList()); + + gen.writePOJO(list); + } catch (IOException e) { + log.log(Level.SEVERE, null, e); + throw new RuntimeException(e); + } + } + + private JsonNode toJson(GenericTagQuery gtq) { + var mapper = IEncoder.MAPPER; + try { + JsonNode node = mapper.valueToTree(gtq); + ObjectNode objNode = (ObjectNode) node; + objNode.set("#" + node.get("tagName").textValue(), node.get("value")); + objNode.remove("tagName"); + objNode.remove("value"); + + return node; + } catch (IllegalArgumentException e) { + log.log(Level.SEVERE, null, e); + throw new RuntimeException(e); + } + } + +} diff --git a/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagQuerySerializer.java b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagQuerySerializer.java new file mode 100644 index 00000000..3a5f6966 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/json/serializer/CustomGenericTagQuerySerializer.java @@ -0,0 +1,55 @@ +package nostr.event.json.serializer; + +import java.io.IOException; +import java.util.logging.Level; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +import lombok.extern.java.Log; +import nostr.base.GenericTagQuery; +import nostr.base.IEncoder; + +/** + * @author guilhermegps + * + */ +@Log +public class CustomGenericTagQuerySerializer extends StdSerializer { + + private static final long serialVersionUID = 6803478463890319884L; + + public CustomGenericTagQuerySerializer() { + super(GenericTagQuery.class); + } + + @Override + public void serialize(GenericTagQuery value, JsonGenerator gen, SerializerProvider serializers) { + try { + gen.writePOJO(toJson(value)); + } catch (IOException e) { + log.log(Level.SEVERE, null, e); + throw new RuntimeException(e); + } + } + + private static JsonNode toJson(GenericTagQuery gtq) { + var mapper = IEncoder.MAPPER; + try { + JsonNode node = mapper.valueToTree(gtq); + ObjectNode objNode = (ObjectNode) node; + objNode.set("#" + node.get("tagName").textValue(), node.get("value")); + objNode.remove("tagName"); + objNode.remove("value"); + + return node; + } catch (IllegalArgumentException e) { + log.log(Level.SEVERE, null, e); + throw new RuntimeException(e); + } + } + +} From c627df5f7c98ddfd82aa89dfa69de343b6f57f57 Mon Sep 17 00:00:00 2001 From: Memory-of-Snow Date: Fri, 30 Jun 2023 11:54:17 +0900 Subject: [PATCH 26/37] Add mention marker --- nostr-java-event/src/main/java/nostr/event/Marker.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nostr-java-event/src/main/java/nostr/event/Marker.java b/nostr-java-event/src/main/java/nostr/event/Marker.java index 1dade15a..3a067853 100644 --- a/nostr-java-event/src/main/java/nostr/event/Marker.java +++ b/nostr-java-event/src/main/java/nostr/event/Marker.java @@ -6,7 +6,8 @@ */ public enum Marker { ROOT("root"), - REPLY("reply"); + REPLY("reply"), + MENTION("mention"); private final String value; From a79024325d44062cca6cebed2f2cac3b7f96b815 Mon Sep 17 00:00:00 2001 From: Memory-of-Snow Date: Fri, 30 Jun 2023 12:00:50 +0900 Subject: [PATCH 27/37] Add repost kind --- nostr-java-event/src/main/java/nostr/event/Kind.java | 1 + 1 file changed, 1 insertion(+) diff --git a/nostr-java-event/src/main/java/nostr/event/Kind.java b/nostr-java-event/src/main/java/nostr/event/Kind.java index 0b98010b..7c0eb67d 100644 --- a/nostr-java-event/src/main/java/nostr/event/Kind.java +++ b/nostr-java-event/src/main/java/nostr/event/Kind.java @@ -18,6 +18,7 @@ public enum Kind { CONTACT_LIST(3, "contact_list"), ENCRYPTED_DIRECT_MESSAGE(4, "encrypted_direct_message"), DELETION(5, "deletion"), + REPOST(6,"repost"), REACTION(7, "reaction"), CHANNEL_CREATE(40, "channel_create"), CHANNEL_METADATA(41, "channel_metadata"), From 58dce0400b9c5ad476c1c270a95de1fa94f90344 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Fri, 30 Jun 2023 10:05:01 +0100 Subject: [PATCH 28/37] Divorce Client and Identity and create a separate module for the Client #54 --- nostr-java-client/pom.xml | 46 +++++++++++++++++++ .../src/main/java/module-info.java | 40 ++++++++++++++++ .../src/main/java/nostr/client}/Client.java | 3 +- nostr-java-examples/pom.xml | 5 ++ .../src/main/java/module-info.java | 1 + .../java/nostr/examples/NostrExamples.java | 3 +- nostr-java-id/pom.xml | 44 +----------------- nostr-java-id/src/main/java/module-info.java | 19 -------- nostr-java-test/pom.xml | 5 ++ .../test/java/nostr/test/id/ClientTest.java | 2 +- nostr-java-ws-handler-default-command/pom.xml | 5 ++ .../src/main/java/module-info.java | 1 + .../provider/DefaultCommandHandler.java | 2 +- pom.xml | 1 + 14 files changed, 110 insertions(+), 67 deletions(-) create mode 100644 nostr-java-client/pom.xml create mode 100644 nostr-java-client/src/main/java/module-info.java rename {nostr-java-id/src/main/java/nostr/id => nostr-java-client/src/main/java/nostr/client}/Client.java (96%) diff --git a/nostr-java-client/pom.xml b/nostr-java-client/pom.xml new file mode 100644 index 00000000..4f22ac0b --- /dev/null +++ b/nostr-java-client/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + nostr-java + nostr-java + 0.2-SNAPSHOT + + nostr-java-client + jar + + + ${project.groupId} + nostr-java-event + ${project.version} + + + ${project.groupId} + nostr-java-base + ${project.version} + + + ${project.groupId} + nostr-java-id + ${project.version} + + + ${project.groupId} + nostr-java-ws-handler-interface + ${project.version} + + + ${project.groupId} + nostr-java-ws-request-handler-provider + ${project.version} + + + ${project.groupId} + nostr-java-ws + ${project.version} + + + + nostr.client.NostrJavaClient + + \ No newline at end of file diff --git a/nostr-java-client/src/main/java/module-info.java b/nostr-java-client/src/main/java/module-info.java new file mode 100644 index 00000000..b2bb6937 --- /dev/null +++ b/nostr-java-client/src/main/java/module-info.java @@ -0,0 +1,40 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/module-info.java to edit this template + */ + +module nostr.client { + requires nostr.event; + requires static lombok; + requires java.logging; + requires nostr.util; + requires nostr.base; + requires com.fasterxml.jackson.databind; + requires com.fasterxml.jackson.annotation; + requires com.fasterxml.jackson.core; + requires nostr.crypto; + requires nostr.id; + requires nostr.ws; + requires org.eclipse.jetty.websocket.jetty.client; + requires org.eclipse.jetty.websocket.jetty.api; + requires org.eclipse.jetty.websocket.jetty.common; + requires org.eclipse.jetty.websocket.core.common; + requires org.eclipse.jetty.websocket.core.client; + requires org.eclipse.jetty.client; + requires org.eclipse.jetty.http; + requires org.eclipse.jetty.util; + requires org.eclipse.jetty.io; + requires org.slf4j; + requires org.eclipse.jetty.http2.client; + requires org.eclipse.jetty.http2.common; + requires org.eclipse.jetty.http2.hpack; + requires org.eclipse.jetty.alpn.client; + requires org.eclipse.jetty.http2.http.client.transport; + requires org.eclipse.jetty.alpn.java.client; + requires nostr.ws.response.handler.provider; + requires org.bouncycastle.provider; + requires nostr.ws.handler; + requires nostr.ws.request.handler.provider; + + exports nostr.client; +} diff --git a/nostr-java-id/src/main/java/nostr/id/Client.java b/nostr-java-client/src/main/java/nostr/client/Client.java similarity index 96% rename from nostr-java-id/src/main/java/nostr/id/Client.java rename to nostr-java-client/src/main/java/nostr/client/Client.java index 803856d1..b7b6d887 100644 --- a/nostr-java-id/src/main/java/nostr/id/Client.java +++ b/nostr-java-client/src/main/java/nostr/client/Client.java @@ -1,4 +1,4 @@ -package nostr.id; +package nostr.client; import java.io.IOException; import java.net.URI; @@ -23,6 +23,7 @@ import nostr.event.BaseMessage; import nostr.event.impl.ClientAuthenticationEvent; import nostr.event.message.ClientAuthenticationMessage; +import nostr.id.Identity; import nostr.util.NostrException; import nostr.ws.Connection; import nostr.ws.handler.spi.IRequestHandler; diff --git a/nostr-java-examples/pom.xml b/nostr-java-examples/pom.xml index 75e8a988..f0adac65 100644 --- a/nostr-java-examples/pom.xml +++ b/nostr-java-examples/pom.xml @@ -43,5 +43,10 @@ nostr-java-ws-handler-command-provider ${project.version} + + ${project.groupId} + nostr-java-client + ${project.version} + \ No newline at end of file diff --git a/nostr-java-examples/src/main/java/module-info.java b/nostr-java-examples/src/main/java/module-info.java index bec07cf9..8ea34272 100644 --- a/nostr-java-examples/src/main/java/module-info.java +++ b/nostr-java-examples/src/main/java/module-info.java @@ -1,6 +1,7 @@ module nostr.examples { requires nostr.event; + requires nostr.client; requires static lombok; requires nostr.ws; requires org.eclipse.jetty.websocket.jetty.client; diff --git a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java index 4cfbe386..4e1e413b 100644 --- a/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java +++ b/nostr-java-examples/src/main/java/nostr/examples/NostrExamples.java @@ -31,7 +31,6 @@ import nostr.event.impl.EphemeralEvent; import nostr.event.impl.Filters; import nostr.event.impl.GenericEvent; -import nostr.event.impl.GenericMessage; import nostr.event.impl.HideMessageEvent; import nostr.event.impl.InternetIdentifierMetadataEvent; import nostr.event.impl.MentionsEvent; @@ -45,7 +44,7 @@ import nostr.event.message.ReqMessage; import nostr.event.tag.EventTag; import nostr.event.tag.PubKeyTag; -import nostr.id.Client; +import nostr.client.Client; import nostr.id.Identity; import nostr.util.NostrException; import nostr.util.UnsupportedNIPException; diff --git a/nostr-java-id/pom.xml b/nostr-java-id/pom.xml index bf7ae1c6..71c241cc 100644 --- a/nostr-java-id/pom.xml +++ b/nostr-java-id/pom.xml @@ -39,37 +39,6 @@ nostr-java-util ${project.version} - - ${project.groupId} - nostr-java-ws - ${project.version} - - - nostr-java - nostr-base - - - nostr-java - nostr-event - - - nostr-java - nostr-util - - - nostr-java - nostr-ws-handler-command-provider - - - nostr-java - nostr-ws-handler-interface - - - nostr-java - nostr-ws-response-handler-provider - - - org.bouncycastle bcprov-jdk18on @@ -77,19 +46,8 @@ ${project.groupId} - nostr-java-ws-handler-interface - ${project.version} - - - ${project.groupId} - nostr-java-ws-request-handler-provider + nostr-java-crypto ${project.version} - - - nostr-java - nostr-ws-handler-interface - - \ No newline at end of file diff --git a/nostr-java-id/src/main/java/module-info.java b/nostr-java-id/src/main/java/module-info.java index 4608068b..f779e52f 100644 --- a/nostr-java-id/src/main/java/module-info.java +++ b/nostr-java-id/src/main/java/module-info.java @@ -5,28 +5,9 @@ requires nostr.crypto; requires nostr.event; requires nostr.util; - requires nostr.ws; - requires nostr.ws.handler; - requires nostr.ws.request.handler.provider; requires com.fasterxml.jackson.databind; requires com.fasterxml.jackson.annotation; requires com.fasterxml.jackson.core; - requires org.eclipse.jetty.websocket.jetty.client; - requires org.eclipse.jetty.websocket.jetty.api; - requires org.eclipse.jetty.websocket.jetty.common; - requires org.eclipse.jetty.websocket.core.common; - requires org.eclipse.jetty.websocket.core.client; - requires org.eclipse.jetty.client; - requires org.eclipse.jetty.http; - requires org.eclipse.jetty.util; - requires org.eclipse.jetty.io; - requires org.slf4j; - requires org.eclipse.jetty.alpn.client; - requires org.eclipse.jetty.alpn.java.client; - requires org.eclipse.jetty.http2.client; - requires org.eclipse.jetty.http2.common; - requires org.eclipse.jetty.http2.hpack; - requires org.eclipse.jetty.http2.http.client.transport; requires org.bouncycastle.provider; requires java.logging; requires java.desktop; diff --git a/nostr-java-test/pom.xml b/nostr-java-test/pom.xml index d1fc86b3..f24739b1 100644 --- a/nostr-java-test/pom.xml +++ b/nostr-java-test/pom.xml @@ -47,6 +47,11 @@ org.junit.jupiter junit-jupiter-engine + + ${project.groupId} + nostr-java-client + ${project.version} + diff --git a/nostr-java-test/src/test/java/nostr/test/id/ClientTest.java b/nostr-java-test/src/test/java/nostr/test/id/ClientTest.java index 8c18ae63..29eab85d 100644 --- a/nostr-java-test/src/test/java/nostr/test/id/ClientTest.java +++ b/nostr-java-test/src/test/java/nostr/test/id/ClientTest.java @@ -9,7 +9,7 @@ import nostr.base.PublicKey; import nostr.event.BaseMessage; import nostr.event.message.EventMessage; -import nostr.id.Client; +import nostr.client.Client; import nostr.id.Identity; import nostr.test.EntityFactory; import nostr.util.NostrException; diff --git a/nostr-java-ws-handler-default-command/pom.xml b/nostr-java-ws-handler-default-command/pom.xml index 8a119c0e..b6d10568 100644 --- a/nostr-java-ws-handler-default-command/pom.xml +++ b/nostr-java-ws-handler-default-command/pom.xml @@ -22,6 +22,11 @@ nostr-java-id ${project.version} + + ${project.groupId} + nostr-java-client + ${project.version} + diff --git a/nostr-java-ws-handler-default-command/src/main/java/module-info.java b/nostr-java-ws-handler-default-command/src/main/java/module-info.java index 1ca27409..e9b44a23 100644 --- a/nostr-java-ws-handler-default-command/src/main/java/module-info.java +++ b/nostr-java-ws-handler-default-command/src/main/java/module-info.java @@ -9,6 +9,7 @@ requires nostr.base; requires nostr.id; requires nostr.event; + requires nostr.client; requires com.fasterxml.jackson.databind; requires com.fasterxml.jackson.annotation; requires com.fasterxml.jackson.core; diff --git a/nostr-java-ws-handler-default-command/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java b/nostr-java-ws-handler-default-command/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java index b025c818..41414ef2 100644 --- a/nostr-java-ws-handler-default-command/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java +++ b/nostr-java-ws-handler-default-command/src/main/java/nostr/ws/handler/command/provider/DefaultCommandHandler.java @@ -9,7 +9,7 @@ import nostr.base.Command; import nostr.base.Relay; import nostr.base.annotation.DefaultHandler; -import nostr.id.Client; +import nostr.client.Client; import nostr.id.Identity; import nostr.util.NostrException; import nostr.ws.handler.command.spi.ICommandHandler; diff --git a/pom.xml b/pom.xml index d6f6ffb8..099caf14 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ nostr-java-ws-handler-default-command nostr-java-ws-request-handler-provider nostr-java-ws-response-handler-provider + nostr-java-client From c568116dbef09dd5358a86aa9848831e5fdafdd0 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Sat, 1 Jul 2023 22:19:40 +0100 Subject: [PATCH 29/37] Update README.md: project description and sample application --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e0c97406..552f76eb 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # nostr-java -A nostr client library written in java, for generating, signing and publishing events to relays. +Introducing the nostr-java library, a solution written in java for generating, signing, and publishing nostr events to relays. + +For detailed instructions on how to utilise the library, please refer to the [nostr-client](https://github.com/tcheeric/nostr-client/) repository. \ No newline at end of file From adcd706c0e0152b67f97cda1a9fbf170e8a8a50a Mon Sep 17 00:00:00 2001 From: tcheeric Date: Sat, 1 Jul 2023 22:21:17 +0100 Subject: [PATCH 30/37] Update README.md: project description and sample application --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e0c97406..552f76eb 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # nostr-java -A nostr client library written in java, for generating, signing and publishing events to relays. +Introducing the nostr-java library, a solution written in java for generating, signing, and publishing nostr events to relays. + +For detailed instructions on how to utilise the library, please refer to the [nostr-client](https://github.com/tcheeric/nostr-client/) repository. \ No newline at end of file From 47992ceda43c83669c61e6eb3ee8cebbae622b5d Mon Sep 17 00:00:00 2001 From: Guilherme Gps Date: Mon, 3 Jul 2023 19:45:34 -0300 Subject: [PATCH 31/37] Improving keys generation to use secp256k1 corectly --- nostr-java-crypto/pom.xml | 4 ++ .../src/main/java/module-info.java | 1 + .../java/nostr/crypto/schnorr/Schnorr.java | 42 ++++++++----------- pom.xml | 5 +++ 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/nostr-java-crypto/pom.xml b/nostr-java-crypto/pom.xml index 1282eaec..71fb9089 100644 --- a/nostr-java-crypto/pom.xml +++ b/nostr-java-crypto/pom.xml @@ -25,6 +25,10 @@ org.projectlombok lombok + + org.bouncycastle + bcprov-jdk15on + diff --git a/nostr-java-crypto/src/main/java/module-info.java b/nostr-java-crypto/src/main/java/module-info.java index d9c79d8e..297ec0b3 100644 --- a/nostr-java-crypto/src/main/java/module-info.java +++ b/nostr-java-crypto/src/main/java/module-info.java @@ -3,6 +3,7 @@ requires java.logging; requires nostr.util; requires static lombok; + requires org.bouncycastle.provider; exports nostr.crypto.bech32; exports nostr.crypto.schnorr; 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 f056161c..5c9c4eae 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 @@ -1,11 +1,18 @@ package nostr.crypto.schnorr; import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; +import java.security.Security; +import java.security.interfaces.ECPrivateKey; +import java.security.spec.ECGenParameterSpec; import java.util.Arrays; -import java.util.logging.Level; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; import lombok.extern.java.Log; import nostr.crypto.Point; @@ -14,12 +21,6 @@ @Log public class Schnorr { - private static final String RANDOM_NUMBER_ALGORITHM = "SHA1PRNG"; - private static final String RANDOM_NUMBER_ALGORITHM_PROVIDER = "SUN"; - - private static final BigInteger MAXPRIVATEKEY - = new BigInteger("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140", 16); - /** * * @param msg @@ -119,26 +120,17 @@ public static boolean verify(byte[] msg, byte[] pubkey, byte[] sig) throws Excep * @return */ public static byte[] generatePrivateKey() { - SecureRandom secureRandom; try { - secureRandom = SecureRandom.getInstance(RANDOM_NUMBER_ALGORITHM, RANDOM_NUMBER_ALGORITHM_PROVIDER); - } catch (NoSuchAlgorithmException | NoSuchProviderException e) { - log.log(Level.SEVERE, null, e); - secureRandom = new SecureRandom(); + Security.addProvider(new BouncyCastleProvider()); + KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDSA", "BC"); + kpg.initialize(new ECGenParameterSpec("secp256k1"), SecureRandom.getInstanceStrong()); + KeyPair processorKeyPair = kpg.genKeyPair(); + + return NostrUtil.bytesFromBigInteger(((ECPrivateKey) processorKeyPair.getPrivate()).getS()); + + } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchProviderException e) { + throw new RuntimeException(e); } - - // Generate the key, skipping as many as desired. - byte[] privateKeyAttempt = new byte[32]; - secureRandom.nextBytes(privateKeyAttempt); - BigInteger privateKeyCheck = new BigInteger(1, privateKeyAttempt); - - while (privateKeyCheck.compareTo(BigInteger.ZERO) == 0 - || privateKeyCheck.compareTo(MAXPRIVATEKEY) == 1) { - secureRandom.nextBytes(privateKeyAttempt); - privateKeyCheck = new BigInteger(1, privateKeyAttempt); - } - - return privateKeyAttempt; } public static byte[] genPubKey(byte[] secKey) throws Exception { diff --git a/pom.xml b/pom.xml index 099caf14..a672a429 100644 --- a/pom.xml +++ b/pom.xml @@ -57,6 +57,11 @@ jackson-databind 2.14.1 + + org.bouncycastle + bcprov-jdk15on + 1.70 + From 40f2432b73ae302571dec51e338915149dceb292 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 4 Jul 2023 17:10:43 +0100 Subject: [PATCH 32/37] Updated the pom version from 0.2-SNAPSHOT to 0.2 --- nostr-java-base/pom.xml | 2 +- nostr-java-client/pom.xml | 2 +- nostr-java-crypto/pom.xml | 2 +- nostr-java-event/pom.xml | 2 +- nostr-java-examples/pom.xml | 2 +- nostr-java-id/pom.xml | 2 +- nostr-java-test/pom.xml | 2 +- nostr-java-util/pom.xml | 2 +- nostr-java-ws-handler-default-command/pom.xml | 2 +- nostr-java-ws-handler-interface/pom.xml | 2 +- nostr-java-ws-request-handler-provider/pom.xml | 2 +- nostr-java-ws-response-handler-provider/pom.xml | 2 +- nostr-java-ws/pom.xml | 2 +- pom.xml | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/nostr-java-base/pom.xml b/nostr-java-base/pom.xml index 24e59440..02f7f841 100644 --- a/nostr-java-base/pom.xml +++ b/nostr-java-base/pom.xml @@ -6,7 +6,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-base diff --git a/nostr-java-client/pom.xml b/nostr-java-client/pom.xml index 4f22ac0b..f28c19cc 100644 --- a/nostr-java-client/pom.xml +++ b/nostr-java-client/pom.xml @@ -4,7 +4,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-client jar diff --git a/nostr-java-crypto/pom.xml b/nostr-java-crypto/pom.xml index 71fb9089..5b0eadc1 100644 --- a/nostr-java-crypto/pom.xml +++ b/nostr-java-crypto/pom.xml @@ -6,7 +6,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-crypto diff --git a/nostr-java-event/pom.xml b/nostr-java-event/pom.xml index 4383d360..1861de39 100644 --- a/nostr-java-event/pom.xml +++ b/nostr-java-event/pom.xml @@ -6,7 +6,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-event diff --git a/nostr-java-examples/pom.xml b/nostr-java-examples/pom.xml index f0adac65..3e5e33c7 100644 --- a/nostr-java-examples/pom.xml +++ b/nostr-java-examples/pom.xml @@ -6,7 +6,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-examples diff --git a/nostr-java-id/pom.xml b/nostr-java-id/pom.xml index 71c241cc..4860d2f2 100644 --- a/nostr-java-id/pom.xml +++ b/nostr-java-id/pom.xml @@ -6,7 +6,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-id diff --git a/nostr-java-test/pom.xml b/nostr-java-test/pom.xml index f24739b1..e4d21bb3 100644 --- a/nostr-java-test/pom.xml +++ b/nostr-java-test/pom.xml @@ -6,7 +6,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-test diff --git a/nostr-java-util/pom.xml b/nostr-java-util/pom.xml index fdf629f0..baf587a2 100644 --- a/nostr-java-util/pom.xml +++ b/nostr-java-util/pom.xml @@ -6,7 +6,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-util diff --git a/nostr-java-ws-handler-default-command/pom.xml b/nostr-java-ws-handler-default-command/pom.xml index b6d10568..faf3f3b3 100644 --- a/nostr-java-ws-handler-default-command/pom.xml +++ b/nostr-java-ws-handler-default-command/pom.xml @@ -5,7 +5,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-ws-handler-command-provider diff --git a/nostr-java-ws-handler-interface/pom.xml b/nostr-java-ws-handler-interface/pom.xml index 479f80cb..f8ae36f2 100644 --- a/nostr-java-ws-handler-interface/pom.xml +++ b/nostr-java-ws-handler-interface/pom.xml @@ -5,7 +5,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-ws-handler-interface diff --git a/nostr-java-ws-request-handler-provider/pom.xml b/nostr-java-ws-request-handler-provider/pom.xml index caf2d3fb..64f10def 100644 --- a/nostr-java-ws-request-handler-provider/pom.xml +++ b/nostr-java-ws-request-handler-provider/pom.xml @@ -4,7 +4,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-ws-request-handler-provider jar diff --git a/nostr-java-ws-response-handler-provider/pom.xml b/nostr-java-ws-response-handler-provider/pom.xml index 12cbf164..726b4614 100644 --- a/nostr-java-ws-response-handler-provider/pom.xml +++ b/nostr-java-ws-response-handler-provider/pom.xml @@ -4,7 +4,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-ws-response-handler-provider jar diff --git a/nostr-java-ws/pom.xml b/nostr-java-ws/pom.xml index 8d4cf430..b70c834e 100644 --- a/nostr-java-ws/pom.xml +++ b/nostr-java-ws/pom.xml @@ -6,7 +6,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 nostr-java-ws diff --git a/pom.xml b/pom.xml index a672a429..d8e45d62 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ nostr-java nostr-java - 0.2-SNAPSHOT + 0.2 pom From 3ccc6cc40c470585ce5bcdea047784fb632656f0 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 4 Jul 2023 17:46:22 +0100 Subject: [PATCH 33/37] resolving conflict --- nostr-java-event/src/main/java/nostr/event/Marker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/nostr-java-event/src/main/java/nostr/event/Marker.java b/nostr-java-event/src/main/java/nostr/event/Marker.java index 3a067853..426c127f 100644 --- a/nostr-java-event/src/main/java/nostr/event/Marker.java +++ b/nostr-java-event/src/main/java/nostr/event/Marker.java @@ -1,3 +1,4 @@ + package nostr.event; /** From 23dad4075126600512156c73a8645b837493be44 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 4 Jul 2023 17:52:55 +0100 Subject: [PATCH 34/37] Updated the readme.md file --- nostr-java-event/README.md | 46 -------------------------------------- 1 file changed, 46 deletions(-) diff --git a/nostr-java-event/README.md b/nostr-java-event/README.md index 6eea6a09..9aa10920 100644 --- a/nostr-java-event/README.md +++ b/nostr-java-event/README.md @@ -22,49 +22,3 @@ The Tags: - Subject Tag Additionally, you may use the `GenericTag` and `GenericEvent` classes to create your custom tags and events. - -## Creating a Custom Tag -Consider the tag syntax: -`[, , , ..., ]` - -Given: - -- The tag is specified in a NIP -- The tag has a code and zero or more attributes -- An attribute may be specified by another NIP -- The tag is related to a parent event - -Practical example: - -For illustration purpose, we will implement a tag defined in **NIP-777** and with three attributes, the last attribute is specified in **NIP-888** - -Here is the corresponding java code: - -```java - // Create the attributes... - // ...using the static builder method - final ElementAttribute attr0 = ElementAttribute.builder().value(new StringValue("value 0")).build(); - - //...by invoking the constructors - final ElementAttribute attr1 = new ElementAttribute("value 1"); - final ElementAttribute attr2 = new ElementAttribute("value 2", 888);; - - Set attributes = new HashSet<>(); - attributes.add(attr0); - attributes.add(attr1); - attributes.add(attr2); - - // Create the tag - GenericTag tag = new GenericTag(777, "code", attributes); - System.out.println(tag.toString()); //["code", "value 0", "value 1", "value 2"] - - // Create the parent event - TagList tags = new TagList(); - tags.add(tag); - TextNoteEvent event = new TextNoteEvent(publicKey, tags, "Hello Nostr!"); -``` - -## Creating a Custom Event - -See my [implementation](https://github.com/tcheeric/nostr-java/blob/main/nostr-event/src/main/java/nostr/event/impl/OtsEvent.java) of the [OTS Event](https://github.com/nostr-protocol/nips/blob/master/03.md) as a cusom event. -Also, review my simple [json implementation](https://github.com/tcheeric/nostr-java/tree/0bd9a8858705e5d39ab34706ea23a584f5dfc9b6/nostr-json). \ No newline at end of file From ce5d1ebb051a996333fc7db2baedf0a7050d75bb Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 4 Jul 2023 17:55:35 +0100 Subject: [PATCH 35/37] minor edit --- nostr-java-event/src/main/java/nostr/event/Marker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nostr-java-event/src/main/java/nostr/event/Marker.java b/nostr-java-event/src/main/java/nostr/event/Marker.java index 426c127f..dbc272e3 100644 --- a/nostr-java-event/src/main/java/nostr/event/Marker.java +++ b/nostr-java-event/src/main/java/nostr/event/Marker.java @@ -19,4 +19,4 @@ public enum Marker { public String getValue() { return value; } -} +} \ No newline at end of file From eb294786f4c64c892a21e799254ac890ed19cff3 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 4 Jul 2023 18:19:00 +0100 Subject: [PATCH 36/37] Resolved merge conflict by keeping Marker.java --- .../src/main/java/nostr/event/Marker.java | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 nostr-java-event/src/main/java/nostr/event/Marker.java diff --git a/nostr-java-event/src/main/java/nostr/event/Marker.java b/nostr-java-event/src/main/java/nostr/event/Marker.java deleted file mode 100644 index dbc272e3..00000000 --- a/nostr-java-event/src/main/java/nostr/event/Marker.java +++ /dev/null @@ -1,22 +0,0 @@ - -package nostr.event; - -/** - * - * @author squirrel - */ -public enum Marker { - ROOT("root"), - REPLY("reply"), - MENTION("mention"); - - private final String value; - - Marker(String value) { - this.value = value; - } - - public String getValue() { - return value; - } -} \ No newline at end of file From 23fe9e284257f26fa6237534970a5846c006f224 Mon Sep 17 00:00:00 2001 From: tcheeric Date: Tue, 4 Jul 2023 18:20:55 +0100 Subject: [PATCH 37/37] Revert "Resolved merge conflict by keeping Marker.java" This reverts commit eb294786f4c64c892a21e799254ac890ed19cff3. --- .../src/main/java/nostr/event/Marker.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 nostr-java-event/src/main/java/nostr/event/Marker.java diff --git a/nostr-java-event/src/main/java/nostr/event/Marker.java b/nostr-java-event/src/main/java/nostr/event/Marker.java new file mode 100644 index 00000000..dbc272e3 --- /dev/null +++ b/nostr-java-event/src/main/java/nostr/event/Marker.java @@ -0,0 +1,22 @@ + +package nostr.event; + +/** + * + * @author squirrel + */ +public enum Marker { + ROOT("root"), + REPLY("reply"), + MENTION("mention"); + + private final String value; + + Marker(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} \ No newline at end of file