Merge pull request #737 from tyiu/nip-10-backwards-compatibility

Add write support for NIP-10 deprecated positional tags in text notes to maximize backwards compatibility
This commit is contained in:
Vitor Pamplona
2023-12-29 10:26:15 -05:00
committed by GitHub
@@ -4,9 +4,6 @@ import androidx.compose.runtime.Immutable
import com.linkedin.urls.detection.UrlDetector import com.linkedin.urls.detection.UrlDetector
import com.linkedin.urls.detection.UrlDetectorOptions import com.linkedin.urls.detection.UrlDetectorOptions
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.ATag import com.vitorpamplona.quartz.encoders.ATag
import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.signers.NostrSigner import com.vitorpamplona.quartz.signers.NostrSigner
@@ -45,16 +42,15 @@ class TextNoteEvent(
onReady: (TextNoteEvent) -> Unit onReady: (TextNoteEvent) -> Unit
) { ) {
val tags = mutableListOf<Array<String>>() val tags = mutableListOf<Array<String>>()
replyTos?.forEach { replyTos?.let {
if (it == root) { tags.addAll(
tags.add(arrayOf("e", it, "", "root")) it.positionalMarkedTags(
} else if (it == replyingTo) { tagName = "e",
tags.add(arrayOf("e", it, "", "reply")) root = root,
} else if (it in directMentions) { replyingTo = replyingTo,
tags.add(arrayOf("e", it, "", "mention")) directMentions = directMentions
} else { )
tags.add(arrayOf("e", it)) )
}
} }
mentions?.forEach { mentions?.forEach {
if (it in directMentions) { if (it in directMentions) {
@@ -63,17 +59,15 @@ class TextNoteEvent(
tags.add(arrayOf("p", it)) tags.add(arrayOf("p", it))
} }
} }
addresses?.forEach { addresses?.map { it.toTag() }?.let {
val aTag = it.toTag() tags.addAll(
if (aTag == root) { it.positionalMarkedTags(
tags.add(arrayOf("a", aTag, "", "root")) tagName = "a",
} else if (aTag == replyingTo) { root = root,
tags.add(arrayOf("a", aTag, "", "reply")) replyingTo = replyingTo,
} else if (aTag in directMentions) { directMentions = directMentions
tags.add(arrayOf("a", aTag, "", "mention")) )
} else { )
tags.add(arrayOf("a", aTag))
}
} }
findHashtags(msg).forEach { findHashtags(msg).forEach {
tags.add(arrayOf("t", it)) tags.add(arrayOf("t", it))
@@ -105,6 +99,41 @@ class TextNoteEvent(
signer.sign(createdAt, kind, tags.toTypedArray(), msg, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), msg, onReady)
} }
/**
* Returns a list of NIP-10 marked tags that are also ordered at best effort
* to support the deprecated method of positional tags to maximize backwards compatibility
* with clients that support replies but have not been updated to understand tag markers.
*
* https://github.com/nostr-protocol/nips/blob/master/10.md
*
* The tag to the root of the reply chain goes first.
* The tag to the reply event being responded to goes last.
* The order for any other tag does not matter, so keep the relative order.
*/
private fun List<String>.positionalMarkedTags(
tagName: String,
root: String?,
replyingTo: String?,
directMentions: Set<HexKey>
) =
sortedWith { o1, o2 ->
when {
o1 == o2 -> 0
o1 == root -> -1 // root goes first
o2 == root -> 1 // root goes first
o1 == replyingTo -> 1 // reply event being responded to goes last
o2 == replyingTo -> -1 // reply event being responded to goes last
else -> 0 // keep the relative order for any other tag
}
}.map {
when (it) {
root -> arrayOf(tagName, it, "", "root")
replyingTo -> arrayOf(tagName, it, "", "reply")
in directMentions -> arrayOf(tagName, it, "", "mention")
else -> arrayOf(tagName, it)
}
}
} }
} }