Migrating Lint to 1.3.1

This commit is contained in:
Vitor Pamplona
2024-07-03 11:06:02 -04:00
parent 692f7c4270
commit 8d88efd27b
201 changed files with 1858 additions and 1814 deletions
@@ -54,7 +54,5 @@ class KeyPair(
}
}
override fun toString(): String {
return "KeyPair(privateKey=${privKey?.toHexKey()}, publicKey=${pubKey.toHexKey()}"
}
override fun toString(): String = "KeyPair(privateKey=${privKey?.toHexKey()}, publicKey=${pubKey.toHexKey()}"
}
@@ -42,9 +42,7 @@ class SharedKeyCache {
fun get(
privateKey: ByteArray,
pubKey: ByteArray,
): ByteArray? {
return sharedKeyCache[combinedHashCode(privateKey, pubKey)]
}
): ByteArray? = sharedKeyCache[combinedHashCode(privateKey, pubKey)]
fun add(
privateKey: ByteArray,
@@ -20,24 +20,20 @@
*/
package com.vitorpamplona.quartz.crypto.nip06
class KeyPath(val path: List<Long>) {
class KeyPath(
val path: List<Long>,
) {
constructor(path: String) : this(computePath(path))
val lastChildNumber: Long get() = if (path.isEmpty()) 0L else path.last()
fun derive(number: Long): KeyPath = KeyPath(path + listOf(number))
fun append(index: Long): KeyPath {
return KeyPath(path + listOf(index))
}
fun append(index: Long): KeyPath = KeyPath(path + listOf(index))
fun append(indexes: List<Long>): KeyPath {
return KeyPath(path + indexes)
}
fun append(indexes: List<Long>): KeyPath = KeyPath(path + indexes)
fun append(that: KeyPath): KeyPath {
return KeyPath(path + that.path)
}
fun append(that: KeyPath): KeyPath = KeyPath(path + that.path)
override fun toString(): String = asString('\'')
@@ -24,20 +24,23 @@ import android.util.Log
import androidx.compose.runtime.Immutable
@Immutable
data class ATag(val kind: Int, val pubKeyHex: String, val dTag: String, val relay: String?) {
data class ATag(
val kind: Int,
val pubKeyHex: String,
val dTag: String,
val relay: String?,
) {
fun toTag() = assembleATag(kind, pubKeyHex, dTag)
fun toNAddr(): String {
return TlvBuilder()
fun toNAddr(): String =
TlvBuilder()
.apply {
addString(Nip19Bech32.TlvTypes.SPECIAL, dTag)
addStringIfNotNull(Nip19Bech32.TlvTypes.RELAY, relay)
addHex(Nip19Bech32.TlvTypes.AUTHOR, pubKeyHex)
addInt(Nip19Bech32.TlvTypes.KIND, kind)
}
.build()
}.build()
.toNAddress()
}
companion object {
fun assembleATag(
@@ -46,26 +49,23 @@ data class ATag(val kind: Int, val pubKeyHex: String, val dTag: String, val rela
dTag: String,
) = "$kind:$pubKeyHex:$dTag"
fun isATag(key: String): Boolean {
return key.startsWith("naddr1") || key.contains(":")
}
fun isATag(key: String): Boolean = key.startsWith("naddr1") || key.contains(":")
fun parse(
address: String,
relay: String?,
): ATag? {
return if (address.startsWith("naddr") || address.startsWith("nostr:naddr")) {
): ATag? =
if (address.startsWith("naddr") || address.startsWith("nostr:naddr")) {
parseNAddr(address)
} else {
parseAtag(address, relay)
}
}
fun parseAtag(
atag: String,
relay: String?,
): ATag? {
return try {
): ATag? =
try {
val parts = atag.split(":")
Hex.decode(parts[1])
ATag(parts[0].toInt(), parts[1], parts[2], relay)
@@ -73,16 +73,14 @@ data class ATag(val kind: Int, val pubKeyHex: String, val dTag: String, val rela
Log.w("ATag", "Error parsing A Tag: $atag: ${t.message}")
null
}
}
fun parseAtagUnckecked(atag: String): ATag? {
return try {
fun parseAtagUnckecked(atag: String): ATag? =
try {
val parts = atag.split(":")
ATag(parts[0].toInt(), parts[1], parts[2], null)
} catch (t: Throwable) {
null
}
}
fun parseNAddr(naddr: String): ATag? {
try {
@@ -51,7 +51,9 @@ object Bech32 {
const val ALPHABET: String = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
const val ALPHABET_UPPERCASE: String = "QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L"
enum class Encoding(val constant: Int) {
enum class Encoding(
val constant: Int,
) {
Bech32(1),
Bech32m(0x2bc830a3),
Beck32WithoutChecksum(0),
@@ -23,23 +23,18 @@ package com.vitorpamplona.quartz.encoders
/** Makes the distinction between String and Hex * */
typealias HexKey = String
fun ByteArray.toHexKey(): HexKey {
return Hex.encode(this)
}
fun ByteArray.toHexKey(): HexKey = Hex.encode(this)
fun HexKey.hexToByteArray(): ByteArray {
return Hex.decode(this)
}
fun HexKey.hexToByteArray(): ByteArray = Hex.decode(this)
object HexValidator {
private fun isHexChar(c: Char): Boolean {
return when (c) {
private fun isHexChar(c: Char): Boolean =
when (c) {
in '0'..'9' -> true
in 'a'..'f' -> true
in 'A'..'F' -> true
else -> false
}
}
fun isHex(hex: String?): Boolean {
if (hex == null) return false
@@ -205,7 +205,9 @@ object LnInvoiceUtil {
return polymod(combined) == 1
}
class AddressFormatException(message: String) : Exception(message)
class AddressFormatException(
message: String,
) : Exception(message)
fun decodeUnlimitedLength(invoice: String): Boolean {
var lower = false
@@ -278,19 +280,16 @@ object LnInvoiceUtil {
val OneNano = BigDecimal("0.000000001")
val OnePico = BigDecimal("0.000000000001")
fun getAmountInSats(invoice: String): BigDecimal {
return getAmount(invoice).multiply(OneHundredK)
}
fun getAmountInSats(invoice: String): BigDecimal = getAmount(invoice).multiply(OneHundredK)
private fun multiplier(multiplier: String): BigDecimal {
return when (multiplier.lowercase()) {
private fun multiplier(multiplier: String): BigDecimal =
when (multiplier.lowercase()) {
"m" -> OneMili
"u" -> OneMicro
"n" -> OneNano
"p" -> OnePico
else -> throw IllegalArgumentException("Invalid multiplier: $multiplier")
}
}
/**
* Finds LN invoice in the provided input string and returns it. For example for input = "aaa bbb
@@ -48,13 +48,12 @@ class Lud06 {
}
}
fun toLnUrlp(str: String): String? {
return try {
fun toLnUrlp(str: String): String? =
try {
String(Bech32.decodeBytes(str, false).second)
} catch (t: Throwable) {
t.printStackTrace()
Log.w("Lud06ToLud16", "Fail to convert LUD06 to LUD16", t)
null
}
}
}
@@ -47,9 +47,12 @@ class Nip01Serializer {
fun dump()
}
class BufferedDigestWriter(val digest: MessageDigest) : Writer {
class BufferedDigestWriter(
val digest: MessageDigest,
) : Writer {
val utf8Encoder =
Charsets.UTF_8.newEncoder()
Charsets.UTF_8
.newEncoder()
.onMalformedInput(CodingErrorAction.IGNORE)
.onUnmappableCharacter(CodingErrorAction.IGNORE)
@@ -151,9 +154,7 @@ class Nip01Serializer {
stringBuilder.append(value.toInt().toChar())
}
override fun toString(): String {
return stringBuilder.toString()
}
override fun toString(): String = stringBuilder.toString()
override fun dump() {
}
@@ -48,9 +48,7 @@ class Nip30CustomEmoji {
return input.contains(":")
}
fun createEmojiMap(tags: ImmutableListOfLists<String>): Map<String, String> {
return tags.lists.filter { it.size > 2 && it[0] == "emoji" }.associate { ":${it[1]}:" to it[2] }
}
fun createEmojiMap(tags: ImmutableListOfLists<String>): Map<String, String> = tags.lists.filter { it.size > 2 && it[0] == "emoji" }.associate { ":${it[1]}:" to it[2] }
fun assembleAnnotatedList(
input: String,
@@ -105,9 +103,13 @@ class Nip30CustomEmoji {
}
}
@Immutable open class Renderable()
@Immutable open class Renderable
@Immutable class TextType(val text: String) : Renderable()
@Immutable class TextType(
val text: String,
) : Renderable()
@Immutable class ImageUrlType(val url: String) : Renderable()
@Immutable class ImageUrlType(
val url: String,
) : Renderable()
}
@@ -52,5 +52,9 @@ class Nip47WalletConnect {
}
}
data class Nip47URI(val pubKeyHex: HexKey, val relayUri: String?, val secret: HexKey?)
data class Nip47URI(
val pubKeyHex: HexKey,
val relayUri: String?,
val secret: HexKey?,
)
}
@@ -40,17 +40,18 @@ class Nip54InlineMetadata {
tags: Array<Array<String>>,
): String {
val extension =
tags.mapNotNull {
if (it.isNotEmpty() && it[0] != "url") {
if (it.size > 1) {
"${it[0]}=${URLEncoder.encode(it[1], "utf-8")}"
tags
.mapNotNull {
if (it.isNotEmpty() && it[0] != "url") {
if (it.size > 1) {
"${it[0]}=${URLEncoder.encode(it[1], "utf-8")}"
} else {
"${it[0]}}="
}
} else {
"${it[0]}}="
null
}
} else {
null
}
}.joinToString("&")
}.joinToString("&")
return if (imageUrl.contains("#")) {
"$imageUrl&$extension"
@@ -59,14 +60,13 @@ class Nip54InlineMetadata {
}
}
fun parse(url: String): Map<String, String> {
return try {
fun parse(url: String): Map<String, String> =
try {
fragments(URI(url))
} catch (e: Exception) {
if (e is CancellationException) throw e
emptyMap()
}
}
private fun fragments(uri: URI): Map<String, String> {
if (uri.rawFragment == null) return emptyMap()
@@ -38,8 +38,8 @@ class Nip92MediaAttachments {
fun createTag(
imageUrl: String,
tags: Array<Array<String>>,
): Array<String> {
return arrayOf(
): Array<String> =
arrayOf(
IMETA,
"url $imageUrl",
) +
@@ -54,23 +54,22 @@ class Nip92MediaAttachments {
null
}
}
}
fun parse(
imageUrl: String,
tags: Array<Array<String>>,
): Map<String, String> {
return tags.firstOrNull {
it.size > 1 && it[0] == IMETA && it[1] == "url $imageUrl"
}?.let { tagList ->
tagList.associate { tag ->
val parts = tag.split(" ", limit = 2)
when (parts.size) {
2 -> parts[0] to parts[1]
1 -> parts[0] to ""
else -> "" to ""
): Map<String, String> =
tags
.firstOrNull {
it.size > 1 && it[0] == IMETA && it[1] == "url $imageUrl"
}?.let { tagList ->
tagList.associate { tag ->
val parts = tag.split(" ", limit = 2)
when (parts.size) {
2 -> parts[0] to parts[1]
1 -> parts[0] to ""
else -> "" to ""
}
}
}
} ?: emptyMap()
}
} ?: emptyMap()
}
@@ -24,9 +24,12 @@ import org.czeal.rfc3986.URIReference
class RelayUrlFormatter {
companion object {
fun displayUrl(url: String): String {
return url.trim().removePrefix("wss://").removePrefix("ws://").removeSuffix("/")
}
fun displayUrl(url: String): String =
url
.trim()
.removePrefix("wss://")
.removePrefix("ws://")
.removeSuffix("/")
fun normalize(url: String): String {
val newUrl =
@@ -49,12 +52,11 @@ class RelayUrlFormatter {
}
}
fun getHttpsUrl(dirtyUrl: String): String {
return if (dirtyUrl.contains("://")) {
fun getHttpsUrl(dirtyUrl: String): String =
if (dirtyUrl.contains("://")) {
dirtyUrl.replace("wss://", "https://").replace("ws://", "http://")
} else {
"https://$dirtyUrl"
}
}
}
}
@@ -24,7 +24,7 @@ import java.io.ByteArrayOutputStream
import java.nio.ByteBuffer
import java.nio.ByteOrder
class TlvBuilder() {
class TlvBuilder {
val outputStream = ByteArrayOutputStream()
private fun add(
@@ -65,9 +65,7 @@ class TlvBuilder() {
data: Int?,
) = data?.let { addInt(type, it) }
fun build(): ByteArray {
return outputStream.toByteArray()
}
fun build(): ByteArray = outputStream.toByteArray()
}
fun Int.to32BitByteArray(): ByteArray {
@@ -81,7 +79,9 @@ fun ByteArray.toInt32(): Int? {
return ByteBuffer.wrap(this, 0, 4).order(ByteOrder.BIG_ENDIAN).int
}
class Tlv(val data: Map<Byte, List<ByteArray>>) {
class Tlv(
val data: Map<Byte, List<ByteArray>>,
) {
fun asInt(type: Byte) = data[type]?.mapNotNull { it.toInt32() }
fun asHex(type: Byte) = data[type]?.map { it.toHexKey().intern() }
@@ -37,8 +37,8 @@ class AdvertisedRelayListEvent(
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
override fun dTag() = FIXED_D_TAG
fun relays(): List<AdvertisedRelayInfo> {
return tags.mapNotNull {
fun relays(): List<AdvertisedRelayInfo> =
tags.mapNotNull {
if (it.size > 1 && it[0] == "r") {
val type =
when (it.getOrNull(2)) {
@@ -52,24 +52,23 @@ class AdvertisedRelayListEvent(
null
}
}
}
fun readRelays(): List<String>? {
return tags.mapNotNull {
if (it.size > 1 && it[0] == "r") {
when (it.getOrNull(2)) {
"read" -> it[1]
"write" -> null
else -> it[1]
fun readRelays(): List<String>? =
tags
.mapNotNull {
if (it.size > 1 && it[0] == "r") {
when (it.getOrNull(2)) {
"read" -> it[1]
"write" -> null
else -> it[1]
}
} else {
null
}
} else {
null
}
}.ifEmpty { null }
}
}.ifEmpty { null }
fun writeRelays(): List<String> {
return tags.mapNotNull {
fun writeRelays(): List<String> =
tags.mapNotNull {
if (it.size > 1 && it[0] == "r") {
when (it.getOrNull(2)) {
"read" -> null
@@ -80,20 +79,15 @@ class AdvertisedRelayListEvent(
null
}
}
}
companion object {
const val KIND = 10002
const val FIXED_D_TAG = ""
const val ALT = "Relay list to discover the user's content"
fun createAddressATag(pubKey: HexKey): ATag {
return ATag(KIND, pubKey, FIXED_D_TAG, null)
}
fun createAddressATag(pubKey: HexKey): ATag = ATag(KIND, pubKey, FIXED_D_TAG, null)
fun createAddressTag(pubKey: HexKey): String {
return ATag.assembleATag(KIND, pubKey, FIXED_D_TAG)
}
fun createAddressTag(pubKey: HexKey): String = ATag.assembleATag(KIND, pubKey, FIXED_D_TAG)
fun updateRelayList(
earlierVersion: AdvertisedRelayListEvent,
@@ -103,9 +97,11 @@ class AdvertisedRelayListEvent(
onReady: (AdvertisedRelayListEvent) -> Unit,
) {
val tags =
earlierVersion.tags.filter { it[0] != "r" }.plus(
relays.map(::createRelayTag),
).toTypedArray()
earlierVersion.tags
.filter { it[0] != "r" }
.plus(
relays.map(::createRelayTag),
).toTypedArray()
signer.sign(createdAt, KIND, tags, earlierVersion.content, onReady)
}
@@ -119,20 +115,18 @@ class AdvertisedRelayListEvent(
create(relays, signer, createdAt, onReady)
}
fun createRelayTag(relay: AdvertisedRelayInfo): Array<String> {
return if (relay.type == AdvertisedRelayType.BOTH) {
fun createRelayTag(relay: AdvertisedRelayInfo): Array<String> =
if (relay.type == AdvertisedRelayType.BOTH) {
arrayOf("r", relay.relayUrl)
} else {
arrayOf("r", relay.relayUrl, relay.type.code)
}
}
fun createTagArray(relays: List<AdvertisedRelayInfo>): Array<Array<String>> {
return relays
fun createTagArray(relays: List<AdvertisedRelayInfo>): Array<Array<String>> =
relays
.map(::createRelayTag)
.plusElement(arrayOf("alt", ALT))
.toTypedArray()
}
fun create(
list: List<AdvertisedRelayInfo>,
@@ -147,10 +141,15 @@ class AdvertisedRelayListEvent(
}
}
@Immutable data class AdvertisedRelayInfo(val relayUrl: String, val type: AdvertisedRelayType)
@Immutable data class AdvertisedRelayInfo(
val relayUrl: String,
val type: AdvertisedRelayType,
)
@Immutable
enum class AdvertisedRelayType(val code: String) {
enum class AdvertisedRelayType(
val code: String,
) {
BOTH(""),
READ("read"),
WRITE("write"),
@@ -58,31 +58,20 @@ class AppMetadata {
@Transient
var tags: ImmutableListOfLists<String>? = null
fun anyName(): String? {
return displayName ?: name ?: username
}
fun anyName(): String? = displayName ?: name ?: username
fun anyNameStartsWith(prefix: String): Boolean {
return listOfNotNull(name, username, displayName, nip05, lud06, lud16).any {
fun anyNameStartsWith(prefix: String): Boolean =
listOfNotNull(name, username, displayName, nip05, lud06, lud16).any {
it.contains(prefix, true)
}
}
fun lnAddress(): String? {
return lud16 ?: lud06
}
fun lnAddress(): String? = lud16 ?: lud06
fun bestName(): String? {
return displayName ?: name ?: username
}
fun bestName(): String? = displayName ?: name ?: username
fun nip05(): String? {
return nip05
}
fun nip05(): String? = nip05
fun profilePicture(): String? {
return picture
}
fun profilePicture(): String? = picture
fun cleanBlankNames() {
if (picture?.isNotEmpty() == true) picture = picture?.trim()
@@ -76,8 +76,7 @@ class AudioHeaderEvent(
}
},
arrayOf("alt", ALT),
)
.toTypedArray()
).toTypedArray()
signer.sign(createdAt, KIND, tags, description, onReady)
}
@@ -73,12 +73,14 @@ class AudioTrackEvent(
cover?.let { arrayOf(COVER, it) },
subject?.let { arrayOf(SUBJECT, it) },
arrayOf("alt", ALT),
)
.toTypedArray()
).toTypedArray()
signer.sign(createdAt, KIND, tags, "", onReady)
}
}
}
@Immutable data class Participant(val key: String, val role: String?)
@Immutable data class Participant(
val key: String,
val role: String?,
)
@@ -42,8 +42,6 @@ class BadgeProfilesEvent(
private const val STANDARD_D_TAG = "profile_badges"
private const val ALT = "List of accepted badges by the author"
fun createAddressTag(pubKey: HexKey): ATag {
return ATag(KIND, pubKey, STANDARD_D_TAG, null)
}
fun createAddressTag(pubKey: HexKey): ATag = ATag(KIND, pubKey, STANDARD_D_TAG, null)
}
}
@@ -192,10 +192,11 @@ open class BaseTextNoteEvent(
fun tagsWithoutCitations(): List<String> {
val repliesTo = replyTos()
val tagAddresses =
taggedAddresses().filter {
it.kind != CommunityDefinitionEvent.KIND && (kind != WikiNoteEvent.KIND || it.kind != WikiNoteEvent.KIND)
// removes forks from itself.
}.map { it.toTag() }
taggedAddresses()
.filter {
it.kind != CommunityDefinitionEvent.KIND && (kind != WikiNoteEvent.KIND || it.kind != WikiNoteEvent.KIND)
// removes forks from itself.
}.map { it.toTag() }
if (repliesTo.isEmpty() && tagAddresses.isEmpty()) return emptyList()
val citations = findCitations()
@@ -54,18 +54,16 @@ class ChannelCreateEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ChannelCreateEvent) -> Unit,
) {
return create(
ChannelData(
name,
about,
picture,
),
signer,
createdAt,
onReady,
)
}
) = create(
ChannelData(
name,
about,
picture,
),
signer,
createdAt,
onReady,
)
fun create(
channelInfo: ChannelData?,
@@ -94,5 +92,9 @@ class ChannelCreateEvent(
}
}
@Immutable data class ChannelData(val name: String?, val about: String?, val picture: String?)
@Immutable data class ChannelData(
val name: String?,
val about: String?,
val picture: String?,
)
}
@@ -33,7 +33,8 @@ class ChannelHideMessageEvent(
tags: Array<Array<String>>,
content: String,
sig: HexKey,
) : Event(id, pubKey, createdAt, KIND, tags, content, sig), IsInPublicChatChannel {
) : Event(id, pubKey, createdAt, KIND, tags, content, sig),
IsInPublicChatChannel {
override fun channel() =
tags.firstOrNull { it.size > 3 && it[0] == "e" && it[3] == "root" }?.get(1)
?: tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1)
@@ -62,9 +62,7 @@ class ChannelListEvent(
const val FIXED_D_TAG = ""
const val ALT = "Public Chat List"
fun blockListFor(pubKeyHex: HexKey): String {
return "$KIND:$pubKeyHex:"
}
fun blockListFor(pubKeyHex: HexKey): String = "$KIND:$pubKeyHex:"
fun createListWithTag(
key: String,
@@ -101,9 +99,7 @@ class ChannelListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ChannelListEvent) -> Unit,
) {
return createListWithTag("e", eventId, isPrivate, signer, createdAt, onReady)
}
) = createListWithTag("e", eventId, isPrivate, signer, createdAt, onReady)
fun addEvents(
earlierVersion: ChannelListEvent,
@@ -152,9 +148,7 @@ class ChannelListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ChannelListEvent) -> Unit,
) {
return addTag(earlierVersion, "e", event, isPrivate, signer, createdAt, onReady)
}
) = addTag(earlierVersion, "e", event, isPrivate, signer, createdAt, onReady)
fun addTag(
earlierVersion: ChannelListEvent,
@@ -202,9 +196,7 @@ class ChannelListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ChannelListEvent) -> Unit,
) {
return removeTag(earlierVersion, "e", event, isPrivate, signer, createdAt, onReady)
}
) = removeTag(earlierVersion, "e", event, isPrivate, signer, createdAt, onReady)
fun removeTag(
earlierVersion: ChannelListEvent,
@@ -34,7 +34,8 @@ class ChannelMessageEvent(
tags: Array<Array<String>>,
content: String,
sig: HexKey,
) : BaseTextNoteEvent(id, pubKey, createdAt, KIND, tags, content, sig), IsInPublicChatChannel {
) : BaseTextNoteEvent(id, pubKey, createdAt, KIND, tags, content, sig),
IsInPublicChatChannel {
override fun channel() =
tags.firstOrNull { it.size > 3 && it[0] == "e" && it[3] == "root" }?.get(1)
?: tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1)
@@ -34,7 +34,8 @@ class ChannelMetadataEvent(
tags: Array<Array<String>>,
content: String,
sig: HexKey,
) : Event(id, pubKey, createdAt, KIND, tags, content, sig), IsInPublicChatChannel {
) : Event(id, pubKey, createdAt, KIND, tags, content, sig),
IsInPublicChatChannel {
override fun channel() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1)
fun channelInfo() =
@@ -33,7 +33,8 @@ class ChannelMuteUserEvent(
tags: Array<Array<String>>,
content: String,
sig: HexKey,
) : Event(id, pubKey, createdAt, KIND, tags, content, sig), IsInPublicChatChannel {
) : Event(id, pubKey, createdAt, KIND, tags, content, sig),
IsInPublicChatChannel {
override fun channel() =
tags.firstOrNull { it.size > 3 && it[0] == "e" && it[3] == "root" }?.get(1)
?: tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1)
@@ -37,33 +37,29 @@ class ChatMessageRelayListEvent(
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
override fun dTag() = FIXED_D_TAG
fun relays(): List<String> {
return tags.mapNotNull {
fun relays(): List<String> =
tags.mapNotNull {
if (it.size > 1 && it[0] == "relay") {
it[1]
} else {
null
}
}
}
companion object {
const val KIND = 10050
const val FIXED_D_TAG = ""
fun createAddressATag(pubKey: HexKey): ATag {
return ATag(KIND, pubKey, FIXED_D_TAG, null)
}
fun createAddressATag(pubKey: HexKey): ATag = ATag(KIND, pubKey, FIXED_D_TAG, null)
fun createAddressTag(pubKey: HexKey): String {
return ATag.assembleATag(KIND, pubKey, FIXED_D_TAG)
}
fun createAddressTag(pubKey: HexKey): String = ATag.assembleATag(KIND, pubKey, FIXED_D_TAG)
fun createTagArray(relays: List<String>): Array<Array<String>> {
return relays.map {
arrayOf("relay", it)
}.plusElement(arrayOf("alt", "Relay list to receive private messages")).toTypedArray()
}
fun createTagArray(relays: List<String>): Array<Array<String>> =
relays
.map {
arrayOf("relay", it)
}.plusElement(arrayOf("alt", "Relay list to receive private messages"))
.toTypedArray()
fun updateRelayList(
earlierVersion: ChatMessageRelayListEvent,
@@ -73,11 +69,13 @@ class ChatMessageRelayListEvent(
onReady: (ChatMessageRelayListEvent) -> Unit,
) {
val tags =
earlierVersion.tags.filter { it[0] != "relay" }.plus(
relays.map {
arrayOf("relay", it)
},
).toTypedArray()
earlierVersion.tags
.filter { it[0] != "relay" }
.plus(
relays.map {
arrayOf("relay", it)
},
).toTypedArray()
signer.sign(createdAt, KIND, tags, earlierVersion.content, onReady)
}
@@ -79,7 +79,9 @@ class ClassifiedsEvent(
null
}
enum class CONDITION(val value: String) {
enum class CONDITION(
val value: String,
) {
NEW("new"),
USED_LIKE_NEW("like new"),
USED_GOOD("good"),
@@ -202,4 +204,8 @@ class ClassifiedsEvent(
}
}
data class Price(val amount: String, val currency: String?, val frequency: String?)
data class Price(
val amount: String,
val currency: String?,
val frequency: String?,
)
@@ -67,9 +67,7 @@ class CommunityListEvent(
const val FIXED_D_TAG = ""
const val ALT = "Community List"
fun blockListFor(pubKeyHex: HexKey): String {
return "$KIND:$pubKeyHex:"
}
fun blockListFor(pubKeyHex: HexKey): String = "$KIND:$pubKeyHex:"
fun createListWithTag(
key: String,
@@ -106,9 +104,7 @@ class CommunityListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (CommunityListEvent) -> Unit,
) {
return createListWithTag("a", address.toTag(), isPrivate, signer, createdAt, onReady)
}
) = createListWithTag("a", address.toTag(), isPrivate, signer, createdAt, onReady)
fun addEvents(
earlierVersion: CommunityListEvent,
@@ -157,9 +153,7 @@ class CommunityListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (CommunityListEvent) -> Unit,
) {
return addTag(earlierVersion, "a", address.toTag(), isPrivate, signer, createdAt, onReady)
}
) = addTag(earlierVersion, "a", address.toTag(), isPrivate, signer, createdAt, onReady)
fun addTag(
earlierVersion: CommunityListEvent,
@@ -207,9 +201,7 @@ class CommunityListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (CommunityListEvent) -> Unit,
) {
return removeTag(earlierVersion, "a", address.toTag(), isPrivate, signer, createdAt, onReady)
}
) = removeTag(earlierVersion, "a", address.toTag(), isPrivate, signer, createdAt, onReady)
fun removeTag(
earlierVersion: CommunityListEvent,
@@ -68,8 +68,7 @@ class CommunityPostApprovalEvent(
it[0] == "e" ||
(it[0] == "a" && ATag.parse(it[1], null)?.kind != CommunityDefinitionEvent.KIND)
)
}
.map { it[1] }
}.map { it[1] }
companion object {
const val KIND = 4550
@@ -32,7 +32,10 @@ import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.signers.NostrSigner
import com.vitorpamplona.quartz.utils.TimeUtils
@Immutable data class Contact(val pubKeyHex: String, val relayUri: String?)
@Immutable data class Contact(
val pubKeyHex: String,
val relayUri: String?,
)
@Stable
class ContactListEvent(
@@ -391,7 +394,10 @@ class ContactListEvent(
}
}
data class ReadWrite(val read: Boolean, val write: Boolean)
data class ReadWrite(
val read: Boolean,
val write: Boolean,
)
}
@Stable
@@ -420,31 +426,20 @@ class UserMetadata {
@Transient
var tags: ImmutableListOfLists<String>? = null
fun anyName(): String? {
return displayName ?: name ?: username
}
fun anyName(): String? = displayName ?: name ?: username
fun anyNameStartsWith(prefix: String): Boolean {
return listOfNotNull(name, username, displayName, nip05, lud06, lud16).any {
fun anyNameStartsWith(prefix: String): Boolean =
listOfNotNull(name, username, displayName, nip05, lud06, lud16).any {
it.contains(prefix, true)
}
}
fun lnAddress(): String? {
return lud16 ?: lud06
}
fun lnAddress(): String? = lud16 ?: lud06
fun bestName(): String? {
return displayName ?: name ?: username
}
fun bestName(): String? = displayName ?: name ?: username
fun nip05(): String? {
return nip05
}
fun nip05(): String? = nip05
fun profilePicture(): String? {
return picture
}
fun profilePicture(): String? = picture
fun cleanBlankNames() {
if (picture?.isNotEmpty() == true) picture = picture?.trim()
@@ -473,10 +468,10 @@ class UserMetadata {
}
}
@Stable class ImmutableListOfLists<T>(val lists: Array<Array<T>>)
@Stable class ImmutableListOfLists<T>(
val lists: Array<Array<T>>,
)
val EmptyTagList = ImmutableListOfLists<String>(emptyArray())
fun Array<Array<String>>.toImmutableListOfLists(): ImmutableListOfLists<String> {
return ImmutableListOfLists(this)
}
fun Array<Array<String>>.toImmutableListOfLists(): ImmutableListOfLists<String> = ImmutableListOfLists(this)
@@ -54,11 +54,12 @@ class DeletionEvent(
val tags = mutableListOf<Array<String>>()
val kinds =
deleteEvents.mapTo(HashSet()) {
"${it.kind}"
}.map {
arrayOf("k", it)
}
deleteEvents
.mapTo(HashSet()) {
"${it.kind}"
}.map {
arrayOf("k", it)
}
tags.addAll(deleteEvents.map { arrayOf("e", it.id) })
tags.addAll(deleteEvents.mapNotNull { if (it is AddressableEvent) arrayOf("a", it.address().toTag()) else null })
@@ -78,11 +79,12 @@ class DeletionEvent(
val tags = mutableListOf<Array<String>>()
val kinds =
deleteEvents.mapTo(HashSet()) {
"${it.kind}"
}.map {
arrayOf("k", it)
}
deleteEvents
.mapTo(HashSet()) {
"${it.kind}"
}.map {
arrayOf("k", it)
}
tags.addAll(deleteEvents.map { arrayOf("e", it.id) })
tags.addAll(kinds)
@@ -41,13 +41,9 @@ class DraftEvent(
fun isDeleted() = content == ""
fun preCachedDraft(signer: NostrSigner): Event? {
return cachedInnerEvent[signer.pubKey]
}
fun preCachedDraft(signer: NostrSigner): Event? = cachedInnerEvent[signer.pubKey]
fun preCachedDraft(pubKey: HexKey): Event? {
return cachedInnerEvent[pubKey]
}
fun preCachedDraft(pubKey: HexKey): Event? = cachedInnerEvent[pubKey]
fun allCache() = cachedInnerEvent.values
@@ -114,9 +110,7 @@ class DraftEvent(
fun createAddressTag(
pubKey: HexKey,
dTag: String,
): String {
return ATag.assembleATag(KIND, pubKey, dTag)
}
): String = ATag.assembleATag(KIND, pubKey, dTag)
fun create(
dTag: String,
@@ -56,10 +56,11 @@ class EmojiPackEvent(
}
@Immutable
data class EmojiUrl(val code: String, val url: String) {
fun encode(): String {
return ":$code:$url"
}
data class EmojiUrl(
val code: String,
val url: String,
) {
fun encode(): String = ":$code:$url"
companion object {
fun decode(encodedEmojiSetup: String): EmojiUrl? {
@@ -123,4 +123,7 @@ class FileHeaderEvent(
}
}
data class AESGCM(val key: String, val nonce: String)
data class AESGCM(
val key: String,
val nonce: String,
)
@@ -42,14 +42,13 @@ class FileStorageEvent(
fun decryptKey() = tags.firstOrNull { it.size > 2 && it[0] == DECRYPT }?.let { AESGCM(it[1], it[2]) }
fun decode(): ByteArray? {
return try {
fun decode(): ByteArray? =
try {
Base64.getDecoder().decode(content)
} catch (e: Exception) {
Log.e("FileStorageEvent", "Unable to decode base 64 ${e.message} $content")
null
}
}
companion object {
const val KIND = 1064
@@ -58,9 +57,7 @@ class FileStorageEvent(
private const val TYPE = "type"
private const val DECRYPT = "decrypt"
fun encode(bytes: ByteArray): String {
return Base64.getEncoder().encodeToString(bytes)
}
fun encode(bytes: ByteArray): String = Base64.getEncoder().encodeToString(bytes)
fun create(
mimeType: String,
@@ -56,9 +56,7 @@ abstract class GeneralListEvent(
fun nameOrTitle() = name() ?: title()
fun cachedPrivateTags(): Array<Array<String>>? {
return privateTagsCache
}
fun cachedPrivateTags(): Array<Array<String>>? = privateTagsCache
fun filterTagList(
key: String,
@@ -79,16 +77,14 @@ abstract class GeneralListEvent(
isPrivate: Boolean,
signer: NostrSigner,
onReady: (Boolean) -> Unit,
) {
return if (isPrivate) {
privateTagsOrEmpty(signer = signer) {
onReady(
it.any { it.size > 1 && it[0] == key && it[1] == tag },
)
}
} else {
onReady(isTagged(key, tag))
) = if (isPrivate) {
privateTagsOrEmpty(signer = signer) {
onReady(
it.any { it.size > 1 && it[0] == key && it[1] == tag },
)
}
} else {
onReady(isTagged(key, tag))
}
fun privateTags(
@@ -147,24 +143,16 @@ abstract class GeneralListEvent(
onReady: (List<ATag>) -> Unit,
) = privateTags(signer) { onReady(filterAddresses(it)) }
fun filterUsers(tags: Array<Array<String>>): List<String> {
return tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] }
}
fun filterUsers(tags: Array<Array<String>>): List<String> = tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] }
fun filterHashtags(tags: Array<Array<String>>): List<String> {
return tags.filter { it.size > 1 && it[0] == "t" }.map { it[1] }
}
fun filterHashtags(tags: Array<Array<String>>): List<String> = tags.filter { it.size > 1 && it[0] == "t" }.map { it[1] }
fun filterGeohashes(tags: Array<Array<String>>): List<String> {
return tags.filter { it.size > 1 && it[0] == "g" }.map { it[1] }
}
fun filterGeohashes(tags: Array<Array<String>>): List<String> = tags.filter { it.size > 1 && it[0] == "g" }.map { it[1] }
fun filterEvents(tags: Array<Array<String>>): List<String> {
return tags.filter { it.size > 1 && it[0] == "e" }.map { it[1] }
}
fun filterEvents(tags: Array<Array<String>>): List<String> = tags.filter { it.size > 1 && it[0] == "e" }.map { it[1] }
fun filterAddresses(tags: Array<Array<String>>): List<ATag> {
return tags
fun filterAddresses(tags: Array<Array<String>>): List<ATag> =
tags
.filter { it.firstOrNull() == "a" }
.mapNotNull {
val aTagValue = it.getOrNull(1)
@@ -172,7 +160,6 @@ abstract class GeneralListEvent(
if (aTagValue != null) ATag.parse(aTagValue, relay) else null
}
}
companion object {
fun createPrivateTags(
@@ -33,7 +33,8 @@ class LnZapEvent(
tags: Array<Array<String>>,
content: String,
sig: HexKey,
) : LnZapEventInterface, Event(id, pubKey, createdAt, KIND, tags, content, sig) {
) : Event(id, pubKey, createdAt, KIND, tags, content, sig),
LnZapEventInterface {
// This event is also kept in LocalCache (same object)
@Transient val zapRequest: LnZapRequestEvent?
@@ -55,7 +56,11 @@ class LnZapEvent(
override fun zappedPollOption(): Int? =
try {
zapRequest?.tags?.firstOrNull { it.size > 1 && it[0] == POLL_OPTION }?.get(1)?.toInt()
zapRequest
?.tags
?.firstOrNull { it.size > 1 && it[0] == POLL_OPTION }
?.get(1)
?.toInt()
} catch (e: Exception) {
Log.e("LnZapEvent", "ZappedPollOption failed to parse", e)
null
@@ -75,9 +80,7 @@ class LnZapEvent(
}
}
override fun content(): String {
return content
}
override fun content(): String = content
fun lnInvoice() = tags.firstOrNull { it.size > 1 && it[0] == "bolt11" }?.get(1)
@@ -88,7 +91,7 @@ class LnZapEvent(
const val ALT = "Zap event"
}
enum class ZapType() {
enum class ZapType {
PUBLIC,
PRIVATE,
ANONYMOUS,
@@ -44,9 +44,7 @@ class LnZapPaymentRequestEvent(
fun walletServicePubKey() = tags.firstOrNull { it.size > 1 && it[0] == "p" }?.get(1)
fun talkingWith(oneSideHex: String): HexKey {
return if (pubKey == oneSideHex) walletServicePubKey() ?: pubKey else pubKey
}
fun talkingWith(oneSideHex: String): HexKey = if (pubKey == oneSideHex) walletServicePubKey() ?: pubKey else pubKey
fun lnInvoice(
signer: NostrSigner,
@@ -97,16 +95,20 @@ class LnZapPaymentRequestEvent(
// REQUEST OBJECTS
abstract class Request(var method: String? = null)
abstract class Request(
var method: String? = null,
)
// PayInvoice Call
class PayInvoiceParams(var invoice: String? = null)
class PayInvoiceParams(
var invoice: String? = null,
)
class PayInvoiceMethod(var params: PayInvoiceParams? = null) : Request("pay_invoice") {
class PayInvoiceMethod(
var params: PayInvoiceParams? = null,
) : Request("pay_invoice") {
companion object {
fun create(bolt11: String): PayInvoiceMethod {
return PayInvoiceMethod(PayInvoiceParams(bolt11))
}
fun create(bolt11: String): PayInvoiceMethod = PayInvoiceMethod(PayInvoiceParams(bolt11))
}
}
@@ -46,9 +46,7 @@ class LnZapPaymentResponseEvent(
fun requestId() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1)
fun talkingWith(oneSideHex: String): HexKey {
return if (pubKey == oneSideHex) requestAuthor() ?: pubKey else pubKey
}
fun talkingWith(oneSideHex: String): HexKey = if (pubKey == oneSideHex) requestAuthor() ?: pubKey else pubKey
private fun plainContent(
signer: NostrSigner,
@@ -97,13 +95,21 @@ abstract class Response(
// PayInvoice Call
class PayInvoiceSuccessResponse(val result: PayInvoiceResultParams? = null) :
Response("pay_invoice") {
class PayInvoiceResultParams(val preimage: String)
class PayInvoiceSuccessResponse(
val result: PayInvoiceResultParams? = null,
) : Response("pay_invoice") {
class PayInvoiceResultParams(
val preimage: String,
)
}
class PayInvoiceErrorResponse(val error: PayInvoiceErrorParams? = null) : Response("pay_invoice") {
class PayInvoiceErrorParams(val code: ErrorType?, val message: String?)
class PayInvoiceErrorResponse(
val error: PayInvoiceErrorParams? = null,
) : Response("pay_invoice") {
class PayInvoiceErrorParams(
val code: ErrorType?,
val message: String?,
)
enum class ErrorType {
@JsonProperty(value = "RATE_LIMITED")
@@ -75,9 +75,7 @@ class LnZapRequestEvent(
return null
}
fun cachedPrivateZap(): LnZapPrivateEvent? {
return privateZapEvent
}
fun cachedPrivateZap(): LnZapPrivateEvent? = privateZapEvent
fun decryptPrivateZap(
signer: NostrSigner,
@@ -34,7 +34,8 @@ class LongTextNoteEvent(
tags: Array<Array<String>>,
content: String,
sig: HexKey,
) : BaseTextNoteEvent(id, pubKey, createdAt, KIND, tags, content, sig), AddressableEvent {
) : BaseTextNoteEvent(id, pubKey, createdAt, KIND, tags, content, sig),
AddressableEvent {
override fun dTag() = tags.firstOrNull { it.size > 1 && it[0] == "d" }?.get(1) ?: ""
override fun address() = ATag(kind, pubKey, dTag(), null)
@@ -71,9 +71,7 @@ class MuteListEvent(
const val FIXED_D_TAG = ""
const val ALT = "Mute List"
fun blockListFor(pubKeyHex: HexKey): String {
return "10000:$pubKeyHex:"
}
fun blockListFor(pubKeyHex: HexKey): String = "10000:$pubKeyHex:"
fun createListWithTag(
key: String,
@@ -110,9 +108,7 @@ class MuteListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (MuteListEvent) -> Unit,
) {
return createListWithTag("p", pubKeyHex, isPrivate, signer, createdAt, onReady)
}
) = createListWithTag("p", pubKeyHex, isPrivate, signer, createdAt, onReady)
fun createListWithWord(
word: String,
@@ -120,9 +116,7 @@ class MuteListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (MuteListEvent) -> Unit,
) {
return createListWithTag("word", word, isPrivate, signer, createdAt, onReady)
}
) = createListWithTag("word", word, isPrivate, signer, createdAt, onReady)
fun addUsers(
earlierVersion: MuteListEvent,
@@ -171,9 +165,7 @@ class MuteListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (MuteListEvent) -> Unit,
) {
return addTag(earlierVersion, "word", word, isPrivate, signer, createdAt, onReady)
}
) = addTag(earlierVersion, "word", word, isPrivate, signer, createdAt, onReady)
fun addUser(
earlierVersion: MuteListEvent,
@@ -182,9 +174,7 @@ class MuteListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (MuteListEvent) -> Unit,
) {
return addTag(earlierVersion, "p", pubKeyHex, isPrivate, signer, createdAt, onReady)
}
) = addTag(earlierVersion, "p", pubKeyHex, isPrivate, signer, createdAt, onReady)
fun addTag(
earlierVersion: MuteListEvent,
@@ -232,9 +222,7 @@ class MuteListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (MuteListEvent) -> Unit,
) {
return removeTag(earlierVersion, "word", word, isPrivate, signer, createdAt, onReady)
}
) = removeTag(earlierVersion, "word", word, isPrivate, signer, createdAt, onReady)
fun removeUser(
earlierVersion: MuteListEvent,
@@ -243,9 +231,7 @@ class MuteListEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (MuteListEvent) -> Unit,
) {
return removeTag(earlierVersion, "p", pubKeyHex, isPrivate, signer, createdAt, onReady)
}
) = removeTag(earlierVersion, "p", pubKeyHex, isPrivate, signer, createdAt, onReady)
fun removeTag(
earlierVersion: MuteListEvent,
@@ -24,7 +24,10 @@ import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.signers.NostrSigner
class NIP17Factory {
data class Result(val msg: Event, val wraps: List<GiftWrapEvent>)
data class Result(
val msg: Event,
val wraps: List<GiftWrapEvent>,
)
private fun recursiveGiftWrapCreation(
event: Event,
@@ -34,22 +34,27 @@ class NIP90StatusEvent(
content: String,
sig: HexKey,
) : Event(id, pubKey, createdAt, KIND, tags, content, sig) {
class StatusCode(val code: String, val description: String)
class StatusCode(
val code: String,
val description: String,
)
class AmountInvoice(val amount: Long?, val lnInvoice: String?)
class AmountInvoice(
val amount: Long?,
val lnInvoice: String?,
)
fun status(): StatusCode? {
return tags.firstOrNull { it.size > 1 && it[0] == "status" }?.let {
fun status(): StatusCode? =
tags.firstOrNull { it.size > 1 && it[0] == "status" }?.let {
if (it.size > 2 && content == "") {
StatusCode(it[1], it[2])
} else {
StatusCode(it[1], content)
}
}
}
fun firstAmount(): AmountInvoice? {
return tags.firstOrNull { it.size > 1 && it[0] == "amount" }?.let {
fun firstAmount(): AmountInvoice? =
tags.firstOrNull { it.size > 1 && it[0] == "amount" }?.let {
val amount = it[1].toLongOrNull()
if (it.size > 2) {
if (it[2].isNotBlank()) {
@@ -65,7 +70,6 @@ class NIP90StatusEvent(
}
}
}
}
companion object {
const val KIND = 7000
@@ -54,22 +54,17 @@ class OtsEvent(
fun digest() = digestEvent()?.hexToByteArray()
fun otsByteArray(): ByteArray {
return Base64.getDecoder().decode(content)
}
fun otsByteArray(): ByteArray = Base64.getDecoder().decode(content)
fun cacheVerify(): Long? {
return if (verifiedTime != null) {
fun cacheVerify(): Long? =
if (verifiedTime != null) {
verifiedTime
} else {
verifiedTime = verify()
verifiedTime
}
}
fun verify(): Long? {
return digestEvent()?.let { OtsEvent.verify(otsByteArray(), it) }
}
fun verify(): Long? = digestEvent()?.let { OtsEvent.verify(otsByteArray(), it) }
fun info(): String {
val detachedOts = DetachedTimestampFile.deserialize(otsByteArray())
@@ -111,16 +106,12 @@ class OtsEvent(
fun verify(
otsFile: String,
eventId: HexKey,
): Long? {
return verify(Base64.getDecoder().decode(otsFile), eventId)
}
): Long? = verify(Base64.getDecoder().decode(otsFile), eventId)
fun verify(
otsFile: ByteArray,
eventId: HexKey,
): Long? {
return verify(DetachedTimestampFile.deserialize(otsFile), eventId)
}
): Long? = verify(DetachedTimestampFile.deserialize(otsFile), eventId)
fun verify(
detachedOts: DetachedTimestampFile,
@@ -37,7 +37,8 @@ class PrivateDmEvent(
tags: Array<Array<String>>,
content: String,
sig: HexKey,
) : Event(id, pubKey, createdAt, KIND, tags, content, sig), ChatroomKeyable {
) : Event(id, pubKey, createdAt, KIND, tags, content, sig),
ChatroomKeyable {
@Transient private var decryptedContent: Map<HexKey, String> = mapOf()
override fun isContentEncoded() = true
@@ -60,13 +61,9 @@ class PrivateDmEvent(
}
}
fun talkingWith(oneSideHex: String): HexKey {
return if (pubKey == oneSideHex) verifiedRecipientPubKey() ?: pubKey else pubKey
}
fun talkingWith(oneSideHex: String): HexKey = if (pubKey == oneSideHex) verifiedRecipientPubKey() ?: pubKey else pubKey
override fun chatroomKey(toRemove: String): ChatroomKey {
return ChatroomKey(persistentSetOf(talkingWith(toRemove)))
}
override fun chatroomKey(toRemove: String): ChatroomKey = ChatroomKey(persistentSetOf(talkingWith(toRemove)))
/**
* To be fully compatible with nip-04, we read e-tags that are in violation to nip-18.
@@ -76,13 +73,9 @@ class PrivateDmEvent(
*/
fun replyTo() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1)
fun with(pubkeyHex: String): Boolean {
return pubkeyHex == pubKey || tags.any { it.size > 1 && it[0] == "p" && it[1] == pubkeyHex }
}
fun with(pubkeyHex: String): Boolean = pubkeyHex == pubKey || tags.any { it.size > 1 && it[0] == "p" && it[1] == pubkeyHex }
fun cachedContentFor(signer: NostrSigner): String? {
return decryptedContent[signer.pubKey]
}
fun cachedContentFor(signer: NostrSigner): String? = decryptedContent[signer.pubKey]
fun plainContent(
signer: NostrSigner,
@@ -178,11 +171,10 @@ class PrivateDmEvent(
}
}
fun geohashMipMap(geohash: String): Array<Array<String>> {
return geohash.indices
fun geohashMipMap(geohash: String): Array<Array<String>> =
geohash.indices
.asSequence()
.map { arrayOf("g", geohash.substring(0, it + 1)) }
.toList()
.reversed()
.toTypedArray()
}
@@ -46,18 +46,14 @@ class ReactionEvent(
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ReactionEvent) -> Unit,
) {
return create("\u26A0\uFE0F", originalNote, signer, createdAt, onReady)
}
) = create("\u26A0\uFE0F", originalNote, signer, createdAt, onReady)
fun createLike(
originalNote: EventInterface,
signer: NostrSigner,
createdAt: Long = TimeUtils.now(),
onReady: (ReactionEvent) -> Unit,
) {
return create("+", originalNote, signer, createdAt, onReady)
}
) = create("+", originalNote, signer, createdAt, onReady)
fun create(
content: String,
@@ -37,33 +37,29 @@ class SearchRelayListEvent(
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
override fun dTag() = FIXED_D_TAG
fun relays(): List<String> {
return tags.mapNotNull {
fun relays(): List<String> =
tags.mapNotNull {
if (it.size > 1 && it[0] == "relay") {
it[1]
} else {
null
}
}
}
companion object {
const val KIND = 10007
const val FIXED_D_TAG = ""
fun createAddressATag(pubKey: HexKey): ATag {
return ATag(KIND, pubKey, FIXED_D_TAG, null)
}
fun createAddressATag(pubKey: HexKey): ATag = ATag(KIND, pubKey, FIXED_D_TAG, null)
fun createAddressTag(pubKey: HexKey): String {
return ATag.assembleATag(KIND, pubKey, FIXED_D_TAG)
}
fun createAddressTag(pubKey: HexKey): String = ATag.assembleATag(KIND, pubKey, FIXED_D_TAG)
fun createTagArray(relays: List<String>): Array<Array<String>> {
return relays.map {
arrayOf("relay", it)
}.plusElement(arrayOf("alt", "Relay list to use for Search")).toTypedArray()
}
fun createTagArray(relays: List<String>): Array<Array<String>> =
relays
.map {
arrayOf("relay", it)
}.plusElement(arrayOf("alt", "Relay list to use for Search"))
.toTypedArray()
fun updateRelayList(
earlierVersion: SearchRelayListEvent,
@@ -73,11 +69,13 @@ class SearchRelayListEvent(
onReady: (SearchRelayListEvent) -> Unit,
) {
val tags =
earlierVersion.tags.filter { it[0] != "relay" }.plus(
relays.map {
arrayOf("relay", it)
},
).toTypedArray()
earlierVersion.tags
.filter { it[0] != "relay" }
.plus(
relays.map {
arrayOf("relay", it)
},
).toTypedArray()
signer.sign(createdAt, KIND, tags, earlierVersion.content, onReady)
}
@@ -134,9 +134,7 @@ class TextNoteEvent(
}
}
fun findURLs(text: String): List<String> {
return UrlDetector(text, UrlDetectorOptions.Default).detect().map { it.originalUrl }
}
fun findURLs(text: String): List<String> = UrlDetector(text, UrlDetectorOptions.Default).detect().map { it.originalUrl }
/**
* Returns a list of NIP-10 marked tags that are also ordered at best effort to support the
@@ -163,13 +161,12 @@ fun List<String>.positionalMarkedTags(
o2 == replyingTo -> -1 // reply event being responded to goes last
else -> 0 // keep the relative order for any other tag
}
}
.map {
when (it) {
root -> arrayOf(tagName, it, "", "root")
replyingTo -> arrayOf(tagName, it, "", "reply")
forkedFrom -> arrayOf(tagName, it, "", "fork")
in directMentions -> arrayOf(tagName, it, "", "mention")
else -> arrayOf(tagName, it)
}
}.map {
when (it) {
root -> arrayOf(tagName, it, "", "root")
replyingTo -> arrayOf(tagName, it, "", "reply")
forkedFrom -> arrayOf(tagName, it, "", "fork")
in directMentions -> arrayOf(tagName, it, "", "mention")
else -> arrayOf(tagName, it)
}
}
@@ -34,7 +34,8 @@ class WikiNoteEvent(
tags: Array<Array<String>>,
content: String,
sig: HexKey,
) : BaseTextNoteEvent(id, pubKey, createdAt, KIND, tags, content, sig), AddressableEvent {
) : BaseTextNoteEvent(id, pubKey, createdAt, KIND, tags, content, sig),
AddressableEvent {
override fun dTag() = tags.firstOrNull { it.size > 1 && it[0] == "d" }?.get(1) ?: ""
override fun address() = ATag(kind, pubKey, dTag(), null)
@@ -27,7 +27,9 @@ import com.vitorpamplona.quartz.events.EventFactory
import com.vitorpamplona.quartz.events.LnZapPrivateEvent
import com.vitorpamplona.quartz.events.LnZapRequestEvent
abstract class NostrSigner(val pubKey: HexKey) {
abstract class NostrSigner(
val pubKey: HexKey,
) {
abstract fun <T : Event> sign(
createdAt: Long,
kind: Int,
@@ -66,8 +66,7 @@ class NostrSignerExternal(
localEvent.content,
localEvent.sig,
) as? T?
)
?.let { onReady(it) }
)?.let { onReady(it) }
} else {
(
EventFactory.create(
@@ -79,8 +78,7 @@ class NostrSignerExternal(
event.content,
signature.split("-")[0],
) as? T?
)
?.let { onReady(it) }
)?.let { onReady(it) }
}
}
}