From ed2d7f57c569a7935f6dca1d549f373c275f98f9 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 7 Jul 2025 17:02:42 -0400 Subject: [PATCH] Adds the incoming relay as a hint to all related keys, addresses and event ids. --- .../vitorpamplona/amethyst/model/Account.kt | 2 +- .../amethyst/model/LocalCache.kt | 36 ++++++- .../SearchWatcherSubAssembler.kt | 4 +- .../vitorpamplona/amethyst/ui/MainActivity.kt | 4 +- .../amethyst/ui/actions/NewMessageTagger.kt | 4 +- .../amethyst/ui/components/ClickableRoute.kt | 2 +- .../markdown/MarkdownMediaRenderer.kt | 2 +- .../ui/screen/AccountStateViewModel.kt | 2 +- .../ui/screen/loggedIn/AccountViewModel.kt | 2 +- .../amethyst/NewMessageTaggerKeyParseTest.kt | 22 ++--- .../experimental/zapPolls/PollNoteEvent.kt | 72 +++++++++++++- .../quartz/nip01Core/hints/HintProviders.kt | 7 ++ .../client/single/basic/BasicRelayClient.kt | 2 +- .../quartz/nip01Core/tags/people/PTag.kt | 6 +- .../nip02FollowList/ContactListEvent.kt | 7 ++ .../quartz/nip03Timestamp/OtsEvent.kt | 2 + .../quartz/nip09Deletions/DeletionEvent.kt | 4 + .../quartz/nip10Notes/BaseThreadedEvent.kt | 46 ++++----- .../quartz/nip10Notes/TextNoteEvent.kt | 72 +++++++++++++- .../quartz/nip10Notes/tags/MarkedETag.kt | 2 +- .../quartz/nip17Dm/base/BaseDMGroupEvent.kt | 2 + .../quartz/nip18Reposts/GenericRepostEvent.kt | 6 ++ .../quartz/nip18Reposts/RepostEvent.kt | 7 ++ .../quartz/nip18Reposts/quotes/EntityExt.kt | 7 +- .../quartz/nip18Reposts/quotes/QTag.kt | 18 +++- .../nip18Reposts/quotes/TagArrayBuilderExt.kt | 4 +- .../quartz/nip18Reposts/quotes/TagArrayExt.kt | 2 +- .../quartz/nip19Bech32/ListEntityExt.kt | 99 +++++++++++++++++++ .../quartz/nip19Bech32/Nip19Parser.kt | 10 +- .../entities/{Note.kt => NNote.kt} | 8 +- .../quartz/nip22Comments/CommentEvent.kt | 65 +++++++++++- .../nip23LongContent/LongTextNoteEvent.kt | 52 +++++++++- .../quartz/nip25Reactions/ReactionEvent.kt | 6 ++ .../admin/ChannelCreateEvent.kt | 2 + .../admin/ChannelHideMessageEvent.kt | 2 + .../admin/ChannelMetadataEvent.kt | 7 +- .../admin/ChannelMuteUserEvent.kt | 2 + .../message/ChannelMessageEvent.kt | 72 +++++++++++++- .../selection/EmojiPackSelectionEvent.kt | 2 + .../quartz/nip34Git/issue/GitIssueEvent.kt | 54 +++++++++- .../quartz/nip34Git/patch/GitPatchEvent.kt | 8 ++ .../quartz/nip34Git/reply/GitReplyEvent.kt | 57 ++++++++++- .../nip35Torrents/TorrentCommentEvent.kt | 54 +++++++++- .../quartz/nip37Drafts/DraftEvent.kt | 8 +- .../quartz/nip51Lists/GeneralListEvent.kt | 6 ++ .../chat/LiveActivitiesChatMessageEvent.kt | 55 ++++++++++- .../streaming/LiveActivitiesEvent.kt | 7 ++ .../quartz/nip54Wiki/WikiNoteEvent.kt | 66 ++++++++++++- .../quartz/nip57Zaps/LnZapEvent.kt | 8 +- .../quartz/nip57Zaps/LnZapPrivateEvent.kt | 8 +- .../quartz/nip57Zaps/LnZapRequestEvent.kt | 8 +- .../quartz/nip58Badges/BadgeAwardEvent.kt | 8 +- .../quartz/nip58Badges/BadgeProfilesEvent.kt | 8 +- .../approval/CommunityPostApprovalEvent.kt | 8 ++ .../definition/CommunityDefinitionEvent.kt | 10 +- .../definition/tags/ModeratorTag.kt | 3 +- .../quartz/nip75ZapGoals/GoalEvent.kt | 8 +- .../quartz/nip84Highlights/HighlightEvent.kt | 55 ++++++++++- .../recommendation/AppRecommendationEvent.kt | 2 + .../quartz/nip19Bech32/NIP19ParserTest.kt | 4 +- 60 files changed, 1001 insertions(+), 117 deletions(-) create mode 100644 quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/ListEntityExt.kt rename quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/{Note.kt => NNote.kt} (92%) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index ace9e8406..f52cf5521 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -1462,7 +1462,7 @@ class Account( when (it) { is NPub -> null is NProfile -> null - is com.vitorpamplona.quartz.nip19Bech32.entities.Note -> cache.getOrCreateNote(it.hex) + is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> cache.getOrCreateNote(it.hex) is NEvent -> cache.getOrCreateNote(it.hex) is NEmbed -> cache.getOrCreateNote(it.event.id) is NAddress -> cache.checkGetOrCreateAddressableNote(it.aTag()) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 89e2c535d..c90eac138 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -191,8 +191,6 @@ import java.time.Instant import java.time.ZoneId import java.time.format.DateTimeFormatter import java.util.concurrent.ConcurrentHashMap -import kotlin.compareTo -import kotlin.text.get interface ILocalCache { fun markAsSeen( @@ -2912,7 +2910,7 @@ object LocalCache : ILocalCache { } getOrCreateUser(nip19.hex) } - is com.vitorpamplona.quartz.nip19Bech32.entities.Note -> { + is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> { getOrCreateNote(nip19.hex) } is NEvent -> { @@ -2976,13 +2974,43 @@ object LocalCache : ILocalCache { ): Boolean { val wasNew = justConsumeInnerInner(event, relay, wasVerified) - if (wasNew && relay != null) { + if (wasNew) { updateHintIndexes(event) } + if (relay != null) { + addIncomingRelayAsHintToAllRelatedEvents(event, relay) + } + return wasNew } + fun addIncomingRelayAsHintToAllRelatedEvents( + event: Event, + relay: NormalizedRelayUrl, + ) { + relayHints.addEvent(event.id, relay) + if (event is AddressableEvent) { + relayHints.addAddress(event.addressTag(), relay) + } + + if (event is EventHintProvider) { + event.linkedEventIds().forEach { + relayHints.addEvent(it, relay) + } + } + if (event is AddressHintProvider) { + event.linkedAddressIds().forEach { + relayHints.addAddress(it, relay) + } + } + if (event is PubKeyHintProvider) { + event.linkedPubKeys().forEach { + relayHints.addKey(it, relay) + } + } + } + fun updateHintIndexes(event: Event) { if (event is EventHintProvider) { event.eventHints().forEach { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/searchCommand/subassemblies/SearchWatcherSubAssembler.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/searchCommand/subassemblies/SearchWatcherSubAssembler.kt index 0b9657cef..39b58880b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/searchCommand/subassemblies/SearchWatcherSubAssembler.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/searchCommand/subassemblies/SearchWatcherSubAssembler.kt @@ -31,11 +31,11 @@ import com.vitorpamplona.quartz.nip19Bech32.Nip19Parser import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.nip19Bech32.entities.NEmbed import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent +import com.vitorpamplona.quartz.nip19Bech32.entities.NNote import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile import com.vitorpamplona.quartz.nip19Bech32.entities.NPub import com.vitorpamplona.quartz.nip19Bech32.entities.NRelay import com.vitorpamplona.quartz.nip19Bech32.entities.NSec -import com.vitorpamplona.quartz.nip19Bech32.entities.Note import com.vitorpamplona.quartz.utils.Hex /** @@ -69,7 +69,7 @@ class SearchWatcherSubAssembler( is NSec -> filterByAuthor(parsed.toPubKeyHex()) is NPub -> filterByAuthor(parsed.hex) is NProfile -> filterByAuthor(parsed.hex) - is Note -> filterByEvent(parsed.hex) + is NNote -> filterByEvent(parsed.hex) is NEvent -> filterByEvent(parsed.hex) is NEmbed -> emptyList() is NRelay -> emptyList() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt index 3b5f46db8..50fb1a403 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt @@ -49,9 +49,9 @@ import com.vitorpamplona.quartz.nip19Bech32.Nip19Parser import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.nip19Bech32.entities.NEmbed import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent +import com.vitorpamplona.quartz.nip19Bech32.entities.NNote import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile import com.vitorpamplona.quartz.nip19Bech32.entities.NPub -import com.vitorpamplona.quartz.nip19Bech32.entities.Note import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent @@ -163,7 +163,7 @@ fun uriToRoute( when (nip19) { is NPub -> Route.Profile(nip19.hex) is NProfile -> Route.Profile(nip19.hex) - is Note -> Route.Note(nip19.hex) + is NNote -> Route.Note(nip19.hex) is NEvent -> { if (nip19.kind == PrivateDmEvent.KIND) { nip19.author?.let { Route.RoomByAuthor(it) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt index f9d0feeb5..4af0330a5 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMessageTagger.kt @@ -73,7 +73,7 @@ class NewMessageTagger( is NPub -> addUserToMentions(dao.getOrCreateUser(entity.hex)) is NProfile -> addUserToMentions(dao.getOrCreateUser(entity.hex)) - is com.vitorpamplona.quartz.nip19Bech32.entities.Note -> addNoteToReplyTos(dao.getOrCreateNote(entity.hex)) + is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> addNoteToReplyTos(dao.getOrCreateNote(entity.hex)) is NEvent -> addNoteToReplyTos(dao.getOrCreateNote(entity.hex)) is NEmbed -> addNoteToReplyTos(dao.getOrCreateNote(entity.event.id)) @@ -107,7 +107,7 @@ class NewMessageTagger( getNostrAddress(dao.getOrCreateUser(entity.hex).toNProfile(), results.restOfWord) } - is com.vitorpamplona.quartz.nip19Bech32.entities.Note -> { + is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> { getNostrAddress(dao.getOrCreateNote(entity.hex).toNEvent(), results.restOfWord) } is NEvent -> { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableRoute.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableRoute.kt index 047ab7398..ce79850d6 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableRoute.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ClickableRoute.kt @@ -95,7 +95,7 @@ fun ClickableRoute( when (val entity = nip19.entity) { is NPub -> DisplayUser(entity.hex, nip19.nip19raw, nip19.additionalChars, accountViewModel, nav) is NProfile -> DisplayUser(entity.hex, nip19.nip19raw, nip19.additionalChars, accountViewModel, nav) - is com.vitorpamplona.quartz.nip19Bech32.entities.Note -> DisplayEvent(entity.hex, null, nip19.nip19raw, nip19.additionalChars, accountViewModel, nav) + is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> DisplayEvent(entity.hex, null, nip19.nip19raw, nip19.additionalChars, accountViewModel, nav) is NEvent -> DisplayEvent(entity.hex, entity.kind, nip19.nip19raw, nip19.additionalChars, accountViewModel, nav) is NEmbed -> LoadAndDisplayEvent(entity.event, nip19.additionalChars, accountViewModel, nav) is NAddress -> DisplayAddress(entity, nip19.nip19raw, nip19.additionalChars, accountViewModel, nav) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/markdown/MarkdownMediaRenderer.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/markdown/MarkdownMediaRenderer.kt index e5784f817..9260f1b58 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/markdown/MarkdownMediaRenderer.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/markdown/MarkdownMediaRenderer.kt @@ -171,7 +171,7 @@ class MarkdownMediaRenderer( when (val entity = loadedLink.nip19.entity) { is NPub -> renderObservableUser(entity.hex, loadedLink.nip19.nip19raw, richTextStringBuilder) is NProfile -> renderObservableUser(entity.hex, loadedLink.nip19.nip19raw, richTextStringBuilder) - is com.vitorpamplona.quartz.nip19Bech32.entities.Note -> renderObservableShortNoteUri(loadedLink, uri, richTextStringBuilder) + is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> renderObservableShortNoteUri(loadedLink, uri, richTextStringBuilder) is NEvent -> renderObservableShortNoteUri(loadedLink, uri, richTextStringBuilder) is NEmbed -> renderObservableShortNoteUri(loadedLink, uri, richTextStringBuilder) is NAddress -> renderObservableShortNoteUri(loadedLink, uri, richTextStringBuilder) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt index 43a832f8f..101800e4d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt @@ -116,7 +116,7 @@ class AccountStateViewModel : ViewModel() { is NSec -> null is NPub -> parsed.hex.hexToByteArray() is NProfile -> parsed.hex.hexToByteArray() - is com.vitorpamplona.quartz.nip19Bech32.entities.Note -> null + is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> null is NEvent -> null is NEmbed -> null is NRelay -> null diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index e45801ec9..9985fc7cd 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -1705,7 +1705,7 @@ class AccountViewModel( is NSec -> {} is NPub -> {} is NProfile -> {} - is com.vitorpamplona.quartz.nip19Bech32.entities.Note -> { + is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> { LocalCache.checkGetOrCreateNote(parsed.hex)?.let { note -> returningNote = note } diff --git a/amethyst/src/test/java/com/vitorpamplona/amethyst/NewMessageTaggerKeyParseTest.kt b/amethyst/src/test/java/com/vitorpamplona/amethyst/NewMessageTaggerKeyParseTest.kt index 18d732481..aad61b5ca 100644 --- a/amethyst/src/test/java/com/vitorpamplona/amethyst/NewMessageTaggerKeyParseTest.kt +++ b/amethyst/src/test/java/com/vitorpamplona/amethyst/NewMessageTaggerKeyParseTest.kt @@ -23,8 +23,8 @@ package com.vitorpamplona.amethyst import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.ui.actions.Dao import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger +import com.vitorpamplona.quartz.nip19Bech32.entities.NNote import com.vitorpamplona.quartz.nip19Bech32.entities.NPub -import com.vitorpamplona.quartz.nip19Bech32.entities.Note import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test @@ -53,10 +53,10 @@ class NewMessageTaggerKeyParseTest { val result = NewMessageTagger(message = "", dao = dao) .parseDirtyWordForKey("note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn") - assertTrue(result?.key?.entity is Note) + assertTrue(result?.key?.entity is NNote) assertEquals( "1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", - (result?.key?.entity as? Note)?.hex, + (result?.key?.entity as? NNote)?.hex, ) assertEquals(null, result?.restOfWord) } @@ -79,10 +79,10 @@ class NewMessageTaggerKeyParseTest { val result = NewMessageTagger(message = "", dao = dao) .parseDirtyWordForKey("note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,") - assertTrue(result?.key?.entity is Note) + assertTrue(result?.key?.entity is NNote) assertEquals( "1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", - (result?.key?.entity as? Note)?.hex, + (result?.key?.entity as? NNote)?.hex, ) assertEquals(",", result?.restOfWord) } @@ -105,10 +105,10 @@ class NewMessageTaggerKeyParseTest { val result = NewMessageTagger(message = "", dao = dao) .parseDirtyWordForKey("@note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,") - assertTrue(result?.key?.entity is Note) + assertTrue(result?.key?.entity is NNote) assertEquals( "1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", - (result?.key?.entity as? Note)?.hex, + (result?.key?.entity as? NNote)?.hex, ) assertEquals(",", result?.restOfWord) } @@ -133,10 +133,10 @@ class NewMessageTaggerKeyParseTest { .parseDirtyWordForKey( "nostr:note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,", ) - assertTrue(result?.key?.entity is Note) + assertTrue(result?.key?.entity is NNote) assertEquals( "1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", - (result?.key?.entity as? Note)?.hex, + (result?.key?.entity as? NNote)?.hex, ) assertEquals(",", result?.restOfWord) } @@ -163,10 +163,10 @@ class NewMessageTaggerKeyParseTest { .parseDirtyWordForKey( "Nostr:note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,", ) - assertTrue(result?.key?.entity is Note) + assertTrue(result?.key?.entity is NNote) assertEquals( "1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", - (result?.key?.entity as? Note)?.hex, + (result?.key?.entity as? NNote)?.hex, ) assertEquals(",", result?.restOfWord) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt index 638de6571..b3ca2fc53 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/PollNoteEvent.kt @@ -28,8 +28,29 @@ import com.vitorpamplona.quartz.experimental.zapPolls.tags.MinimumTag import com.vitorpamplona.quartz.experimental.zapPolls.tags.PollOptionTag import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder +import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate +import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag +import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag.Companion.parseAsHint +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag.Companion.parseAsHint import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent +import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag +import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag.Companion.parseAsHint +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseAddressAsHint +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseEventAsHint +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip31Alts.alt import com.vitorpamplona.quartz.utils.TimeUtils @@ -41,7 +62,56 @@ class PollNoteEvent( tags: Array>, content: String, sig: HexKey, -) : BaseThreadedEvent(id, pubKey, createdAt, KIND, tags, content, sig) { +) : BaseThreadedEvent(id, pubKey, createdAt, KIND, tags, content, sig), + EventHintProvider, + AddressHintProvider, + PubKeyHintProvider { + override fun eventHints(): List { + val eHints = tags.mapNotNull(MarkedETag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() + + return eHints + qHints + nip19Hints + } + + override fun linkedEventIds(): List { + val eHints = tags.mapNotNull(MarkedETag::parseId) + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return eHints + qHints + nip19Hints + } + + override fun addressHints(): List { + val aHints = tags.mapNotNull(ATag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return aHints + qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val aHints = tags.mapNotNull(ATag::parseAddressId) + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return aHints + qHints + nip19Hints + } + + override fun pubKeyHints(): List { + val pHints = tags.mapNotNull(PTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() + + return pHints + nip19Hints + } + + override fun linkedPubKeys(): List { + val pHints = tags.mapNotNull(PTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } + fun pollOptionsArray() = tags.mapNotNull(PollOptionTag::parse) fun pollOptions() = pollOptionsArray().associate { it.index to it.descriptor } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/HintProviders.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/HintProviders.kt index e6ddd472d..704ebd770 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/HintProviders.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/hints/HintProviders.kt @@ -20,18 +20,25 @@ */ package com.vitorpamplona.quartz.nip01Core.hints +import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint interface EventHintProvider { fun eventHints(): List + + fun linkedEventIds(): List } interface AddressHintProvider { fun addressHints(): List + + fun linkedAddressIds(): List } interface PubKeyHintProvider { fun pubKeyHints(): List + + fun linkedPubKeys(): List } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/basic/BasicRelayClient.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/basic/BasicRelayClient.kt index 80bb399f4..6ff4c37c5 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/basic/BasicRelayClient.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/client/single/basic/BasicRelayClient.kt @@ -415,7 +415,7 @@ open class BasicRelayClient( ) } socket?.let { - // Log.d(logTag, "Sending: $str") + Log.d(logTag, "Sending: $str") val result = it.send(str) listener.onSend(this@BasicRelayClient, str, result) stats.addBytesSent(str.bytesUsedInMemory()) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt index 2f8cda9fd..1b712af7a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt @@ -20,7 +20,6 @@ */ package com.vitorpamplona.quartz.nip01Core.tags.people -import android.util.Log import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Tag @@ -80,10 +79,7 @@ data class PTag( fun parseKey(tag: Array): HexKey? { ensure(tag.has(1)) { return null } ensure(tag[0] == TAG_NAME) { return null } - ensure(tag[1].length == 64) { - Log.w("PTag", "Invalid `$TAG_NAME` value ${tag.joinToString(", ")}") - return null - } + ensure(tag[1].length == 64) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt index c91a6550b..56f46bad2 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/ContactListEvent.kt @@ -31,10 +31,13 @@ import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerSync import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.tags.addressables.isTaggedAddressableNote +import com.vitorpamplona.quartz.nip01Core.tags.events.ETag.Companion.parseAsHint import com.vitorpamplona.quartz.nip01Core.tags.geohash.isTaggedGeoHash import com.vitorpamplona.quartz.nip01Core.tags.hashtags.countHashtags import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHash +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag.Companion.parseAsHint +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag.Companion.parseKey import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser import com.vitorpamplona.quartz.nip02FollowList.tags.AddressFollowTag import com.vitorpamplona.quartz.nip02FollowList.tags.ContactTag @@ -54,8 +57,12 @@ class ContactListEvent( PubKeyHintProvider { override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + override fun pubKeyHints() = tags.mapNotNull(ContactTag::parseAsHint) + override fun linkedPubKeys() = tags.mapNotNull(ContactTag::parseKey) + /** * Returns a list of p-tags that are verified as hex keys. */ diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsEvent.kt index e9125efcc..d05879a26 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip03Timestamp/OtsEvent.kt @@ -45,6 +45,8 @@ class OtsEvent( EventHintProvider { override fun eventHints() = tags.mapNotNull(TargetEventTag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(TargetEventTag::parseId) + override fun isContentEncoded() = true fun digestEventId() = tags.firstNotNullOfOrNull(TargetEventTag::parseId) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip09Deletions/DeletionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip09Deletions/DeletionEvent.kt index 592949a0a..45df04bd0 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip09Deletions/DeletionEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip09Deletions/DeletionEvent.kt @@ -55,8 +55,12 @@ class DeletionEvent( AddressHintProvider { override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + fun deleteEvents() = taggedEvents() fun deleteEventIds() = taggedEventIds() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/BaseThreadedEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/BaseThreadedEvent.kt index e44910158..402bbb0bc 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/BaseThreadedEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/BaseThreadedEvent.kt @@ -23,27 +23,23 @@ package com.vitorpamplona.quartz.nip10Notes import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.HexKey -import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider -import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider -import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider -import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.tags.addressables.taggedATags -import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers import com.vitorpamplona.quartz.nip10Notes.content.findIndexTagsWithEventsOrAddresses import com.vitorpamplona.quartz.nip10Notes.content.findIndexTagsWithPeople import com.vitorpamplona.quartz.nip10Notes.content.findNostrUris import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag -import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip19Bech32.entities.Entity import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.nip19Bech32.entities.NEmbed import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent +import com.vitorpamplona.quartz.nip19Bech32.entities.NNote import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile import com.vitorpamplona.quartz.nip19Bech32.entities.NPub -import com.vitorpamplona.quartz.nip19Bech32.entities.Note import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent import com.vitorpamplona.quartz.utils.lastNotNullOfOrNull +import kotlin.collections.plus @Immutable open class BaseThreadedEvent( @@ -54,21 +50,15 @@ open class BaseThreadedEvent( tags: Array>, content: String, sig: HexKey, -) : Event(id, pubKey, createdAt, kind, tags, content, sig), - EventHintProvider, - AddressHintProvider, - PubKeyHintProvider { +) : Event(id, pubKey, createdAt, kind, tags, content, sig) { @Transient private var citedUsersCache: Set? = null @Transient private var citedNotesCache: Set? = null - override fun eventHints() = tags.mapNotNull(MarkedETag::parseAsHint) + tags.mapNotNull(QTag::parseEventAsHint) - - override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + tags.mapNotNull(QTag::parseAddressAsHint) - - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + @Transient + private var citedNIP19Cache: List? = null fun mentions() = taggedUsers() @@ -95,16 +85,6 @@ open class BaseThreadedEvent( ?: markedRoot()?.eventId ?: unmarkedReply()?.eventId - /* - Not sure if this is needed - open fun replyingToAddress(): ATag? { - val oldStylePositional = tags.lastOrNull { it.size > 1 && it.size <= 3 && it[0] == "a" }?.let { ATag.parseAtag(it[1], it[2]) } - val newStyleReply = tags.lastOrNull { it.size > 3 && it[0] == "a" && it[3] == "reply" }?.let { ATag.parseAtag(it[1], it[2]) } - val newStyleRoot = tags.lastOrNull { it.size > 3 && it[0] == "a" && it[3] == "root" }?.let { ATag.parseAtag(it[1], it[2]) } - - return newStyleReply ?: newStyleRoot ?: oldStylePositional - }*/ - open fun replyingToAddressOrEvent(): String? { val oldStylePositional = tags.lastOrNull { it.size > 1 && it.size <= 3 && (it[0] == "e" || it[0] == "a") }?.get(1) val newStyleReply = tags.lastOrNull { it.size > 3 && (it[0] == "e" || it[0] == "a") && it[3] == "reply" }?.get(1) @@ -113,6 +93,14 @@ open class BaseThreadedEvent( return newStyleReply ?: newStyleRoot ?: oldStylePositional } + fun citedNIP19(): List { + citedNIP19Cache?.let { + return it + } + + return findNostrUris(content).also { citedNIP19Cache = it } + } + fun citedUsers(): Set { citedUsersCache?.let { return it @@ -121,7 +109,7 @@ open class BaseThreadedEvent( val citedUsers = mutableSetOf() findIndexTagsWithPeople(content, tags, citedUsers) - findNostrUris(content).forEach { parsed -> + citedNIP19().forEach { parsed -> when (parsed) { is NProfile -> citedUsers.add(parsed.hex) is NPub -> citedUsers.add(parsed.hex) @@ -140,11 +128,11 @@ open class BaseThreadedEvent( val citations = mutableSetOf() findIndexTagsWithEventsOrAddresses(content, tags, citations).toMutableSet() - findNostrUris(content).forEach { entity -> + citedNIP19().forEach { entity -> when (entity) { is NEvent -> citations.add(entity.hex) is NAddress -> citations.add(entity.aTag()) - is Note -> citations.add(entity.hex) + is NNote -> citations.add(entity.hex) is NEmbed -> citations.add(entity.event.id) } } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/TextNoteEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/TextNoteEvent.kt index 8ef8ce6bb..061d7a26a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/TextNoteEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/TextNoteEvent.kt @@ -23,10 +23,31 @@ package com.vitorpamplona.quartz.nip10Notes import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder +import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle +import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate +import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag +import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag.Companion.parseAsHint +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag.Companion.parseAsHint +import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag +import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag.Companion.parseAsHint import com.vitorpamplona.quartz.nip10Notes.tags.markedETags import com.vitorpamplona.quartz.nip10Notes.tags.prepareETagsAsReplyTo +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseAddressAsHint +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseEventAsHint +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip31Alts.alt import com.vitorpamplona.quartz.utils.TimeUtils @@ -38,7 +59,56 @@ class TextNoteEvent( tags: Array>, content: String, sig: HexKey, -) : BaseThreadedEvent(id, pubKey, createdAt, KIND, tags, content, sig) { +) : BaseThreadedEvent(id, pubKey, createdAt, KIND, tags, content, sig), + EventHintProvider, + AddressHintProvider, + PubKeyHintProvider { + override fun eventHints(): List { + val eHints = tags.mapNotNull(MarkedETag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() + + return eHints + qHints + nip19Hints + } + + override fun linkedEventIds(): List { + val eHints = tags.mapNotNull(MarkedETag::parseId) + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return eHints + qHints + nip19Hints + } + + override fun addressHints(): List { + val aHints = tags.mapNotNull(ATag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return aHints + qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val aHints = tags.mapNotNull(ATag::parseAddressId) + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return aHints + qHints + nip19Hints + } + + override fun pubKeyHints(): List { + val pHints = tags.mapNotNull(PTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() + + return pHints + nip19Hints + } + + override fun linkedPubKeys(): List { + val pHints = tags.mapNotNull(PTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } + companion object { const val KIND = 1 const val ALT = "A short note: " diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt index 576b04b17..98870c374 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt @@ -104,7 +104,7 @@ data class MarkedETag( @JvmStatic fun parseId(tag: Array): HexKey? { - ensure(tag.has(2)) { return null } + ensure(tag.has(1)) { return null } ensure(tag[0] == TAG_NAME) { return null } ensure(tag[1].length == 64) { return null } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/BaseDMGroupEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/BaseDMGroupEvent.kt index 81f7ad813..807329a8b 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/BaseDMGroupEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/base/BaseDMGroupEvent.kt @@ -42,6 +42,8 @@ open class BaseDMGroupEvent( PubKeyHintProvider { override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + /** Recipients intended to receive this conversation */ fun recipients() = tags.mapNotNull(PTag::parse) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/GenericRepostEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/GenericRepostEvent.kt index 2439e25cf..a47bbd275 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/GenericRepostEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/GenericRepostEvent.kt @@ -56,10 +56,16 @@ class GenericRepostEvent( AddressHintProvider { override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + fun boostedEvents() = tags.mapNotNull(ETag::parse) fun boostedATags() = tags.mapNotNull(ATag::parse) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/RepostEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/RepostEvent.kt index 05aa903e4..8dbb539c1 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/RepostEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/RepostEvent.kt @@ -39,6 +39,7 @@ import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip01Core.tags.people.pTag import com.vitorpamplona.quartz.nip31Alts.alt import com.vitorpamplona.quartz.utils.TimeUtils +import kotlin.collections.mapNotNull @Immutable class RepostEvent( @@ -54,10 +55,16 @@ class RepostEvent( AddressHintProvider { override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + fun boostedEvents() = tags.mapNotNull(ETag::parse) fun boostedATags() = tags.mapNotNull(ATag::parse) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/EntityExt.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/EntityExt.kt index f9e3d746a..927eb0c87 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/EntityExt.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/EntityExt.kt @@ -26,10 +26,9 @@ import com.vitorpamplona.quartz.nip01Core.tags.events.ETag import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.nip19Bech32.entities.NEmbed import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent -import com.vitorpamplona.quartz.nip19Bech32.entities.Note -import org.apache.commons.lang3.text.translate.CharSequenceTranslator.hex +import com.vitorpamplona.quartz.nip19Bech32.entities.NNote -fun Note.toQuoteTag() = QEventTag(hex, null, null) +fun NNote.toQuoteTag() = QEventTag(hex, null, null) fun NEvent.toQuoteTag() = QEventTag(hex, relay.firstOrNull(), author) @@ -42,7 +41,7 @@ fun NEmbed.toQuoteTag() = QEventTag(event.id, null, event.pubKey) } -fun Note.toQuoteTagArray() = QEventTag.assemble(hex, null, null) +fun NNote.toQuoteTagArray() = QEventTag.assemble(hex, null, null) fun NEvent.toQuoteTagArray() = QEventTag.assemble(hex, relay.firstOrNull(), author) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt index ae275a8dc..14c74e3af 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt @@ -63,12 +63,20 @@ interface QTag { } @JvmStatic - fun parseKey(tag: Array): String? { + fun parseId(tag: Array): String? { ensure(tag.has(1)) { return null } ensure(tag[0] == TAG_NAME) { return null } return tag[1] } + @JvmStatic + fun parseEventId(tag: Array): HexKey? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + return tag[1] + } + @JvmStatic fun parseEventAsHint(tag: Array): EventIdHint? { ensure(tag.has(2)) { return null } @@ -82,6 +90,14 @@ interface QTag { return EventIdHint(tag[1], relayHint) } + fun parseAddressId(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length != 64) { return null } + ensure(!tag[1].contains(':')) { return null } + return tag[1] + } + @JvmStatic fun parseAddressAsHint(tag: Array): AddressHint? { ensure(tag.has(2)) { return null } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayBuilderExt.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayBuilderExt.kt index 11a1f3c93..74aea66ea 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayBuilderExt.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayBuilderExt.kt @@ -27,9 +27,9 @@ import com.vitorpamplona.quartz.nip19Bech32.entities.Entity import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.nip19Bech32.entities.NEmbed import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent +import com.vitorpamplona.quartz.nip19Bech32.entities.NNote import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile import com.vitorpamplona.quartz.nip19Bech32.entities.NPub -import com.vitorpamplona.quartz.nip19Bech32.entities.Note fun TagArrayBuilder.quote(tag: QTag) = add(tag.toTagArray()) @@ -37,7 +37,7 @@ fun TagArrayBuilder.quotes(tag: List) = addAll(tag.map { it fun TagArrayBuilder.quote(entity: Entity) = when (entity) { - is Note -> add(entity.toQuoteTagArray()) + is NNote -> add(entity.toQuoteTagArray()) is NEvent -> add(entity.toQuoteTagArray()) is NAddress -> add(entity.toQuoteTagArray()) is NEmbed -> add(entity.toQuoteTagArray()) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayExt.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayExt.kt index ffd0bd5f7..84a46fcc7 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayExt.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/TagArrayExt.kt @@ -32,7 +32,7 @@ fun TagArray.mapTaggedQuoteId(map: (eventId: HexKey) -> R) = this.mapValueTa fun TagArray.taggedQuotes() = this.mapNotNull(QTag::parse) -fun TagArray.taggedQuoteIds() = this.mapNotNull(QTag::parseKey) +fun TagArray.taggedQuoteIds() = this.mapNotNull(QTag::parseId) fun TagArray.firstTaggedQuote() = this.firstNotNullOfOrNull(QTag.Companion::parse) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/ListEntityExt.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/ListEntityExt.kt new file mode 100644 index 000000000..38ec04492 --- /dev/null +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/ListEntityExt.kt @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.nip19Bech32 + +import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent +import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint +import com.vitorpamplona.quartz.nip19Bech32.entities.Entity +import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress +import com.vitorpamplona.quartz.nip19Bech32.entities.NEmbed +import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent +import com.vitorpamplona.quartz.nip19Bech32.entities.NNote +import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile +import com.vitorpamplona.quartz.nip19Bech32.entities.NPub +import com.vitorpamplona.quartz.nip19Bech32.entities.NSec +import org.apache.commons.lang3.text.translate.CharSequenceTranslator.hex +import kotlin.collections.mapNotNull + +fun NEvent.toEventHint() = relay.map { EventIdHint(hex, it) } + +fun NAddress.toAddressHint() = relay.map { AddressHint(aTag(), it) } + +fun NProfile.toPubKeyHint() = relay.map { PubKeyHint(hex, it) } + +fun List.eventHints(): List = + mapNotNull { entity -> + if (entity is NEvent) { + entity.toEventHint() + } else { + null + } + }.flatten() + +fun List.eventIds(): List = + mapNotNull { entity -> + when (entity) { + is NEvent -> entity.hex + is NNote -> entity.hex + is NEmbed -> entity.event.id + else -> null + } + } + +fun List.addressHints(): List = + mapNotNull { entity -> + if (entity is NAddress) { + entity.toAddressHint() + } else { + null + } + }.flatten() + +fun List.addressIds(): List = + mapNotNull { entity -> + when (entity) { + is NAddress -> entity.aTag() + is NEmbed -> if (entity.event is AddressableEvent) entity.event.addressTag() else null + else -> null + } + } + +fun List.pubKeyHints(): List = + mapNotNull { entity -> + if (entity is NProfile) { + entity.relay.map { PubKeyHint(entity.hex, it) } + } else { + null + } + }.flatten() + +fun List.pubKeys(): List = + mapNotNull { entity -> + when (entity) { + is NProfile -> entity.hex + is NPub -> entity.hex + is NSec -> entity.hex + else -> null + } + } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/Nip19Parser.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/Nip19Parser.kt index 140706a7c..4afd159f6 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/Nip19Parser.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/Nip19Parser.kt @@ -31,11 +31,11 @@ import com.vitorpamplona.quartz.nip19Bech32.entities.Entity import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.nip19Bech32.entities.NEmbed import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent +import com.vitorpamplona.quartz.nip19Bech32.entities.NNote import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile import com.vitorpamplona.quartz.nip19Bech32.entities.NPub import com.vitorpamplona.quartz.nip19Bech32.entities.NRelay import com.vitorpamplona.quartz.nip19Bech32.entities.NSec -import com.vitorpamplona.quartz.nip19Bech32.entities.Note import com.vitorpamplona.quartz.utils.Hex import kotlinx.coroutines.CancellationException import java.util.regex.Pattern @@ -121,7 +121,7 @@ object Nip19Parser { when (type.lowercase()) { "nsec1" -> NSec.parse(bytes) "npub1" -> NPub.parse(bytes) - "note1" -> Note.parse(bytes) + "note1" -> NNote.parse(bytes) "nprofile1" -> NProfile.parse(bytes) "nevent1" -> NEvent.parse(bytes) "nrelay1" -> NRelay.parse(bytes) @@ -177,7 +177,7 @@ fun decodePrivateKeyAsHexOrNull(key: String): HexKey? = is NSec -> parsed.hex is NPub -> null is NProfile -> null - is Note -> null + is NNote -> null is NEvent -> null is NEmbed -> null is NRelay -> null @@ -195,7 +195,7 @@ fun decodePublicKeyAsHexOrNull(key: String): HexKey? = is NSec -> Nip01.pubKeyCreate(parsed.hex.hexToByteArray()).toHexKey() is NPub -> parsed.hex is NProfile -> parsed.hex - is Note -> null + is NNote -> null is NEvent -> null is NEmbed -> null is NRelay -> null @@ -213,7 +213,7 @@ fun decodeEventIdAsHexOrNull(key: String): HexKey? = is NSec -> null is NPub -> null is NProfile -> null - is Note -> parsed.hex + is NNote -> parsed.hex is NEvent -> parsed.hex is NAddress -> parsed.aTag() is NEmbed -> null diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/Note.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NNote.kt similarity index 92% rename from quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/Note.kt rename to quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NNote.kt index 6ac4c7c14..89bb869e8 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/Note.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip19Bech32/entities/NNote.kt @@ -27,13 +27,13 @@ import com.vitorpamplona.quartz.nip01Core.core.toHexKey import com.vitorpamplona.quartz.nip19Bech32.toNote @Immutable -data class Note( +data class NNote( val hex: String, ) : Entity { - companion object { - fun parse(bytes: ByteArray): Note? { + companion object Companion { + fun parse(bytes: ByteArray): NNote? { if (bytes.isEmpty()) return null - return Note(bytes.toHexKey()) + return NNote(bytes.toHexKey()) } fun create(eventId: HexKey): String = eventId.hexToByteArray().toNote() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt index 0aaf57f23..7713994ea 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt @@ -29,9 +29,24 @@ import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate +import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag.Companion.parseAsHint import com.vitorpamplona.quartz.nip01Core.tags.geohash.GeoHashTag +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag.Companion.parseAsHint import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent +import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag.Companion.parseAsHint +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseAddressAsHint +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseEventAsHint +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip21UriScheme.toNostrUri import com.vitorpamplona.quartz.nip22Comments.tags.ReplyAddressTag import com.vitorpamplona.quartz.nip22Comments.tags.ReplyAuthorTag @@ -62,11 +77,55 @@ class CommentEvent( EventHintProvider, PubKeyHintProvider, AddressHintProvider { - override fun pubKeyHints() = tags.mapNotNull(RootAuthorTag::parseAsHint) + tags.mapNotNull(ReplyAuthorTag::parseAsHint) + override fun pubKeyHints(): List { + val pHints = + tags.mapNotNull(RootAuthorTag::parseAsHint) + + tags.mapNotNull(ReplyAuthorTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() - override fun eventHints() = tags.mapNotNull(RootEventTag::parseAsHint) + tags.mapNotNull(ReplyEventTag::parseAsHint) + return pHints + nip19Hints + } - override fun addressHints() = tags.mapNotNull(RootAddressTag::parseAsHint) + tags.mapNotNull(ReplyAddressTag::parseAsHint) + override fun linkedPubKeys(): List { + val pHints = + tags.mapNotNull(RootAuthorTag::parseKey) + + tags.mapNotNull(ReplyAuthorTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } + + override fun eventHints(): List { + val eHints = tags.mapNotNull(RootEventTag::parseAsHint) + tags.mapNotNull(ReplyEventTag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() + + return eHints + qHints + nip19Hints + } + + override fun linkedEventIds(): List { + val eHints = tags.mapNotNull(RootEventTag::parseKey) + tags.mapNotNull(ReplyEventTag::parseKey) + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return eHints + qHints + nip19Hints + } + + override fun addressHints(): List { + val aHints = tags.mapNotNull(RootAddressTag::parseAsHint) + tags.mapNotNull(ReplyAddressTag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return aHints + qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val aHints = tags.mapNotNull(RootAddressTag::parseAddressId) + tags.mapNotNull(ReplyAddressTag::parseAddressId) + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return aHints + qHints + nip19Hints + } fun rootAuthor() = tags.firstNotNullOfOrNull(RootAuthorTag::parse) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/LongTextNoteEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/LongTextNoteEvent.kt index e130211f1..4a026c577 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/LongTextNoteEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/LongTextNoteEvent.kt @@ -27,6 +27,9 @@ import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag @@ -35,7 +38,14 @@ import com.vitorpamplona.quartz.nip01Core.tags.dTags.dTag import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent +import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag.Companion.parseAsHint import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip22Comments.RootScope import com.vitorpamplona.quartz.nip23LongContent.tags.ImageTag import com.vitorpamplona.quartz.nip23LongContent.tags.PublishedAtTag @@ -59,11 +69,47 @@ class LongTextNoteEvent( PubKeyHintProvider, AddressHintProvider, RootScope { - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun eventHints(): List { + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() - override fun eventHints() = tags.mapNotNull(QTag::parseEventAsHint) + return qHints + nip19Hints + } - override fun addressHints() = tags.mapNotNull(QTag::parseAddressAsHint) + override fun linkedEventIds(): List { + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return qHints + nip19Hints + } + + override fun addressHints(): List { + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return qHints + nip19Hints + } + + override fun pubKeyHints(): List { + val pHints = tags.mapNotNull(PTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() + + return pHints + nip19Hints + } + + override fun linkedPubKeys(): List { + val pHints = tags.mapNotNull(PTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } override fun dTag() = tags.dTag() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip25Reactions/ReactionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip25Reactions/ReactionEvent.kt index 5fc3948b1..3c11b0d01 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip25Reactions/ReactionEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip25Reactions/ReactionEvent.kt @@ -54,10 +54,16 @@ class ReactionEvent( AddressHintProvider { override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + fun originalPost() = tags.mapNotNull(ETag::parseId) fun originalAuthor() = tags.mapNotNull(PTag::parseKey) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelCreateEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelCreateEvent.kt index c7164a668..5953c078a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelCreateEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelCreateEvent.kt @@ -48,6 +48,8 @@ class ChannelCreateEvent( EventHintProvider { override fun eventHints() = channelInfo().relays?.map { EventIdHint(id, it) } ?: emptyList() + override fun linkedEventIds() = listOf(id) + fun channelInfo(): ChannelDataNorm = try { ChannelData.parse(content)?.normalize() ?: ChannelDataNorm() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelHideMessageEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelHideMessageEvent.kt index eaa611d32..66b579577 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelHideMessageEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelHideMessageEvent.kt @@ -46,6 +46,8 @@ class ChannelHideMessageEvent( EventHintProvider { override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + fun eventsToHide() = tags.taggedEventIds() companion object { diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMetadataEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMetadataEvent.kt index d46c0ece8..6446edcef 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMetadataEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMetadataEvent.kt @@ -48,7 +48,12 @@ class ChannelMetadataEvent( sig: HexKey, ) : BasePublicChatEvent(id, pubKey, createdAt, KIND, tags, content, sig), EventHintProvider { - override fun eventHints() = channelInfo().relays?.map { EventIdHint(id, it) } ?: emptyList() + override fun eventHints() = + channelInfo().relays?.mapNotNull { relay -> + channelId()?.let { EventIdHint(it, relay) } + } ?: emptyList() + + override fun linkedEventIds() = channelId()?.let { listOf(it) } ?: emptyList() fun channelInfo(): ChannelDataNorm = try { diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMuteUserEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMuteUserEvent.kt index 634e9e847..3d3b96403 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMuteUserEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/admin/ChannelMuteUserEvent.kt @@ -46,6 +46,8 @@ class ChannelMuteUserEvent( PubKeyHintProvider { override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + fun usersToMute() = tags.taggedUserIds() companion object { diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/message/ChannelMessageEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/message/ChannelMessageEvent.kt index 37ff66f2b..32fd1e3ce 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/message/ChannelMessageEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip28PublicChat/message/ChannelMessageEvent.kt @@ -24,11 +24,32 @@ import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder import com.vitorpamplona.quartz.nip01Core.core.tagArray +import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle +import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate +import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag +import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag.Companion.parseAsHint import com.vitorpamplona.quartz.nip01Core.tags.events.ETag +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag.Companion.parseAsHint import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent +import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag +import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag.Companion.parseAsHint import com.vitorpamplona.quartz.nip10Notes.tags.markedETag +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseAddressAsHint +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseEventAsHint +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent import com.vitorpamplona.quartz.nip28PublicChat.base.IsInPublicChatChannel import com.vitorpamplona.quartz.nip28PublicChat.base.channel @@ -46,7 +67,56 @@ class ChannelMessageEvent( sig: HexKey, ) : BaseThreadedEvent(id, pubKey, createdAt, KIND, tags, content, sig), IsInPublicChatChannel, - ExposeInDraft { + ExposeInDraft, + EventHintProvider, + AddressHintProvider, + PubKeyHintProvider { + override fun eventHints(): List { + val eHints = tags.mapNotNull(MarkedETag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() + + return eHints + qHints + nip19Hints + } + + override fun linkedEventIds(): List { + val eHints = tags.mapNotNull(MarkedETag::parseId) + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return eHints + qHints + nip19Hints + } + + override fun addressHints(): List { + val aHints = tags.mapNotNull(ATag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return aHints + qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val aHints = tags.mapNotNull(ATag::parseAddressId) + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return aHints + qHints + nip19Hints + } + + override fun pubKeyHints(): List { + val pHints = tags.mapNotNull(PTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() + + return pHints + nip19Hints + } + + override fun linkedPubKeys(): List { + val pHints = tags.mapNotNull(PTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } + override fun channel() = markedRoot() ?: unmarkedRoot() override fun channelId() = channel()?.eventId diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt index a4c62ff18..e4073aa41 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt @@ -46,6 +46,8 @@ class EmojiPackSelectionEvent( AddressHintProvider { override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + fun emojiPacks() = tags.mapNotNull(ATag::parseAddress) fun emojiPackIds() = tags.mapNotNull(ATag::parseAddressId) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/issue/GitIssueEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/issue/GitIssueEvent.kt index 806685606..e5f90580b 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/issue/GitIssueEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/issue/GitIssueEvent.kt @@ -27,13 +27,23 @@ import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag +import com.vitorpamplona.quartz.nip01Core.tags.events.ETag.Companion.parseAsHint import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent import com.vitorpamplona.quartz.nip14Subject.SubjectTag import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip31Alts.alt import com.vitorpamplona.quartz.nip34Git.repository.GitRepositoryEvent import com.vitorpamplona.quartz.utils.TimeUtils @@ -50,11 +60,49 @@ class GitIssueEvent( PubKeyHintProvider, EventHintProvider, AddressHintProvider { - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun eventHints(): List { + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() - override fun eventHints() = tags.mapNotNull(QTag::parseEventAsHint) + return qHints + nip19Hints + } - override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + tags.mapNotNull(QTag::parseAddressAsHint) + override fun linkedEventIds(): List { + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return qHints + nip19Hints + } + + override fun addressHints(): List { + val aHints = tags.mapNotNull(ATag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return aHints + qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val aHints = tags.mapNotNull(ATag::parseAddressId) + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return aHints + qHints + nip19Hints + } + + override fun pubKeyHints(): List { + val pHints = tags.mapNotNull(PTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() + + return pHints + nip19Hints + } + + override fun linkedPubKeys(): List { + val pHints = tags.mapNotNull(PTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } fun repositoryHex() = tags.firstNotNullOfOrNull(ATag::parseAddressId) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/patch/GitPatchEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/patch/GitPatchEvent.kt index 243ec363b..dd87ff02b 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/patch/GitPatchEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/patch/GitPatchEvent.kt @@ -29,6 +29,8 @@ import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address +import com.vitorpamplona.quartz.nip01Core.tags.events.ETag.Companion.parseAsHint +import com.vitorpamplona.quartz.nip01Core.tags.events.ETag.Companion.parseId import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag import com.vitorpamplona.quartz.nip31Alts.AltTag @@ -48,10 +50,16 @@ class GitPatchEvent( AddressHintProvider { override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(MarkedETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(MarkedETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + private fun innerRepository() = tags.firstOrNull { it.size > 3 && it[0] == "a" && it[3] == "root" } ?: tags.firstOrNull { it.size > 1 && it[0] == "a" } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/reply/GitReplyEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/reply/GitReplyEvent.kt index 9e7ccb409..894d6701a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/reply/GitReplyEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/reply/GitReplyEvent.kt @@ -27,14 +27,25 @@ import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag +import com.vitorpamplona.quartz.nip01Core.tags.events.ETag +import com.vitorpamplona.quartz.nip01Core.tags.events.ETag.Companion.parseAsHint import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag import com.vitorpamplona.quartz.nip10Notes.tags.markedETags import com.vitorpamplona.quartz.nip10Notes.tags.prepareMarkedETagsAsReplyTo import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip34Git.issue.GitIssueEvent import com.vitorpamplona.quartz.nip34Git.patch.GitPatchEvent import com.vitorpamplona.quartz.utils.TimeUtils @@ -53,11 +64,51 @@ class GitReplyEvent( PubKeyHintProvider, EventHintProvider, AddressHintProvider { - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun eventHints(): List { + val eHints = tags.mapNotNull(ETag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() - override fun eventHints() = tags.mapNotNull(MarkedETag::parseAsHint) + tags.mapNotNull(QTag::parseEventAsHint) + return eHints + qHints + nip19Hints + } - override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + tags.mapNotNull(QTag::parseAddressAsHint) + override fun linkedEventIds(): List { + val eHints = tags.mapNotNull(ETag::parseId) + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return eHints + qHints + nip19Hints + } + + override fun addressHints(): List { + val aHints = tags.mapNotNull(ATag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return aHints + qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val aHints = tags.mapNotNull(ATag::parseAddressId) + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return aHints + qHints + nip19Hints + } + + override fun pubKeyHints(): List { + val pHints = tags.mapNotNull(PTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() + + return pHints + nip19Hints + } + + override fun linkedPubKeys(): List { + val pHints = tags.mapNotNull(PTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } fun repositoryHex() = tags.firstNotNullOfOrNull(ATag::parseAddressId) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/TorrentCommentEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/TorrentCommentEvent.kt index 99b8fc251..9ef7531d3 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/TorrentCommentEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/TorrentCommentEvent.kt @@ -27,8 +27,12 @@ import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate +import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag.Companion.parseAsHint import com.vitorpamplona.quartz.nip01Core.tags.events.ETag import com.vitorpamplona.quartz.nip01Core.tags.events.eTags import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEvents @@ -37,6 +41,12 @@ import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag import com.vitorpamplona.quartz.nip10Notes.tags.positionalMarkedTags import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip31Alts.alt import com.vitorpamplona.quartz.utils.TimeUtils @@ -53,11 +63,49 @@ class TorrentCommentEvent( EventHintProvider, PubKeyHintProvider, AddressHintProvider { - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun eventHints(): List { + val eHints = tags.mapNotNull(MarkedETag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() - override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + tags.mapNotNull(QTag::parseEventAsHint) + return eHints + qHints + nip19Hints + } - override fun addressHints() = tags.mapNotNull(QTag::parseAddressAsHint) + override fun linkedEventIds(): List { + val eHints = tags.mapNotNull(MarkedETag::parseId) + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return eHints + qHints + nip19Hints + } + + override fun addressHints(): List { + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return qHints + nip19Hints + } + + override fun pubKeyHints(): List { + val pHints = tags.mapNotNull(PTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() + + return pHints + nip19Hints + } + + override fun linkedPubKeys(): List { + val pHints = tags.mapNotNull(PTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } fun torrent() = tags.firstNotNullOfOrNull(MarkedETag::parseRoot) ?: tags.firstNotNullOfOrNull(ETag::parse) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/DraftEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/DraftEvent.kt index 5e2d0dade..e785d00fa 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/DraftEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip37Drafts/DraftEvent.kt @@ -58,11 +58,17 @@ class DraftEvent( EventHintProvider, AddressHintProvider, PubKeyHintProvider { + override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) @Transient private var cachedInnerEvent: Map = mapOf() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/GeneralListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/GeneralListEvent.kt index e50c41beb..20e773840 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/GeneralListEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip51Lists/GeneralListEvent.kt @@ -56,10 +56,16 @@ abstract class GeneralListEvent( PubKeyHintProvider { override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + (cachedPrivateTags()?.mapNotNull(ETag::parseAsHint) ?: emptyList()) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + (cachedPrivateTags()?.mapNotNull(ETag::parseId) ?: emptyList()) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + (cachedPrivateTags()?.mapNotNull(ATag::parseAsHint) ?: emptyList()) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + (cachedPrivateTags()?.mapNotNull(ATag::parseAddressId) ?: emptyList()) + override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + (cachedPrivateTags()?.mapNotNull(PTag::parseAsHint) ?: emptyList()) + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + (cachedPrivateTags()?.mapNotNull(PTag::parseKey) ?: emptyList()) + fun name() = tags.firstNotNullOfOrNull(NameTag::parse) @Deprecated("NIP-51 has deprecated Title. Use name instead", ReplaceWith("name()")) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/chat/LiveActivitiesChatMessageEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/chat/LiveActivitiesChatMessageEvent.kt index e15892394..11ef4ec95 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/chat/LiveActivitiesChatMessageEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/chat/LiveActivitiesChatMessageEvent.kt @@ -28,6 +28,9 @@ import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.tags.addressables.aTag @@ -36,6 +39,12 @@ import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent import com.vitorpamplona.quartz.nip10Notes.tags.markedETag import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip37Drafts.ExposeInDraft import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent import com.vitorpamplona.quartz.utils.TimeUtils @@ -53,11 +62,51 @@ class LiveActivitiesChatMessageEvent( PubKeyHintProvider, AddressHintProvider, ExposeInDraft { - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun eventHints(): List { + val eHints = tags.mapNotNull(ETag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() - override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + tags.mapNotNull(QTag::parseEventAsHint) + return eHints + qHints + nip19Hints + } - override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + tags.mapNotNull(QTag::parseAddressAsHint) + override fun linkedEventIds(): List { + val eHints = tags.mapNotNull(ETag::parseId) + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return eHints + qHints + nip19Hints + } + + override fun addressHints(): List { + val aHints = tags.mapNotNull(ATag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return aHints + qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val aHints = tags.mapNotNull(ATag::parseAddressId) + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return aHints + qHints + nip19Hints + } + + override fun pubKeyHints(): List { + val pHints = tags.mapNotNull(PTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() + + return pHints + nip19Hints + } + + override fun linkedPubKeys(): List { + val pHints = tags.mapNotNull(PTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } private fun activityHex() = tags.firstNotNullOfOrNull(ATag::parseAddressId) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/LiveActivitiesEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/LiveActivitiesEvent.kt index df9a1dc4c..293865dc3 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/LiveActivitiesEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/LiveActivitiesEvent.kt @@ -33,6 +33,7 @@ import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag.Companion.parse import com.vitorpamplona.quartz.nip01Core.tags.events.ETag import com.vitorpamplona.quartz.nip01Core.tags.events.ETag.Companion.parseAsHint import com.vitorpamplona.quartz.nip01Core.tags.people.PTag.Companion.parseAsHint +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag.Companion.parseKey import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseAddressAsHint import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseEventAsHint @@ -65,10 +66,16 @@ class LiveActivitiesEvent( PubKeyHintProvider { override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + tags.mapNotNull(QTag::parseEventAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + tags.mapNotNull(QTag::parseEventId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + tags.mapNotNull(QTag::parseAddressAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + tags.mapNotNull(QTag::parseAddressId) + override fun pubKeyHints() = tags.mapNotNull(ParticipantTag::parseAsHint) + override fun linkedPubKeys() = tags.mapNotNull(ParticipantTag::parseKey) + fun title() = tags.firstNotNullOfOrNull(TitleTag::parse) fun summary() = tags.firstNotNullOfOrNull(SummaryTag::parse) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip54Wiki/WikiNoteEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip54Wiki/WikiNoteEvent.kt index 823edee0d..cc490826a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip54Wiki/WikiNoteEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip54Wiki/WikiNoteEvent.kt @@ -23,13 +23,28 @@ package com.vitorpamplona.quartz.nip54Wiki import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address import com.vitorpamplona.quartz.nip01Core.tags.dTags.dTag import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent +import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag +import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip31Alts.AltTag import com.vitorpamplona.quartz.utils.TimeUtils @@ -42,7 +57,56 @@ class WikiNoteEvent( content: String, sig: HexKey, ) : BaseThreadedEvent(id, pubKey, createdAt, KIND, tags, content, sig), - AddressableEvent { + AddressableEvent, + EventHintProvider, + AddressHintProvider, + PubKeyHintProvider { + override fun eventHints(): List { + val eHints = tags.mapNotNull(MarkedETag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() + + return eHints + qHints + nip19Hints + } + + override fun linkedEventIds(): List { + val eHints = tags.mapNotNull(MarkedETag::parseId) + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return eHints + qHints + nip19Hints + } + + override fun addressHints(): List { + val aHints = tags.mapNotNull(ATag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return aHints + qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val aHints = tags.mapNotNull(ATag::parseAddressId) + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return aHints + qHints + nip19Hints + } + + override fun pubKeyHints(): List { + val pHints = tags.mapNotNull(PTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() + + return pHints + nip19Hints + } + + override fun linkedPubKeys(): List { + val pHints = tags.mapNotNull(PTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } + override fun dTag() = tags.dTag() override fun aTag(relayHint: NormalizedRelayUrl?) = ATag(kind, pubKey, dTag(), relayHint) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapEvent.kt index 28c669c91..245d0aa91 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapEvent.kt @@ -51,11 +51,17 @@ class LnZapEvent( EventHintProvider, AddressHintProvider, PubKeyHintProvider { + override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) // This event is also kept in LocalCache (same object) @Transient val zapRequest: LnZapRequestEvent? diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapPrivateEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapPrivateEvent.kt index 071f95c14..edbe70ff1 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapPrivateEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapPrivateEvent.kt @@ -48,11 +48,17 @@ class LnZapPrivateEvent( EventHintProvider, AddressHintProvider, PubKeyHintProvider { + override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) companion object { const val KIND = 9733 diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt index 8df671132..04a7d450d 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/LnZapRequestEvent.kt @@ -52,11 +52,17 @@ class LnZapRequestEvent( EventHintProvider, AddressHintProvider, PubKeyHintProvider { + override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) @Transient private var privateZapEvent: LnZapPrivateEvent? = null diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeAwardEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeAwardEvent.kt index be7996a23..519b13206 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeAwardEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeAwardEvent.kt @@ -48,11 +48,17 @@ class BadgeAwardEvent( EventHintProvider, AddressHintProvider, PubKeyHintProvider { + override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) fun awardees() = taggedUsers() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeProfilesEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeProfilesEvent.kt index 9488881d9..84ab8aa2b 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeProfilesEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip58Badges/BadgeProfilesEvent.kt @@ -47,11 +47,17 @@ class BadgeProfilesEvent( EventHintProvider, AddressHintProvider, PubKeyHintProvider { + override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) fun badgeAwardEvents() = taggedEvents() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/CommunityPostApprovalEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/CommunityPostApprovalEvent.kt index 726a0b819..8cb0fb897 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/CommunityPostApprovalEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/approval/CommunityPostApprovalEvent.kt @@ -44,6 +44,8 @@ import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseAddressAsHint import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseEventAsHint import com.vitorpamplona.quartz.nip31Alts.alt +import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ParticipantTag.Companion.parseAsHint +import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ParticipantTag.Companion.parseKey import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent import com.vitorpamplona.quartz.utils.TimeUtils @@ -61,10 +63,16 @@ class CommunityPostApprovalEvent( PubKeyHintProvider { override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + tags.mapNotNull(QTag::parseEventAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + tags.mapNotNull(QTag::parseEventId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + tags.mapNotNull(QTag::parseAddressAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + tags.mapNotNull(QTag::parseAddressId) + override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + fun containedPost(): Event? = try { content.ifBlank { null }?.let { fromJson(it) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/CommunityDefinitionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/CommunityDefinitionEvent.kt index 51feebe0d..c18c9b1a2 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/CommunityDefinitionEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/CommunityDefinitionEvent.kt @@ -39,6 +39,8 @@ import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseAddressAsHint import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseEventAsHint import com.vitorpamplona.quartz.nip31Alts.alt +import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ParticipantTag.Companion.parseAsHint +import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ParticipantTag.Companion.parseKey import com.vitorpamplona.quartz.nip72ModCommunities.definition.tags.DescriptionTag import com.vitorpamplona.quartz.nip72ModCommunities.definition.tags.ImageTag import com.vitorpamplona.quartz.nip72ModCommunities.definition.tags.ModeratorTag @@ -62,13 +64,19 @@ class CommunityDefinitionEvent( PubKeyHintProvider { override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + tags.mapNotNull(QTag::parseEventAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + tags.mapNotNull(QTag::parseEventId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + tags.mapNotNull(QTag::parseAddressAsHint) + - tags.mapNotNull(RelayTag::parse).mapNotNull { AddressHint(addressTag(), it.url) } + tags.mapNotNull(RelayTag::parse).map { AddressHint(addressTag(), it.url) } + + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) + tags.mapNotNull(QTag::parseAddressId) override fun pubKeyHints() = tags.mapNotNull(ModeratorTag::parseAsHint) + override fun linkedPubKeys() = tags.mapNotNull(ModeratorTag::parseKey) + fun name() = tags.firstNotNullOfOrNull(NameTag::parse) fun description() = tags.firstNotNullOfOrNull(DescriptionTag::parse) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt index ba33b8abb..2bccc4790 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt @@ -28,7 +28,6 @@ import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer import com.vitorpamplona.quartz.nip01Core.tags.people.PubKeyReferenceTag -import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ParticipantTag import com.vitorpamplona.quartz.utils.arrayOfNotNull import com.vitorpamplona.quartz.utils.ensure @@ -65,7 +64,7 @@ data class ModeratorTag( @JvmStatic fun parseAsHint(tag: Array): PubKeyHint? { ensure(tag.has(2)) { return null } - ensure(tag[0] == ParticipantTag.Companion.TAG_NAME) { return null } + ensure(tag[0] == TAG_NAME) { return null } ensure(tag[1].length == 64) { return null } ensure(tag[2].isNotEmpty()) { return null } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/GoalEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/GoalEvent.kt index f55600e48..7ee4f5440 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/GoalEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/GoalEvent.kt @@ -59,11 +59,17 @@ class GoalEvent( EventHintProvider, AddressHintProvider, PubKeyHintProvider { + override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + + override fun linkedPubKeys() = tags.mapNotNull(PTag::parseKey) + override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + override fun linkedEventIds() = tags.mapNotNull(ETag::parseId) + override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId) fun topics() = hashtags() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/HighlightEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/HighlightEvent.kt index 7fbad7d95..d1c17157e 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/HighlightEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/HighlightEvent.kt @@ -25,6 +25,9 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider +import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint +import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag.Companion.parseAsHint @@ -41,6 +44,12 @@ import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag.Companion.parseAsHint import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseAddressAsHint import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag.Companion.parseEventAsHint +import com.vitorpamplona.quartz.nip19Bech32.addressHints +import com.vitorpamplona.quartz.nip19Bech32.addressIds +import com.vitorpamplona.quartz.nip19Bech32.eventHints +import com.vitorpamplona.quartz.nip19Bech32.eventIds +import com.vitorpamplona.quartz.nip19Bech32.pubKeyHints +import com.vitorpamplona.quartz.nip19Bech32.pubKeys import com.vitorpamplona.quartz.nip22Comments.RootScope import com.vitorpamplona.quartz.nip31Alts.AltTag import com.vitorpamplona.quartz.nip84Highlights.tags.CommentTag @@ -60,11 +69,51 @@ class HighlightEvent( EventHintProvider, AddressHintProvider, PubKeyHintProvider { - override fun eventHints() = tags.mapNotNull(ETag::parseAsHint) + tags.mapNotNull(QTag::parseEventAsHint) + override fun eventHints(): List { + val eHints = tags.mapNotNull(ETag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseEventAsHint) + val nip19Hints = citedNIP19().eventHints() - override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) + tags.mapNotNull(QTag::parseAddressAsHint) + return eHints + qHints + nip19Hints + } - override fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint) + override fun linkedEventIds(): List { + val eHints = tags.mapNotNull(ETag::parseId) + val qHints = tags.mapNotNull(QTag::parseEventId) + val nip19Hints = citedNIP19().eventIds() + + return eHints + qHints + nip19Hints + } + + override fun addressHints(): List { + val aHints = tags.mapNotNull(ATag::parseAsHint) + val qHints = tags.mapNotNull(QTag::parseAddressAsHint) + val nip19Hints = citedNIP19().addressHints() + + return aHints + qHints + nip19Hints + } + + override fun linkedAddressIds(): List { + val aHints = tags.mapNotNull(ATag::parseAddressId) + val qHints = tags.mapNotNull(QTag::parseAddressId) + val nip19Hints = citedNIP19().addressIds() + + return aHints + qHints + nip19Hints + } + + override fun pubKeyHints(): List { + val pHints = tags.mapNotNull(PTag::parseAsHint) + val nip19Hints = citedNIP19().pubKeyHints() + + return pHints + nip19Hints + } + + override fun linkedPubKeys(): List { + val pHints = tags.mapNotNull(PTag::parseKey) + val nip19Hints = citedNIP19().pubKeys() + + return pHints + nip19Hints + } fun inUrl() = tags.firstNotNullOfOrNull(ReferenceTag::parse) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt index c8266e82a..04291e4df 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt @@ -46,6 +46,8 @@ class AppRecommendationEvent( AddressHintProvider { override fun addressHints() = tags.mapNotNull(RecommendationTag::parseAsHint) + override fun linkedAddressIds() = tags.mapNotNull(RecommendationTag::parseAddressId) + fun recommendations() = tags.mapNotNull(RecommendationTag::parse) fun recommendationAddresses() = tags.mapNotNull(RecommendationTag::parseAddressId) diff --git a/quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt b/quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt index f1143e1ce..c4609ba93 100644 --- a/quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt +++ b/quartz/src/test/java/com/vitorpamplona/quartz/nip19Bech32/NIP19ParserTest.kt @@ -26,9 +26,9 @@ import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip19Bech32.bech32.bechToBytes import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent +import com.vitorpamplona.quartz.nip19Bech32.entities.NNote import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile import com.vitorpamplona.quartz.nip19Bech32.entities.NPub -import com.vitorpamplona.quartz.nip19Bech32.entities.Note import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull @@ -65,7 +65,7 @@ class NIP19ParserTest { @Test() fun uri_to_route_note() { val result = - Nip19Parser.uriToRoute("nostr:note1stqea6wmwezg9x6yyr6qkukw95ewtdukyaztycws65l8wppjmtpscawevv")?.entity as? Note + Nip19Parser.uriToRoute("nostr:note1stqea6wmwezg9x6yyr6qkukw95ewtdukyaztycws65l8wppjmtpscawevv")?.entity as? NNote assertNotNull(result) Assert.assertEquals(