Skip to content

Commit

Permalink
✨ Create a mod event when automod applies labels to a record (#1927)
Browse files Browse the repository at this point in the history
  • Loading branch information
foysalit authored Dec 20, 2023
1 parent aadd35e commit f365dc5
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
19 changes: 19 additions & 0 deletions packages/bsky/src/auto-moderator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,25 @@ export class AutoModerator {

async storeLabels(uri: AtUri, cid: CID, labels: string[]): Promise<void> {
if (labels.length < 1) return

// Given that moderation service is available, log the labeling event for historical purposes
if (this.services.moderation) {
await this.ctx.db.transaction(async (dbTxn) => {
if (!this.services.moderation) return
const modSrvc = this.services.moderation(dbTxn)
await modSrvc.logEvent({
event: {
$type: 'com.atproto.admin.defs#modEventLabel',
createLabelVals: labels,
negateLabelVals: [],
comment: '[AutoModerator]: Applying labels',
},
subject: { uri, cid },
createdBy: this.ctx.cfg.labelerDid,
})
})
}

const labelSrvc = this.services.label(this.ctx.db)
await labelSrvc.formatAndCreate(
this.ctx.cfg.labelerDid,
Expand Down
39 changes: 39 additions & 0 deletions packages/bsky/tests/auto-moderator/labeler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { LabelService } from '../../src/services/label'
import usersSeed from '../seeds/users'
import { CID } from 'multiformats/cid'
import { ImgLabeler } from '../../src/auto-moderator/hive'
import { ModerationService } from '../../src/services/moderation'
import { ImageInvalidator } from '../../src/image/invalidator'

// outside of test suite so that TestLabeler can access them
let badCid1: CID | undefined = undefined
Expand Down Expand Up @@ -75,6 +77,10 @@ describe('labeler', () => {
})

it('labels text in posts', async () => {
autoMod.services.moderation = ModerationService.creator(
new NoopImageUriBuilder(''),
new NoopInvalidator(),
)
const post = {
$type: 'app.bsky.feed.post',
text: 'blah blah label_me',
Expand All @@ -93,6 +99,28 @@ describe('labeler', () => {
val: 'test-label',
neg: false,
})

// Verify that along with applying the labels, we are also leaving trace of the label as moderation event
// Temporarily assign an instance of moderation service to the autoMod so that we can validate label event
const modSrvc = autoMod.services.moderation(ctx.db)
const { events } = await modSrvc.getEvents({
includeAllUserRecords: false,
subject: uri.toString(),
limit: 10,
types: [],
})
expect(events.length).toBe(1)
expect(events[0]).toMatchObject({
action: 'com.atproto.admin.defs#modEventLabel',
subjectUri: uri.toString(),
createLabelVals: 'test-label',
negateLabelVals: null,
comment: `[AutoModerator]: Applying labels`,
createdBy: labelerDid,
})

// Cleanup the temporary assignment, knowing that by default, moderation service is not available
autoMod.services.moderation = undefined
})

it('labels embeds in posts', async () => {
Expand Down Expand Up @@ -165,3 +193,14 @@ class TestImgLabeler implements ImgLabeler {
return []
}
}

class NoopInvalidator implements ImageInvalidator {
async invalidate() {}
}
class NoopImageUriBuilder {
constructor(public endpoint: string) {}

getPresetUri() {
return ''
}
}

0 comments on commit f365dc5

Please sign in to comment.