Checking HexKeys across the board.. Too many errors in tags.

This commit is contained in:
Vitor Pamplona 2023-02-20 20:49:54 -05:00
parent a153f577c9
commit d31c11f70d
6 changed files with 171 additions and 66 deletions

View File

@ -47,4 +47,37 @@ fun decodePublicKey(key: String): ByteArray {
//} else {
Hex.decode(key)
}
}
data class DirtyKeyInfo(val type: String, val keyHex: String, val restOfWord: String)
fun parseDirtyWordForKey(mightBeAKey: String): DirtyKeyInfo? {
var key = mightBeAKey
if (key.startsWith("nostr:", true)) {
key = key.substring("nostr:".length)
}
key = key.removePrefix("@")
if (key.length < 63)
return null
try {
val keyB32 = key.substring(0, 63)
val restOfWord = key.substring(63)
if (key.startsWith("nsec1", true)) {
return DirtyKeyInfo("npub", Persona(privKey = keyB32.bechToBytes()).pubKey.toHexKey(), restOfWord)
} else if (key.startsWith("npub1", true)) {
return DirtyKeyInfo("npub", keyB32.bechToBytes().toHexKey(), restOfWord)
} else if (key.startsWith("note1", true)) {
return DirtyKeyInfo("note", keyB32.bechToBytes().toHexKey(), restOfWord)
}
} catch (e: Exception) {
e.printStackTrace()
}
return null
}

View File

@ -74,6 +74,16 @@ object LocalCache {
}
}
fun checkGetOrCreateNote(key: HexKey): Note? {
return try {
val checkHex = Hex.decode(key) // Checks if this is a valid Hex
getOrCreateNote(key)
} catch (e: IllegalArgumentException) {
Log.e("LocalCache", "Invalid Key to create note: $key", e)
null
}
}
@Synchronized
fun getOrCreateNote(idHex: String): Note {
return notes[idHex] ?: run {
@ -83,6 +93,17 @@ object LocalCache {
}
}
fun checkGetOrCreateChannel(key: HexKey): Channel? {
return try {
val checkHex = Hex.decode(key) // Checks if this is a valid Hex
getOrCreateChannel(key)
} catch (e: IllegalArgumentException) {
Log.e("LocalCache", "Invalid Key to create channel: $key", e)
null
}
}
@Synchronized
fun getOrCreateChannel(key: String): Channel {
return channels[key] ?: run {
@ -145,7 +166,6 @@ object LocalCache {
if (isRepeatedMessageSpam(event)) return
val note = getOrCreateNote(event.id.toHex())
val author = getOrCreateUser(event.pubKey.toHexKey())
if (relay != null) {
@ -157,7 +177,7 @@ object LocalCache {
if (note.event != null) return
val mentions = event.mentions.mapNotNull { checkGetOrCreateUser(it) }
val replyTo = replyToWithoutCitations(event).map { getOrCreateNote(it) }
val replyTo = replyToWithoutCitations(event).mapNotNull { checkGetOrCreateNote(it) }
note.loadEvent(event, author, mentions, replyTo)
@ -266,7 +286,7 @@ object LocalCache {
//Log.d("PM", "${author.toBestDisplayName()} to ${recipient?.toBestDisplayName()}")
val repliesTo = event.tags.filter { it.firstOrNull() == "e" }.mapNotNull { it.getOrNull(1) }.map { getOrCreateNote(it) }
val repliesTo = event.tags.filter { it.firstOrNull() == "e" }.mapNotNull { it.getOrNull(1) }.mapNotNull { checkGetOrCreateNote(it) }
val mentions = event.tags.filter { it.firstOrNull() == "p" }.mapNotNull { it.getOrNull(1) }.mapNotNull { checkGetOrCreateUser(it) }
note.loadEvent(event, author, mentions, repliesTo)
@ -293,7 +313,7 @@ object LocalCache {
val author = getOrCreateUser(event.pubKey.toHexKey())
val mentions = event.originalAuthor.mapNotNull { checkGetOrCreateUser(it) }
val repliesTo = event.boostedPost.map { getOrCreateNote(it) }
val repliesTo = event.boostedPost.mapNotNull { checkGetOrCreateNote(it) }
note.loadEvent(event, author, mentions, repliesTo)
@ -324,7 +344,7 @@ object LocalCache {
val author = getOrCreateUser(event.pubKey.toHexKey())
val mentions = event.originalAuthor.mapNotNull { checkGetOrCreateUser(it) }
val repliesTo = event.originalPost.map { getOrCreateNote(it) }
val repliesTo = event.originalPost.mapNotNull { checkGetOrCreateNote(it) }
note.loadEvent(event, author, mentions, repliesTo)
@ -369,7 +389,7 @@ object LocalCache {
val author = getOrCreateUser(event.pubKey.toHexKey())
val mentions = event.reportedAuthor.mapNotNull { checkGetOrCreateUser(it) }
val repliesTo = event.reportedPost.map { getOrCreateNote(it) }
val repliesTo = event.reportedPost.mapNotNull { checkGetOrCreateNote(it) }
note.loadEvent(event, author, mentions, repliesTo)
@ -410,7 +430,7 @@ object LocalCache {
if (event.channel.isNullOrBlank()) return
// new event
val oldChannel = getOrCreateChannel(event.channel)
val oldChannel = checkGetOrCreateChannel(event.channel) ?: return
val author = getOrCreateUser(event.pubKey.toHexKey())
if (event.createdAt > oldChannel.updatedMetadataAt) {
if (oldChannel.creator == null || oldChannel.creator == author) {
@ -432,7 +452,7 @@ object LocalCache {
if (event.channel.isNullOrBlank()) return
if (isRepeatedMessageSpam(event)) return
val channel = getOrCreateChannel(event.channel)
val channel = checkGetOrCreateChannel(event.channel) ?: return
val note = getOrCreateNote(event.id.toHex())
channel.addNote(note)
@ -449,7 +469,7 @@ object LocalCache {
val mentions = event.mentions.mapNotNull { checkGetOrCreateUser(it) }
val replyTo = event.replyTos
.map { getOrCreateNote(it) }
.mapNotNull { checkGetOrCreateNote(it) }
.filter { it.event !is ChannelCreateEvent }
note.channel = channel
@ -489,7 +509,7 @@ object LocalCache {
val author = getOrCreateUser(event.pubKey.toHexKey())
val mentions = event.zappedAuthor.mapNotNull { checkGetOrCreateUser(it) }
val repliesTo = event.zappedPost.map { getOrCreateNote(it) }
val repliesTo = event.zappedPost.mapNotNull { checkGetOrCreateNote(it) }
note.loadEvent(event, author, mentions, repliesTo)
@ -525,7 +545,7 @@ object LocalCache {
val author = getOrCreateUser(event.pubKey.toHexKey())
val mentions = event.zappedAuthor.mapNotNull { checkGetOrCreateUser(it) }
val repliesTo = event.zappedPost.map { getOrCreateNote(it) }
val repliesTo = event.zappedPost.mapNotNull { checkGetOrCreateNote(it) }
note.loadEvent(event, author, mentions, repliesTo)

View File

@ -9,7 +9,7 @@ class ThreadAssembler {
if (note.replyTo == null || note.replyTo?.isEmpty() == true) return note
val markedAsRoot = note.event?.tags?.firstOrNull { it[0] == "e" && it.size > 3 && it[3] == "root" }?.getOrNull(1)
if (markedAsRoot != null) return LocalCache.getOrCreateNote(markedAsRoot)
if (markedAsRoot != null) return LocalCache.checkGetOrCreateNote(markedAsRoot)
val hasNoReplyTo = note.replyTo?.firstOrNull { it.replyTo?.isEmpty() == true }
if (hasNoReplyTo != null) return hasNoReplyTo

View File

@ -76,24 +76,12 @@ class NewPostViewModel: ViewModel() {
// adds all references to mentions and reply tos
message.text.split('\n').forEach { paragraph: String ->
paragraph.split(' ').forEach { word: String ->
try {
if (word.startsWith("@npub") && word.length >= 64) {
val keyB32 = word.substring(0, 64)
val results = parseDirtyWordForKey(word)
val key = decodePublicKey(keyB32.removePrefix("@"))
val user = LocalCache.getOrCreateUser(key.toHexKey())
addUserToMentions(user)
} else if (word.startsWith("@note") && word.length >= 64) {
val keyB32 = word.substring(0, 64)
val key = decodePublicKey(keyB32.removePrefix("@"))
val note = LocalCache.getOrCreateNote(key.toHexKey())
addNoteToReplyTos(note)
}
} catch (e: Exception) {
e.printStackTrace()
if (results?.type == "npub") {
addUserToMentions(LocalCache.getOrCreateUser(results.keyHex))
} else if (results?.type == "note") {
addNoteToReplyTos(LocalCache.getOrCreateNote(results.keyHex))
}
}
}
@ -101,29 +89,16 @@ class NewPostViewModel: ViewModel() {
// Tags the text in the correct order.
val newMessage = message.text.split('\n').map { paragraph: String ->
paragraph.split(' ').map { word: String ->
try {
if (word.startsWith("@npub") && word.length >= 64) {
val keyB32 = word.substring(0, 64)
val restOfWord = word.substring(64)
val results = parseDirtyWordForKey(word)
if (results?.type == "npub") {
val user = LocalCache.getOrCreateUser(results.keyHex)
val key = decodePublicKey(keyB32.removePrefix("@"))
val user = LocalCache.getOrCreateUser(key.toHexKey())
"#[${tagIndex(user)}]${results.restOfWord}"
} else if (results?.type == "note") {
val note = LocalCache.getOrCreateNote(results.keyHex)
"#[${tagIndex(user)}]$restOfWord"
} else if (word.startsWith("@note") && word.length >= 64) {
val keyB32 = word.substring(0, 64)
val restOfWord = word.substring(64)
val key = decodePublicKey(keyB32.removePrefix("@"))
val note = LocalCache.getOrCreateNote(key.toHexKey())
"#[${tagIndex(note)}]$restOfWord"
} else {
word
}
} catch (e: Exception) {
e.printStackTrace()
// if it can't parse the key, don't try to change.
"#[${tagIndex(note)}]${results.restOfWord}"
} else {
word
}
}.joinToString(" ")

View File

@ -1,16 +0,0 @@
package com.vitorpamplona.amethyst
import org.junit.Assert.assertEquals
import org.junit.Test
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@ -0,0 +1,93 @@
package com.vitorpamplona.amethyst
import com.vitorpamplona.amethyst.model.parseDirtyWordForKey
import org.junit.Assert.assertEquals
import org.junit.Test
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class KeyParseTest {
@Test
fun keyParseTestNote() {
val result = parseDirtyWordForKey("note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn")
assertEquals("note", result?.type)
assertEquals("1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", result?.keyHex)
assertEquals("", result?.restOfWord)
}
@Test
fun keyParseTestPub() {
val result = parseDirtyWordForKey("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z")
assertEquals("npub", result?.type)
assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.keyHex)
assertEquals("", result?.restOfWord)
}
@Test
fun keyParseTestNoteWithExtraChars() {
val result = parseDirtyWordForKey("note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,")
assertEquals("note", result?.type)
assertEquals("1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", result?.keyHex)
assertEquals(",", result?.restOfWord)
}
@Test
fun keyParseTestPubWithExtraChars() {
val result = parseDirtyWordForKey("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,")
assertEquals("npub", result?.type)
assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.keyHex)
assertEquals(",", result?.restOfWord)
}
@Test
fun keyParseTestNoteWithExtraCharsAndAt() {
val result = parseDirtyWordForKey("@note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,")
assertEquals("note", result?.type)
assertEquals("1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", result?.keyHex)
assertEquals(",", result?.restOfWord)
}
@Test
fun keyParseTestPubWithExtraCharsAndAt() {
val result = parseDirtyWordForKey("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,")
assertEquals("npub", result?.type)
assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.keyHex)
assertEquals(",", result?.restOfWord)
}
@Test
fun keyParseTestNoteWithExtraCharsAndNostrPrefix() {
val result = parseDirtyWordForKey("nostr:note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,")
assertEquals("note", result?.type)
assertEquals("1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", result?.keyHex)
assertEquals(",", result?.restOfWord)
}
@Test
fun keyParseTestPubWithExtraCharsAndNostrPrefix() {
val result = parseDirtyWordForKey("nostr:npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,")
assertEquals("npub", result?.type)
assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.keyHex)
assertEquals(",", result?.restOfWord)
}
@Test
fun keyParseTestUppercaseNoteWithExtraCharsAndNostrPrefix() {
val result = parseDirtyWordForKey("Nostr:note1z5e2m0smx6d7e2d0zaq8d3rnd7httm6j0uf8tf90yqqjrs842czshwtkmn,")
assertEquals("note", result?.type)
assertEquals("1532adbe1b369beca9af174076c4736faeb5ef527f1275a4af200121c0f55605", result?.keyHex)
assertEquals(",", result?.restOfWord)
}
@Test
fun keyParseTestUppercasePubWithExtraCharsAndNostrPrefix() {
val result = parseDirtyWordForKey("nOstr:npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z,")
assertEquals("npub", result?.type)
assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", result?.keyHex)
assertEquals(",", result?.restOfWord)
}
}