add support for reports

This commit is contained in:
greenart7c3
2023-09-01 13:32:39 -03:00
parent bbba27752d
commit 6d691c4741
4 changed files with 151 additions and 82 deletions

View File

@@ -272,7 +272,7 @@ class Account(
return null return null
} }
if (note.event is ChatMessageEvent) { if (note.event is ChatMessageEvent && signEvent) {
val event = note.event as ChatMessageEvent val event = note.event as ChatMessageEvent
val users = event.recipientsPubKey().plus(event.pubKey).toSet().toList() val users = event.recipientsPubKey().plus(event.pubKey).toSet().toList()
@@ -284,7 +284,7 @@ class Account(
emojiUrl = emojiUrl, emojiUrl = emojiUrl,
originalNote = it, originalNote = it,
to = users, to = users,
from = keyPair.privKey!! from = keyPair
) )
broadcastPrivately(giftWraps) broadcastPrivately(giftWraps)
@@ -299,7 +299,7 @@ class Account(
content = reaction, content = reaction,
originalNote = it, originalNote = it,
to = users, to = users,
from = keyPair.privKey!! from = keyPair
) )
broadcastPrivately(giftWraps) broadcastPrivately(giftWraps)
@@ -310,11 +310,11 @@ class Account(
val emojiUrl = EmojiUrl.decode(reaction) val emojiUrl = EmojiUrl.decode(reaction)
if (emojiUrl != null) { if (emojiUrl != null) {
note.event?.let { note.event?.let {
val event = ReactionEvent.create(emojiUrl, it, keyPair)
if (!signEvent) { if (!signEvent) {
return ReactionEvent.create(emojiUrl, it, keyPair.pubKey.toHexKey()) return event
} }
val event = ReactionEvent.create(emojiUrl, it, keyPair.privKey!!)
Client.send(event) Client.send(event)
LocalCache.consume(event) LocalCache.consume(event)
} }
@@ -324,11 +324,10 @@ class Account(
} }
note.event?.let { note.event?.let {
val event = ReactionEvent.create(reaction, it, keyPair)
if (!signEvent) { if (!signEvent) {
return ReactionEvent.create(reaction, it, keyPair.pubKey.toHexKey()) return event
} }
val event = ReactionEvent.create(reaction, it, keyPair.privKey!!)
Client.send(event) Client.send(event)
LocalCache.consume(event) LocalCache.consume(event)
} }
@@ -468,7 +467,7 @@ class Account(
} }
fun report(note: Note, type: ReportEvent.ReportType, content: String = "") { fun report(note: Note, type: ReportEvent.ReportType, content: String = "") {
if (!isWriteable()) return if (!isWriteable() && !loginWithAmber) return
if (note.hasReacted(userProfile(), "⚠️")) { if (note.hasReacted(userProfile(), "⚠️")) {
// has already liked this note // has already liked this note
@@ -476,27 +475,66 @@ class Account(
} }
note.event?.let { note.event?.let {
val event = ReactionEvent.createWarning(it, keyPair.privKey!!) var event = ReactionEvent.createWarning(it, keyPair)
if (loginWithAmber) {
AmberUtils.content = ""
AmberUtils.openAmber(event)
if (AmberUtils.content.isBlank()) return
event = ReactionEvent(
event.id,
event.pubKey,
event.createdAt,
event.tags,
event.content,
AmberUtils.content
)
}
Client.send(event) Client.send(event)
LocalCache.consume(event) LocalCache.consume(event)
} }
note.event?.let { note.event?.let {
val event = ReportEvent.create(it, type, keyPair.privKey!!, content = content) var event = ReportEvent.create(it, type, keyPair, content = content)
if (loginWithAmber) {
AmberUtils.content = ""
AmberUtils.openAmber(event)
if (AmberUtils.content.isBlank()) return
event = ReportEvent(
event.id,
event.pubKey,
event.createdAt,
event.tags,
event.content,
AmberUtils.content
)
}
Client.send(event) Client.send(event)
LocalCache.consume(event, null) LocalCache.consume(event, null)
} }
} }
fun report(user: User, type: ReportEvent.ReportType) { fun report(user: User, type: ReportEvent.ReportType) {
if (!isWriteable()) return if (!isWriteable() && !loginWithAmber) return
if (user.hasReport(userProfile(), type)) { if (user.hasReport(userProfile(), type)) {
// has already reported this note // has already reported this note
return return
} }
val event = ReportEvent.create(user.pubkeyHex, type, keyPair.privKey!!) var event = ReportEvent.create(user.pubkeyHex, type, keyPair)
if (loginWithAmber) {
AmberUtils.content = ""
AmberUtils.openAmber(event)
if (AmberUtils.content.isBlank()) return
event = ReportEvent(
event.id,
event.pubKey,
event.createdAt,
event.tags,
event.content,
AmberUtils.content
)
}
Client.send(event) Client.send(event)
LocalCache.consume(event, null) LocalCache.consume(event, null)
} }
@@ -1819,25 +1857,81 @@ class Account(
fun hideUser(pubkeyHex: String) { fun hideUser(pubkeyHex: String) {
val blockList = migrateHiddenUsersIfNeeded(getBlockList()) val blockList = migrateHiddenUsersIfNeeded(getBlockList())
if (loginWithAmber) {
val content = blockList?.content ?: ""
val encryptedContent = if (content.isBlank()) {
val privateTags = listOf(listOf("p", pubkeyHex))
val msg = Event.mapper.writeValueAsString(privateTags)
val event = if (blockList != null) { AmberUtils.content = ""
PeopleListEvent.addUser( AmberUtils.encrypt(msg, keyPair.pubKey.toHexKey())
earlierVersion = blockList, if (AmberUtils.content.isBlank()) return
pubKeyHex = pubkeyHex, AmberUtils.content
isPrivate = true, } else {
privateKey = keyPair.privKey!! AmberUtils.content = ""
AmberUtils.decrypt(content, keyPair.pubKey.toHexKey())
if (AmberUtils.content.isBlank()) return
val decryptedContent = AmberUtils.content
AmberUtils.content = ""
val privateTags = blockList?.privateTagsOrEmpty(decryptedContent)?.plus(element = listOf("p", pubkeyHex))
val msg = Event.mapper.writeValueAsString(privateTags)
AmberUtils.content = ""
AmberUtils.encrypt(msg, keyPair.pubKey.toHexKey())
if (AmberUtils.content.isBlank()) return
AmberUtils.content
}
var event = if (blockList != null) {
PeopleListEvent.addUser(
earlierVersion = blockList,
pubKeyHex = pubkeyHex,
isPrivate = true,
pubKey = keyPair.pubKey.toHexKey(),
encryptedContent
)
} else {
PeopleListEvent.createListWithUser(
name = PeopleListEvent.blockList,
pubKeyHex = pubkeyHex,
isPrivate = true,
pubKey = keyPair.pubKey.toHexKey(),
encryptedContent
)
}
AmberUtils.content = ""
AmberUtils.openAmber(event)
event = PeopleListEvent(
event.id,
event.pubKey,
event.createdAt,
event.tags,
event.content,
AmberUtils.content
) )
Client.send(event)
LocalCache.consume(event)
} else { } else {
PeopleListEvent.createListWithUser( val event = if (blockList != null) {
name = PeopleListEvent.blockList, PeopleListEvent.addUser(
pubKeyHex = pubkeyHex, earlierVersion = blockList,
isPrivate = true, pubKeyHex = pubkeyHex,
privateKey = keyPair.privKey!! isPrivate = true,
) privateKey = keyPair.privKey!!
} )
} else {
PeopleListEvent.createListWithUser(
name = PeopleListEvent.blockList,
pubKeyHex = pubkeyHex,
isPrivate = true,
privateKey = keyPair.privKey!!
)
}
Client.send(event) Client.send(event)
LocalCache.consume(event) LocalCache.consume(event)
}
live.invalidateData() live.invalidateData()
saveable.invalidateData() saveable.invalidateData()

View File

@@ -2,6 +2,7 @@ package com.vitorpamplona.quartz.events
import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.crypto.CryptoUtils import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.HexKey
class NIP24Factory { class NIP24Factory {
@@ -44,8 +45,8 @@ class NIP24Factory {
} }
} }
fun createReactionWithinGroup(content: String, originalNote: EventInterface, to: List<HexKey>, from: ByteArray): List<GiftWrapEvent> { fun createReactionWithinGroup(content: String, originalNote: EventInterface, to: List<HexKey>, from: KeyPair): List<GiftWrapEvent> {
val senderPublicKey = CryptoUtils.pubkeyCreate(from).toHexKey() val senderPublicKey = CryptoUtils.pubkeyCreate(from.privKey!!).toHexKey()
val senderReaction = ReactionEvent.create( val senderReaction = ReactionEvent.create(
content, content,
@@ -58,15 +59,15 @@ class NIP24Factory {
event = SealedGossipEvent.create( event = SealedGossipEvent.create(
event = senderReaction, event = senderReaction,
encryptTo = it, encryptTo = it,
privateKey = from privateKey = from.privKey
), ),
recipientPubKey = it recipientPubKey = it
) )
} }
} }
fun createReactionWithinGroup(emojiUrl: EmojiUrl, originalNote: EventInterface, to: List<HexKey>, from: ByteArray): List<GiftWrapEvent> { fun createReactionWithinGroup(emojiUrl: EmojiUrl, originalNote: EventInterface, to: List<HexKey>, from: KeyPair): List<GiftWrapEvent> {
val senderPublicKey = CryptoUtils.pubkeyCreate(from).toHexKey() val senderPublicKey = CryptoUtils.pubkeyCreate(from.privKey!!).toHexKey()
val senderReaction = ReactionEvent.create( val senderReaction = ReactionEvent.create(
emojiUrl, emojiUrl,
@@ -79,7 +80,7 @@ class NIP24Factory {
event = SealedGossipEvent.create( event = SealedGossipEvent.create(
event = senderReaction, event = senderReaction,
encryptTo = it, encryptTo = it,
privateKey = from privateKey = from.privKey
), ),
recipientPubKey = it recipientPubKey = it
) )

View File

@@ -4,6 +4,7 @@ import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.crypto.CryptoUtils import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.HexKey
@Immutable @Immutable
@@ -22,39 +23,29 @@ class ReactionEvent(
companion object { companion object {
const val kind = 7 const val kind = 7
fun createWarning(originalNote: EventInterface, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ReactionEvent { fun createWarning(originalNote: EventInterface, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ReactionEvent {
return create("\u26A0\uFE0F", originalNote, privateKey, createdAt) return create("\u26A0\uFE0F", originalNote, keyPair, createdAt)
} }
fun createLike(originalNote: EventInterface, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ReactionEvent { fun createLike(originalNote: EventInterface, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ReactionEvent {
return create("+", originalNote, privateKey, createdAt) return create("+", originalNote, keyPair, createdAt)
} }
fun create(content: String, originalNote: EventInterface, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ReactionEvent { fun create(content: String, originalNote: EventInterface, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ReactionEvent {
val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey()
var tags = listOf(listOf("e", originalNote.id()), listOf("p", originalNote.pubKey())) var tags = listOf(listOf("e", originalNote.id()), listOf("p", originalNote.pubKey()))
if (originalNote is AddressableEvent) { if (originalNote is AddressableEvent) {
tags = tags + listOf(listOf("a", originalNote.address().toTag())) tags = tags + listOf(listOf("a", originalNote.address().toTag()))
} }
val pubKey = keyPair.pubKey.toHexKey()
val id = generateId(pubKey, createdAt, kind, tags, content) val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = CryptoUtils.sign(id, privateKey) val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey)
return ReactionEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) return ReactionEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "")
} }
fun create(content: String, originalNote: EventInterface, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ReactionEvent { fun create(emojiUrl: EmojiUrl, originalNote: EventInterface, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ReactionEvent {
var tags = listOf(listOf("e", originalNote.id()), listOf("p", originalNote.pubKey()))
if (originalNote is AddressableEvent) {
tags = tags + listOf(listOf("a", originalNote.address().toTag()))
}
val id = generateId(pubKey, createdAt, kind, tags, content)
return ReactionEvent(id.toHexKey(), pubKey, createdAt, tags, content, "")
}
fun create(emojiUrl: EmojiUrl, originalNote: EventInterface, pubKey: HexKey, createdAt: Long = TimeUtils.now()): ReactionEvent {
val content = ":${emojiUrl.code}:" val content = ":${emojiUrl.code}:"
val pubKey = keyPair.pubKey.toHexKey()
var tags = listOf( var tags = listOf(
listOf("e", originalNote.id()), listOf("e", originalNote.id()),
@@ -67,26 +58,8 @@ class ReactionEvent(
} }
val id = generateId(pubKey, createdAt, kind, tags, content) val id = generateId(pubKey, createdAt, kind, tags, content)
return ReactionEvent(id.toHexKey(), pubKey, createdAt, tags, content, "") val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey)
} return ReactionEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "")
fun create(emojiUrl: EmojiUrl, originalNote: EventInterface, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ReactionEvent {
val content = ":${emojiUrl.code}:"
val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey()
var tags = listOf(
listOf("e", originalNote.id()),
listOf("p", originalNote.pubKey()),
listOf("emoji", emojiUrl.code, emojiUrl.url)
)
if (originalNote is AddressableEvent) {
tags = tags + listOf(listOf("a", originalNote.address().toTag()))
}
val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = CryptoUtils.sign(id, privateKey)
return ReactionEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
} }
} }
} }

View File

@@ -4,6 +4,7 @@ import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.crypto.CryptoUtils import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.HexKey
@Immutable @Immutable
@@ -56,14 +57,14 @@ class ReportEvent(
fun create( fun create(
reportedPost: EventInterface, reportedPost: EventInterface,
type: ReportType, type: ReportType,
privateKey: ByteArray, keyPair: KeyPair,
content: String = "", content: String = "",
createdAt: Long = TimeUtils.now() createdAt: Long = TimeUtils.now()
): ReportEvent { ): ReportEvent {
val reportPostTag = listOf("e", reportedPost.id(), type.name.lowercase()) val reportPostTag = listOf("e", reportedPost.id(), type.name.lowercase())
val reportAuthorTag = listOf("p", reportedPost.pubKey(), type.name.lowercase()) val reportAuthorTag = listOf("p", reportedPost.pubKey(), type.name.lowercase())
val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() val pubKey = keyPair.pubKey.toHexKey()
var tags: List<List<String>> = listOf(reportPostTag, reportAuthorTag) var tags: List<List<String>> = listOf(reportPostTag, reportAuthorTag)
if (reportedPost is AddressableEvent) { if (reportedPost is AddressableEvent) {
@@ -71,20 +72,20 @@ class ReportEvent(
} }
val id = generateId(pubKey, createdAt, kind, tags, content) val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = CryptoUtils.sign(id, privateKey) val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey)
return ReportEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) return ReportEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "")
} }
fun create(reportedUser: String, type: ReportType, privateKey: ByteArray, createdAt: Long = TimeUtils.now()): ReportEvent { fun create(reportedUser: String, type: ReportType, keyPair: KeyPair, createdAt: Long = TimeUtils.now()): ReportEvent {
val content = "" val content = ""
val reportAuthorTag = listOf("p", reportedUser, type.name.lowercase()) val reportAuthorTag = listOf("p", reportedUser, type.name.lowercase())
val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey() val pubKey = keyPair.pubKey.toHexKey()
val tags: List<List<String>> = listOf(reportAuthorTag) val tags: List<List<String>> = listOf(reportAuthorTag)
val id = generateId(pubKey, createdAt, kind, tags, content) val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = CryptoUtils.sign(id, privateKey) val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey)
return ReportEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey()) return ReportEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig?.toHexKey() ?: "")
} }
} }