|
|
|
@@ -18,62 +18,94 @@ class PeopleListEvent(
|
|
|
|
|
content: String,
|
|
|
|
|
sig: HexKey
|
|
|
|
|
) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) {
|
|
|
|
|
@Transient
|
|
|
|
|
var decryptedContent: String? = null
|
|
|
|
|
@Transient
|
|
|
|
|
var publicAndPrivateUserCache: ImmutableSet<HexKey>? = null
|
|
|
|
|
@Transient
|
|
|
|
|
var publicAndPrivateWordCache: ImmutableSet<String>? = null
|
|
|
|
|
|
|
|
|
|
fun filterTagList(key: String, privateTags: List<List<String>>?): ImmutableSet<String> {
|
|
|
|
|
val privateUserList = privateTags?.let {
|
|
|
|
|
it.filter { it.size > 1 && it[0] == key }.map { it[1] }.toSet()
|
|
|
|
|
} ?: emptySet()
|
|
|
|
|
val publicUserList = tags.filter { it.size > 1 && it[0] == key }.map { it[1] }.toSet()
|
|
|
|
|
|
|
|
|
|
return (privateUserList + publicUserList).toImmutableSet()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun publicAndPrivateWords(privateKey: ByteArray?): ImmutableSet<String> {
|
|
|
|
|
publicAndPrivateWordCache?.let {
|
|
|
|
|
return it
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
publicAndPrivateWordCache = filterTagList("word", privateTagsOrEmpty(privKey = privateKey))
|
|
|
|
|
|
|
|
|
|
return publicAndPrivateWordCache ?: persistentSetOf()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun publicAndPrivateUsers(privateKey: ByteArray?): ImmutableSet<HexKey> {
|
|
|
|
|
publicAndPrivateUserCache?.let {
|
|
|
|
|
return it
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val privateUserList = privateKey?.let {
|
|
|
|
|
privateTagsOrEmpty(privKey = it).filter { it.size > 1 && it[0] == "p" }.map { it[1] }.toSet()
|
|
|
|
|
} ?: emptySet()
|
|
|
|
|
val publicUserList = tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] }.toSet()
|
|
|
|
|
|
|
|
|
|
publicAndPrivateUserCache = (privateUserList + publicUserList).toImmutableSet()
|
|
|
|
|
publicAndPrivateUserCache = filterTagList("p", privateTagsOrEmpty(privKey = privateKey))
|
|
|
|
|
|
|
|
|
|
return publicAndPrivateUserCache ?: persistentSetOf()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun publicAndPrivateWords(decryptedContent: String): ImmutableSet<HexKey> {
|
|
|
|
|
publicAndPrivateWordCache?.let {
|
|
|
|
|
return it
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
publicAndPrivateWordCache = filterTagList("word", privateTagsOrEmpty(decryptedContent))
|
|
|
|
|
|
|
|
|
|
return publicAndPrivateWordCache ?: persistentSetOf()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun publicAndPrivateUsers(decryptedContent: String): ImmutableSet<HexKey> {
|
|
|
|
|
publicAndPrivateUserCache?.let {
|
|
|
|
|
return it
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val privateUserList = privateTagsOrEmpty(decryptedContent).filter { it.size > 1 && it[0] == "p" }.map { it[1] }.toSet()
|
|
|
|
|
|
|
|
|
|
val publicUserList = tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] }.toSet()
|
|
|
|
|
|
|
|
|
|
publicAndPrivateUserCache = (privateUserList + publicUserList).toImmutableSet()
|
|
|
|
|
publicAndPrivateUserCache = filterTagList("p", privateTagsOrEmpty(decryptedContent))
|
|
|
|
|
|
|
|
|
|
return publicAndPrivateUserCache ?: persistentSetOf()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun isTaggedUser(idHex: String, isPrivate: Boolean, privateKey: ByteArray): Boolean {
|
|
|
|
|
fun isTagged(key: String, tag: String, isPrivate: Boolean, privateKey: ByteArray): Boolean {
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
privateTagsOrEmpty(privKey = privateKey).any { it.size > 1 && it[0] == "p" && it[1] == idHex }
|
|
|
|
|
privateTagsOrEmpty(privKey = privateKey).any { it.size > 1 && it[0] == key && it[1] == tag }
|
|
|
|
|
} else {
|
|
|
|
|
isTaggedUser(idHex)
|
|
|
|
|
isTagged(key, tag)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun isTaggedUser(idHex: String, isPrivate: Boolean, content: String): Boolean {
|
|
|
|
|
fun isTagged(key: String, tag: String, isPrivate: Boolean, decryptedContent: String): Boolean {
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
privateTagsOrEmpty(content).any { it.size > 1 && it[0] == "p" && it[1] == idHex }
|
|
|
|
|
privateTagsOrEmpty(decryptedContent).any { it.size > 1 && it[0] == key && it[1] == tag }
|
|
|
|
|
} else {
|
|
|
|
|
isTaggedUser(idHex)
|
|
|
|
|
isTagged(key, tag)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun isTaggedWord(word: String, isPrivate: Boolean, privateKey: ByteArray) = isTagged( "word", word, isPrivate, privateKey)
|
|
|
|
|
|
|
|
|
|
fun isTaggedUser(idHex: String, isPrivate: Boolean, privateKey: ByteArray) = isTagged( "p", idHex, isPrivate, privateKey)
|
|
|
|
|
|
|
|
|
|
fun isTaggedUser(idHex: String, isPrivate: Boolean, decryptedContent: String) = isTagged( "p", idHex, isPrivate, decryptedContent)
|
|
|
|
|
|
|
|
|
|
fun isTaggedWord(idHex: String, isPrivate: Boolean, decryptedContent: String) = isTagged( "word", idHex, isPrivate, decryptedContent)
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
const val kind = 30000
|
|
|
|
|
const val blockList = "mute"
|
|
|
|
|
|
|
|
|
|
fun createListWithUser(name: String, pubKeyHex: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
fun createListWithTag(name: String, key: String, tag: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
create(
|
|
|
|
|
content = encryptTags(listOf(listOf("p", pubKeyHex)), privateKey),
|
|
|
|
|
content = encryptTags(listOf(listOf(key, tag)), privateKey),
|
|
|
|
|
tags = listOf(listOf("d", name)),
|
|
|
|
|
privateKey = privateKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
@@ -81,13 +113,21 @@ class PeopleListEvent(
|
|
|
|
|
} else {
|
|
|
|
|
create(
|
|
|
|
|
content = "",
|
|
|
|
|
tags = listOf(listOf("d", name), listOf("p", pubKeyHex)),
|
|
|
|
|
tags = listOf(listOf("d", name), listOf(key, tag)),
|
|
|
|
|
privateKey = privateKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun createListWithUser(name: String, pubKeyHex: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return createListWithTag(name, "p", pubKeyHex, isPrivate, privateKey, createdAt)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun createListWithWord(name: String, word: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return createListWithTag(name, "word", word, isPrivate, privateKey, createdAt)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun createListWithUser(name: String, pubKeyHex: String, isPrivate: Boolean, pubKey: HexKey, encryptedContent: String, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
create(
|
|
|
|
@@ -106,6 +146,24 @@ class PeopleListEvent(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun createListWithWord(name: String, word: String, isPrivate: Boolean, pubKey: HexKey, encryptedContent: String, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
create(
|
|
|
|
|
content = encryptedContent,
|
|
|
|
|
tags = listOf(listOf("d", name)),
|
|
|
|
|
pubKey = pubKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
create(
|
|
|
|
|
content = "",
|
|
|
|
|
tags = listOf(listOf("d", name), listOf("word", word)),
|
|
|
|
|
pubKey = pubKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun addUsers(earlierVersion: PeopleListEvent, listPubKeyHex: List<String>, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
create(
|
|
|
|
@@ -135,6 +193,24 @@ class PeopleListEvent(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun addWord(earlierVersion: PeopleListEvent, word: String, isPrivate: Boolean, pubKey: HexKey, encryptedContent: String, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
create(
|
|
|
|
|
content = encryptedContent,
|
|
|
|
|
tags = earlierVersion.tags,
|
|
|
|
|
pubKey = pubKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
create(
|
|
|
|
|
content = earlierVersion.content,
|
|
|
|
|
tags = earlierVersion.tags.plus(element = listOf("word", word)),
|
|
|
|
|
pubKey = pubKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun addUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, pubKey: HexKey, encryptedContent: String, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
create(
|
|
|
|
@@ -153,13 +229,40 @@ class PeopleListEvent(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun removeTag(earlierVersion: PeopleListEvent, tag: String, isPrivate: Boolean, pubKey: HexKey, encryptedContent: String, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
create(
|
|
|
|
|
content = encryptedContent,
|
|
|
|
|
tags = earlierVersion.tags,
|
|
|
|
|
pubKey = pubKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
create(
|
|
|
|
|
content = earlierVersion.content,
|
|
|
|
|
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != tag },
|
|
|
|
|
pubKey = pubKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun addWord(earlierVersion: PeopleListEvent, word: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return addTag(earlierVersion, "word", word, isPrivate, privateKey, createdAt)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun addUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
if (earlierVersion.isTaggedUser(pubKeyHex, isPrivate, privateKey)) return earlierVersion
|
|
|
|
|
return addTag(earlierVersion, "p", pubKeyHex, isPrivate, privateKey, createdAt)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fun addTag(earlierVersion: PeopleListEvent, key: String, tag: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
if (earlierVersion.isTagged(key, tag, isPrivate, privateKey)) return earlierVersion
|
|
|
|
|
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
create(
|
|
|
|
|
content = encryptTags(
|
|
|
|
|
privateTags = earlierVersion.privateTagsOrEmpty(privKey = privateKey).plus(element = listOf("p", pubKeyHex)),
|
|
|
|
|
privateTags = earlierVersion.privateTagsOrEmpty(privKey = privateKey).plus(element = listOf(key, tag)),
|
|
|
|
|
privateKey = privateKey
|
|
|
|
|
),
|
|
|
|
|
tags = earlierVersion.tags,
|
|
|
|
@@ -169,48 +272,38 @@ class PeopleListEvent(
|
|
|
|
|
} else {
|
|
|
|
|
create(
|
|
|
|
|
content = earlierVersion.content,
|
|
|
|
|
tags = earlierVersion.tags.plus(element = listOf("p", pubKeyHex)),
|
|
|
|
|
tags = earlierVersion.tags.plus(element = listOf(key, tag)),
|
|
|
|
|
privateKey = privateKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun removeUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, encryptedContent: String, pubKey: HexKey, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
create(
|
|
|
|
|
content = encryptedContent,
|
|
|
|
|
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex },
|
|
|
|
|
pubKey = pubKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
create(
|
|
|
|
|
content = earlierVersion.content,
|
|
|
|
|
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex },
|
|
|
|
|
pubKey = pubKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
fun removeWord(earlierVersion: PeopleListEvent, word: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
return removeTag(earlierVersion, "word", word, isPrivate, privateKey, createdAt)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun removeUser(earlierVersion: PeopleListEvent, pubKeyHex: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
if (!earlierVersion.isTaggedUser(pubKeyHex, isPrivate, privateKey)) return earlierVersion
|
|
|
|
|
return removeTag(earlierVersion, "p", pubKeyHex, isPrivate, privateKey, createdAt)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun removeTag(earlierVersion: PeopleListEvent, key: String, tag: String, isPrivate: Boolean, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): PeopleListEvent {
|
|
|
|
|
if (!earlierVersion.isTagged(key, tag, isPrivate, privateKey)) return earlierVersion
|
|
|
|
|
|
|
|
|
|
return if (isPrivate) {
|
|
|
|
|
create(
|
|
|
|
|
content = encryptTags(
|
|
|
|
|
privateTags = earlierVersion.privateTagsOrEmpty(privKey = privateKey).filter { it.size > 1 && it[1] != pubKeyHex },
|
|
|
|
|
privateTags = earlierVersion.privateTagsOrEmpty(privKey = privateKey).filter { it.size > 1 && !(it[0] == key && it[1] == tag) },
|
|
|
|
|
privateKey = privateKey
|
|
|
|
|
),
|
|
|
|
|
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex },
|
|
|
|
|
tags = earlierVersion.tags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) },
|
|
|
|
|
privateKey = privateKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
create(
|
|
|
|
|
content = earlierVersion.content,
|
|
|
|
|
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex },
|
|
|
|
|
tags = earlierVersion.tags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) },
|
|
|
|
|
privateKey = privateKey,
|
|
|
|
|
createdAt = createdAt
|
|
|
|
|
)
|
|
|
|
|