diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 9b0c50270..a3e0d81ad 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -47,6 +47,7 @@ import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.Nip47WalletConnect import com.vitorpamplona.quartz.encoders.hexToByteArray import com.vitorpamplona.quartz.encoders.toHexKey +import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent import com.vitorpamplona.quartz.events.BookmarkListEvent import com.vitorpamplona.quartz.events.ChannelCreateEvent import com.vitorpamplona.quartz.events.ChannelMessageEvent @@ -2580,6 +2581,34 @@ class Account( } } + fun sendNip65RelayList(relays: List) { + if (!isWriteable()) return + + val nip65RelayList = + LocalCache.getOrCreateAddressableNote( + AdvertisedRelayListEvent.createAddressATag(signer.pubKey), + ).event as? AdvertisedRelayListEvent + + if (nip65RelayList != null) { + AdvertisedRelayListEvent.updateRelayList( + earlierVersion = nip65RelayList, + relays = relays, + signer = signer, + ) { + Client.send(it) + LocalCache.justConsume(it, null) + } + } else { + AdvertisedRelayListEvent.createFromScratch( + relays = relays, + signer = signer, + ) { + Client.send(it) + LocalCache.justConsume(it, null) + } + } + } + fun setHideDeleteRequestDialog() { hideDeleteRequestDialog = true saveable.invalidateData() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/AdvertisedRelayListEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/AdvertisedRelayListEvent.kt index cac3b5d9f..4d61e3f78 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/AdvertisedRelayListEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/events/AdvertisedRelayListEvent.kt @@ -57,28 +57,62 @@ class AdvertisedRelayListEvent( companion object { const val KIND = 10002 const val FIXED_D_TAG = "" + const val ALT = "Relay list to discover the user's content" - fun createAddressTag(pubKey: HexKey): ATag { + fun createAddressATag(pubKey: HexKey): ATag { return ATag(KIND, pubKey, FIXED_D_TAG, null) } + fun createAddressTag(pubKey: HexKey): String { + return ATag.assembleATag(KIND, pubKey, FIXED_D_TAG) + } + + fun updateRelayList( + earlierVersion: AdvertisedRelayListEvent, + relays: List, + signer: NostrSigner, + createdAt: Long = TimeUtils.now(), + onReady: (AdvertisedRelayListEvent) -> Unit, + ) { + val tags = + earlierVersion.tags.filter { it[0] != "r" }.plus( + relays.map(::createRelayTag), + ).toTypedArray() + + signer.sign(createdAt, KIND, tags, earlierVersion.content, onReady) + } + + fun createFromScratch( + relays: List, + signer: NostrSigner, + createdAt: Long = TimeUtils.now(), + onReady: (AdvertisedRelayListEvent) -> Unit, + ) { + create(relays, signer, createdAt, onReady) + } + + fun createRelayTag(relay: AdvertisedRelayInfo): Array { + return if (relay.type == AdvertisedRelayType.BOTH) { + arrayOf("r", relay.relayUrl) + } else { + arrayOf("r", relay.relayUrl, relay.type.code) + } + } + + fun createTagArray(relays: List): Array> { + return relays + .map(::createRelayTag) + .plusElement(arrayOf("alt", ALT)) + .toTypedArray() + } + fun create( list: List, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (AdvertisedRelayListEvent) -> Unit, ) { - val tags = - list - .map { - if (it.type == AdvertisedRelayType.BOTH) { - arrayOf(it.relayUrl) - } else { - arrayOf(it.relayUrl, it.type.code) - } - } - .plusElement(arrayOf("alt", "Relay list event with ${list.size} relays")) - .toTypedArray() + val tags = createTagArray(list) val msg = "" signer.sign(createdAt, KIND, tags, msg, onReady)