Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add date range and comment filter to queryModerationEvents endpoint #2124

Merged
merged 9 commits into from
Feb 6, 2024
16 changes: 16 additions & 0 deletions lexicons/com/atproto/admin/queryModerationEvents.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,22 @@
"type": "string",
"description": "If specified, only events with comments containing the keyword are returned"
},
"addedLabels": {
"type": "array",
"items": { "type": "string" },
"description": "If specified, only events where one of these labels were added are returned"
},
"removedLabels": {
"type": "array",
"items": { "type": "string" },
"description": "If specified, only events where one of these labels were removed are returned"
},
"reportTypes": {
"type": "array",
"items": {
"type": "string"
}
},
"cursor": { "type": "string" }
}
},
Expand Down
22 changes: 22 additions & 0 deletions packages/api/src/client/lexicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,28 @@ export const schemaDict = {
description:
'If specified, only events with comments containing the keyword are returned',
},
addedLabels: {
type: 'array',
items: {
type: 'string',
},
description:
'If specified, only events where one of these labels were added are returned',
},
removedLabels: {
type: 'array',
items: {
type: 'string',
},
description:
'If specified, only events where one of these labels were removed are returned',
},
reportTypes: {
type: 'array',
items: {
type: 'string',
},
},
cursor: {
type: 'string',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export interface QueryParams {
hasComment?: boolean
/** If specified, only events with comments containing the keyword are returned */
commentKeyword?: string
/** If specified, only events where one of these labels were added are returned */
addedLabels?: string[]
/** If specified, only events where one of these labels were removed are returned */
removedLabels?: string[]
reportTypes?: string[]
cursor?: string
}

Expand Down
22 changes: 22 additions & 0 deletions packages/bsky/src/lexicon/lexicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,28 @@ export const schemaDict = {
description:
'If specified, only events with comments containing the keyword are returned',
},
addedLabels: {
type: 'array',
items: {
type: 'string',
},
description:
'If specified, only events where one of these labels were added are returned',
},
removedLabels: {
type: 'array',
items: {
type: 'string',
},
description:
'If specified, only events where one of these labels were removed are returned',
},
reportTypes: {
type: 'array',
items: {
type: 'string',
},
},
cursor: {
type: 'string',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ export interface QueryParams {
hasComment?: boolean
/** If specified, only events with comments containing the keyword are returned */
commentKeyword?: string
/** If specified, only events where one of these labels were added are returned */
addedLabels?: string[]
/** If specified, only events where one of these labels were removed are returned */
removedLabels?: string[]
reportTypes?: string[]
cursor?: string
}

Expand Down
6 changes: 6 additions & 0 deletions packages/ozone/src/api/admin/queryModerationEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export default function (server: Server, ctx: AppContext) {
createdBy,
createdAfter,
createdBefore,
addedLabels = [],
removedLabels = [],
reportTypes,
} = params
const db = ctx.db
const modService = ctx.modService(db)
Expand All @@ -33,6 +36,9 @@ export default function (server: Server, ctx: AppContext) {
commentKeyword,
createdAfter,
createdBefore,
addedLabels,
removedLabels,
reportTypes,
})
return {
encoding: 'application/json',
Expand Down
22 changes: 22 additions & 0 deletions packages/ozone/src/lexicon/lexicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,28 @@ export const schemaDict = {
description:
'If specified, only events with comments containing the keyword are returned',
},
addedLabels: {
type: 'array',
items: {
type: 'string',
},
description:
'If specified, only events where one of these labels were added are returned',
},
removedLabels: {
type: 'array',
items: {
type: 'string',
},
description:
'If specified, only events where one of these labels were removed are returned',
},
reportTypes: {
type: 'array',
items: {
type: 'string',
},
},
cursor: {
type: 'string',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ export interface QueryParams {
hasComment?: boolean
/** If specified, only events with comments containing the keyword are returned */
commentKeyword?: string
/** If specified, only events where one of these labels were added are returned */
addedLabels?: string[]
/** If specified, only events where one of these labels were removed are returned */
removedLabels?: string[]
reportTypes?: string[]
cursor?: string
}

Expand Down
25 changes: 25 additions & 0 deletions packages/ozone/src/mod-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ export class ModerationService {
commentKeyword?: string
createdAfter?: string
createdBefore?: string
addedLabels: string[]
removedLabels: string[]
reportTypes?: string[]
}): Promise<{ cursor?: string; events: ModerationEventRow[] }> {
const {
subject,
Expand All @@ -113,6 +116,9 @@ export class ModerationService {
commentKeyword,
createdAfter,
createdBefore,
addedLabels,
removedLabels,
reportTypes,
} = opts
let builder = this.db.db.selectFrom('moderation_event').selectAll()
if (subject) {
Expand Down Expand Up @@ -162,6 +168,25 @@ export class ModerationService {
})
}

// If multiple labels are passed, then only retrieve events where all those labels exist
foysalit marked this conversation as resolved.
Show resolved Hide resolved
if (addedLabels.length) {
builder = builder.where(
'createLabelVals',
'ilike',
`%${addedLabels.join('%')}%`,
)
}
foysalit marked this conversation as resolved.
Show resolved Hide resolved
if (removedLabels.length) {
builder = builder.where(
'negateLabelVals',
'ilike',
`%${removedLabels.join('%')}%`,
)
}
if (reportTypes?.length) {
builder = builder.where(sql`meta->>'reportType'`, 'in', reportTypes)
}

const { ref } = this.db.db.dynamic
const keyset = new TimeIdKeyset(
ref(`moderation_event.createdAt`),
Expand Down
75 changes: 75 additions & 0 deletions packages/ozone/tests/moderation-events.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { TestNetwork, SeedClient, basicSeed } from '@atproto/dev-env'
import AtpAgent, { ComAtprotoAdminDefs } from '@atproto/api'
import { forSnapshot } from './_util'
import {
REASONAPPEAL,
REASONMISLEADING,
REASONSPAM,
} from '../src/lexicon/types/com/atproto/moderation/defs'
Expand Down Expand Up @@ -201,6 +202,80 @@ describe('moderation-events', () => {
expect(reversedEvents.length).toEqual(allEvents.data.events.length)
expect(reversedEvents[0].id).toEqual(defaultEvents[4].id)
})

it('returns report events matching reportType filters', async () => {
const [spamEvents, misleadingEvents] = await Promise.all([
queryModerationEvents({
reportTypes: [REASONSPAM],
}),
queryModerationEvents({
reportTypes: [REASONMISLEADING, REASONAPPEAL],
}),
])

expect(misleadingEvents.data.events.length).toEqual(2)
expect(spamEvents.data.events.length).toEqual(6)
})

it('returns events matching filter params for columns', async () => {
const [negatedLabelEvent, createdLabelEvent] = await Promise.all([
emitModerationEvent({
event: {
$type: 'com.atproto.admin.defs#modEventLabel',
comment: 'X',
negateLabelVals: ['L1', 'L2'],
createLabelVals: [],
},
// Report bob's account by alice and vice versa
subject: {
$type: 'com.atproto.admin.defs#repoRef',
did: sc.dids.alice,
},
createdBy: sc.dids.bob,
}),
emitModerationEvent({
event: {
$type: 'com.atproto.admin.defs#modEventLabel',
comment: 'X',
createLabelVals: ['L1', 'L2'],
negateLabelVals: [],
},
// Report bob's account by alice and vice versa
subject: {
$type: 'com.atproto.admin.defs#repoRef',
did: sc.dids.bob,
},
createdBy: sc.dids.alice,
}),
])
const [withTwoLabels, withoutTwoLabels, withOneLabel, withoutOneLabel] =
await Promise.all([
queryModerationEvents({
addedLabels: ['L1', 'L3'],
}),
queryModerationEvents({
removedLabels: ['L1', 'L2'],
}),
queryModerationEvents({
addedLabels: ['L1'],
}),
queryModerationEvents({
removedLabels: ['L2'],
}),
])

// Verify that when querying for events where 2 different labels were added
// events where all of the labels from the list was added are returned
expect(withTwoLabels.data.events.length).toEqual(0)
expect(negatedLabelEvent.data.id).toEqual(
withoutTwoLabels.data.events[0].id,
)

expect(createdLabelEvent.data.id).toEqual(withOneLabel.data.events[0].id)
expect(negatedLabelEvent.data.id).toEqual(
withoutOneLabel.data.events[0].id,
)
})
})

describe('get event', () => {
Expand Down
22 changes: 22 additions & 0 deletions packages/pds/src/lexicon/lexicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,28 @@ export const schemaDict = {
description:
'If specified, only events with comments containing the keyword are returned',
},
addedLabels: {
type: 'array',
items: {
type: 'string',
},
description:
'If specified, only events where one of these labels were added are returned',
},
removedLabels: {
type: 'array',
items: {
type: 'string',
},
description:
'If specified, only events where one of these labels were removed are returned',
},
reportTypes: {
type: 'array',
items: {
type: 'string',
},
},
cursor: {
type: 'string',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ export interface QueryParams {
hasComment?: boolean
/** If specified, only events with comments containing the keyword are returned */
commentKeyword?: string
/** If specified, only events where one of these labels were added are returned */
addedLabels?: string[]
/** If specified, only events where one of these labels were removed are returned */
removedLabels?: string[]
reportTypes?: string[]
cursor?: string
}

Expand Down
Loading