From b09577f81694ba0ff82cbe82108757dc497bc354 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Tue, 28 Feb 2023 15:24:23 -0500 Subject: [PATCH] Updating reports to the latest spec --- .../amethyst/model/LocalCache.kt | 4 +- .../com/vitorpamplona/amethyst/model/User.kt | 2 +- .../amethyst/service/model/ReportEvent.kt | 55 ++++++++++++++----- .../amethyst/ui/note/NoteCompose.kt | 21 +++++-- .../ui/screen/loggedIn/ProfileScreen.kt | 11 +++- 5 files changed, 67 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 7d040a53ef..e9575eea8f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -408,8 +408,8 @@ object LocalCache { // Already processed this event. if (note.event != null) return - val mentions = event.reportedAuthor.mapNotNull { checkGetOrCreateUser(it) } - val repliesTo = event.reportedPost.mapNotNull { checkGetOrCreateNote(it) } + val mentions = event.reportedAuthor.mapNotNull { checkGetOrCreateUser(it.key) } + val repliesTo = event.reportedPost.mapNotNull { checkGetOrCreateNote(it.key) } note.loadEvent(event, author, mentions, repliesTo) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt index 64139fdce8..7d9c4925a0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/User.kt @@ -289,7 +289,7 @@ class User(val pubkeyHex: String) { fun hasReport(loggedIn: User, type: ReportEvent.ReportType): Boolean { return reports[loggedIn]?.firstOrNull() { - it.event is ReportEvent && (it.event as ReportEvent).reportType.contains(type) + it.event is ReportEvent && (it.event as ReportEvent).reportedAuthor.any { it.reportType == type } } != null } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/ReportEvent.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/ReportEvent.kt index 1d962e4211..cbee5cf0b2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/ReportEvent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/ReportEvent.kt @@ -5,6 +5,8 @@ import nostr.postr.Utils import nostr.postr.events.Event import nostr.postr.toHex +data class ReportedKey(val key: String, val reportType: ReportEvent.ReportType) + // NIP 56 event. class ReportEvent ( id: ByteArray, @@ -15,14 +17,37 @@ class ReportEvent ( sig: ByteArray ): Event(id, pubKey, createdAt, kind, tags, content, sig) { - @Transient val reportType: List - @Transient val reportedPost: List - @Transient val reportedAuthor: List + @Transient val reportedPost: List + @Transient val reportedAuthor: List init { - reportType = tags.filter { it.firstOrNull() == "report" }.mapNotNull { it.getOrNull(1) }.map { ReportType.valueOf(it.toUpperCase()) } - reportedPost = tags.filter { it.firstOrNull() == "e" }.mapNotNull { it.getOrNull(1) } - reportedAuthor = tags.filter { it.firstOrNull() == "p" }.mapNotNull { it.getOrNull(1) } + // Works with old and new structures for report. + + var reportType = tags.filter { it.firstOrNull() == "report" }.mapNotNull { it.getOrNull(1) }.map { ReportType.valueOf(it.toUpperCase()) }.firstOrNull() + if (reportType == null) { + reportType = tags.mapNotNull { it.getOrNull(2) }.map { ReportType.valueOf(it.toUpperCase()) }.firstOrNull() + } + if (reportType == null) { + reportType = ReportType.SPAM + } + + reportedPost = tags + .filter { it.firstOrNull() == "e" && it.getOrNull(1) != null } + .map { + ReportedKey( + it[1], + it.getOrNull(2)?.toUpperCase()?.let { it1 -> ReportType.valueOf(it1) }?: reportType + ) + } + + reportedAuthor = tags + .filter { it.firstOrNull() == "p" && it.getOrNull(1) != null } + .map { + ReportedKey( + it[1], + it.getOrNull(2)?.toUpperCase()?.let { it1 -> ReportType.valueOf(it1) }?: reportType + ) + } } companion object { @@ -31,12 +56,11 @@ class ReportEvent ( fun create(reportedPost: Event, type: ReportType, privateKey: ByteArray, createdAt: Long = Date().time / 1000): ReportEvent { val content = "" - val reportTypeTag = listOf("report", type.name.toLowerCase()) - val reportPostTag = listOf("e", reportedPost.id.toHex()) - val reportAuthorTag = listOf("p", reportedPost.pubKey.toHex()) + val reportPostTag = listOf("e", reportedPost.id.toHex(), type.name.toLowerCase()) + val reportAuthorTag = listOf("p", reportedPost.pubKey.toHex(), type.name.toLowerCase()) val pubKey = Utils.pubkeyCreate(privateKey) - val tags:List> = listOf(reportTypeTag, reportPostTag, reportAuthorTag) + val tags:List> = listOf(reportPostTag, reportAuthorTag) val id = generateId(pubKey, createdAt, kind, tags, content) val sig = Utils.sign(id, privateKey) return ReportEvent(id, pubKey, createdAt, tags, content, sig) @@ -45,11 +69,10 @@ class ReportEvent ( fun create(reportedUser: String, type: ReportType, privateKey: ByteArray, createdAt: Long = Date().time / 1000): ReportEvent { val content = "" - val reportTypeTag = listOf("report", type.name.toLowerCase()) - val reportAuthorTag = listOf("p", reportedUser) + val reportAuthorTag = listOf("p", reportedUser, type.name.toLowerCase()) val pubKey = Utils.pubkeyCreate(privateKey) - val tags:List> = listOf(reportTypeTag, reportAuthorTag) + val tags:List> = listOf(reportAuthorTag) val id = generateId(pubKey, createdAt, kind, tags, content) val sig = Utils.sign(id, privateKey) return ReportEvent(id, pubKey, createdAt, tags, content, sig) @@ -57,9 +80,11 @@ class ReportEvent ( } enum class ReportType() { - EXPLICIT, + EXPLICIT, // Not used anymore. ILLEGAL, SPAM, - IMPERSONATION + IMPERSONATION, + NUDITY, + PROFANITY, } } \ No newline at end of file diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index 368c32ea4b..0374060306 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -315,22 +315,24 @@ fun NoteCompose( ) } } else if (noteEvent is ReportEvent) { - val reportType = noteEvent.reportType.map { - when (it) { + val reportType = (noteEvent.reportedPost + noteEvent.reportedAuthor).map { + when (it.reportType) { ReportEvent.ReportType.EXPLICIT -> "Explicit Content" + ReportEvent.ReportType.NUDITY -> "Nudity" + ReportEvent.ReportType.PROFANITY -> "Profanity / Hateful speech" ReportEvent.ReportType.SPAM -> "Spam" ReportEvent.ReportType.IMPERSONATION -> "Impersonation" ReportEvent.ReportType.ILLEGAL -> "Illegal Behavior" else -> "Unknown" } - }.joinToString(", ") + }.toSet().joinToString(", ") Text( text = reportType ) Divider( - modifier = Modifier.padding(top = 10.dp), + modifier = Modifier.padding(top = 40.dp), thickness = 0.25.dp ) } else { @@ -602,6 +604,13 @@ fun NoteDropDownMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Unit, }) { Text("Report Spam / Scam") } + DropdownMenuItem(onClick = { + accountViewModel.report(note, ReportEvent.ReportType.PROFANITY); + note.author?.let { accountViewModel.hide(it, context) } + onDismiss() + }) { + Text("Report Hateful Speech") + } DropdownMenuItem(onClick = { accountViewModel.report(note, ReportEvent.ReportType.IMPERSONATION); note.author?.let { accountViewModel.hide(it, context) } @@ -610,11 +619,11 @@ fun NoteDropDownMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Unit, Text("Report Impersonation") } DropdownMenuItem(onClick = { - accountViewModel.report(note, ReportEvent.ReportType.EXPLICIT); + accountViewModel.report(note, ReportEvent.ReportType.NUDITY); note.author?.let { accountViewModel.hide(it, context) } onDismiss() }) { - Text("Report Explicit Content") + Text("Report Nudity") } DropdownMenuItem(onClick = { accountViewModel.report(note, ReportEvent.ReportType.ILLEGAL); diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt index 1dcda0caaf..31e4720bf2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt @@ -828,6 +828,13 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () -> }) { Text("Report Spam / Scam") } + DropdownMenuItem(onClick = { + accountViewModel.report(user, ReportEvent.ReportType.PROFANITY); + user.let { accountViewModel.hide(it, context) } + onDismiss() + }) { + Text("Report Hateful speech") + } DropdownMenuItem(onClick = { accountViewModel.report(user, ReportEvent.ReportType.IMPERSONATION); user.let { accountViewModel.hide(it, context) } @@ -836,11 +843,11 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () -> Text("Report Impersonation") } DropdownMenuItem(onClick = { - accountViewModel.report(user, ReportEvent.ReportType.EXPLICIT); + accountViewModel.report(user, ReportEvent.ReportType.NUDITY); user.let { accountViewModel.hide(it, context) } onDismiss() }) { - Text("Report Explicit Content") + Text("Report Nudity / Porn") } DropdownMenuItem(onClick = { accountViewModel.report(user, ReportEvent.ReportType.ILLEGAL);