- Updates several libraries

- Reformats code to the newest Klint
- Fixes isEmpty bug on Filters
This commit is contained in:
Vitor Pamplona
2026-02-09 14:06:07 -05:00
parent 710f15f790
commit eb66182211
133 changed files with 1373 additions and 580 deletions
@@ -41,9 +41,11 @@ class SqlSelectionBuilder(
is Condition.Empty -> {
""
}
is Condition.Raw -> {
cond.condition
}
is Condition.Equals -> {
if (cond.value == null) {
"${cond.column} IS NULL"
@@ -52,6 +54,7 @@ class SqlSelectionBuilder(
"${cond.column} = ?"
}
}
is Condition.NotEquals -> {
if (cond.value == null) {
"${cond.column} IS NULL"
@@ -60,36 +63,45 @@ class SqlSelectionBuilder(
"${cond.column} != ?"
}
}
is Condition.GreaterThan -> {
selectionArgs.add(cond.value.toString())
"${cond.column} > ?"
}
is Condition.GreaterThanOrEquals -> {
selectionArgs.add(cond.value.toString())
"${cond.column} >= ?"
}
is Condition.LessThan -> {
selectionArgs.add(cond.value.toString())
"${cond.column} < ?"
}
is Condition.LessThanOrEquals -> {
selectionArgs.add(cond.value.toString())
"${cond.column} <= ?"
}
is Condition.Like -> {
selectionArgs.add(cond.value)
"${cond.column} LIKE ?"
}
is Condition.Match -> {
selectionArgs.add(cond.value)
"${cond.table} MATCH ?"
}
is Condition.IsNull -> {
"${cond.column} IS NULL"
}
is Condition.IsNotNull -> {
"${cond.column} IS NOT NULL"
}
is Condition.In -> {
if (cond.values.isEmpty()) {
// Handle empty IN clause gracefully, perhaps by making it always false
@@ -102,6 +114,7 @@ class SqlSelectionBuilder(
"${cond.column} IN ($placeholders)"
}
}
is Condition.And -> {
if (cond.conditions.isEmpty()) {
"1 = 1" // Always true for an empty AND
@@ -109,6 +122,7 @@ class SqlSelectionBuilder(
cond.conditions.joinToString(" AND ") { "(${buildCondition(it)})" }
}
}
is Condition.Or -> {
if (cond.conditions.isEmpty()) {
"1 = 0" // Always false for an empty OR
@@ -184,10 +184,8 @@ class NostrSignerExternal(
is SignerResult.RequestAddressed.Successful<*> -> IllegalStateException("$title: This should not happen. There is a bug on Quartz.")
is SignerResult.RequestAddressed.ReceivedButCouldNotParseEventFromResult<*> -> IllegalStateException("$title: Failed to parse event: ${result.eventJson}.")
is SignerResult.RequestAddressed.ReceivedButCouldNotVerifyResultingEvent<*> -> IllegalStateException("$title: Failed to verify event: ${result.invalidEvent.toJson()}.")
is SignerResult.RequestAddressed.ReceivedButCouldNotPerform<*> -> SignerExceptions.CouldNotPerformException("$title: ${result.message}")
is SignerResult.RequestAddressed.SignerNotFound<*> -> SignerExceptions.SignerNotFoundException("$title: Signer app was not found.")
is SignerResult.RequestAddressed.AutomaticallyRejected<*> -> SignerExceptions.AutomaticallyUnauthorizedException("$title: User has rejected the request.")
is SignerResult.RequestAddressed.ManuallyRejected<*> -> SignerExceptions.ManuallyUnauthorizedException("$title: User has rejected the request.")
is SignerResult.RequestAddressed.TimedOut<*> -> SignerExceptions.TimedOutException("$title: User didn't accept or reject in time.")
@@ -136,6 +136,7 @@ class PoolCounts {
relay.sendOrConnectAndSync(cmd)
}
}
is ClosedMessage -> {
subState(msg.subId).onClosed(relay.url)
sendToRelayIfChanged(msg.subId, relay.url) { cmd ->
@@ -170,6 +170,7 @@ class PoolRequests {
forFilters = cmd.filters,
)
}
is CloseCmd -> {
subState(cmd.subId).onCloseReq(relay)
desiredSubListeners.get(cmd.subId)?.onCloseReq(
@@ -197,6 +198,7 @@ class PoolRequests {
forFilters = state?.lastKnownFilterStates(relay.url),
)
}
is EoseMessage -> {
val state = relayState.get(msg.subId)
state?.onEose(relay.url)
@@ -210,6 +212,7 @@ class PoolRequests {
relay.sendOrConnectAndSync(cmd)
}
}
is ClosedMessage -> {
val state = relayState.get(msg.subId)
state?.onClosed(relay.url)
@@ -83,14 +83,23 @@ class RelayStats(
stat.addBytesReceived(msgStr.bytesUsedInMemory())
when (msg) {
is NoticeMessage -> stat.newNotice(msg.message)
is NotifyMessage -> stat.newNotice("Notify user: " + msg.message)
is NoticeMessage -> {
stat.newNotice(msg.message)
}
is NotifyMessage -> {
stat.newNotice("Notify user: " + msg.message)
}
is OkMessage -> {
if (!msg.success) {
stat.newNotice("Rejected event ${msg.eventId}: ${msg.message}")
}
}
is ClosedMessage -> stat.newNotice("Subscription closed: ${msg.subId} ${msg.message}")
is ClosedMessage -> {
stat.newNotice("Subscription closed: ${msg.subId} ${msg.message}")
}
}
}
}
@@ -80,8 +80,8 @@ class Filter(
(ids == null || ids.isEmpty()) &&
(authors == null || authors.isEmpty()) &&
(kinds == null || kinds.isEmpty()) &&
(tags == null || tags.isEmpty() && tags.values.all { it.isNotEmpty() }) &&
(tagsAll == null || tagsAll.isEmpty() && tagsAll.values.all { it.isNotEmpty() }) &&
(tags == null || tags.isEmpty() || tags.values.all { it.isEmpty() }) &&
(tagsAll == null || tagsAll.isEmpty() || tagsAll.values.all { it.isEmpty() }) &&
(since == null) &&
(until == null) &&
(limit == null) &&
@@ -100,8 +100,14 @@ abstract class DecryptCache<I : Any, T : Any>(
suspend fun decrypt(input: I): T? {
val cachedResult = cache
return when (cachedResult) {
is CacheResults.Success<T> -> cachedResult.value
is CacheResults.DontTryAgain -> null
is CacheResults.Success<T> -> {
cachedResult.value
}
is CacheResults.DontTryAgain -> {
null
}
is CacheResults.CanTryAgain -> {
if (TimeUtils.now() > cachedResult.after) {
performDecrypt(input)
@@ -109,6 +115,7 @@ abstract class DecryptCache<I : Any, T : Any>(
null
}
}
is CacheResults.NeedsForegroundActivityToTryAgain<*> -> {
if (TimeUtils.now() > cachedResult.after && signer.hasForegroundSupport()) {
performDecrypt(input)
@@ -38,8 +38,14 @@ class VerificationStateCache(
suspend fun cacheVerify(event: OtsEvent): VerificationState =
when (val verif = cache[event.id]) {
is VerificationState.Verifying -> verif
is VerificationState.Verified -> verif
is VerificationState.Verifying -> {
verif
}
is VerificationState.Verified -> {
verif
}
is VerificationState.NetworkError -> {
// try again in 5 mins
if (verif.time < TimeUtils.fiveMinutesAgo()) {
@@ -48,7 +54,11 @@ class VerificationStateCache(
verif
}
}
is VerificationState.Error -> verif
is VerificationState.Error -> {
verif
}
else -> {
verify(event)
}
@@ -399,7 +399,7 @@ class Timestamp(
}
val isTimestampComplete: Boolean
/**
/*
* Determine if timestamp is complete and can be verified.
*
* @return True if the timestamp is complete, False otherwise.
@@ -39,10 +39,22 @@ abstract class OpUnary : Op() {
tag: Byte,
): Op? =
when (tag) {
OpSHA1.TAG -> OpSHA1()
OpSHA256.TAG -> OpSHA256()
OpRIPEMD160.TAG -> OpRIPEMD160()
OpKECCAK256.TAG -> OpKECCAK256()
OpSHA1.TAG -> {
OpSHA1()
}
OpSHA256.TAG -> {
OpSHA256()
}
OpRIPEMD160.TAG -> {
OpRIPEMD160()
}
OpKECCAK256.TAG -> {
OpKECCAK256()
}
else -> {
Log.e("OpenTimestamp", "Unknown operation tag: $tag")
@@ -41,10 +41,19 @@ fun List<ETag>.positionalMarkedTags(
sortedWith { o1, o2 ->
when {
o1.eventId == o2.eventId -> 0
o1.eventId == root?.eventId -> -1 // root goes first
o2.eventId == root?.eventId -> 1 // root goes first
o1.eventId == replyingTo?.eventId -> 1 // reply event being responded to goes last
o2.eventId == replyingTo?.eventId -> -1 // reply event being responded to goes last
o1.eventId == root?.eventId -> -1
// root goes first
o2.eventId == root?.eventId -> 1
// root goes first
o1.eventId == replyingTo?.eventId -> 1
// reply event being responded to goes last
o2.eventId == replyingTo?.eventId -> -1
// reply event being responded to goes last
else -> 0 // keep the relative order for any other tag
}
}.map {
@@ -45,7 +45,9 @@ object FlexibleIntListSerializer : KSerializer<List<String>?> {
return when (val element = decoder.decodeJsonElement()) {
// Handle JSON null
is JsonNull -> null
is JsonNull -> {
null
}
// Handle array format (spec-compliant): [1, 2, 3]
is JsonArray -> {
@@ -72,7 +74,9 @@ object FlexibleIntListSerializer : KSerializer<List<String>?> {
}
// Unsupported format (strings, objects, etc.)
else -> null
else -> {
null
}
}
}
@@ -43,9 +43,7 @@ fun <T : Event> TagArrayBuilder<T>.quote(entity: Entity) =
is NEmbed -> add(entity.toQuoteTagArray())
is NPub -> add(entity.toQuoteTagArray())
is NProfile -> add(entity.toQuoteTagArray())
else -> {
this
}
else -> this
}
fun <T : Event> TagArrayBuilder<T>.quotes(entities: List<Entity>) = entities.forEach { quote(it) }
@@ -102,7 +102,9 @@ object Nip44 {
v2.decrypt(encryptedInfo, privateKey, pubKey)
}
else -> throw IllegalArgumentException("Invalid or unsupported NIP-44 version code ${info.v}")
else -> {
throw IllegalArgumentException("Invalid or unsupported NIP-44 version code ${info.v}")
}
}
}
@@ -31,9 +31,11 @@ class Nip04DecryptResponse {
is BunkerResponseDecrypt -> {
SignerResult.RequestAddressed.Successful(DecryptionResult(response.plaintext))
}
is BunkerResponseError -> {
SignerResult.RequestAddressed.Rejected()
}
else -> {
SignerResult.RequestAddressed.ReceivedButCouldNotPerform()
}
@@ -46,14 +46,12 @@ enum class ReportType(
"harassment" -> HARASSMENT
"Harassment" -> HARASSMENT
"Harrassment" -> HARASSMENT
"impersonation" -> IMPERSONATION
"Impersonation" -> IMPERSONATION
"Falsificação de identidade \uD83E\uDD78" -> IMPERSONATION
"Suplantación de identidad \uD83E\uDD78" -> IMPERSONATION
"Impersonation \uD83E\uDD78" -> IMPERSONATION
"Předstírání identity \uD83E\uDD78" -> IMPERSONATION
"illegal" -> ILLEGAL
"Illegal" -> ILLEGAL
"Illegal Material" -> ILLEGAL
@@ -63,7 +61,6 @@ enum class ReportType(
"csam" -> ILLEGAL
"abuse" -> ILLEGAL
"fraud" -> ILLEGAL
"explicit" -> NUDITY
"explıcıt" -> NUDITY
"Explicit" -> NUDITY
@@ -73,14 +70,11 @@ enum class ReportType(
"sexual-content" -> NUDITY
"inappropriate" -> NUDITY
"Naaktheid \uD83C\uDF51\uD83C\uDF46" -> NUDITY
"profanity" -> PROFANITY
"Profanity" -> PROFANITY
"Profanity \uD83D\uDDEF\uFE0F" -> PROFANITY
"malware" -> MALWARE
"Malware" -> MALWARE
"other" -> OTHER
"Other" -> OTHER
"mod" -> OTHER
@@ -89,20 +83,14 @@ enum class ReportType(
"ai-generated" -> OTHER
"duplicate" -> OTHER
"" -> OTHER
"spam" -> SPAM
"Spam" -> SPAM
"Spam \uD83D\uDCE3" -> SPAM
"Bot Activity" -> SPAM
"スパム \uD83D\uDCE3" -> SPAM
"Pourriel \uD83D\uDCE3" -> SPAM
"violence" -> VIOLENCE
else -> {
Log.w("ReportedEventTag", "Report type not supported: `$code` ${tag.joinToString(", ")}")
OTHER
}
else -> Log.w("ReportedEventTag", "Report type not supported: `$code` ${tag.joinToString(", ")}").let { OTHER }
}
}
}
@@ -111,16 +111,23 @@ class LnZapRequestEvent(
}
return when (zapType) {
LnZapEvent.ZapType.PUBLIC -> signer.sign(createdAt, KIND, tags.toTypedArray(), message)
LnZapEvent.ZapType.PUBLIC -> {
signer.sign(createdAt, KIND, tags.toTypedArray(), message)
}
LnZapEvent.ZapType.ANONYMOUS -> {
tags = tags + listOf(arrayOf("anon"))
NostrSignerInternal(KeyPair()).sign(createdAt, KIND, tags.toTypedArray(), message)
}
LnZapEvent.ZapType.PRIVATE -> {
tags = tags + listOf(arrayOf("anon", ""))
signer.sign(createdAt, KIND, tags.toTypedArray(), message)
}
LnZapEvent.ZapType.NONZAP -> throw IllegalArgumentException("Invalid zap type")
LnZapEvent.ZapType.NONZAP -> {
throw IllegalArgumentException("Invalid zap type")
}
}
}
@@ -139,16 +146,23 @@ class LnZapRequestEvent(
)
return when (zapType) {
LnZapEvent.ZapType.PUBLIC -> signer.sign(createdAt, KIND, tags, message)
LnZapEvent.ZapType.PUBLIC -> {
signer.sign(createdAt, KIND, tags, message)
}
LnZapEvent.ZapType.ANONYMOUS -> {
tags += arrayOf(arrayOf("anon", ""))
NostrSignerInternal(KeyPair()).sign(createdAt, KIND, tags, message)
}
LnZapEvent.ZapType.PRIVATE -> {
tags += arrayOf(arrayOf("anon", ""))
signer.sign(createdAt, KIND, tags, message)
}
LnZapEvent.ZapType.NONZAP -> throw IllegalArgumentException("Invalid zap type")
LnZapEvent.ZapType.NONZAP -> {
throw IllegalArgumentException("Invalid zap type")
}
}
}
}
@@ -189,34 +189,8 @@ class EventFactory {
ChannelMessageEvent.KIND -> ChannelMessageEvent(id, pubKey, createdAt, tags, content, sig)
ChannelMetadataEvent.KIND -> ChannelMetadataEvent(id, pubKey, createdAt, tags, content, sig)
ChannelMuteUserEvent.KIND -> ChannelMuteUserEvent(id, pubKey, createdAt, tags, content, sig)
ChatMessageEncryptedFileHeaderEvent.KIND -> {
if (id.isBlank()) {
ChatMessageEncryptedFileHeaderEvent(
EventHasher.hashId(pubKey, createdAt, kind, tags, content),
pubKey,
createdAt,
tags,
content,
sig,
)
} else {
ChatMessageEncryptedFileHeaderEvent(id, pubKey, createdAt, tags, content, sig)
}
}
ChatMessageEvent.KIND -> {
if (id.isBlank()) {
ChatMessageEvent(
EventHasher.hashId(pubKey, createdAt, kind, tags, content),
pubKey,
createdAt,
tags,
content,
sig,
)
} else {
ChatMessageEvent(id, pubKey, createdAt, tags, content, sig)
}
}
ChatMessageEncryptedFileHeaderEvent.KIND -> ChatMessageEncryptedFileHeaderEvent(id.ifBlank { EventHasher.hashId(pubKey, createdAt, kind, tags, content) }, pubKey, createdAt, tags, content, sig)
ChatMessageEvent.KIND -> ChatMessageEvent(id.ifBlank { EventHasher.hashId(pubKey, createdAt, kind, tags, content) }, pubKey, createdAt, tags, content, sig)
ChatMessageRelayListEvent.KIND -> ChatMessageRelayListEvent(id, pubKey, createdAt, tags, content, sig)
ClassifiedsEvent.KIND -> ClassifiedsEvent(id, pubKey, createdAt, tags, content, sig)
CommentEvent.KIND -> CommentEvent(id, pubKey, createdAt, tags, content, sig)
@@ -307,10 +281,7 @@ class EventFactory {
VoiceEvent.KIND -> VoiceEvent(id, pubKey, createdAt, tags, content, sig)
VoiceReplyEvent.KIND -> VoiceReplyEvent(id, pubKey, createdAt, tags, content, sig)
WikiNoteEvent.KIND -> WikiNoteEvent(id, pubKey, createdAt, tags, content, sig)
else -> {
factories[kind]?.build(id, pubKey, createdAt, tags, content, sig)
?: Event(id, pubKey, createdAt, kind, tags, content, sig)
}
else -> factories[kind]?.build(id, pubKey, createdAt, tags, content, sig) ?: Event(id, pubKey, createdAt, kind, tags, content, sig)
} as T
}
}
@@ -51,38 +51,44 @@ class MessageDeserializer : StdDeserializer<Message>(Message::class.java) {
)
}
EoseMessage.LABEL ->
EoseMessage.LABEL -> {
EoseMessage(
subId = jp.nextTextValue(),
)
}
NoticeMessage.LABEL ->
NoticeMessage.LABEL -> {
NoticeMessage(
message = jp.nextTextValue(),
)
}
OkMessage.LABEL ->
OkMessage.LABEL -> {
OkMessage(
eventId = jp.nextTextValue(),
success = jp.nextBooleanValue(),
message = jp.nextTextValue() ?: "",
)
}
AuthMessage.LABEL ->
AuthMessage.LABEL -> {
AuthMessage(
challenge = jp.nextTextValue(),
)
}
NotifyMessage.LABEL ->
NotifyMessage.LABEL -> {
NotifyMessage(
message = jp.nextTextValue(),
)
}
ClosedMessage.LABEL ->
ClosedMessage.LABEL -> {
ClosedMessage(
subId = jp.nextTextValue(),
message = jp.nextTextValue() ?: "",
)
}
CountMessage.LABEL -> {
val queryId = jp.nextTextValue()
@@ -72,7 +72,9 @@ class MessageSerializer : StdSerializer<Message>(Message::class.java) {
countSerializer.serialize(msg.result, gen, provider)
}
else -> null
else -> {
null
}
}
gen.writeEndArray()
@@ -84,10 +84,11 @@ class CommandDeserializer : StdDeserializer<Command>(Command::class.java) {
)
}
CloseCmd.LABEL ->
CloseCmd.LABEL -> {
CloseCmd(
subId = jp.nextTextValue(),
)
}
AuthCmd.LABEL -> {
jp.nextToken()
@@ -65,7 +65,9 @@ class CommandSerializer : StdSerializer<Command>(Command::class.java) {
}
}
else -> null
else -> {
null
}
}
gen.writeEndArray()
@@ -50,12 +50,10 @@ class BunkerRequestDeserializer : StdDeserializer<BunkerRequest>(BunkerRequest::
BunkerRequestConnect.METHOD_NAME -> BunkerRequestConnect.parse(id, params)
BunkerRequestGetPublicKey.METHOD_NAME -> BunkerRequestGetPublicKey.parse(id, params)
BunkerRequestGetRelays.METHOD_NAME -> BunkerRequestGetRelays.parse(id, params)
BunkerRequestNip04Decrypt.METHOD_NAME -> BunkerRequestNip04Decrypt.parse(id, params)
BunkerRequestNip04Encrypt.METHOD_NAME -> BunkerRequestNip04Encrypt.parse(id, params)
BunkerRequestNip44Decrypt.METHOD_NAME -> BunkerRequestNip44Decrypt.parse(id, params)
BunkerRequestNip44Encrypt.METHOD_NAME -> BunkerRequestNip44Encrypt.parse(id, params)
BunkerRequestPing.METHOD_NAME -> BunkerRequestPing.parse(id, params)
BunkerRequestSign.METHOD_NAME -> BunkerRequestSign.parse(id, params)
else -> BunkerRequest(id, method, params)
@@ -50,8 +50,14 @@ class BunkerResponseDeserializer : StdDeserializer<BunkerResponse>(BunkerRespons
if (result != null) {
when (result) {
BunkerResponseAck.RESULT -> return BunkerResponseAck.parse(id, result, error)
BunkerResponsePong.RESULT -> return BunkerResponsePong.parse(id, result, error)
BunkerResponseAck.RESULT -> {
return BunkerResponseAck.parse(id, result, error)
}
BunkerResponsePong.RESULT -> {
return BunkerResponsePong.parse(id, result, error)
}
else -> {
if (result.length == 64 && Hex.isHex(result)) {
return BunkerResponsePublicKey.parse(id, result)
@@ -64,14 +64,17 @@ class NostrClientRepeatSubTest : BaseNostrClientTest() {
) {
Log.d("Test", "Receiving message: $msgStr")
when (msg) {
is EventMessage ->
is EventMessage -> {
if (mySubId == msg.subId) {
resultChannel.trySend(msg.event.id)
}
is EoseMessage ->
}
is EoseMessage -> {
if (mySubId == msg.subId) {
resultChannel.trySend("EOSE")
}
}
}
}
}