Adds a Count reply message to relays

This commit is contained in:
Vitor Pamplona
2025-10-10 11:17:43 -04:00
parent 973cfd24fa
commit 24f7d76dc4
5 changed files with 132 additions and 0 deletions
@@ -0,0 +1,37 @@
/**
* 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.nip01Core.relay.commands.toClient
class CountMessage(
val queryId: String,
val result: CountResult,
) : Message {
override fun label() = LABEL
companion object {
const val LABEL = "COUNT"
}
}
class CountResult(
val count: Int,
val approximate: Boolean = false,
)
@@ -0,0 +1,33 @@
/**
* 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.nip01Core.relay.commands.toClient
import com.fasterxml.jackson.databind.JsonNode
class CountResultDeserializer {
companion object {
fun fromJson(jsonObject: JsonNode): CountResult =
CountResult(
count = jsonObject.get("count").asInt(),
approximate = jsonObject.get("approximate").asBoolean(),
)
}
}
@@ -0,0 +1,39 @@
/**
* 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.nip01Core.relay.commands.toClient
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.ser.std.StdSerializer
import kotlin.jvm.java
class CountResultSerializer : StdSerializer<CountResult>(CountResult::class.java) {
override fun serialize(
result: CountResult,
gen: JsonGenerator,
provider: SerializerProvider,
) {
gen.writeStartObject()
gen.writeNumberField("count", result.count)
gen.writeBooleanField("pubkey", result.approximate)
gen.writeEndObject()
}
}
@@ -50,33 +50,51 @@ class MessageDeserializer : StdDeserializer<Message>(Message::class.java) {
event = EventManualDeserializer.fromJson(event),
)
}
EoseMessage.LABEL ->
EoseMessage(
subId = jp.nextTextValue(),
)
NoticeMessage.LABEL ->
NoticeMessage(
message = jp.nextTextValue(),
)
OkMessage.LABEL ->
OkMessage(
eventId = jp.nextTextValue(),
success = jp.nextBooleanValue(),
message = jp.nextTextValue() ?: "",
)
AuthMessage.LABEL ->
AuthMessage(
challenge = jp.nextTextValue(),
)
NotifyMessage.LABEL ->
NotifyMessage(
message = jp.nextTextValue(),
)
ClosedMessage.LABEL ->
ClosedMessage(
subId = jp.nextTextValue(),
message = jp.nextTextValue(),
)
CountMessage.LABEL -> {
val queryId = jp.nextTextValue()
jp.nextToken()
val result: JsonNode = jp.codec.readTree(jp)
CountMessage(
queryId = queryId,
result = CountResultDeserializer.fromJson(result),
)
}
else -> {
throw IllegalArgumentException("Message $type is not supported")
}
@@ -27,6 +27,7 @@ import com.vitorpamplona.quartz.nip01Core.jackson.EventSerializer
class MessageSerializer : StdSerializer<Message>(Message::class.java) {
val eventSerializer = EventSerializer()
val countSerializer = CountResultSerializer()
override fun serialize(
msg: Message,
@@ -67,6 +68,10 @@ class MessageSerializer : StdSerializer<Message>(Message::class.java) {
gen.writeString(msg.message)
}
is CountMessage -> {
countSerializer.serialize(msg.result, gen, provider)
}
else -> null
}