Adds the incoming relay as a hint to all related keys, addresses and event ids.

This commit is contained in:
Vitor Pamplona
2025-07-07 17:02:42 -04:00
parent eb5d113298
commit ed2d7f57c5
60 changed files with 1001 additions and 117 deletions
@@ -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())
@@ -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 {
@@ -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()
@@ -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) }
@@ -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 -> {
@@ -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)
@@ -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)
@@ -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
@@ -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
}
@@ -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)
}
@@ -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<Array<String>>,
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<EventIdHint> {
val eHints = tags.mapNotNull(MarkedETag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseEventAsHint)
val nip19Hints = citedNIP19().eventHints()
return eHints + qHints + nip19Hints
}
override fun linkedEventIds(): List<HexKey> {
val eHints = tags.mapNotNull(MarkedETag::parseId)
val qHints = tags.mapNotNull(QTag::parseEventId)
val nip19Hints = citedNIP19().eventIds()
return eHints + qHints + nip19Hints
}
override fun addressHints(): List<AddressHint> {
val aHints = tags.mapNotNull(ATag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
val nip19Hints = citedNIP19().addressHints()
return aHints + qHints + nip19Hints
}
override fun linkedAddressIds(): List<String> {
val aHints = tags.mapNotNull(ATag::parseAddressId)
val qHints = tags.mapNotNull(QTag::parseAddressId)
val nip19Hints = citedNIP19().addressIds()
return aHints + qHints + nip19Hints
}
override fun pubKeyHints(): List<PubKeyHint> {
val pHints = tags.mapNotNull(PTag::parseAsHint)
val nip19Hints = citedNIP19().pubKeyHints()
return pHints + nip19Hints
}
override fun linkedPubKeys(): List<HexKey> {
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 }
@@ -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<EventIdHint>
fun linkedEventIds(): List<HexKey>
}
interface AddressHintProvider {
fun addressHints(): List<AddressHint>
fun linkedAddressIds(): List<String>
}
interface PubKeyHintProvider {
fun pubKeyHints(): List<PubKeyHint>
fun linkedPubKeys(): List<HexKey>
}
@@ -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())
@@ -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<String>): 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]
}
@@ -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.
*/
@@ -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)
@@ -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()
@@ -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<Array<String>>,
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<String>? = null
@Transient
private var citedNotesCache: Set<String>? = 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<Entity>? = 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<Entity> {
citedNIP19Cache?.let {
return it
}
return findNostrUris(content).also { citedNIP19Cache = it }
}
fun citedUsers(): Set<HexKey> {
citedUsersCache?.let {
return it
@@ -121,7 +109,7 @@ open class BaseThreadedEvent(
val citedUsers = mutableSetOf<String>()
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<String>()
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)
}
}
@@ -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<Array<String>>,
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<EventIdHint> {
val eHints = tags.mapNotNull(MarkedETag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseEventAsHint)
val nip19Hints = citedNIP19().eventHints()
return eHints + qHints + nip19Hints
}
override fun linkedEventIds(): List<HexKey> {
val eHints = tags.mapNotNull(MarkedETag::parseId)
val qHints = tags.mapNotNull(QTag::parseEventId)
val nip19Hints = citedNIP19().eventIds()
return eHints + qHints + nip19Hints
}
override fun addressHints(): List<AddressHint> {
val aHints = tags.mapNotNull(ATag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
val nip19Hints = citedNIP19().addressHints()
return aHints + qHints + nip19Hints
}
override fun linkedAddressIds(): List<String> {
val aHints = tags.mapNotNull(ATag::parseAddressId)
val qHints = tags.mapNotNull(QTag::parseAddressId)
val nip19Hints = citedNIP19().addressIds()
return aHints + qHints + nip19Hints
}
override fun pubKeyHints(): List<PubKeyHint> {
val pHints = tags.mapNotNull(PTag::parseAsHint)
val nip19Hints = citedNIP19().pubKeyHints()
return pHints + nip19Hints
}
override fun linkedPubKeys(): List<HexKey> {
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: "
@@ -104,7 +104,7 @@ data class MarkedETag(
@JvmStatic
fun parseId(tag: Array<String>): 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 }
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -63,12 +63,20 @@ interface QTag {
}
@JvmStatic
fun parseKey(tag: Array<String>): String? {
fun parseId(tag: Array<String>): String? {
ensure(tag.has(1)) { return null }
ensure(tag[0] == TAG_NAME) { return null }
return tag[1]
}
@JvmStatic
fun parseEventId(tag: Array<String>): 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<String>): EventIdHint? {
ensure(tag.has(2)) { return null }
@@ -82,6 +90,14 @@ interface QTag {
return EventIdHint(tag[1], relayHint)
}
fun parseAddressId(tag: Array<String>): 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<String>): AddressHint? {
ensure(tag.has(2)) { return null }
@@ -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 <T : Event> TagArrayBuilder<T>.quote(tag: QTag) = add(tag.toTagArray())
@@ -37,7 +37,7 @@ fun <T : Event> TagArrayBuilder<T>.quotes(tag: List<QTag>) = addAll(tag.map { it
fun <T : Event> TagArrayBuilder<T>.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())
@@ -32,7 +32,7 @@ fun <R> 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)
@@ -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<Entity>.eventHints(): List<EventIdHint> =
mapNotNull { entity ->
if (entity is NEvent) {
entity.toEventHint()
} else {
null
}
}.flatten()
fun List<Entity>.eventIds(): List<HexKey> =
mapNotNull { entity ->
when (entity) {
is NEvent -> entity.hex
is NNote -> entity.hex
is NEmbed -> entity.event.id
else -> null
}
}
fun List<Entity>.addressHints(): List<AddressHint> =
mapNotNull { entity ->
if (entity is NAddress) {
entity.toAddressHint()
} else {
null
}
}.flatten()
fun List<Entity>.addressIds(): List<String> =
mapNotNull { entity ->
when (entity) {
is NAddress -> entity.aTag()
is NEmbed -> if (entity.event is AddressableEvent) entity.event.addressTag() else null
else -> null
}
}
fun List<Entity>.pubKeyHints(): List<PubKeyHint> =
mapNotNull { entity ->
if (entity is NProfile) {
entity.relay.map { PubKeyHint(entity.hex, it) }
} else {
null
}
}.flatten()
fun List<Entity>.pubKeys(): List<HexKey> =
mapNotNull { entity ->
when (entity) {
is NProfile -> entity.hex
is NPub -> entity.hex
is NSec -> entity.hex
else -> null
}
}
@@ -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
@@ -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()
@@ -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<PubKeyHint> {
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<HexKey> {
val pHints =
tags.mapNotNull(RootAuthorTag::parseKey) +
tags.mapNotNull(ReplyAuthorTag::parseKey)
val nip19Hints = citedNIP19().pubKeys()
return pHints + nip19Hints
}
override fun eventHints(): List<EventIdHint> {
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<HexKey> {
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<AddressHint> {
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<String> {
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)
@@ -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<EventIdHint> {
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<HexKey> {
val qHints = tags.mapNotNull(QTag::parseEventId)
val nip19Hints = citedNIP19().eventIds()
return qHints + nip19Hints
}
override fun addressHints(): List<AddressHint> {
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
val nip19Hints = citedNIP19().addressHints()
return qHints + nip19Hints
}
override fun linkedAddressIds(): List<String> {
val qHints = tags.mapNotNull(QTag::parseAddressId)
val nip19Hints = citedNIP19().addressIds()
return qHints + nip19Hints
}
override fun pubKeyHints(): List<PubKeyHint> {
val pHints = tags.mapNotNull(PTag::parseAsHint)
val nip19Hints = citedNIP19().pubKeyHints()
return pHints + nip19Hints
}
override fun linkedPubKeys(): List<HexKey> {
val pHints = tags.mapNotNull(PTag::parseKey)
val nip19Hints = citedNIP19().pubKeys()
return pHints + nip19Hints
}
override fun dTag() = tags.dTag()
@@ -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)
@@ -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()
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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<EventIdHint> {
val eHints = tags.mapNotNull(MarkedETag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseEventAsHint)
val nip19Hints = citedNIP19().eventHints()
return eHints + qHints + nip19Hints
}
override fun linkedEventIds(): List<HexKey> {
val eHints = tags.mapNotNull(MarkedETag::parseId)
val qHints = tags.mapNotNull(QTag::parseEventId)
val nip19Hints = citedNIP19().eventIds()
return eHints + qHints + nip19Hints
}
override fun addressHints(): List<AddressHint> {
val aHints = tags.mapNotNull(ATag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
val nip19Hints = citedNIP19().addressHints()
return aHints + qHints + nip19Hints
}
override fun linkedAddressIds(): List<String> {
val aHints = tags.mapNotNull(ATag::parseAddressId)
val qHints = tags.mapNotNull(QTag::parseAddressId)
val nip19Hints = citedNIP19().addressIds()
return aHints + qHints + nip19Hints
}
override fun pubKeyHints(): List<PubKeyHint> {
val pHints = tags.mapNotNull(PTag::parseAsHint)
val nip19Hints = citedNIP19().pubKeyHints()
return pHints + nip19Hints
}
override fun linkedPubKeys(): List<HexKey> {
val pHints = tags.mapNotNull(PTag::parseKey)
val nip19Hints = citedNIP19().pubKeys()
return pHints + nip19Hints
}
override fun channel() = markedRoot() ?: unmarkedRoot()
override fun channelId() = channel()?.eventId
@@ -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)
@@ -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<EventIdHint> {
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<HexKey> {
val qHints = tags.mapNotNull(QTag::parseEventId)
val nip19Hints = citedNIP19().eventIds()
return qHints + nip19Hints
}
override fun addressHints(): List<AddressHint> {
val aHints = tags.mapNotNull(ATag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
val nip19Hints = citedNIP19().addressHints()
return aHints + qHints + nip19Hints
}
override fun linkedAddressIds(): List<String> {
val aHints = tags.mapNotNull(ATag::parseAddressId)
val qHints = tags.mapNotNull(QTag::parseAddressId)
val nip19Hints = citedNIP19().addressIds()
return aHints + qHints + nip19Hints
}
override fun pubKeyHints(): List<PubKeyHint> {
val pHints = tags.mapNotNull(PTag::parseAsHint)
val nip19Hints = citedNIP19().pubKeyHints()
return pHints + nip19Hints
}
override fun linkedPubKeys(): List<HexKey> {
val pHints = tags.mapNotNull(PTag::parseKey)
val nip19Hints = citedNIP19().pubKeys()
return pHints + nip19Hints
}
fun repositoryHex() = tags.firstNotNullOfOrNull(ATag::parseAddressId)
@@ -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" }
@@ -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<EventIdHint> {
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<HexKey> {
val eHints = tags.mapNotNull(ETag::parseId)
val qHints = tags.mapNotNull(QTag::parseEventId)
val nip19Hints = citedNIP19().eventIds()
return eHints + qHints + nip19Hints
}
override fun addressHints(): List<AddressHint> {
val aHints = tags.mapNotNull(ATag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
val nip19Hints = citedNIP19().addressHints()
return aHints + qHints + nip19Hints
}
override fun linkedAddressIds(): List<String> {
val aHints = tags.mapNotNull(ATag::parseAddressId)
val qHints = tags.mapNotNull(QTag::parseAddressId)
val nip19Hints = citedNIP19().addressIds()
return aHints + qHints + nip19Hints
}
override fun pubKeyHints(): List<PubKeyHint> {
val pHints = tags.mapNotNull(PTag::parseAsHint)
val nip19Hints = citedNIP19().pubKeyHints()
return pHints + nip19Hints
}
override fun linkedPubKeys(): List<HexKey> {
val pHints = tags.mapNotNull(PTag::parseKey)
val nip19Hints = citedNIP19().pubKeys()
return pHints + nip19Hints
}
fun repositoryHex() = tags.firstNotNullOfOrNull(ATag::parseAddressId)
@@ -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<EventIdHint> {
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<HexKey> {
val eHints = tags.mapNotNull(MarkedETag::parseId)
val qHints = tags.mapNotNull(QTag::parseEventId)
val nip19Hints = citedNIP19().eventIds()
return eHints + qHints + nip19Hints
}
override fun addressHints(): List<AddressHint> {
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
val nip19Hints = citedNIP19().addressHints()
return qHints + nip19Hints
}
override fun linkedAddressIds(): List<String> {
val qHints = tags.mapNotNull(QTag::parseAddressId)
val nip19Hints = citedNIP19().addressIds()
return qHints + nip19Hints
}
override fun pubKeyHints(): List<PubKeyHint> {
val pHints = tags.mapNotNull(PTag::parseAsHint)
val nip19Hints = citedNIP19().pubKeyHints()
return pHints + nip19Hints
}
override fun linkedPubKeys(): List<HexKey> {
val pHints = tags.mapNotNull(PTag::parseKey)
val nip19Hints = citedNIP19().pubKeys()
return pHints + nip19Hints
}
fun torrent() = tags.firstNotNullOfOrNull(MarkedETag::parseRoot) ?: tags.firstNotNullOfOrNull(ETag::parse)
@@ -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<HexKey, Event?> = mapOf()
@@ -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()"))
@@ -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<EventIdHint> {
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<HexKey> {
val eHints = tags.mapNotNull(ETag::parseId)
val qHints = tags.mapNotNull(QTag::parseEventId)
val nip19Hints = citedNIP19().eventIds()
return eHints + qHints + nip19Hints
}
override fun addressHints(): List<AddressHint> {
val aHints = tags.mapNotNull(ATag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
val nip19Hints = citedNIP19().addressHints()
return aHints + qHints + nip19Hints
}
override fun linkedAddressIds(): List<String> {
val aHints = tags.mapNotNull(ATag::parseAddressId)
val qHints = tags.mapNotNull(QTag::parseAddressId)
val nip19Hints = citedNIP19().addressIds()
return aHints + qHints + nip19Hints
}
override fun pubKeyHints(): List<PubKeyHint> {
val pHints = tags.mapNotNull(PTag::parseAsHint)
val nip19Hints = citedNIP19().pubKeyHints()
return pHints + nip19Hints
}
override fun linkedPubKeys(): List<HexKey> {
val pHints = tags.mapNotNull(PTag::parseKey)
val nip19Hints = citedNIP19().pubKeys()
return pHints + nip19Hints
}
private fun activityHex() = tags.firstNotNullOfOrNull(ATag::parseAddressId)
@@ -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)
@@ -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<EventIdHint> {
val eHints = tags.mapNotNull(MarkedETag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseEventAsHint)
val nip19Hints = citedNIP19().eventHints()
return eHints + qHints + nip19Hints
}
override fun linkedEventIds(): List<HexKey> {
val eHints = tags.mapNotNull(MarkedETag::parseId)
val qHints = tags.mapNotNull(QTag::parseEventId)
val nip19Hints = citedNIP19().eventIds()
return eHints + qHints + nip19Hints
}
override fun addressHints(): List<AddressHint> {
val aHints = tags.mapNotNull(ATag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
val nip19Hints = citedNIP19().addressHints()
return aHints + qHints + nip19Hints
}
override fun linkedAddressIds(): List<String> {
val aHints = tags.mapNotNull(ATag::parseAddressId)
val qHints = tags.mapNotNull(QTag::parseAddressId)
val nip19Hints = citedNIP19().addressIds()
return aHints + qHints + nip19Hints
}
override fun pubKeyHints(): List<PubKeyHint> {
val pHints = tags.mapNotNull(PTag::parseAsHint)
val nip19Hints = citedNIP19().pubKeyHints()
return pHints + nip19Hints
}
override fun linkedPubKeys(): List<HexKey> {
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)
@@ -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?
@@ -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
@@ -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
@@ -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()
@@ -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()
@@ -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) }
@@ -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)
@@ -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<String>): 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 }
@@ -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()
@@ -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<EventIdHint> {
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<HexKey> {
val eHints = tags.mapNotNull(ETag::parseId)
val qHints = tags.mapNotNull(QTag::parseEventId)
val nip19Hints = citedNIP19().eventIds()
return eHints + qHints + nip19Hints
}
override fun addressHints(): List<AddressHint> {
val aHints = tags.mapNotNull(ATag::parseAsHint)
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
val nip19Hints = citedNIP19().addressHints()
return aHints + qHints + nip19Hints
}
override fun linkedAddressIds(): List<String> {
val aHints = tags.mapNotNull(ATag::parseAddressId)
val qHints = tags.mapNotNull(QTag::parseAddressId)
val nip19Hints = citedNIP19().addressIds()
return aHints + qHints + nip19Hints
}
override fun pubKeyHints(): List<PubKeyHint> {
val pHints = tags.mapNotNull(PTag::parseAsHint)
val nip19Hints = citedNIP19().pubKeyHints()
return pHints + nip19Hints
}
override fun linkedPubKeys(): List<HexKey> {
val pHints = tags.mapNotNull(PTag::parseKey)
val nip19Hints = citedNIP19().pubKeys()
return pHints + nip19Hints
}
fun inUrl() = tags.firstNotNullOfOrNull(ReferenceTag::parse)
@@ -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)
@@ -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(