Skip to content

Commit

Permalink
✨ Allow muting reporter (#2390)
Browse files Browse the repository at this point in the history
* ✨ Allow muting reporter

* ✨ Allow fetching ONLY muted subjects

* 🚨 re-run linter on fixed main

* ✨ Track muted reports

* ✅ Adjust snapshot

* ✅ Adjust snapshot

* ✅ Adjust snapshot

* 📝 Add changesets

* ♻️ Refactor muted reporter check

* ✨ Use new event type for muting/unmuting reporter

* 🧹 Cleanup
  • Loading branch information
foysalit committed Apr 25, 2024
1 parent b9e205a commit 58551bb
Show file tree
Hide file tree
Showing 30 changed files with 582 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .changeset/eleven-timers-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@atproto/ozone": patch
"@atproto/api": patch
"@atproto/pds": patch
---

Allow muting reports from accounts via `#modEventMuteReporter` event
36 changes: 36 additions & 0 deletions lexicons/tools/ozone/moderation/defs.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
"#modEventAcknowledge",
"#modEventEscalate",
"#modEventMute",
"#modEventUnmute",
"#modEventMuteReporter",
"#modEventUnmuteReporter",
"#modEventEmail",
"#modEventResolveAppeal",
"#modEventDivert"
Expand Down Expand Up @@ -67,6 +70,9 @@
"#modEventAcknowledge",
"#modEventEscalate",
"#modEventMute",
"#modEventUnmute",
"#modEventMuteReporter",
"#modEventUnmuteReporter",
"#modEventEmail",
"#modEventResolveAppeal",
"#modEventDivert"
Expand Down Expand Up @@ -128,6 +134,10 @@
"type": "string",
"format": "datetime"
},
"muteReportingUntil": {
"type": "string",
"format": "datetime"
},
"lastReviewedBy": {
"type": "string",
"format": "did"
Expand Down Expand Up @@ -242,6 +252,10 @@
"comment": {
"type": "string"
},
"isReporterMuted": {
"type": "boolean",
"description": "Set to true if the reporter was muted from reporting at the time of the event. These reports won't impact the reviewState of the subject."
},
"reportType": {
"type": "ref",
"ref": "com.atproto.moderation.defs#reasonType"
Expand Down Expand Up @@ -300,6 +314,28 @@
}
}
},
"modEventMuteReporter": {
"type": "object",
"description": "Mute incoming reports from an account",
"required": ["durationInHours"],
"properties": {
"comment": { "type": "string" },
"durationInHours": {
"type": "integer",
"description": "Indicates how long the account should remain muted."
}
}
},
"modEventUnmuteReporter": {
"type": "object",
"description": "Unmute incoming reports from an account",
"properties": {
"comment": {
"type": "string",
"description": "Describe reasoning behind the reversal."
}
}
},
"modEventEmail": {
"type": "object",
"description": "Keep a log of outgoing email to a user",
Expand Down
3 changes: 3 additions & 0 deletions lexicons/tools/ozone/moderation/emitEvent.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
"tools.ozone.moderation.defs#modEventLabel",
"tools.ozone.moderation.defs#modEventReport",
"tools.ozone.moderation.defs#modEventMute",
"tools.ozone.moderation.defs#modEventUnmute",
"tools.ozone.moderation.defs#modEventMuteReporter",
"tools.ozone.moderation.defs#modEventUnmuteReporter",
"tools.ozone.moderation.defs#modEventReverseTakedown",
"tools.ozone.moderation.defs#modEventUnmute",
"tools.ozone.moderation.defs#modEventEmail",
Expand Down
4 changes: 4 additions & 0 deletions lexicons/tools/ozone/moderation/queryStatuses.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
"type": "boolean",
"description": "By default, we don't include muted subjects in the results. Set this to true to include them."
},
"onlyMuted": {
"type": "boolean",
"description": "When set to true, only muted subjects and reporters will be returned."
},
"reviewState": {
"type": "string",
"description": "Specify when fetching subjects in a certain state"
Expand Down
47 changes: 47 additions & 0 deletions packages/api/src/client/lexicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8408,6 +8408,9 @@ export const schemaDict = {
'lex:tools.ozone.moderation.defs#modEventAcknowledge',
'lex:tools.ozone.moderation.defs#modEventEscalate',
'lex:tools.ozone.moderation.defs#modEventMute',
'lex:tools.ozone.moderation.defs#modEventUnmute',
'lex:tools.ozone.moderation.defs#modEventMuteReporter',
'lex:tools.ozone.moderation.defs#modEventUnmuteReporter',
'lex:tools.ozone.moderation.defs#modEventEmail',
'lex:tools.ozone.moderation.defs#modEventResolveAppeal',
'lex:tools.ozone.moderation.defs#modEventDivert',
Expand Down Expand Up @@ -8467,6 +8470,9 @@ export const schemaDict = {
'lex:tools.ozone.moderation.defs#modEventAcknowledge',
'lex:tools.ozone.moderation.defs#modEventEscalate',
'lex:tools.ozone.moderation.defs#modEventMute',
'lex:tools.ozone.moderation.defs#modEventUnmute',
'lex:tools.ozone.moderation.defs#modEventMuteReporter',
'lex:tools.ozone.moderation.defs#modEventUnmuteReporter',
'lex:tools.ozone.moderation.defs#modEventEmail',
'lex:tools.ozone.moderation.defs#modEventResolveAppeal',
'lex:tools.ozone.moderation.defs#modEventDivert',
Expand Down Expand Up @@ -8546,6 +8552,10 @@ export const schemaDict = {
type: 'string',
format: 'datetime',
},
muteReportingUntil: {
type: 'string',
format: 'datetime',
},
lastReviewedBy: {
type: 'string',
format: 'did',
Expand Down Expand Up @@ -8669,6 +8679,11 @@ export const schemaDict = {
comment: {
type: 'string',
},
isReporterMuted: {
type: 'boolean',
description:
"Set to true if the reporter was muted from reporting at the time of the event. These reports won't impact the reviewState of the subject.",
},
reportType: {
type: 'ref',
ref: 'lex:com.atproto.moderation.defs#reasonType',
Expand Down Expand Up @@ -8737,6 +8752,30 @@ export const schemaDict = {
},
},
},
modEventMuteReporter: {
type: 'object',
description: 'Mute incoming reports from an account',
required: ['durationInHours'],
properties: {
comment: {
type: 'string',
},
durationInHours: {
type: 'integer',
description: 'Indicates how long the account should remain muted.',
},
},
},
modEventUnmuteReporter: {
type: 'object',
description: 'Unmute incoming reports from an account',
properties: {
comment: {
type: 'string',
description: 'Describe reasoning behind the reversal.',
},
},
},
modEventEmail: {
type: 'object',
description: 'Keep a log of outgoing email to a user',
Expand Down Expand Up @@ -9121,6 +9160,9 @@ export const schemaDict = {
'lex:tools.ozone.moderation.defs#modEventLabel',
'lex:tools.ozone.moderation.defs#modEventReport',
'lex:tools.ozone.moderation.defs#modEventMute',
'lex:tools.ozone.moderation.defs#modEventUnmute',
'lex:tools.ozone.moderation.defs#modEventMuteReporter',
'lex:tools.ozone.moderation.defs#modEventUnmuteReporter',
'lex:tools.ozone.moderation.defs#modEventReverseTakedown',
'lex:tools.ozone.moderation.defs#modEventUnmute',
'lex:tools.ozone.moderation.defs#modEventEmail',
Expand Down Expand Up @@ -9429,6 +9471,11 @@ export const schemaDict = {
description:
"By default, we don't include muted subjects in the results. Set this to true to include them.",
},
onlyMuted: {
type: 'boolean',
description:
'When set to true, only muted subjects and reporters will be returned.',
},
reviewState: {
type: 'string',
description: 'Specify when fetching subjects in a certain state',
Expand Down
56 changes: 56 additions & 0 deletions packages/api/src/client/types/tools/ozone/moderation/defs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export interface ModEventView {
| ModEventAcknowledge
| ModEventEscalate
| ModEventMute
| ModEventUnmute
| ModEventMuteReporter
| ModEventUnmuteReporter
| ModEventEmail
| ModEventResolveAppeal
| ModEventDivert
Expand Down Expand Up @@ -61,6 +64,9 @@ export interface ModEventViewDetail {
| ModEventAcknowledge
| ModEventEscalate
| ModEventMute
| ModEventUnmute
| ModEventMuteReporter
| ModEventUnmuteReporter
| ModEventEmail
| ModEventResolveAppeal
| ModEventDivert
Expand Down Expand Up @@ -105,6 +111,7 @@ export interface SubjectStatusView {
/** Sticky comment on the subject. */
comment?: string
muteUntil?: string
muteReportingUntil?: string
lastReviewedBy?: string
lastReviewedAt?: string
lastReportedAt?: string
Expand Down Expand Up @@ -237,6 +244,8 @@ export function validateModEventComment(v: unknown): ValidationResult {
/** Report a subject */
export interface ModEventReport {
comment?: string
/** Set to true if the reporter was muted from reporting at the time of the event. These reports won't impact the reviewState of the subject. */
isReporterMuted?: boolean
reportType: ComAtprotoModerationDefs.ReasonType
[k: string]: unknown
}
Expand Down Expand Up @@ -346,6 +355,53 @@ export function validateModEventUnmute(v: unknown): ValidationResult {
return lexicons.validate('tools.ozone.moderation.defs#modEventUnmute', v)
}

/** Mute incoming reports from an account */
export interface ModEventMuteReporter {
comment?: string
/** Indicates how long the account should remain muted. */
durationInHours: number
[k: string]: unknown
}

export function isModEventMuteReporter(v: unknown): v is ModEventMuteReporter {
return (
isObj(v) &&
hasProp(v, '$type') &&
v.$type === 'tools.ozone.moderation.defs#modEventMuteReporter'
)
}

export function validateModEventMuteReporter(v: unknown): ValidationResult {
return lexicons.validate(
'tools.ozone.moderation.defs#modEventMuteReporter',
v,
)
}

/** Unmute incoming reports from an account */
export interface ModEventUnmuteReporter {
/** Describe reasoning behind the reversal. */
comment?: string
[k: string]: unknown
}

export function isModEventUnmuteReporter(
v: unknown,
): v is ModEventUnmuteReporter {
return (
isObj(v) &&
hasProp(v, '$type') &&
v.$type === 'tools.ozone.moderation.defs#modEventUnmuteReporter'
)
}

export function validateModEventUnmuteReporter(v: unknown): ValidationResult {
return lexicons.validate(
'tools.ozone.moderation.defs#modEventUnmuteReporter',
v,
)
}

/** Keep a log of outgoing email to a user */
export interface ModEventEmail {
/** The subject line of the email sent to the user. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export interface InputSchema {
| ToolsOzoneModerationDefs.ModEventLabel
| ToolsOzoneModerationDefs.ModEventReport
| ToolsOzoneModerationDefs.ModEventMute
| ToolsOzoneModerationDefs.ModEventUnmute
| ToolsOzoneModerationDefs.ModEventMuteReporter
| ToolsOzoneModerationDefs.ModEventUnmuteReporter
| ToolsOzoneModerationDefs.ModEventReverseTakedown
| ToolsOzoneModerationDefs.ModEventUnmute
| ToolsOzoneModerationDefs.ModEventEmail
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface QueryParams {
reviewedBefore?: string
/** By default, we don't include muted subjects in the results. Set this to true to include them. */
includeMuted?: boolean
/** When set to true, only muted subjects and reporters will be returned. */
onlyMuted?: boolean
/** Specify when fetching subjects in a certain state */
reviewState?: string
ignoreSubjects?: string[]
Expand Down
9 changes: 9 additions & 0 deletions packages/ozone/src/api/moderation/emitEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import {
isModEventDivert,
isModEventEmail,
isModEventLabel,
isModEventMuteReporter,
isModEventReverseTakedown,
isModEventTakedown,
isModEventUnmuteReporter,
} from '../../lexicon/types/tools/ozone/moderation/defs'
import { HandlerInput } from '../../lexicon/types/tools/ozone/moderation/emitEvent'
import { subjectFromInput } from '../../mod-service/subject'
Expand Down Expand Up @@ -113,6 +115,13 @@ const handleModerationEvent = async ({
await ctx.blobDiverter.uploadBlobOnService(subject.info())
}

if (
(isModEventMuteReporter(event) || isModEventUnmuteReporter(event)) &&
!subject.isRepo()
) {
throw new InvalidRequestError('Subject must be a repo when muting reporter')
}

const moderationEvent = await db.transaction(async (dbTxn) => {
const moderationTxn = ctx.modService(dbTxn)

Expand Down
2 changes: 2 additions & 0 deletions packages/ozone/src/api/moderation/queryStatuses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function (server: Server, ctx: AppContext) {
sortDirection = 'desc',
sortField = 'lastReportedAt',
includeMuted = false,
onlyMuted = false,
limit = 50,
cursor,
tags = [],
Expand All @@ -37,6 +38,7 @@ export default function (server: Server, ctx: AppContext) {
reportedAfter,
reportedBefore,
includeMuted,
onlyMuted,
ignoreSubjects,
sortDirection,
lastReviewedBy,
Expand Down
2 changes: 2 additions & 0 deletions packages/ozone/src/api/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ const eventTypes = new Set([
'tools.ozone.moderation.defs#modEventReport',
'tools.ozone.moderation.defs#modEventMute',
'tools.ozone.moderation.defs#modEventUnmute',
'tools.ozone.moderation.defs#modEventMuteReporter',
'tools.ozone.moderation.defs#modEventUnmuteReporter',
'tools.ozone.moderation.defs#modEventReverseTakedown',
'tools.ozone.moderation.defs#modEventEmail',
'tools.ozone.moderation.defs#modEventResolveAppeal',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Kysely } from 'kysely'

export async function up(db: Kysely<unknown>): Promise<void> {
await db.schema
.alterTable('moderation_subject_status')
.addColumn('muteReportingUntil', 'varchar')
.execute()
}

export async function down(db: Kysely<unknown>): Promise<void> {
await db.schema
.alterTable('moderation_subject_status')
.dropColumn('muteReportingUntil')
.execute()
}
1 change: 1 addition & 0 deletions packages/ozone/src/db/migrations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * as _20240116T085607200Z from './20240116T085607200Z-communication-templ
export * as _20240201T051104136Z from './20240201T051104136Z-mod-event-blobs'
export * as _20240208T213404429Z from './20240208T213404429Z-add-tags-column-to-moderation-subject'
export * as _20240228T003647759Z from './20240228T003647759Z-add-label-sigs'
export * as _20240408T192432676Z from './20240408T192432676Z-mute-reporting'
3 changes: 3 additions & 0 deletions packages/ozone/src/db/schema/moderation_event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export interface ModerationEvent {
| 'tools.ozone.moderation.defs#modEventLabel'
| 'tools.ozone.moderation.defs#modEventReport'
| 'tools.ozone.moderation.defs#modEventMute'
| 'tools.ozone.moderation.defs#modEventUnmute'
| 'tools.ozone.moderation.defs#modEventMuteReporter'
| 'tools.ozone.moderation.defs#modEventUnmuteReporter'
| 'tools.ozone.moderation.defs#modEventReverseTakedown'
| 'tools.ozone.moderation.defs#modEventEmail'
| 'tools.ozone.moderation.defs#modEventResolveAppeal'
Expand Down
1 change: 1 addition & 0 deletions packages/ozone/src/db/schema/moderation_subject_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface ModerationSubjectStatus {
lastReportedAt: string | null
lastAppealedAt: string | null
muteUntil: string | null
muteReportingUntil: string | null
suspendUntil: string | null
takendown: boolean
appealed: boolean | null
Expand Down

0 comments on commit 58551bb

Please sign in to comment.