More correctly parses null and default values from NIP-55 using Jackson
This commit is contained in:
+1
-1
@@ -74,7 +74,7 @@ class BlossomServerListState(
|
|||||||
return if (serverList != null && serverList.tags.isNotEmpty()) {
|
return if (serverList != null && serverList.tags.isNotEmpty()) {
|
||||||
BlossomServersEvent.updateRelayList(
|
BlossomServersEvent.updateRelayList(
|
||||||
earlierVersion = serverList,
|
earlierVersion = serverList,
|
||||||
relays = servers,
|
servers = servers,
|
||||||
signer = signer,
|
signer = signer,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+3
-2
@@ -27,6 +27,7 @@ import com.vitorpamplona.amethyst.R
|
|||||||
import com.vitorpamplona.amethyst.service.cashu.CashuToken
|
import com.vitorpamplona.amethyst.service.cashu.CashuToken
|
||||||
import com.vitorpamplona.amethyst.service.lnurl.LightningAddressResolver
|
import com.vitorpamplona.amethyst.service.lnurl.LightningAddressResolver
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
|
import com.vitorpamplona.quartz.utils.asTextOrNull
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
@@ -127,7 +128,7 @@ class MeltProcessor {
|
|||||||
val msg =
|
val msg =
|
||||||
tree
|
tree
|
||||||
?.get("detail")
|
?.get("detail")
|
||||||
?.asText()
|
?.asTextOrNull()
|
||||||
?.split('.')
|
?.split('.')
|
||||||
?.getOrNull(0)
|
?.getOrNull(0)
|
||||||
?.ifBlank { null }
|
?.ifBlank { null }
|
||||||
@@ -203,7 +204,7 @@ class MeltProcessor {
|
|||||||
val msg =
|
val msg =
|
||||||
tree
|
tree
|
||||||
?.get("detail")
|
?.get("detail")
|
||||||
?.asText()
|
?.asTextOrNull()
|
||||||
?.split('.')
|
?.split('.')
|
||||||
?.getOrNull(0)
|
?.getOrNull(0)
|
||||||
?.ifBlank { null }
|
?.ifBlank { null }
|
||||||
|
|||||||
+2
-2
@@ -102,7 +102,7 @@ class BlossomServersViewModel : ViewModel() {
|
|||||||
serverUrl: String,
|
serverUrl: String,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val serverName = if (name.isNotBlank()) name else Rfc3986.host(serverUrl)
|
val serverName = name.ifBlank { Rfc3986.host(serverUrl) }
|
||||||
_fileServers.update {
|
_fileServers.update {
|
||||||
it.minus(
|
it.minus(
|
||||||
ServerName(serverName, serverUrl, ServerType.Blossom),
|
ServerName(serverName, serverUrl, ServerType.Blossom),
|
||||||
@@ -127,5 +127,5 @@ class BlossomServersViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun obtainFileServers(): List<String>? = account.blossomServers.flow.value
|
private fun obtainFileServers(): List<String> = account.blossomServers.flow.value
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -27,6 +27,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule
|
|||||||
import com.fasterxml.jackson.databind.node.ArrayNode
|
import com.fasterxml.jackson.databind.node.ArrayNode
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode
|
import com.fasterxml.jackson.databind.node.ObjectNode
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.vitorpamplona.quartz.nip01Core.jackson.InliningTagArrayPrettyPrinter
|
import com.vitorpamplona.quartz.nip01Core.jackson.InliningTagArrayPrettyPrinter
|
||||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.results.IntentResult
|
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.results.IntentResult
|
||||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.results.IntentResultJsonDeserializer
|
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.results.IntentResultJsonDeserializer
|
||||||
@@ -50,9 +51,9 @@ object JsonMapperNip55 {
|
|||||||
.addSerializer(Permission::class.java, PermissionSerializer()),
|
.addSerializer(Permission::class.java, PermissionSerializer()),
|
||||||
)
|
)
|
||||||
|
|
||||||
inline fun <reified T> fromJsonTo(json: String): T = defaultMapper.readValue(json, T::class.java)
|
inline fun <reified T> fromJsonTo(json: String): T = defaultMapper.readValue<T>(json)
|
||||||
|
|
||||||
inline fun <reified T> fromJsonTo(json: InputStream): T = defaultMapper.readValue(json, T::class.java)
|
inline fun <reified T> fromJsonTo(json: InputStream): T = defaultMapper.readValue<T>(json)
|
||||||
|
|
||||||
fun toJson(event: ArrayNode): String = defaultMapper.writeValueAsString(event)
|
fun toJson(event: ArrayNode): String = defaultMapper.writeValueAsString(event)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ class DecryptZapResponse {
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun parse(intent: IntentResult): SignerResult.RequestAddressed<ZapEventDecryptionResult> {
|
fun parse(intent: IntentResult): SignerResult.RequestAddressed<ZapEventDecryptionResult> {
|
||||||
if (intent.rejected) {
|
if (intent.rejected == true) {
|
||||||
return SignerResult.RequestAddressed.ManuallyRejected()
|
return SignerResult.RequestAddressed.ManuallyRejected()
|
||||||
}
|
}
|
||||||
val eventJson = intent.result
|
val eventJson = intent.result
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ class DeriveKeyResponse {
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun parse(intent: IntentResult): SignerResult.RequestAddressed<DerivationResult> {
|
fun parse(intent: IntentResult): SignerResult.RequestAddressed<DerivationResult> {
|
||||||
if (intent.rejected) {
|
if (intent.rejected == true) {
|
||||||
return SignerResult.RequestAddressed.ManuallyRejected()
|
return SignerResult.RequestAddressed.ManuallyRejected()
|
||||||
}
|
}
|
||||||
val newPrivateKey = intent.result
|
val newPrivateKey = intent.result
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ class Nip04DecryptResponse {
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun parse(intent: IntentResult): SignerResult.RequestAddressed<DecryptionResult> {
|
fun parse(intent: IntentResult): SignerResult.RequestAddressed<DecryptionResult> {
|
||||||
if (intent.rejected) {
|
if (intent.rejected == true) {
|
||||||
return SignerResult.RequestAddressed.ManuallyRejected()
|
return SignerResult.RequestAddressed.ManuallyRejected()
|
||||||
}
|
}
|
||||||
val plaintext = intent.result
|
val plaintext = intent.result
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ class Nip04EncryptResponse {
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun parse(intent: IntentResult): SignerResult.RequestAddressed<EncryptionResult> {
|
fun parse(intent: IntentResult): SignerResult.RequestAddressed<EncryptionResult> {
|
||||||
if (intent.rejected) {
|
if (intent.rejected == true) {
|
||||||
return SignerResult.RequestAddressed.ManuallyRejected()
|
return SignerResult.RequestAddressed.ManuallyRejected()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ class Nip44DecryptResponse {
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun parse(intent: IntentResult): SignerResult.RequestAddressed<DecryptionResult> {
|
fun parse(intent: IntentResult): SignerResult.RequestAddressed<DecryptionResult> {
|
||||||
if (intent.rejected) {
|
if (intent.rejected == true) {
|
||||||
return SignerResult.RequestAddressed.ManuallyRejected()
|
return SignerResult.RequestAddressed.ManuallyRejected()
|
||||||
}
|
}
|
||||||
val plaintext = intent.result
|
val plaintext = intent.result
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ class Nip44EncryptResponse {
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun parse(intent: IntentResult): SignerResult.RequestAddressed<EncryptionResult> {
|
fun parse(intent: IntentResult): SignerResult.RequestAddressed<EncryptionResult> {
|
||||||
if (intent.rejected) {
|
if (intent.rejected == true) {
|
||||||
return SignerResult.RequestAddressed.ManuallyRejected()
|
return SignerResult.RequestAddressed.ManuallyRejected()
|
||||||
}
|
}
|
||||||
val ciphertext = intent.result
|
val ciphertext = intent.result
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ class SignResponse {
|
|||||||
intent: IntentResult,
|
intent: IntentResult,
|
||||||
unsignedEvent: Event,
|
unsignedEvent: Event,
|
||||||
): SignerResult.RequestAddressed<SignResult> {
|
): SignerResult.RequestAddressed<SignResult> {
|
||||||
if (intent.rejected) {
|
if (intent.rejected == true) {
|
||||||
return SignerResult.RequestAddressed.ManuallyRejected()
|
return SignerResult.RequestAddressed.ManuallyRejected()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -31,16 +31,17 @@ data class IntentResult(
|
|||||||
val result: String? = null,
|
val result: String? = null,
|
||||||
val event: String? = null,
|
val event: String? = null,
|
||||||
val id: String? = null,
|
val id: String? = null,
|
||||||
val rejected: Boolean = false,
|
val rejected: Boolean? = false,
|
||||||
) : OptimizedSerializable {
|
) : OptimizedSerializable {
|
||||||
fun toJson(): String = JsonMapperNip55.toJson(this)
|
fun toJson(): String = JsonMapperNip55.toJson(this)
|
||||||
|
|
||||||
fun toIntent(): Intent {
|
fun toIntent(): Intent {
|
||||||
val intent = Intent()
|
val intent = Intent()
|
||||||
intent.putExtra("id", id)
|
if (id != null) intent.putExtra("id", id)
|
||||||
intent.putExtra("result", result)
|
if (result != null) intent.putExtra("result", result)
|
||||||
intent.putExtra("event", event)
|
if (event != null) intent.putExtra("event", event)
|
||||||
intent.putExtra("package", `package`)
|
if (`package` != null) intent.putExtra("package", `package`)
|
||||||
|
if (rejected != null) intent.putExtra("rejected", rejected)
|
||||||
return intent
|
return intent
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +52,12 @@ data class IntentResult(
|
|||||||
result = data.getStringExtra("result"),
|
result = data.getStringExtra("result"),
|
||||||
event = data.getStringExtra("event"),
|
event = data.getStringExtra("event"),
|
||||||
`package` = data.getStringExtra("package"),
|
`package` = data.getStringExtra("package"),
|
||||||
rejected = data.extras?.containsKey("rejected") == true,
|
rejected =
|
||||||
|
if (data.extras?.containsKey("rejected") == true) {
|
||||||
|
data.getBooleanExtra("rejected", false)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
fun fromJson(json: String): IntentResult = JsonMapperNip55.fromJsonTo<IntentResult>(json)
|
fun fromJson(json: String): IntentResult = JsonMapperNip55.fromJsonTo<IntentResult>(json)
|
||||||
|
|||||||
+8
-5
@@ -24,6 +24,8 @@ import com.fasterxml.jackson.core.JsonParser
|
|||||||
import com.fasterxml.jackson.databind.DeserializationContext
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
import com.fasterxml.jackson.databind.JsonNode
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||||
|
import com.vitorpamplona.quartz.utils.asBooleanOrNull
|
||||||
|
import com.vitorpamplona.quartz.utils.asTextOrNull
|
||||||
|
|
||||||
class IntentResultJsonDeserializer : StdDeserializer<IntentResult>(IntentResult::class.java) {
|
class IntentResultJsonDeserializer : StdDeserializer<IntentResult>(IntentResult::class.java) {
|
||||||
override fun deserialize(
|
override fun deserialize(
|
||||||
@@ -31,12 +33,13 @@ class IntentResultJsonDeserializer : StdDeserializer<IntentResult>(IntentResult:
|
|||||||
ctxt: DeserializationContext,
|
ctxt: DeserializationContext,
|
||||||
): IntentResult {
|
): IntentResult {
|
||||||
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
||||||
|
|
||||||
return IntentResult(
|
return IntentResult(
|
||||||
`package` = jsonObject.get("package")?.asText()?.intern(),
|
`package` = jsonObject.get("package")?.asTextOrNull()?.intern(),
|
||||||
result = jsonObject.get("result")?.asText(),
|
result = jsonObject.get("result")?.asTextOrNull(),
|
||||||
event = jsonObject.get("event")?.asText(),
|
event = jsonObject.get("event")?.asTextOrNull(),
|
||||||
id = jsonObject.get("id")?.asText()?.intern(),
|
id = jsonObject.get("id")?.asTextOrNull()?.intern(),
|
||||||
rejected = jsonObject.get("rejected")?.asBoolean() ?: false,
|
rejected = jsonObject.get("rejected")?.asBooleanOrNull(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ class IntentResultJsonSerializer : StdSerializer<IntentResult>(IntentResult::cla
|
|||||||
result.result?.let { gen.writeStringField("result", it) }
|
result.result?.let { gen.writeStringField("result", it) }
|
||||||
result.event?.let { gen.writeStringField("event", it) }
|
result.event?.let { gen.writeStringField("event", it) }
|
||||||
result.id?.let { gen.writeStringField("id", it) }
|
result.id?.let { gen.writeStringField("id", it) }
|
||||||
result.rejected.let { gen.writeBooleanField("rejected", it) }
|
result.rejected?.let { gen.writeBooleanField("rejected", it) }
|
||||||
gen.writeEndObject()
|
gen.writeEndObject()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* 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.nip55AndroidSigner.foreground.intents.results
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.results.IntentResult
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertNull
|
||||||
|
|
||||||
|
class IntentResultSerializerTest {
|
||||||
|
val example =
|
||||||
|
"""
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"package": null,
|
||||||
|
"signature": "336590c3f90dc6b3e709090f48b63cc82db01f4a53702d3a9802c7647d43b8a946964fd8178a5439a655e6a2a9af1143573c64d5828f526b2bf9b24bfbde61dd",
|
||||||
|
"result": "336590c3f90dc6b3e709090f48b63cc82db01f4a53702d3a9802c7647d43b8a946964fd8178a5439a655e6a2a9af1143573c64d5828f526b2bf9b24bfbde61dd",
|
||||||
|
"rejected": null,
|
||||||
|
"id": "z6AkVNy2jAH4vcUcUaYIZHrOhi6oWROj"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": null,
|
||||||
|
"signature": "2560b238cabffd3c4b02b3f9f131fceb96c388f68e4a60382b833b74871ef5474baa409e6278768a47330e8b1be041a3980c242fb05014d451603e86e6240683",
|
||||||
|
"result": "2560b238cabffd3c4b02b3f9f131fceb96c388f68e4a60382b833b74871ef5474baa409e6278768a47330e8b1be041a3980c242fb05014d451603e86e6240683",
|
||||||
|
"rejected": null,
|
||||||
|
"id": "ZQGMSmJbSbqCBRxc7elKskWHEPldIJ2j"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": null,
|
||||||
|
"signature": "3577ce8638367ed0569e1953bc8379ec252d66903edf6e607bbc0c081039b3ca8bee82df1956981e598a7ea172d84671d66b052a138ce41c5f43f96aed05f536",
|
||||||
|
"result": "3577ce8638367ed0569e1953bc8379ec252d66903edf6e607bbc0c081039b3ca8bee82df1956981e598a7ea172d84671d66b052a138ce41c5f43f96aed05f536",
|
||||||
|
"rejected": null,
|
||||||
|
"id": "yuIGh0hwUN5vN3mYTJoMAP1kE7EjedEu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": null,
|
||||||
|
"signature": "2c39187a337083f473e0b3b31867efbc5399e5d64e8085295eb6f5cd94149f7a2563be90a38ca26519b2e4943137d08ebd743ae7c65d11715c9ff8b99d676c57",
|
||||||
|
"result": "2c39187a337083f473e0b3b31867efbc5399e5d64e8085295eb6f5cd94149f7a2563be90a38ca26519b2e4943137d08ebd743ae7c65d11715c9ff8b99d676c57",
|
||||||
|
"rejected": null,
|
||||||
|
"id": "iAGHGc9OKEkSze36Zqhtep0cGi26oWZp"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDeserializer() {
|
||||||
|
val results = IntentResult.fromJsonArray(example)
|
||||||
|
|
||||||
|
println("${results.get(0).javaClass.simpleName}")
|
||||||
|
assertEquals(4, results.size)
|
||||||
|
|
||||||
|
assertEquals("z6AkVNy2jAH4vcUcUaYIZHrOhi6oWROj", results[0].id)
|
||||||
|
assertNull(results[0].`package`)
|
||||||
|
assertEquals("336590c3f90dc6b3e709090f48b63cc82db01f4a53702d3a9802c7647d43b8a946964fd8178a5439a655e6a2a9af1143573c64d5828f526b2bf9b24bfbde61dd", results[0].result)
|
||||||
|
assertNull(results[0].rejected)
|
||||||
|
|
||||||
|
assertEquals("ZQGMSmJbSbqCBRxc7elKskWHEPldIJ2j", results[1].id)
|
||||||
|
assertNull(results[1].`package`)
|
||||||
|
assertEquals("2560b238cabffd3c4b02b3f9f131fceb96c388f68e4a60382b833b74871ef5474baa409e6278768a47330e8b1be041a3980c242fb05014d451603e86e6240683", results[1].result)
|
||||||
|
assertNull(results[1].rejected)
|
||||||
|
|
||||||
|
assertEquals("yuIGh0hwUN5vN3mYTJoMAP1kE7EjedEu", results[2].id)
|
||||||
|
assertNull(results[2].`package`)
|
||||||
|
assertEquals("3577ce8638367ed0569e1953bc8379ec252d66903edf6e607bbc0c081039b3ca8bee82df1956981e598a7ea172d84671d66b052a138ce41c5f43f96aed05f536", results[2].result)
|
||||||
|
assertNull(results[2].rejected)
|
||||||
|
|
||||||
|
assertEquals("iAGHGc9OKEkSze36Zqhtep0cGi26oWZp", results[3].id)
|
||||||
|
assertNull(results[3].`package`)
|
||||||
|
assertEquals("2c39187a337083f473e0b3b31867efbc5399e5d64e8085295eb6f5cd94149f7a2563be90a38ca26519b2e4943137d08ebd743ae7c65d11715c9ff8b99d676c57", results[3].result)
|
||||||
|
assertNull(results[3].rejected)
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-6
@@ -66,18 +66,15 @@ class BlossomServersEvent(
|
|||||||
|
|
||||||
suspend fun updateRelayList(
|
suspend fun updateRelayList(
|
||||||
earlierVersion: BlossomServersEvent,
|
earlierVersion: BlossomServersEvent,
|
||||||
relays: List<String>,
|
servers: List<String>,
|
||||||
signer: NostrSigner,
|
signer: NostrSigner,
|
||||||
createdAt: Long = TimeUtils.now(),
|
createdAt: Long = TimeUtils.now(),
|
||||||
): BlossomServersEvent {
|
): BlossomServersEvent {
|
||||||
val tags =
|
val tags =
|
||||||
earlierVersion.tags
|
earlierVersion.tags
|
||||||
.filter { it[0] != "server" }
|
.filter { it[0] != "server" }
|
||||||
.plus(
|
.plus(servers.map { arrayOf("server", it) })
|
||||||
relays.map {
|
.toTypedArray()
|
||||||
arrayOf("server", it)
|
|
||||||
},
|
|
||||||
).toTypedArray()
|
|
||||||
|
|
||||||
return signer.sign(createdAt, KIND, tags, earlierVersion.content)
|
return signer.sign(createdAt, KIND, tags, earlierVersion.content)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-8
@@ -24,6 +24,9 @@ import com.fasterxml.jackson.core.JsonParser
|
|||||||
import com.fasterxml.jackson.databind.DeserializationContext
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode
|
import com.fasterxml.jackson.databind.node.ObjectNode
|
||||||
|
import com.vitorpamplona.quartz.utils.asIntOrNull
|
||||||
|
import com.vitorpamplona.quartz.utils.asLongOrNull
|
||||||
|
import com.vitorpamplona.quartz.utils.asTextOrNull
|
||||||
|
|
||||||
class FilterDeserializer : StdDeserializer<Filter>(Filter::class.java) {
|
class FilterDeserializer : StdDeserializer<Filter>(Filter::class.java) {
|
||||||
override fun deserialize(
|
override fun deserialize(
|
||||||
@@ -43,14 +46,14 @@ class ManualFilterDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Filter(
|
return Filter(
|
||||||
ids = jsonObject.get("ids").map { it.asText() },
|
ids = jsonObject.get("ids").mapNotNull { it.asTextOrNull() },
|
||||||
authors = jsonObject.get("authors").map { it.asText() },
|
authors = jsonObject.get("authors").mapNotNull { it.asTextOrNull() },
|
||||||
kinds = jsonObject.get("kinds").map { it.asInt() },
|
kinds = jsonObject.get("kinds").mapNotNull { it.asIntOrNull() },
|
||||||
tags = tags.associateWith { jsonObject.get(it).map { it.asText() } },
|
tags = tags.associateWith { jsonObject.get(it).mapNotNull { it.asTextOrNull() } },
|
||||||
since = jsonObject.get("since").asLong(),
|
since = jsonObject.get("since").asLongOrNull(),
|
||||||
until = jsonObject.get("until").asLong(),
|
until = jsonObject.get("until").asLongOrNull(),
|
||||||
limit = jsonObject.get("limit").asInt(),
|
limit = jsonObject.get("limit").asIntOrNull(),
|
||||||
search = jsonObject.get("search").asText(),
|
search = jsonObject.get("search").asTextOrNull(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -26,6 +26,7 @@ import com.fasterxml.jackson.databind.JsonNode
|
|||||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||||
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponse
|
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponse
|
||||||
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponseAck
|
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponseAck
|
||||||
|
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponseError
|
||||||
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponseGetRelays
|
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponseGetRelays
|
||||||
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponsePong
|
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponsePong
|
||||||
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponsePublicKey
|
import com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponsePublicKey
|
||||||
@@ -43,8 +44,7 @@ class BunkerResponseDeserializer : StdDeserializer<BunkerResponse>(BunkerRespons
|
|||||||
val error = jsonObject.get("error")?.asText()
|
val error = jsonObject.get("error")?.asText()
|
||||||
|
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return com.vitorpamplona.quartz.nip46RemoteSigner.BunkerResponseError
|
return BunkerResponseError.parse(id, result, error)
|
||||||
.parse(id, result, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
|
|||||||
+2
-1
@@ -26,6 +26,7 @@ import com.fasterxml.jackson.databind.JsonNode
|
|||||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||||
import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceMethod
|
import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceMethod
|
||||||
import com.vitorpamplona.quartz.nip47WalletConnect.Request
|
import com.vitorpamplona.quartz.nip47WalletConnect.Request
|
||||||
|
import com.vitorpamplona.quartz.utils.asTextOrNull
|
||||||
|
|
||||||
class RequestDeserializer : StdDeserializer<Request>(Request::class.java) {
|
class RequestDeserializer : StdDeserializer<Request>(Request::class.java) {
|
||||||
override fun deserialize(
|
override fun deserialize(
|
||||||
@@ -33,7 +34,7 @@ class RequestDeserializer : StdDeserializer<Request>(Request::class.java) {
|
|||||||
ctxt: DeserializationContext,
|
ctxt: DeserializationContext,
|
||||||
): Request? {
|
): Request? {
|
||||||
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
||||||
val method = jsonObject.get("method")?.asText()
|
val method = jsonObject.get("method")?.asTextOrNull()
|
||||||
|
|
||||||
if (method == "pay_invoice") {
|
if (method == "pay_invoice") {
|
||||||
return jp.codec.treeToValue(jsonObject, PayInvoiceMethod::class.java)
|
return jp.codec.treeToValue(jsonObject, PayInvoiceMethod::class.java)
|
||||||
|
|||||||
+2
-1
@@ -27,6 +27,7 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
|||||||
import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceErrorResponse
|
import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceErrorResponse
|
||||||
import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceSuccessResponse
|
import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceSuccessResponse
|
||||||
import com.vitorpamplona.quartz.nip47WalletConnect.Response
|
import com.vitorpamplona.quartz.nip47WalletConnect.Response
|
||||||
|
import com.vitorpamplona.quartz.utils.asTextOrNull
|
||||||
|
|
||||||
class ResponseDeserializer : StdDeserializer<Response>(Response::class.java) {
|
class ResponseDeserializer : StdDeserializer<Response>(Response::class.java) {
|
||||||
override fun deserialize(
|
override fun deserialize(
|
||||||
@@ -34,7 +35,7 @@ class ResponseDeserializer : StdDeserializer<Response>(Response::class.java) {
|
|||||||
ctxt: DeserializationContext,
|
ctxt: DeserializationContext,
|
||||||
): Response? {
|
): Response? {
|
||||||
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
||||||
val resultType = jsonObject.get("result_type")?.asText()
|
val resultType = jsonObject.get("result_type")?.asTextOrNull()
|
||||||
|
|
||||||
if (resultType == "pay_invoice") {
|
if (resultType == "pay_invoice") {
|
||||||
val result = jsonObject.get("result")
|
val result = jsonObject.get("result")
|
||||||
|
|||||||
+8
-5
@@ -26,6 +26,9 @@ import com.fasterxml.jackson.databind.JsonNode
|
|||||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||||
import com.vitorpamplona.quartz.nip01Core.jackson.TagArrayManualDeserializer
|
import com.vitorpamplona.quartz.nip01Core.jackson.TagArrayManualDeserializer
|
||||||
import com.vitorpamplona.quartz.nip59Giftwrap.rumors.Rumor
|
import com.vitorpamplona.quartz.nip59Giftwrap.rumors.Rumor
|
||||||
|
import com.vitorpamplona.quartz.utils.asIntOrNull
|
||||||
|
import com.vitorpamplona.quartz.utils.asLongOrNull
|
||||||
|
import com.vitorpamplona.quartz.utils.asTextOrNull
|
||||||
|
|
||||||
class RumorDeserializer : StdDeserializer<Rumor>(Rumor::class.java) {
|
class RumorDeserializer : StdDeserializer<Rumor>(Rumor::class.java) {
|
||||||
override fun deserialize(
|
override fun deserialize(
|
||||||
@@ -34,12 +37,12 @@ class RumorDeserializer : StdDeserializer<Rumor>(Rumor::class.java) {
|
|||||||
): Rumor {
|
): Rumor {
|
||||||
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
||||||
return Rumor(
|
return Rumor(
|
||||||
id = jsonObject.get("id")?.asText()?.intern(),
|
id = jsonObject.get("id")?.asTextOrNull()?.intern(),
|
||||||
pubKey = jsonObject.get("pubkey")?.asText()?.intern(),
|
pubKey = jsonObject.get("pubkey")?.asTextOrNull()?.intern(),
|
||||||
createdAt = jsonObject.get("created_at")?.asLong(),
|
createdAt = jsonObject.get("created_at")?.asLongOrNull(),
|
||||||
kind = jsonObject.get("kind")?.asInt(),
|
kind = jsonObject.get("kind")?.asIntOrNull(),
|
||||||
tags = TagArrayManualDeserializer.fromJson(jsonObject.get("tags")),
|
tags = TagArrayManualDeserializer.fromJson(jsonObject.get("tags")),
|
||||||
content = jsonObject.get("content")?.asText(),
|
content = jsonObject.get("content")?.asTextOrNull(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
|
||||||
|
fun JsonNode.asBooleanOrNull() = if (!this.isNull && this.isBoolean) this.booleanValue() else null
|
||||||
|
|
||||||
|
fun JsonNode.asTextOrNull() = if (!this.isNull && this.isTextual) this.textValue() else null
|
||||||
|
|
||||||
|
fun JsonNode.asLongOrNull() = if (!this.isNull && this.isNumber) this.longValue() else null
|
||||||
|
|
||||||
|
fun JsonNode.asIntOrNull() = if (!this.isNull && this.isNumber) this.intValue() else null
|
||||||
Reference in New Issue
Block a user