* ✨ Add reporter_stats materialized view and endpoint to fetch reporter stats * 🚨 Fix linter issues * ✨ Change reporter stats query from materialized view to on demand select * Add "createdAt" as part of the index --------- Co-authored-by: Matthieu Sieben <matthieu.sieben@gmail.com> Co-authored-by: Matthieu Sieben <matthieusieben@users.noreply.github.com>
118 lines
3.1 KiB
TypeScript
118 lines
3.1 KiB
TypeScript
import {
|
|
ComAtprotoModerationDefs,
|
|
ToolsOzoneModerationDefs,
|
|
} from '@atproto/api'
|
|
import {
|
|
ModeratorClient,
|
|
SeedClient,
|
|
TestNetwork,
|
|
basicSeed,
|
|
} from '@atproto/dev-env'
|
|
|
|
describe('reporter-stats', () => {
|
|
let network: TestNetwork
|
|
let sc: SeedClient
|
|
let modClient: ModeratorClient
|
|
|
|
beforeAll(async () => {
|
|
network = await TestNetwork.create({
|
|
dbPostgresSchema: 'ozone_reporter_stats',
|
|
ozone: {
|
|
dbMaterializedViewRefreshIntervalMs: 1000,
|
|
},
|
|
})
|
|
sc = network.getSeedClient()
|
|
modClient = network.ozone.getModClient()
|
|
await basicSeed(sc)
|
|
await network.processAll()
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await network.close()
|
|
})
|
|
|
|
const getReporterStats = async (
|
|
did: string,
|
|
): Promise<ToolsOzoneModerationDefs.ReporterStats | undefined> => {
|
|
const { stats } = await modClient.getReporterStats([did])
|
|
return stats[0]
|
|
}
|
|
|
|
it('updates reporter stats based on actions', async () => {
|
|
const bobsPostSubject = {
|
|
$type: 'com.atproto.repo.strongRef',
|
|
uri: sc.posts[sc.dids.bob][1].ref.uriStr,
|
|
cid: sc.posts[sc.dids.bob][1].ref.cidStr,
|
|
}
|
|
const carolsAccountSubject = {
|
|
$type: 'com.atproto.admin.defs#repoRef',
|
|
did: sc.dids.carol,
|
|
}
|
|
|
|
await Promise.all([
|
|
sc.createReport({
|
|
reportedBy: sc.dids.alice,
|
|
reasonType: ComAtprotoModerationDefs.REASONMISLEADING,
|
|
reason: 'misleading',
|
|
subject: bobsPostSubject,
|
|
}),
|
|
sc.createReport({
|
|
reportedBy: sc.dids.alice,
|
|
reasonType: ComAtprotoModerationDefs.REASONOTHER,
|
|
reason: 'test',
|
|
subject: bobsPostSubject,
|
|
}),
|
|
sc.createReport({
|
|
reportedBy: sc.dids.alice,
|
|
reasonType: ComAtprotoModerationDefs.REASONMISLEADING,
|
|
reason: 'misleading',
|
|
subject: carolsAccountSubject,
|
|
}),
|
|
])
|
|
|
|
await network.processAll()
|
|
const statsAfterReport = await getReporterStats(sc.dids.alice)
|
|
expect(statsAfterReport).toMatchObject({
|
|
did: sc.dids.alice,
|
|
accountReportCount: 1,
|
|
recordReportCount: 2,
|
|
reportedAccountCount: 1,
|
|
reportedRecordCount: 1,
|
|
takendownAccountCount: 0,
|
|
takendownRecordCount: 0,
|
|
labeledAccountCount: 0,
|
|
labeledRecordCount: 0,
|
|
})
|
|
|
|
await Promise.all([
|
|
modClient.performTakedown({
|
|
subject: bobsPostSubject,
|
|
policies: ['trolling'],
|
|
}),
|
|
modClient.emitEvent({
|
|
subject: carolsAccountSubject,
|
|
event: {
|
|
$type: 'tools.ozone.moderation.defs#modEventLabel',
|
|
createLabelVals: ['spam'],
|
|
negateLabelVals: [],
|
|
},
|
|
}),
|
|
])
|
|
|
|
await network.processAll()
|
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
const statsAfterAction = await getReporterStats(sc.dids.alice)
|
|
expect(statsAfterAction).toMatchObject({
|
|
did: sc.dids.alice,
|
|
accountReportCount: 1,
|
|
recordReportCount: 2,
|
|
reportedAccountCount: 1,
|
|
reportedRecordCount: 1,
|
|
takendownAccountCount: 0,
|
|
takendownRecordCount: 1,
|
|
labeledAccountCount: 1,
|
|
labeledRecordCount: 0,
|
|
})
|
|
})
|
|
})
|