Merge branch 'vitorpamplona:main' into profiles-list-management

This commit is contained in:
KotlinGeekDev
2025-09-01 17:28:50 +00:00
committed by GitHub
259 changed files with 1358 additions and 603 deletions
+53 -33
View File
@@ -1,42 +1,55 @@
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidKotlinMultiplatformLibrary)
alias(libs.plugins.androidLibrary)
}
android {
namespace = "com.vitorpamplona.quartz"
compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
targetSdk = libs.versions.android.targetSdk.get().toInt()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = true
proguardFiles (getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
create("benchmark") {
initWith(getByName("release"))
signingConfig = signingConfigs.getByName("debug")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
packaging {
resources {
excludes.add("**/libscrypt.dylib")
}
}
publishing {
singleVariant("release")
}
}
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xstring-concat=inline")
}
jvm()
// Target declarations - add or remove as needed below. These define
// which platforms this KMP module supports.
// See: https://kotlinlang.org/docs/multiplatform-discover-project.html#targets
androidLibrary {
namespace = "com.vitorpamplona.quartz"
compileSdk = libs.versions.android.compileSdk.get().toInt()
minSdk = libs.versions.android.minSdk.get().toInt()
withHostTestBuilder {
}
withDeviceTestBuilder {
sourceSetTreeName = "test"
}.configure {
instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
optimization {
consumerKeepRules.publish = true
consumerKeepRules.files.add(File(project.projectDir, "proguard-rules.pro"))
}
packaging {
resources {
excludes.add("**/libscrypt.dylib")
}
}
compilerOptions {
freeCompilerArgs.add("-Xstring-concat=inline")
}
androidTarget {
publishLibraryVariants("release")
}
// For iOS targets, this is also where you should
@@ -84,6 +97,12 @@ kotlin {
}
}
commonTest {
dependencies {
implementation(libs.kotlin.test)
}
}
jvmMain {
dependencies {
// Bitcoin secp256k1 bindings
@@ -106,11 +125,10 @@ kotlin {
}
}
commonTest {
jvmTest {
dependencies {
implementation(libs.kotlin.test)
// Bitcoin secp256k1 bindings
api(libs.secp256k1.kmp.jni.jvm)
implementation(libs.secp256k1.kmp.jni.jvm)
}
}
@@ -145,7 +163,9 @@ kotlin {
}
}
getByName("androidDeviceTest") {
androidUnitTest.configure { dependsOn(jvmTest.get()) }
androidInstrumentedTest {
dependencies {
implementation(libs.androidx.runner)
implementation(libs.androidx.core)
@@ -34,7 +34,7 @@ import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
import com.vitorpamplona.quartz.experimental.nns.NNSEvent
import com.vitorpamplona.quartz.experimental.profileGallery.ProfileGalleryEntryEvent
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
import com.vitorpamplona.quartz.experimental.relationshipStatus.RelationshipStatusEvent
import com.vitorpamplona.quartz.experimental.relationshipStatus.ContactCardEvent
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
@@ -272,7 +272,7 @@ class EventFactory {
ProxyRelayListEvent.KIND -> ProxyRelayListEvent(id, pubKey, createdAt, tags, content, sig)
PublicMessageEvent.KIND -> PublicMessageEvent(id, pubKey, createdAt, tags, content, sig)
ReactionEvent.KIND -> ReactionEvent(id, pubKey, createdAt, tags, content, sig)
RelationshipStatusEvent.KIND -> RelationshipStatusEvent(id, pubKey, createdAt, tags, content, sig)
ContactCardEvent.KIND -> ContactCardEvent(id, pubKey, createdAt, tags, content, sig)
RelayAuthEvent.KIND -> RelayAuthEvent(id, pubKey, createdAt, tags, content, sig)
RelaySetEvent.KIND -> RelaySetEvent(id, pubKey, createdAt, tags, content, sig)
ReportEvent.KIND -> ReportEvent(id, pubKey, createdAt, tags, content, sig)
@@ -22,9 +22,7 @@ package com.vitorpamplona.quartz.experimental.ephemChat.list
import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId
import com.vitorpamplona.quartz.experimental.ephemChat.list.rooms
import com.vitorpamplona.quartz.experimental.ephemChat.list.tags.RoomIdTag
import com.vitorpamplona.quartz.experimental.ephemChat.list.tags.RoomIdTag.Companion.parse
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.TagArray
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
@@ -39,7 +37,6 @@ import com.vitorpamplona.quartz.nip51Lists.PrivateTagArrayEvent
import com.vitorpamplona.quartz.nip51Lists.encryption.PrivateTagsInContent
import com.vitorpamplona.quartz.nip51Lists.removeParsing
import com.vitorpamplona.quartz.utils.TimeUtils
import java.lang.reflect.Modifier.isPrivate
@Immutable
class EphemeralChatListEvent(
@@ -35,7 +35,7 @@ import com.vitorpamplona.quartz.nip51Lists.encryption.PrivateTagsInContent
import com.vitorpamplona.quartz.utils.TimeUtils
@Immutable
class RelationshipStatusEvent(
class ContactCardEvent(
id: HexKey,
pubKey: HexKey,
createdAt: Long,
@@ -49,9 +49,9 @@ class RelationshipStatusEvent(
fun summary() = tags.firstNotNullOfOrNull(SummaryTag::parse)
companion object {
companion object Companion {
const val KIND = 30382
const val ALT = "Relationship Status"
const val ALT = "Contact Card"
suspend fun create(
targetUser: HexKey,
@@ -59,9 +59,9 @@ class RelationshipStatusEvent(
summary: String? = null,
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
publicInitializer: TagArrayBuilder<RelationshipStatusEvent>.() -> Unit = {},
privateInitializer: TagArrayBuilder<RelationshipStatusEvent>.() -> Unit = {},
): RelationshipStatusEvent {
publicInitializer: TagArrayBuilder<ContactCardEvent>.() -> Unit = {},
privateInitializer: TagArrayBuilder<ContactCardEvent>.() -> Unit = {},
): ContactCardEvent {
val publicTags =
tagArray {
alt(ALT)
@@ -25,8 +25,8 @@ import com.vitorpamplona.quartz.experimental.relationshipStatus.tags.RankTag
import com.vitorpamplona.quartz.experimental.relationshipStatus.tags.SummaryTag
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
fun TagArrayBuilder<RelationshipStatusEvent>.rank(rank: Int) = add(RankTag.assemble(rank))
fun TagArrayBuilder<ContactCardEvent>.rank(rank: Int) = add(RankTag.assemble(rank))
fun TagArrayBuilder<RelationshipStatusEvent>.petName(name: String) = add(PetNameTag.assemble(name))
fun TagArrayBuilder<ContactCardEvent>.petName(name: String) = add(PetNameTag.assemble(name))
fun TagArrayBuilder<RelationshipStatusEvent>.summary(summary: String) = add(SummaryTag.assemble(summary))
fun TagArrayBuilder<ContactCardEvent>.summary(summary: String) = add(SummaryTag.assemble(summary))
@@ -24,7 +24,6 @@ import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.ser.std.StdSerializer
import com.vitorpamplona.quartz.nip01Core.core.Event
import kotlin.collections.indices
class EventSerializer : StdSerializer<Event>(Event::class.java) {
override fun serialize(
@@ -103,7 +103,7 @@ class NostrClient(
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Companion.Eagerly,
SharingStarted.Eagerly,
activeRequests.relays.value + activeCounts.relays.value + eventOutbox.relays.value,
)
@@ -24,11 +24,10 @@ import android.util.Log
import androidx.collection.LruCache
import kotlinx.coroutines.CancellationException
import org.czeal.rfc3986.URIReference
import java.lang.IllegalArgumentException
import kotlin.contracts.ExperimentalContracts
sealed interface NormalizationResult {
class Sucess(
class Success(
val url: NormalizedRelayUrl,
) : NormalizationResult
@@ -158,28 +157,16 @@ class RelayUrlNormalizer {
}
fun normalize(url: String): NormalizedRelayUrl {
normalizedUrls[url]?.let {
return when (it) {
is NormalizationResult.Sucess -> it.url
else -> throw IllegalArgumentException("Invalid Url: $url")
}
}
return try {
val fixed = fix(url) ?: return NormalizedRelayUrl(url)
val normalized = norm(fixed)
normalizedUrls.put(url, NormalizationResult.Sucess(normalized))
normalized
} catch (e: Exception) {
NormalizedRelayUrl(url)
}
val result = normalizeOrNull(url)
return result ?: throw IllegalArgumentException("Invalid Relay Url: $url")
}
fun normalizeOrNull(url: String): NormalizedRelayUrl? {
if (url.isEmpty()) return null
// happy path when the url has been fixed already
normalizedUrls[url]?.let {
return when (it) {
is NormalizationResult.Sucess -> it.url
is NormalizationResult.Success -> it.url
else -> null
}
}
@@ -188,8 +175,8 @@ class RelayUrlNormalizer {
val fixed = fix(url)
if (fixed != null) {
val normalized = norm(fixed)
normalizedUrls.put(url, NormalizationResult.Sucess(normalized))
return normalized
normalizedUrls.put(url, NormalizationResult.Success(normalized))
normalized
} else {
Log.w("NormalizedRelayUrl", "Rejected Error $url")
normalizedUrls.put(url, NormalizationResult.Error)
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.quartz.nip10Notes.tags
import android.R.attr.tag
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent
@@ -29,6 +29,7 @@ import com.vitorpamplona.quartz.nip17Dm.files.ChatMessageEncryptedFileHeaderEven
import com.vitorpamplona.quartz.nip17Dm.messages.ChatMessageEvent
import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag
import com.vitorpamplona.quartz.nip40Expiration.expiration
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
import com.vitorpamplona.quartz.utils.mapNotNullAsync
@@ -43,8 +44,17 @@ class NIP17Factory {
event: Event,
to: Set<HexKey>,
signer: NostrSigner,
): List<GiftWrapEvent> =
mapNotNullAsync(
): List<GiftWrapEvent> {
val innerExpDelta =
event.expiration()?.let {
if (it > event.createdAt) {
it - event.createdAt
} else {
null
}
}
return mapNotNullAsync(
to.toList(),
) { next ->
GiftWrapEvent.create(
@@ -52,11 +62,14 @@ class NIP17Factory {
SealedRumorEvent.create(
event = event,
encryptTo = next,
expirationDelta = innerExpDelta,
signer = signer,
),
recipientPubKey = next,
expirationDelta = innerExpDelta,
)
}
}
suspend fun createMessageNIP17(
template: EventTemplate<ChatMessageEvent>,
@@ -80,7 +80,7 @@ object Nip19Parser {
return type!! + key
} catch (e: Throwable) {
Log.e("NIP19 Parser", "Issue trying to Decode NIP19 $uri: ${e.message}", e)
Log.e("NIP19 Parser", "Issue trying to Decode NIP19 $uri: ${e.message}")
}
return null
@@ -103,7 +103,7 @@ object Nip19Parser {
return parseComponents(type, key, additionalChars.ifEmpty { null })
} catch (e: Throwable) {
Log.e("NIP19 Parser", "Issue trying to Decode NIP19 $uri: ${e.message}", e)
Log.e("NIP19 Parser", "Issue trying to Decode NIP19 $uri: ${e.message}")
}
return null
@@ -132,7 +132,7 @@ object Nip19Parser {
ParseReturn(it, nip19, additionalChars)
}
} catch (e: Throwable) {
Log.w("NIP19 Parser", "Issue trying to Decode NIP19 $key: ${e.message}", e)
Log.w("NIP19 Parser", "Issue trying to Decode NIP19 $key: ${e.message}")
null
}
@@ -62,7 +62,6 @@ import com.vitorpamplona.quartz.nip73ExternalIds.ExternalId
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
import com.vitorpamplona.quartz.utils.TimeUtils
import com.vitorpamplona.quartz.utils.lastNotNullOfOrNull
import kotlin.collections.mapNotNull
@Immutable
class CommentEvent(
@@ -78,7 +78,7 @@ class PrivateOutboxRelayListEvent(
val privateTags = earlierVersion.privateTags(signer) ?: throw SignerExceptions.UnauthorizedDecryptionException()
val publicTags = earlierVersion.tags.remove(RelayTag::match)
val newPrivateTags = privateTags.remove(RelayTag::notMatch).plus(newRelayList)
val newPrivateTags = privateTags.remove(RelayTag::match).plus(newRelayList)
return signer.signNip51List(createdAt, KIND, publicTags, newPrivateTags)
}
@@ -40,8 +40,6 @@ import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.relays
import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.searchRelays
import com.vitorpamplona.quartz.nip51Lists.remove
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlin.collections.plus
import kotlin.collections.toTypedArray
@Immutable
class SearchRelayListEvent(
@@ -79,7 +77,7 @@ class SearchRelayListEvent(
val privateTags = earlierVersion.privateTags(signer) ?: throw SignerExceptions.UnauthorizedDecryptionException()
val publicTags = earlierVersion.tags.remove(RelayTag::match)
val newPrivateTags = privateTags.remove(RelayTag::notMatch).plus(newRelayList)
val newPrivateTags = privateTags.remove(RelayTag::match).plus(newRelayList)
return signer.signNip51List(createdAt, KIND, publicTags, newPrivateTags)
}
@@ -24,7 +24,6 @@ import androidx.collection.LruCache
import com.vitorpamplona.quartz.nip01Core.core.TagArray
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.signers.caches.DecryptCache
import kotlin.collections.plus
class PrivateTagArrayEventCache<T : PrivateTagArrayEvent>(
signer: NostrSigner,
@@ -24,7 +24,6 @@ import com.vitorpamplona.quartz.nip01Core.core.Tag
import com.vitorpamplona.quartz.nip01Core.core.TagArray
import com.vitorpamplona.quartz.utils.startsWith
import com.vitorpamplona.quartz.utils.startsWithAny
import kotlin.collections.ArrayList
inline fun TagArray.filterToArray(predicate: (Array<String>) -> Boolean): TagArray = filterTo(ArrayList(), predicate).toTypedArray()
@@ -38,7 +38,6 @@ import com.vitorpamplona.quartz.nip51Lists.tags.ImageTag
import com.vitorpamplona.quartz.nip51Lists.tags.TitleTag
import com.vitorpamplona.quartz.utils.TimeUtils
import java.util.UUID
import kotlin.collections.plus
@Immutable
class FollowListEvent(
@@ -39,7 +39,6 @@ import com.vitorpamplona.quartz.nip51Lists.encryption.signNip51List
import com.vitorpamplona.quartz.nip51Lists.remove
import com.vitorpamplona.quartz.nip51Lists.removeAny
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlin.collections.map
@Immutable
class HashtagListEvent(
@@ -22,7 +22,6 @@ package com.vitorpamplona.quartz.nip51Lists.hashtagList
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.HashtagTag
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtag
fun TagArrayBuilder<HashtagListEvent>.followHashTag(hashtag: String) = add(HashtagTag.assemble(hashtag))
@@ -38,7 +38,6 @@ import com.vitorpamplona.quartz.nip51Lists.muteList.tags.MuteTag
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.UserTag
import com.vitorpamplona.quartz.nip51Lists.remove
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlin.collections.plus
@Immutable
class MuteListEvent(
@@ -44,8 +44,6 @@ import com.vitorpamplona.quartz.nip51Lists.tags.DescriptionTag
import com.vitorpamplona.quartz.nip51Lists.tags.NameTag
import com.vitorpamplona.quartz.utils.TimeUtils
import java.util.UUID
import kotlin.collections.map
import kotlin.collections.plus
@Immutable
class PeopleListEvent(
@@ -77,7 +77,7 @@ class BlockedRelayListEvent(
val privateTags = earlierVersion.privateTags(signer) ?: throw SignerExceptions.UnauthorizedDecryptionException()
val publicTags = earlierVersion.tags.remove(RelayTag::match)
val newPrivateTags = privateTags.remove(RelayTag::notMatch).plus(newRelayList)
val newPrivateTags = privateTags.remove(RelayTag::match).plus(newRelayList)
return signer.signNip51List(createdAt, KIND, publicTags, newPrivateTags)
}
@@ -40,7 +40,6 @@ import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.broadcastRelays
import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.relays
import com.vitorpamplona.quartz.nip51Lists.remove
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlin.collections.plus
@Immutable
class BroadcastRelayListEvent(
@@ -77,7 +76,7 @@ class BroadcastRelayListEvent(
val newRelayList = relays.map { RelayTag.assemble(it) }
val privateTags = earlierVersion.privateTags(signer) ?: throw SignerExceptions.UnauthorizedDecryptionException()
val publicTags = earlierVersion.tags.remove(RelayTag::match)
val newPrivateTags = privateTags.remove(RelayTag::notMatch).plus(newRelayList)
val newPrivateTags = privateTags.remove(RelayTag::match).plus(newRelayList)
return signer.signNip51List(createdAt, KIND, publicTags, newPrivateTags)
}
@@ -40,7 +40,6 @@ import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.indexerRelays
import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.relays
import com.vitorpamplona.quartz.nip51Lists.remove
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlin.collections.plus
@Immutable
class IndexerRelayListEvent(
@@ -78,7 +77,7 @@ class IndexerRelayListEvent(
val privateTags = earlierVersion.privateTags(signer) ?: throw SignerExceptions.UnauthorizedDecryptionException()
val publicTags = earlierVersion.tags.remove(RelayTag::match)
val newPrivateTags = privateTags.remove(RelayTag::notMatch).plus(newRelayList)
val newPrivateTags = privateTags.remove(RelayTag::match).plus(newRelayList)
return signer.signNip51List(createdAt, KIND, publicTags, newPrivateTags)
}
@@ -40,7 +40,6 @@ import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.proxyRelays
import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.relays
import com.vitorpamplona.quartz.nip51Lists.remove
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlin.collections.plus
@Immutable
class ProxyRelayListEvent(
@@ -78,7 +77,7 @@ class ProxyRelayListEvent(
val privateTags = earlierVersion.privateTags(signer) ?: throw SignerExceptions.UnauthorizedDecryptionException()
val publicTags = earlierVersion.tags.remove(RelayTag::match)
val newPrivateTags = privateTags.remove(RelayTag::notMatch).plus(newRelayList)
val newPrivateTags = privateTags.remove(RelayTag::match).plus(newRelayList)
return signer.signNip51List(createdAt, KIND, publicTags, newPrivateTags)
}
@@ -40,7 +40,6 @@ import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.relays
import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.trustedRelays
import com.vitorpamplona.quartz.nip51Lists.remove
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlin.collections.plus
@Immutable
class TrustedRelayListEvent(
@@ -78,7 +77,7 @@ class TrustedRelayListEvent(
val privateTags = earlierVersion.privateTags(signer) ?: throw SignerExceptions.UnauthorizedDecryptionException()
val publicTags = earlierVersion.tags.remove(RelayTag::match)
val newPrivateTags = privateTags.remove(RelayTag::notMatch).plus(newRelayList)
val newPrivateTags = privateTags.remove(RelayTag::match).plus(newRelayList)
return signer.signNip51List(createdAt, KIND, publicTags, newPrivateTags)
}
@@ -32,7 +32,6 @@ import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
import com.vitorpamplona.quartz.nip51Lists.relaySets.RelaySetEvent
import com.vitorpamplona.quartz.nip51Lists.tags.NameTag
import kotlin.collections.map
fun <T : PrivateTagArrayEvent> TagArrayBuilder<T>.name(name: String) = addUnique(NameTag.assemble(name))
@@ -73,7 +73,7 @@ class RelaySetEvent(
val privateTags = earlierVersion.privateTags(signer) ?: throw SignerExceptions.UnauthorizedDecryptionException()
val publicTags = earlierVersion.tags.remove(RelayTag::match)
val newPrivateTags = privateTags.remove(RelayTag::notMatch).plus(newRelayList)
val newPrivateTags = privateTags.remove(RelayTag::match).plus(newRelayList)
return signer.signNip51List(createdAt, KIND, publicTags, newPrivateTags)
}
@@ -29,7 +29,6 @@ import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.results.IntentResult
import com.vitorpamplona.quartz.utils.RandomInstance
import com.vitorpamplona.quartz.utils.tryAndWait
import kotlin.collections.forEach
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
@@ -37,7 +37,6 @@ import com.vitorpamplona.quartz.nip55AndroidSigner.client.handlers.BackgroundReq
import com.vitorpamplona.quartz.nip55AndroidSigner.client.handlers.ForegroundRequestHandler
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
import java.lang.Exception
class NostrSignerExternal(
pubKey: HexKey,
@@ -25,6 +25,7 @@ import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip40Expiration.ExpirationTag
import com.vitorpamplona.quartz.nip59Giftwrap.HostStub
import com.vitorpamplona.quartz.nip59Giftwrap.WrappedEvent
import com.vitorpamplona.quartz.nip59Giftwrap.rumors.Rumor
@@ -99,23 +100,33 @@ class SealedRumorEvent(
event: Event,
encryptTo: HexKey,
signer: NostrSigner,
expirationDelta: Long? = null,
createdAt: Long = TimeUtils.now(),
): SealedRumorEvent {
val rumor = Rumor.create(event)
return create(rumor, encryptTo, signer, createdAt)
return create(rumor, encryptTo, signer, expirationDelta, createdAt)
}
suspend fun create(
rumor: Rumor,
encryptTo: HexKey,
signer: NostrSigner,
expirationDelta: Long? = null,
createdAt: Long = TimeUtils.randomWithTwoDays(),
): SealedRumorEvent {
val msg = Rumor.toJson(rumor)
val tags =
expirationDelta?.let {
// minimum expiration is two days in the future due to the random created at
// this will make sure the even arrives and is not deleted because of the 2 days.
arrayOf(ExpirationTag.assemble(createdAt + it + TimeUtils.twoDays()))
} ?: emptyArray()
return signer.sign(
createdAt = createdAt,
kind = KIND,
tags = emptyArray(),
tags = tags,
content = signer.nip44Encrypt(msg, encryptTo),
)
}
@@ -28,7 +28,9 @@ import com.vitorpamplona.quartz.nip01Core.core.firstTagValue
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
import com.vitorpamplona.quartz.nip21UriScheme.toNostrUri
import com.vitorpamplona.quartz.nip40Expiration.ExpirationTag
import com.vitorpamplona.quartz.nip59Giftwrap.HostStub
import com.vitorpamplona.quartz.nip59Giftwrap.WrappedEvent
import com.vitorpamplona.quartz.utils.TimeUtils
@@ -103,13 +105,27 @@ class GiftWrapEvent(
suspend fun create(
event: Event,
recipientPubKey: HexKey,
expirationDelta: Long? = null,
createdAt: Long = TimeUtils.randomWithTwoDays(),
): GiftWrapEvent {
val signer = NostrSignerInternal(KeyPair()) // GiftWrap is always a random key
val tags =
expirationDelta?.let {
// minimum expiration is two days in the future due to the random created at
// this will make sure the even arrives and is not deleted because of the 2 days.
arrayOf(
PTag.assemble(recipientPubKey, null),
ExpirationTag.assemble(createdAt + it + TimeUtils.twoDays()),
)
} ?: arrayOf(
PTag.assemble(recipientPubKey, null),
)
return signer.sign(
createdAt = createdAt,
kind = KIND,
tags = arrayOf(arrayOf("p", recipientPubKey)),
tags = tags,
content = signer.nip44Encrypt(event.toJson(), recipientPubKey),
)
}
@@ -20,7 +20,6 @@
*/
package com.vitorpamplona.quartz.nip62RequestToVanish.tags
import android.R.attr.tag
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
@@ -20,10 +20,8 @@
*/
package com.vitorpamplona.quartz.nip62RequestToVanish.tags
import com.vitorpamplona.quartz.experimental.ephemChat.chat.relay
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
import com.vitorpamplona.quartz.nip62RequestToVanish.RequestToVanishEvent
import kotlin.collections.map
fun TagArrayBuilder<RequestToVanishEvent>.vanishFromEverywhere() = add(RelayTag.assembleEverywhere())
@@ -41,6 +41,8 @@ class AdvertisedRelayListEvent(
) : BaseReplaceableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
fun relays() = tags.mapNotNull(AdvertisedRelayInfo::parse)
fun relaysNorm() = tags.mapNotNull(AdvertisedRelayInfo::parseNorm)
fun readRelays() = tags.mapNotNull(AdvertisedRelayInfo::parseRead).ifEmpty { null }
fun readRelaysNorm() = tags.mapNotNull(AdvertisedRelayInfo::parseReadNorm).ifEmpty { null }
@@ -58,6 +58,13 @@ class AdvertisedRelayInfo(
return AdvertisedRelayInfo(normalizedUrl, type)
}
@JvmStatic
fun parseNorm(tag: Array<String>): NormalizedRelayUrl? {
ensure(match(tag)) { return null }
val normalizedUrl = RelayUrlNormalizer.normalizeOrNull(tag[1])
return normalizedUrl
}
@JvmStatic
fun parseRead(tag: Array<String>): String? {
ensure(match(tag)) { return null }
@@ -31,23 +31,15 @@ import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider
import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag.Companion.isTagged
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip01Core.tags.kinds.kind
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
import com.vitorpamplona.quartz.nip31Alts.alt
import com.vitorpamplona.quartz.nip72ModCommunities.approval.tags.ApprovedAddressTag
import com.vitorpamplona.quartz.nip72ModCommunities.approval.tags.ApprovedAddressTag.Companion.parseAddress
import com.vitorpamplona.quartz.nip72ModCommunities.approval.tags.ApprovedAddressTag.Companion.parseAddressId
import com.vitorpamplona.quartz.nip72ModCommunities.approval.tags.ApprovedAddressTag.Companion.parseAsHint
import com.vitorpamplona.quartz.nip72ModCommunities.approval.tags.ApprovedEventTag
import com.vitorpamplona.quartz.nip72ModCommunities.approval.tags.ApprovedEventTag.Companion.parse
import com.vitorpamplona.quartz.nip72ModCommunities.approval.tags.ApprovedEventTag.Companion.parseAsHint
import com.vitorpamplona.quartz.nip72ModCommunities.approval.tags.ApprovedEventTag.Companion.parseId
import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent
import com.vitorpamplona.quartz.nip72ModCommunities.follow.tags.CommunityTag
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlin.collections.mapNotNull
@Immutable
class CommunityPostApprovalEvent(
@@ -38,7 +38,6 @@ import com.vitorpamplona.quartz.nip51Lists.remove
import com.vitorpamplona.quartz.nip51Lists.removeAny
import com.vitorpamplona.quartz.nip72ModCommunities.follow.tags.CommunityTag
import com.vitorpamplona.quartz.utils.TimeUtils
import kotlin.collections.plus
@Immutable
class CommunityListEvent(
@@ -22,7 +22,6 @@ package com.vitorpamplona.quartz.nipA0VoiceMessages.tags
import com.vitorpamplona.quartz.nip01Core.core.has
import com.vitorpamplona.quartz.utils.ensure
import kotlin.collections.joinToString
class WaveformTag(
val wave: List<Float>,
@@ -117,9 +117,7 @@ class LargeSoftCache<K, V> : CacheOperations<K, V> {
}
keysToRemove.forEach { key, value ->
cache.remove(key, value)
println("Cleaned up entry for key: $key (object was garbage collected)")
}
println("Cache cleanup completed. Remaining size: ${cache.size}")
}
override fun forEach(consumer: BiConsumer<K, V>) {

Some files were not shown because too many files have changed in this diff Show More