Updating reports to the latest spec

This commit is contained in:
Vitor Pamplona
2023-02-28 15:24:23 -05:00
parent 3780ed001a
commit b09577f816
5 changed files with 67 additions and 26 deletions
@@ -408,8 +408,8 @@ object LocalCache {
// Already processed this event. // Already processed this event.
if (note.event != null) return if (note.event != null) return
val mentions = event.reportedAuthor.mapNotNull { checkGetOrCreateUser(it) } val mentions = event.reportedAuthor.mapNotNull { checkGetOrCreateUser(it.key) }
val repliesTo = event.reportedPost.mapNotNull { checkGetOrCreateNote(it) } val repliesTo = event.reportedPost.mapNotNull { checkGetOrCreateNote(it.key) }
note.loadEvent(event, author, mentions, repliesTo) note.loadEvent(event, author, mentions, repliesTo)
@@ -289,7 +289,7 @@ class User(val pubkeyHex: String) {
fun hasReport(loggedIn: User, type: ReportEvent.ReportType): Boolean { fun hasReport(loggedIn: User, type: ReportEvent.ReportType): Boolean {
return reports[loggedIn]?.firstOrNull() { 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 } != null
} }
@@ -5,6 +5,8 @@ import nostr.postr.Utils
import nostr.postr.events.Event import nostr.postr.events.Event
import nostr.postr.toHex import nostr.postr.toHex
data class ReportedKey(val key: String, val reportType: ReportEvent.ReportType)
// NIP 56 event. // NIP 56 event.
class ReportEvent ( class ReportEvent (
id: ByteArray, id: ByteArray,
@@ -15,14 +17,37 @@ class ReportEvent (
sig: ByteArray sig: ByteArray
): Event(id, pubKey, createdAt, kind, tags, content, sig) { ): Event(id, pubKey, createdAt, kind, tags, content, sig) {
@Transient val reportType: List<ReportType> @Transient val reportedPost: List<ReportedKey>
@Transient val reportedPost: List<String> @Transient val reportedAuthor: List<ReportedKey>
@Transient val reportedAuthor: List<String>
init { init {
reportType = tags.filter { it.firstOrNull() == "report" }.mapNotNull { it.getOrNull(1) }.map { ReportType.valueOf(it.toUpperCase()) } // Works with old and new structures for report.
reportedPost = tags.filter { it.firstOrNull() == "e" }.mapNotNull { it.getOrNull(1) }
reportedAuthor = tags.filter { it.firstOrNull() == "p" }.mapNotNull { it.getOrNull(1) } 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 { companion object {
@@ -31,12 +56,11 @@ class ReportEvent (
fun create(reportedPost: Event, type: ReportType, privateKey: ByteArray, createdAt: Long = Date().time / 1000): ReportEvent { fun create(reportedPost: Event, type: ReportType, privateKey: ByteArray, createdAt: Long = Date().time / 1000): ReportEvent {
val content = "" val content = ""
val reportTypeTag = listOf("report", type.name.toLowerCase()) val reportPostTag = listOf("e", reportedPost.id.toHex(), type.name.toLowerCase())
val reportPostTag = listOf("e", reportedPost.id.toHex()) val reportAuthorTag = listOf("p", reportedPost.pubKey.toHex(), type.name.toLowerCase())
val reportAuthorTag = listOf("p", reportedPost.pubKey.toHex())
val pubKey = Utils.pubkeyCreate(privateKey) val pubKey = Utils.pubkeyCreate(privateKey)
val tags:List<List<String>> = listOf(reportTypeTag, reportPostTag, reportAuthorTag) val tags:List<List<String>> = listOf(reportPostTag, reportAuthorTag)
val id = generateId(pubKey, createdAt, kind, tags, content) val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = Utils.sign(id, privateKey) val sig = Utils.sign(id, privateKey)
return ReportEvent(id, pubKey, createdAt, tags, content, sig) 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 { fun create(reportedUser: String, type: ReportType, privateKey: ByteArray, createdAt: Long = Date().time / 1000): ReportEvent {
val content = "" val content = ""
val reportTypeTag = listOf("report", type.name.toLowerCase()) val reportAuthorTag = listOf("p", reportedUser, type.name.toLowerCase())
val reportAuthorTag = listOf("p", reportedUser)
val pubKey = Utils.pubkeyCreate(privateKey) val pubKey = Utils.pubkeyCreate(privateKey)
val tags:List<List<String>> = listOf(reportTypeTag, 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 = Utils.sign(id, privateKey) val sig = Utils.sign(id, privateKey)
return ReportEvent(id, pubKey, createdAt, tags, content, sig) return ReportEvent(id, pubKey, createdAt, tags, content, sig)
@@ -57,9 +80,11 @@ class ReportEvent (
} }
enum class ReportType() { enum class ReportType() {
EXPLICIT, EXPLICIT, // Not used anymore.
ILLEGAL, ILLEGAL,
SPAM, SPAM,
IMPERSONATION IMPERSONATION,
NUDITY,
PROFANITY,
} }
} }
@@ -315,22 +315,24 @@ fun NoteCompose(
) )
} }
} else if (noteEvent is ReportEvent) { } else if (noteEvent is ReportEvent) {
val reportType = noteEvent.reportType.map { val reportType = (noteEvent.reportedPost + noteEvent.reportedAuthor).map {
when (it) { when (it.reportType) {
ReportEvent.ReportType.EXPLICIT -> "Explicit Content" ReportEvent.ReportType.EXPLICIT -> "Explicit Content"
ReportEvent.ReportType.NUDITY -> "Nudity"
ReportEvent.ReportType.PROFANITY -> "Profanity / Hateful speech"
ReportEvent.ReportType.SPAM -> "Spam" ReportEvent.ReportType.SPAM -> "Spam"
ReportEvent.ReportType.IMPERSONATION -> "Impersonation" ReportEvent.ReportType.IMPERSONATION -> "Impersonation"
ReportEvent.ReportType.ILLEGAL -> "Illegal Behavior" ReportEvent.ReportType.ILLEGAL -> "Illegal Behavior"
else -> "Unknown" else -> "Unknown"
} }
}.joinToString(", ") }.toSet().joinToString(", ")
Text( Text(
text = reportType text = reportType
) )
Divider( Divider(
modifier = Modifier.padding(top = 10.dp), modifier = Modifier.padding(top = 40.dp),
thickness = 0.25.dp thickness = 0.25.dp
) )
} else { } else {
@@ -602,6 +604,13 @@ fun NoteDropDownMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Unit,
}) { }) {
Text("Report Spam / Scam") 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 = { DropdownMenuItem(onClick = {
accountViewModel.report(note, ReportEvent.ReportType.IMPERSONATION); accountViewModel.report(note, ReportEvent.ReportType.IMPERSONATION);
note.author?.let { accountViewModel.hide(it, context) } note.author?.let { accountViewModel.hide(it, context) }
@@ -610,11 +619,11 @@ fun NoteDropDownMenu(note: Note, popupExpanded: Boolean, onDismiss: () -> Unit,
Text("Report Impersonation") Text("Report Impersonation")
} }
DropdownMenuItem(onClick = { DropdownMenuItem(onClick = {
accountViewModel.report(note, ReportEvent.ReportType.EXPLICIT); accountViewModel.report(note, ReportEvent.ReportType.NUDITY);
note.author?.let { accountViewModel.hide(it, context) } note.author?.let { accountViewModel.hide(it, context) }
onDismiss() onDismiss()
}) { }) {
Text("Report Explicit Content") Text("Report Nudity")
} }
DropdownMenuItem(onClick = { DropdownMenuItem(onClick = {
accountViewModel.report(note, ReportEvent.ReportType.ILLEGAL); accountViewModel.report(note, ReportEvent.ReportType.ILLEGAL);
@@ -828,6 +828,13 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
}) { }) {
Text("Report Spam / Scam") 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 = { DropdownMenuItem(onClick = {
accountViewModel.report(user, ReportEvent.ReportType.IMPERSONATION); accountViewModel.report(user, ReportEvent.ReportType.IMPERSONATION);
user.let { accountViewModel.hide(it, context) } user.let { accountViewModel.hide(it, context) }
@@ -836,11 +843,11 @@ fun UserProfileDropDownMenu(user: User, popupExpanded: Boolean, onDismiss: () ->
Text("Report Impersonation") Text("Report Impersonation")
} }
DropdownMenuItem(onClick = { DropdownMenuItem(onClick = {
accountViewModel.report(user, ReportEvent.ReportType.EXPLICIT); accountViewModel.report(user, ReportEvent.ReportType.NUDITY);
user.let { accountViewModel.hide(it, context) } user.let { accountViewModel.hide(it, context) }
onDismiss() onDismiss()
}) { }) {
Text("Report Explicit Content") Text("Report Nudity / Porn")
} }
DropdownMenuItem(onClick = { DropdownMenuItem(onClick = {
accountViewModel.report(user, ReportEvent.ReportType.ILLEGAL); accountViewModel.report(user, ReportEvent.ReportType.ILLEGAL);