@atproto/ozone 0.2.8 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/package.json +25 -21
- package/bin/migration-create.ts +0 -38
- package/jest.config.cjs +0 -22
- package/src/api/chat/getActorMetadata.ts +0 -23
- package/src/api/chat/getConvo.ts +0 -23
- package/src/api/chat/getConvoMembers.ts +0 -23
- package/src/api/chat/getConvos.ts +0 -23
- package/src/api/chat/getMessageContext.ts +0 -42
- package/src/api/chat/index.ts +0 -16
- package/src/api/communication/createTemplate.ts +0 -51
- package/src/api/communication/deleteTemplate.ts +0 -23
- package/src/api/communication/listTemplates.ts +0 -31
- package/src/api/communication/updateTemplate.ts +0 -51
- package/src/api/health.ts +0 -27
- package/src/api/index.ts +0 -146
- package/src/api/label/fetchLabels.ts +0 -32
- package/src/api/label/queryLabels.ts +0 -57
- package/src/api/label/subscribeLabels.ts +0 -25
- package/src/api/moderation/cancelScheduledActions.ts +0 -72
- package/src/api/moderation/emitEvent.ts +0 -475
- package/src/api/moderation/getAccountTimeline.ts +0 -160
- package/src/api/moderation/getEvent.ts +0 -19
- package/src/api/moderation/getRecord.ts +0 -40
- package/src/api/moderation/getRecords.ts +0 -50
- package/src/api/moderation/getRepo.ts +0 -34
- package/src/api/moderation/getReporterStats.ts +0 -18
- package/src/api/moderation/getRepos.ts +0 -41
- package/src/api/moderation/getSubjects.ts +0 -101
- package/src/api/moderation/listScheduledActions.ts +0 -45
- package/src/api/moderation/queryEvents.ts +0 -72
- package/src/api/moderation/queryStatuses.ts +0 -23
- package/src/api/moderation/scheduleAction.ts +0 -129
- package/src/api/moderation/searchRepos.ts +0 -46
- package/src/api/moderation/util.ts +0 -96
- package/src/api/proxied.ts +0 -327
- package/src/api/queue/assignModerator.ts +0 -31
- package/src/api/queue/createQueue.ts +0 -62
- package/src/api/queue/deleteQueue.ts +0 -56
- package/src/api/queue/getAssignments.ts +0 -19
- package/src/api/queue/listQueues.ts +0 -39
- package/src/api/queue/routeReports.ts +0 -44
- package/src/api/queue/unassignModerator.ts +0 -26
- package/src/api/queue/updateQueue.ts +0 -54
- package/src/api/report/assignModerator.ts +0 -36
- package/src/api/report/createActivity.ts +0 -57
- package/src/api/report/createReport.ts +0 -93
- package/src/api/report/getAssignments.ts +0 -20
- package/src/api/report/getHistoricalStats.ts +0 -41
- package/src/api/report/getLatestReport.ts +0 -44
- package/src/api/report/getLiveStats.ts +0 -26
- package/src/api/report/getReport.ts +0 -55
- package/src/api/report/listActivities.ts +0 -37
- package/src/api/report/queryActivities.ts +0 -64
- package/src/api/report/queryReports.ts +0 -44
- package/src/api/report/reassignQueue.ts +0 -68
- package/src/api/report/refreshStats.ts +0 -27
- package/src/api/report/unassignModerator.ts +0 -21
- package/src/api/safelink/addRule.ts +0 -48
- package/src/api/safelink/queryEvents.ts +0 -32
- package/src/api/safelink/queryRules.ts +0 -58
- package/src/api/safelink/removeRule.ts +0 -42
- package/src/api/safelink/updateRule.ts +0 -48
- package/src/api/server/getConfig.ts +0 -35
- package/src/api/set/addValues.ts +0 -28
- package/src/api/set/deleteSet.ts +0 -34
- package/src/api/set/deleteValues.ts +0 -31
- package/src/api/set/getValues.ts +0 -42
- package/src/api/set/querySets.ts +0 -36
- package/src/api/set/upsertSet.ts +0 -38
- package/src/api/setting/listOptions.ts +0 -44
- package/src/api/setting/removeOptions.ts +0 -64
- package/src/api/setting/upsertOption.ts +0 -156
- package/src/api/team/addMember.ts +0 -51
- package/src/api/team/deleteMember.ts +0 -29
- package/src/api/team/listMembers.ts +0 -20
- package/src/api/team/updateMember.ts +0 -47
- package/src/api/util.ts +0 -265
- package/src/api/verification/grantVerifications.ts +0 -90
- package/src/api/verification/listVerifications.ts +0 -44
- package/src/api/verification/revokeVerifications.ts +0 -43
- package/src/api/well-known.ts +0 -46
- package/src/assignment/index.ts +0 -728
- package/src/auth-verifier.ts +0 -227
- package/src/background.ts +0 -183
- package/src/communication-service/template.ts +0 -110
- package/src/communication-service/util.ts +0 -8
- package/src/config/config.ts +0 -211
- package/src/config/env.ts +0 -95
- package/src/config/index.ts +0 -3
- package/src/config/secrets.ts +0 -17
- package/src/context.ts +0 -399
- package/src/daemon/blob-diverter.ts +0 -186
- package/src/daemon/context.ts +0 -247
- package/src/daemon/event-pusher.ts +0 -363
- package/src/daemon/event-reverser.ts +0 -128
- package/src/daemon/index.ts +0 -33
- package/src/daemon/job-cursor.ts +0 -33
- package/src/daemon/materialized-view-refresher.ts +0 -33
- package/src/daemon/queue-router.ts +0 -101
- package/src/daemon/scheduled-action-processor.ts +0 -304
- package/src/daemon/stats-computer.ts +0 -101
- package/src/daemon/strike-expiry-processor.ts +0 -95
- package/src/daemon/team-profile-synchronizer.ts +0 -15
- package/src/daemon/verification-listener.ts +0 -169
- package/src/db/index.ts +0 -203
- package/src/db/migrations/20231219T205730722Z-init.ts +0 -170
- package/src/db/migrations/20240116T085607200Z-communication-template.ts +0 -23
- package/src/db/migrations/20240201T051104136Z-mod-event-blobs.ts +0 -15
- package/src/db/migrations/20240208T213404429Z-add-tags-column-to-moderation-subject.ts +0 -31
- package/src/db/migrations/20240228T003647759Z-add-label-sigs.ts +0 -25
- package/src/db/migrations/20240408T192432676Z-mute-reporting.ts +0 -15
- package/src/db/migrations/20240506T225055595Z-message-subject.ts +0 -21
- package/src/db/migrations/20240521T211332580Z-member.ts +0 -17
- package/src/db/migrations/20240814T003647759Z-event-created-at-index.ts +0 -13
- package/src/db/migrations/20240903T205730722Z-add-template-lang.ts +0 -12
- package/src/db/migrations/20240904T205730722Z-add-subject-did-index.ts +0 -13
- package/src/db/migrations/20241001T205730722Z-subject-status-review-state-index.ts +0 -15
- package/src/db/migrations/20241008T205730722Z-sets.ts +0 -53
- package/src/db/migrations/20241018T205730722Z-setting.ts +0 -27
- package/src/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.ts +0 -57
- package/src/db/migrations/20241220T144630860Z-stats-materialized-views.ts +0 -215
- package/src/db/migrations/20250204T003647759Z-add-subject-priority-score.ts +0 -22
- package/src/db/migrations/20250211T003647759Z-add-reporter-stats-index.ts +0 -38
- package/src/db/migrations/20250211T132135150Z-moderation-event-message-partial-idx.ts +0 -26
- package/src/db/migrations/20250221T132135150Z-member-details.ts +0 -14
- package/src/db/migrations/20250404T201720309Z-subject-status-sort-idxs.ts +0 -18
- package/src/db/migrations/20250415T201720309Z-verification.ts +0 -34
- package/src/db/migrations/20250417T201720309Z-firehose-cursor.ts +0 -16
- package/src/db/migrations/20250609T110704000Z-safelink.ts +0 -53
- package/src/db/migrations/20250618T180246000Z-add-mod-tool-to-moderation-event.ts +0 -18
- package/src/db/migrations/20250701T000000000Z-add-age-assurance-state.ts +0 -25
- package/src/db/migrations/20250715T000000000Z-add-mod-event-external-id.ts +0 -15
- package/src/db/migrations/20250718T150931000Z-update-appeal-reason-stats.ts +0 -310
- package/src/db/migrations/20250813T000000000Z-mod-tool-batch-id-index.ts +0 -14
- package/src/db/migrations/20250923T000000000Z-scheduled-actions.ts +0 -56
- package/src/db/migrations/20251008T120000000Z-add-strike-system.ts +0 -87
- package/src/db/migrations/20260210T154806448Z-mod-event-created-by-indexes.ts +0 -22
- package/src/db/migrations/20260219T164523000Z-create-report-table.ts +0 -155
- package/src/db/migrations/20260219T165302248Z-moderator-assignment.ts +0 -42
- package/src/db/migrations/20260225T000000000Z-add-report-queue-table.ts +0 -41
- package/src/db/migrations/20260313T000000000Z-add-report-activity-table.ts +0 -48
- package/src/db/migrations/20260318T152058935Z-add-report-stat.ts +0 -35
- package/src/db/migrations/20260428T000000000Z-add-expiring-tag-table.ts +0 -32
- package/src/db/migrations/20260513T202941104Z-add-subject-convo-id.ts +0 -114
- package/src/db/migrations/20260602T120000000Z-add-report-activity-created-index.ts +0 -17
- package/src/db/migrations/index.ts +0 -44
- package/src/db/migrations/provider.ts +0 -26
- package/src/db/pagination.ts +0 -335
- package/src/db/schema/account_events_stats.ts +0 -16
- package/src/db/schema/account_record_events_stats.ts +0 -15
- package/src/db/schema/account_record_status_stats.ts +0 -15
- package/src/db/schema/account_strike.ts +0 -13
- package/src/db/schema/blob_push_event.ts +0 -21
- package/src/db/schema/communication_template.ts +0 -19
- package/src/db/schema/expiring_tag.ts +0 -18
- package/src/db/schema/firehose_cursor.ts +0 -13
- package/src/db/schema/index.ts +0 -60
- package/src/db/schema/job_cursor.ts +0 -13
- package/src/db/schema/label.ts +0 -22
- package/src/db/schema/member.ts +0 -22
- package/src/db/schema/moderation_event.ts +0 -61
- package/src/db/schema/moderation_subject_status.ts +0 -52
- package/src/db/schema/moderator_assignment.ts +0 -16
- package/src/db/schema/ozone_set.ts +0 -24
- package/src/db/schema/record_events_stats.ts +0 -15
- package/src/db/schema/record_push_event.ts +0 -21
- package/src/db/schema/repo_push_event.ts +0 -19
- package/src/db/schema/report.ts +0 -28
- package/src/db/schema/report_activity.ts +0 -22
- package/src/db/schema/report_queue.ts +0 -21
- package/src/db/schema/report_stat.ts +0 -27
- package/src/db/schema/safelink.ts +0 -39
- package/src/db/schema/scheduled-action.ts +0 -25
- package/src/db/schema/setting.ts +0 -24
- package/src/db/schema/signing_key.ts +0 -10
- package/src/db/schema/verification.ts +0 -21
- package/src/db/types.ts +0 -24
- package/src/error.ts +0 -12
- package/src/image-invalidator.ts +0 -7
- package/src/index.ts +0 -154
- package/src/jetstream/service.ts +0 -107
- package/src/logger.ts +0 -29
- package/src/mod-service/expiring-tags.ts +0 -104
- package/src/mod-service/index.ts +0 -1842
- package/src/mod-service/profile.ts +0 -139
- package/src/mod-service/report.ts +0 -429
- package/src/mod-service/status.ts +0 -549
- package/src/mod-service/strike.ts +0 -96
- package/src/mod-service/subject.ts +0 -311
- package/src/mod-service/types.ts +0 -96
- package/src/mod-service/util.ts +0 -99
- package/src/mod-service/views.ts +0 -912
- package/src/queue/service.ts +0 -603
- package/src/report/activity.ts +0 -281
- package/src/report/handle-report-update.ts +0 -209
- package/src/report/reassign.ts +0 -109
- package/src/report/stats.ts +0 -852
- package/src/report/views.ts +0 -239
- package/src/safelink/service.ts +0 -304
- package/src/scheduled-action/service.ts +0 -281
- package/src/scheduled-action/types.ts +0 -17
- package/src/sequencer/index.ts +0 -2
- package/src/sequencer/outbox.ts +0 -123
- package/src/sequencer/sequencer.ts +0 -147
- package/src/set/service.ts +0 -230
- package/src/setting/constants.ts +0 -3
- package/src/setting/service.ts +0 -148
- package/src/setting/types.ts +0 -3
- package/src/setting/validators.ts +0 -333
- package/src/tag-service/content-tagger.ts +0 -30
- package/src/tag-service/embed-tagger.ts +0 -70
- package/src/tag-service/index.ts +0 -70
- package/src/tag-service/language-data.ts +0 -561
- package/src/tag-service/language-tagger.ts +0 -101
- package/src/tag-service/util.ts +0 -13
- package/src/team/index.ts +0 -296
- package/src/util.ts +0 -230
- package/src/verification/issuer.ts +0 -146
- package/src/verification/service.ts +0 -208
- package/src/verification/util.ts +0 -53
- package/test.env +0 -2
- package/tests/3p-labeler.test.ts +0 -288
- package/tests/__snapshots__/account-strikes.test.ts.snap +0 -159
- package/tests/__snapshots__/age-assurance.test.ts.snap +0 -66
- package/tests/__snapshots__/blob-divert.test.ts.snap +0 -219
- package/tests/__snapshots__/get-account-timeline.test.ts.snap +0 -36
- package/tests/__snapshots__/get-record.test.ts.snap +0 -271
- package/tests/__snapshots__/get-records.test.ts.snap +0 -175
- package/tests/__snapshots__/get-repo.test.ts.snap +0 -91
- package/tests/__snapshots__/get-repos.test.ts.snap +0 -127
- package/tests/__snapshots__/get-starter-pack.test.ts.snap +0 -535
- package/tests/__snapshots__/get-subjects.test.ts.snap +0 -529
- package/tests/__snapshots__/moderation-events.test.ts.snap +0 -347
- package/tests/__snapshots__/moderation-statuses.test.ts.snap +0 -276
- package/tests/__snapshots__/moderation.test.ts.snap +0 -85
- package/tests/__snapshots__/report-reason.test.ts.snap +0 -14
- package/tests/__snapshots__/safelink.test.ts.snap +0 -179
- package/tests/__snapshots__/scheduled-action.test.ts.snap +0 -61
- package/tests/__snapshots__/sets.test.ts.snap +0 -46
- package/tests/__snapshots__/settings.test.ts.snap +0 -52
- package/tests/__snapshots__/team.test.ts.snap +0 -374
- package/tests/__snapshots__/verification-listener.test.ts.snap +0 -152
- package/tests/__snapshots__/verification.test.ts.snap +0 -302
- package/tests/_util.ts +0 -242
- package/tests/account-strikes.test.ts +0 -184
- package/tests/ack-all-subjects-of-account.test.ts +0 -177
- package/tests/age-assurance.test.ts +0 -372
- package/tests/blob-divert.test.ts +0 -106
- package/tests/communication-templates.test.ts +0 -149
- package/tests/content-tagger.test.ts +0 -170
- package/tests/db.test.ts +0 -184
- package/tests/expiring-label.test.ts +0 -72
- package/tests/expiring-tags.test.ts +0 -232
- package/tests/get-account-timeline.test.ts +0 -85
- package/tests/get-config.test.ts +0 -55
- package/tests/get-lists.test.ts +0 -111
- package/tests/get-profiles.test.ts +0 -70
- package/tests/get-record.test.ts +0 -130
- package/tests/get-records.test.ts +0 -91
- package/tests/get-repo.test.ts +0 -171
- package/tests/get-report.test.ts +0 -136
- package/tests/get-reporter-stats.test.ts +0 -132
- package/tests/get-repos.test.ts +0 -91
- package/tests/get-starter-pack.test.ts +0 -115
- package/tests/get-subjects.test.ts +0 -81
- package/tests/mod-tool.test.ts +0 -268
- package/tests/moderation-appeals.test.ts +0 -260
- package/tests/moderation-events.test.ts +0 -756
- package/tests/moderation-status-tags.test.ts +0 -140
- package/tests/moderation-statuses.test.ts +0 -495
- package/tests/moderation.test.ts +0 -992
- package/tests/protected-tags.test.ts +0 -218
- package/tests/query-labels.test.ts +0 -238
- package/tests/query-reports.test.ts +0 -608
- package/tests/queue-assignment.test.ts +0 -428
- package/tests/queue-router.test.ts +0 -306
- package/tests/queues.test.ts +0 -690
- package/tests/record-and-account-events.test.ts +0 -197
- package/tests/repo-search.test.ts +0 -136
- package/tests/report-action.test.ts +0 -308
- package/tests/report-activity.test.ts +0 -711
- package/tests/report-assignment.test.ts +0 -517
- package/tests/report-muting.test.ts +0 -100
- package/tests/report-reason.test.ts +0 -154
- package/tests/report-reassign-queue.test.ts +0 -340
- package/tests/report-routing.test.ts +0 -245
- package/tests/report-stats.test.ts +0 -545
- package/tests/revoke-account-credentials.test.ts +0 -54
- package/tests/safelink.test.ts +0 -534
- package/tests/scheduled-action-processor.test.ts +0 -488
- package/tests/scheduled-action.test.ts +0 -334
- package/tests/sequencer.test.ts +0 -227
- package/tests/server.test.ts +0 -62
- package/tests/sets.test.ts +0 -246
- package/tests/settings.test.ts +0 -308
- package/tests/strike-expiry-processor.test.ts +0 -299
- package/tests/subject-priority-score.test.ts +0 -96
- package/tests/takedown.test.ts +0 -105
- package/tests/team.test.ts +0 -216
- package/tests/verification-listener.test.ts +0 -129
- package/tests/verification.test.ts +0 -186
- package/tsconfig.build.json +0 -9
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
|
@@ -1,756 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import EventEmitter, { once } from 'node:events'
|
|
3
|
-
import { ToolsOzoneModerationDefs } from '@atproto/api'
|
|
4
|
-
import {
|
|
5
|
-
ModeratorClient,
|
|
6
|
-
SeedClient,
|
|
7
|
-
TestNetwork,
|
|
8
|
-
basicSeed,
|
|
9
|
-
} from '@atproto/dev-env'
|
|
10
|
-
import { isRepoRef } from '../src/lexicon/types/com/atproto/admin/defs.js'
|
|
11
|
-
import {
|
|
12
|
-
REASONAPPEAL,
|
|
13
|
-
REASONMISLEADING,
|
|
14
|
-
REASONSPAM,
|
|
15
|
-
} from '../src/lexicon/types/com/atproto/moderation/defs.js'
|
|
16
|
-
import { isMain as isStrongRef } from '../src/lexicon/types/com/atproto/repo/strongRef.js'
|
|
17
|
-
import { forSnapshot } from './_util.js'
|
|
18
|
-
|
|
19
|
-
describe('moderation-events', () => {
|
|
20
|
-
let network: TestNetwork
|
|
21
|
-
let sc: SeedClient
|
|
22
|
-
let modClient: ModeratorClient
|
|
23
|
-
|
|
24
|
-
const seedEvents = async () => {
|
|
25
|
-
const bobsAccount = {
|
|
26
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
27
|
-
did: sc.dids.bob,
|
|
28
|
-
}
|
|
29
|
-
const alicesAccount = {
|
|
30
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
31
|
-
did: sc.dids.alice,
|
|
32
|
-
}
|
|
33
|
-
const bobsPost = {
|
|
34
|
-
$type: 'com.atproto.repo.strongRef',
|
|
35
|
-
uri: sc.posts[sc.dids.bob][0].ref.uriStr,
|
|
36
|
-
cid: sc.posts[sc.dids.bob][0].ref.cidStr,
|
|
37
|
-
}
|
|
38
|
-
const alicesPost = {
|
|
39
|
-
$type: 'com.atproto.repo.strongRef',
|
|
40
|
-
uri: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
41
|
-
cid: sc.posts[sc.dids.alice][0].ref.cidStr,
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
for (let i = 0; i < 4; i++) {
|
|
45
|
-
await sc.createReport({
|
|
46
|
-
reasonType: i % 2 ? REASONSPAM : REASONMISLEADING,
|
|
47
|
-
reason: 'X',
|
|
48
|
-
// Report bob's account by alice and vice versa
|
|
49
|
-
subject: i % 2 ? bobsAccount : alicesAccount,
|
|
50
|
-
reportedBy: i % 2 ? sc.dids.alice : sc.dids.bob,
|
|
51
|
-
})
|
|
52
|
-
await sc.createReport({
|
|
53
|
-
reasonType: REASONSPAM,
|
|
54
|
-
reason: 'X',
|
|
55
|
-
// Report bob's post by alice and vice versa
|
|
56
|
-
subject: i % 2 ? bobsPost : alicesPost,
|
|
57
|
-
reportedBy: i % 2 ? sc.dids.alice : sc.dids.bob,
|
|
58
|
-
})
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
beforeAll(async () => {
|
|
63
|
-
network = await TestNetwork.create({
|
|
64
|
-
dbPostgresSchema: 'ozone_moderation_events',
|
|
65
|
-
})
|
|
66
|
-
sc = network.getSeedClient()
|
|
67
|
-
modClient = network.ozone.getModClient()
|
|
68
|
-
await basicSeed(sc)
|
|
69
|
-
await network.processAll()
|
|
70
|
-
await seedEvents()
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
beforeEach(async () => {
|
|
74
|
-
await network.processAll()
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
afterAll(async () => {
|
|
78
|
-
await network?.close()
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
describe('query events', () => {
|
|
82
|
-
it('returns all events for record or repo', async () => {
|
|
83
|
-
const [bobsEvents, alicesPostEvents] = await Promise.all([
|
|
84
|
-
modClient.queryEvents({
|
|
85
|
-
subject: sc.dids.bob,
|
|
86
|
-
}),
|
|
87
|
-
modClient.queryEvents({
|
|
88
|
-
subject: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
89
|
-
}),
|
|
90
|
-
])
|
|
91
|
-
|
|
92
|
-
expect(forSnapshot(bobsEvents.events)).toMatchSnapshot()
|
|
93
|
-
expect(forSnapshot(alicesPostEvents.events)).toMatchSnapshot()
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('filters events by types', async () => {
|
|
97
|
-
const alicesAccount = {
|
|
98
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
99
|
-
did: sc.dids.alice,
|
|
100
|
-
}
|
|
101
|
-
await Promise.all([
|
|
102
|
-
modClient.emitEvent({
|
|
103
|
-
event: {
|
|
104
|
-
$type: 'tools.ozone.moderation.defs#modEventComment',
|
|
105
|
-
comment: 'X',
|
|
106
|
-
},
|
|
107
|
-
subject: alicesAccount,
|
|
108
|
-
}),
|
|
109
|
-
modClient.emitEvent({
|
|
110
|
-
event: {
|
|
111
|
-
$type: 'tools.ozone.moderation.defs#modEventEscalate',
|
|
112
|
-
comment: 'X',
|
|
113
|
-
},
|
|
114
|
-
subject: alicesAccount,
|
|
115
|
-
}),
|
|
116
|
-
])
|
|
117
|
-
const [allEvents, reportEvents] = await Promise.all([
|
|
118
|
-
modClient.queryEvents({
|
|
119
|
-
subject: sc.dids.alice,
|
|
120
|
-
}),
|
|
121
|
-
modClient.queryEvents({
|
|
122
|
-
subject: sc.dids.alice,
|
|
123
|
-
types: ['tools.ozone.moderation.defs#modEventReport'],
|
|
124
|
-
}),
|
|
125
|
-
])
|
|
126
|
-
|
|
127
|
-
expect(allEvents.events.length).toBeGreaterThan(
|
|
128
|
-
reportEvents.events.length,
|
|
129
|
-
)
|
|
130
|
-
expect(
|
|
131
|
-
[...new Set(reportEvents.events.map((e) => e.event.$type))].length,
|
|
132
|
-
).toEqual(1)
|
|
133
|
-
|
|
134
|
-
expect(
|
|
135
|
-
[...new Set(allEvents.events.map((e) => e.event.$type))].length,
|
|
136
|
-
).toEqual(4)
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
it('returns events for all content by user', async () => {
|
|
140
|
-
const [forAccount, forPost] = await Promise.all([
|
|
141
|
-
modClient.queryEvents({
|
|
142
|
-
subject: sc.dids.bob,
|
|
143
|
-
includeAllUserRecords: true,
|
|
144
|
-
}),
|
|
145
|
-
modClient.queryEvents({
|
|
146
|
-
subject: sc.posts[sc.dids.bob][0].ref.uriStr,
|
|
147
|
-
includeAllUserRecords: true,
|
|
148
|
-
}),
|
|
149
|
-
])
|
|
150
|
-
|
|
151
|
-
expect(forAccount.events.length).toEqual(forPost.events.length)
|
|
152
|
-
// Save events are returned from both requests
|
|
153
|
-
expect(forPost.events.map(({ id }) => id).sort()).toEqual(
|
|
154
|
-
forAccount.events.map(({ id }) => id).sort(),
|
|
155
|
-
)
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
it('returns paginated list of events with cursor', async () => {
|
|
159
|
-
const allEvents = await modClient.queryEvents({
|
|
160
|
-
subject: sc.dids.bob,
|
|
161
|
-
includeAllUserRecords: true,
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
const getPaginatedEvents = async (
|
|
165
|
-
sortDirection: 'asc' | 'desc' = 'desc',
|
|
166
|
-
) => {
|
|
167
|
-
let defaultCursor: undefined | string = undefined
|
|
168
|
-
const events: ToolsOzoneModerationDefs.ModEventView[] = []
|
|
169
|
-
let count = 0
|
|
170
|
-
do {
|
|
171
|
-
// get 1 event at a time and check we get all events
|
|
172
|
-
const res = await modClient.queryEvents({
|
|
173
|
-
limit: 1,
|
|
174
|
-
subject: sc.dids.bob,
|
|
175
|
-
includeAllUserRecords: true,
|
|
176
|
-
cursor: defaultCursor,
|
|
177
|
-
sortDirection,
|
|
178
|
-
})
|
|
179
|
-
events.push(...res.events)
|
|
180
|
-
defaultCursor = res.cursor
|
|
181
|
-
count++
|
|
182
|
-
// The count is a circuit breaker to prevent infinite loop in case of failing test
|
|
183
|
-
} while (defaultCursor && count < 10)
|
|
184
|
-
|
|
185
|
-
return events
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const defaultEvents = await getPaginatedEvents()
|
|
189
|
-
const reversedEvents = await getPaginatedEvents('asc')
|
|
190
|
-
|
|
191
|
-
expect(allEvents.events.length).toEqual(6)
|
|
192
|
-
expect(defaultEvents.length).toEqual(allEvents.events.length)
|
|
193
|
-
expect(reversedEvents.length).toEqual(allEvents.events.length)
|
|
194
|
-
// First event in the reversed list is the last item in the default list
|
|
195
|
-
expect(reversedEvents[0].id).toEqual(
|
|
196
|
-
defaultEvents[defaultEvents.length - 1].id,
|
|
197
|
-
)
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
it('returns report events matching reportType filters', async () => {
|
|
201
|
-
const [spamEvents, misleadingEvents] = await Promise.all([
|
|
202
|
-
modClient.queryEvents({
|
|
203
|
-
reportTypes: [REASONSPAM],
|
|
204
|
-
}),
|
|
205
|
-
modClient.queryEvents({
|
|
206
|
-
reportTypes: [REASONMISLEADING, REASONAPPEAL],
|
|
207
|
-
}),
|
|
208
|
-
])
|
|
209
|
-
|
|
210
|
-
// Verify all spam events have the correct report type
|
|
211
|
-
expect(spamEvents.events.length).toEqual(6)
|
|
212
|
-
spamEvents.events.forEach((event) => {
|
|
213
|
-
expect(event.event.$type).toEqual(
|
|
214
|
-
'tools.ozone.moderation.defs#modEventReport',
|
|
215
|
-
)
|
|
216
|
-
expect((event.event as any).reportType).toEqual(REASONSPAM)
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
// Verify all misleading events have one of the correct report types
|
|
220
|
-
expect(misleadingEvents.events.length).toEqual(2)
|
|
221
|
-
misleadingEvents.events.forEach((event) => {
|
|
222
|
-
expect(event.event.$type).toEqual(
|
|
223
|
-
'tools.ozone.moderation.defs#modEventReport',
|
|
224
|
-
)
|
|
225
|
-
expect([REASONMISLEADING, REASONAPPEAL]).toContain(
|
|
226
|
-
(event.event as any).reportType,
|
|
227
|
-
)
|
|
228
|
-
})
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
it('returns events matching keyword in comment', async () => {
|
|
232
|
-
const [eventsWithX, eventsWithTest, eventsWithComment] =
|
|
233
|
-
await Promise.all([
|
|
234
|
-
modClient.queryEvents({
|
|
235
|
-
comment: 'X',
|
|
236
|
-
}),
|
|
237
|
-
modClient.queryEvents({
|
|
238
|
-
comment: 'test',
|
|
239
|
-
}),
|
|
240
|
-
modClient.queryEvents({
|
|
241
|
-
hasComment: true,
|
|
242
|
-
}),
|
|
243
|
-
])
|
|
244
|
-
|
|
245
|
-
expect(eventsWithX.events.length).toEqual(10)
|
|
246
|
-
expect(eventsWithTest.events.length).toEqual(0)
|
|
247
|
-
expect(eventsWithComment.events.length).toEqual(10)
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
it('returns events matching multiple keywords in comment', async () => {
|
|
251
|
-
await sc.createReport({
|
|
252
|
-
reasonType: REASONSPAM,
|
|
253
|
-
reason: 'november rain',
|
|
254
|
-
subject: {
|
|
255
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
256
|
-
did: sc.dids.alice,
|
|
257
|
-
},
|
|
258
|
-
reportedBy: sc.dids.bob,
|
|
259
|
-
})
|
|
260
|
-
await sc.createReport({
|
|
261
|
-
reasonType: REASONSPAM,
|
|
262
|
-
reason: 'rainy days feel lazy',
|
|
263
|
-
subject: {
|
|
264
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
265
|
-
did: sc.dids.alice,
|
|
266
|
-
},
|
|
267
|
-
reportedBy: sc.dids.bob,
|
|
268
|
-
})
|
|
269
|
-
const [eventsMatchingBothKeywords, unusedTrailingSeparator, extraSpaces] =
|
|
270
|
-
await Promise.all([
|
|
271
|
-
modClient.queryEvents({
|
|
272
|
-
hasComment: true,
|
|
273
|
-
comment: 'november||lazy',
|
|
274
|
-
}),
|
|
275
|
-
modClient.queryEvents({
|
|
276
|
-
hasComment: true,
|
|
277
|
-
comment: 'november||lazy||',
|
|
278
|
-
}),
|
|
279
|
-
modClient.queryEvents({
|
|
280
|
-
hasComment: true,
|
|
281
|
-
comment: '||november||lazy|| ',
|
|
282
|
-
}),
|
|
283
|
-
])
|
|
284
|
-
|
|
285
|
-
expect(forSnapshot(eventsMatchingBothKeywords.events)).toMatchSnapshot()
|
|
286
|
-
expect(forSnapshot(unusedTrailingSeparator.events)).toMatchSnapshot()
|
|
287
|
-
expect(forSnapshot(extraSpaces.events)).toMatchSnapshot()
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
it('returns events matching filter params for labels', async () => {
|
|
291
|
-
const [negatedLabelEvent, createdLabelEvent] = await Promise.all([
|
|
292
|
-
modClient.emitEvent({
|
|
293
|
-
event: {
|
|
294
|
-
$type: 'tools.ozone.moderation.defs#modEventLabel',
|
|
295
|
-
comment: 'X',
|
|
296
|
-
negateLabelVals: ['L1', 'L2'],
|
|
297
|
-
createLabelVals: [],
|
|
298
|
-
},
|
|
299
|
-
// Report bob's account by alice and vice versa
|
|
300
|
-
subject: {
|
|
301
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
302
|
-
did: sc.dids.alice,
|
|
303
|
-
},
|
|
304
|
-
}),
|
|
305
|
-
modClient.emitEvent({
|
|
306
|
-
event: {
|
|
307
|
-
$type: 'tools.ozone.moderation.defs#modEventLabel',
|
|
308
|
-
comment: 'X',
|
|
309
|
-
createLabelVals: ['L1', 'L2'],
|
|
310
|
-
negateLabelVals: [],
|
|
311
|
-
},
|
|
312
|
-
// Report bob's account by alice and vice versa
|
|
313
|
-
subject: {
|
|
314
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
315
|
-
did: sc.dids.bob,
|
|
316
|
-
},
|
|
317
|
-
}),
|
|
318
|
-
])
|
|
319
|
-
const [withTwoLabels, withoutTwoLabels, withOneLabel, withoutOneLabel] =
|
|
320
|
-
await Promise.all([
|
|
321
|
-
modClient.queryEvents({
|
|
322
|
-
addedLabels: ['L1', 'L3'],
|
|
323
|
-
}),
|
|
324
|
-
modClient.queryEvents({
|
|
325
|
-
removedLabels: ['L1', 'L2'],
|
|
326
|
-
}),
|
|
327
|
-
modClient.queryEvents({
|
|
328
|
-
addedLabels: ['L1'],
|
|
329
|
-
}),
|
|
330
|
-
modClient.queryEvents({
|
|
331
|
-
removedLabels: ['L2'],
|
|
332
|
-
}),
|
|
333
|
-
])
|
|
334
|
-
|
|
335
|
-
// Verify that when querying for events where 2 different labels were added
|
|
336
|
-
// events where all of the labels from the list was added are returned
|
|
337
|
-
expect(withTwoLabels.events.length).toEqual(0)
|
|
338
|
-
expect(negatedLabelEvent.id).toEqual(withoutTwoLabels.events[0].id)
|
|
339
|
-
|
|
340
|
-
expect(createdLabelEvent.id).toEqual(withOneLabel.events[0].id)
|
|
341
|
-
expect(negatedLabelEvent.id).toEqual(withoutOneLabel.events[0].id)
|
|
342
|
-
})
|
|
343
|
-
it('returns events matching filter params for tags', async () => {
|
|
344
|
-
const tagEvent = async ({
|
|
345
|
-
add,
|
|
346
|
-
remove,
|
|
347
|
-
}: {
|
|
348
|
-
add: string[]
|
|
349
|
-
remove: string[]
|
|
350
|
-
}) =>
|
|
351
|
-
modClient.emitEvent({
|
|
352
|
-
event: {
|
|
353
|
-
$type: 'tools.ozone.moderation.defs#modEventTag',
|
|
354
|
-
comment: 'X',
|
|
355
|
-
add,
|
|
356
|
-
remove,
|
|
357
|
-
},
|
|
358
|
-
subject: {
|
|
359
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
360
|
-
did: sc.dids.carol,
|
|
361
|
-
},
|
|
362
|
-
})
|
|
363
|
-
const addEvent = await tagEvent({ add: ['L1', 'L2'], remove: [] })
|
|
364
|
-
const addAndRemoveEvent = await tagEvent({ add: ['L3'], remove: ['L2'] })
|
|
365
|
-
const [addFinder, addAndRemoveFinder, _removeFinder] = await Promise.all([
|
|
366
|
-
modClient.queryEvents({
|
|
367
|
-
addedTags: ['L1'],
|
|
368
|
-
}),
|
|
369
|
-
modClient.queryEvents({
|
|
370
|
-
addedTags: ['L3'],
|
|
371
|
-
removedTags: ['L2'],
|
|
372
|
-
}),
|
|
373
|
-
modClient.queryEvents({
|
|
374
|
-
removedTags: ['L2'],
|
|
375
|
-
}),
|
|
376
|
-
])
|
|
377
|
-
|
|
378
|
-
expect(addFinder.events.length).toEqual(1)
|
|
379
|
-
expect(addEvent.id).toEqual(addFinder.events[0].id)
|
|
380
|
-
|
|
381
|
-
expect(addAndRemoveEvent.id).toEqual(addAndRemoveFinder.events[0].id)
|
|
382
|
-
expect(addAndRemoveEvent.id).toEqual(addAndRemoveFinder.events[0].id)
|
|
383
|
-
assert(ToolsOzoneModerationDefs.isModEventTag(addAndRemoveEvent.event))
|
|
384
|
-
expect(addAndRemoveEvent.event.add).toEqual(['L3'])
|
|
385
|
-
expect(addAndRemoveEvent.event.remove).toEqual(['L2'])
|
|
386
|
-
})
|
|
387
|
-
|
|
388
|
-
it('returns events for specified collections', async () => {
|
|
389
|
-
const sp = await sc.createStarterPack(
|
|
390
|
-
sc.dids.alice,
|
|
391
|
-
"alice's about to get blocked starter pack",
|
|
392
|
-
[sc.dids.bob, sc.dids.carol],
|
|
393
|
-
[],
|
|
394
|
-
)
|
|
395
|
-
await sc.createReport({
|
|
396
|
-
reasonType: REASONSPAM,
|
|
397
|
-
reason: 'X',
|
|
398
|
-
subject: {
|
|
399
|
-
$type: 'com.atproto.repo.strongRef',
|
|
400
|
-
...sp.raw,
|
|
401
|
-
},
|
|
402
|
-
reportedBy: sc.dids.bob,
|
|
403
|
-
})
|
|
404
|
-
|
|
405
|
-
const [
|
|
406
|
-
onlyStarterPackReports,
|
|
407
|
-
onlyAlicesStarterPackReports,
|
|
408
|
-
onlyBobsStarterPackReports,
|
|
409
|
-
onlyPostReports,
|
|
410
|
-
] = await Promise.all([
|
|
411
|
-
modClient.queryEvents({
|
|
412
|
-
types: ['tools.ozone.moderation.defs#modEventReport'],
|
|
413
|
-
collections: ['app.bsky.graph.starterpack'],
|
|
414
|
-
}),
|
|
415
|
-
modClient.queryEvents({
|
|
416
|
-
subject: sc.dids.alice,
|
|
417
|
-
includeAllUserRecords: true,
|
|
418
|
-
types: ['tools.ozone.moderation.defs#modEventReport'],
|
|
419
|
-
collections: ['app.bsky.graph.starterpack'],
|
|
420
|
-
}),
|
|
421
|
-
modClient.queryEvents({
|
|
422
|
-
subject: sc.dids.bob,
|
|
423
|
-
includeAllUserRecords: true,
|
|
424
|
-
types: ['tools.ozone.moderation.defs#modEventReport'],
|
|
425
|
-
collections: ['app.bsky.graph.starterpack'],
|
|
426
|
-
}),
|
|
427
|
-
modClient.queryEvents({
|
|
428
|
-
types: ['tools.ozone.moderation.defs#modEventReport'],
|
|
429
|
-
collections: ['app.bsky.feed.post'],
|
|
430
|
-
}),
|
|
431
|
-
])
|
|
432
|
-
|
|
433
|
-
expect(onlyStarterPackReports.events.length).toEqual(1)
|
|
434
|
-
assert(isStrongRef(onlyStarterPackReports.events[0].subject))
|
|
435
|
-
expect(onlyStarterPackReports.events[0].subject.uri).toContain(
|
|
436
|
-
'app.bsky.graph.starterpack',
|
|
437
|
-
)
|
|
438
|
-
|
|
439
|
-
expect(onlyAlicesStarterPackReports.events.length).toEqual(1)
|
|
440
|
-
assert(isStrongRef(onlyAlicesStarterPackReports.events[0].subject))
|
|
441
|
-
expect(onlyAlicesStarterPackReports.events[0].subject.uri).toContain(
|
|
442
|
-
sp.uriStr,
|
|
443
|
-
)
|
|
444
|
-
expect(onlyBobsStarterPackReports.events.length).toEqual(0)
|
|
445
|
-
expect(onlyPostReports.events.length).toEqual(4)
|
|
446
|
-
})
|
|
447
|
-
|
|
448
|
-
it('returns events for account or records', async () => {
|
|
449
|
-
const [onlyAccountReports, onlyRecordReports, onlyReportsOnBobsAccount] =
|
|
450
|
-
await Promise.all([
|
|
451
|
-
modClient.queryEvents({
|
|
452
|
-
types: ['tools.ozone.moderation.defs#modEventReport'],
|
|
453
|
-
subjectType: 'account',
|
|
454
|
-
}),
|
|
455
|
-
modClient.queryEvents({
|
|
456
|
-
types: ['tools.ozone.moderation.defs#modEventReport'],
|
|
457
|
-
subjectType: 'record',
|
|
458
|
-
}),
|
|
459
|
-
modClient.queryEvents({
|
|
460
|
-
subject: sc.dids.bob,
|
|
461
|
-
types: ['tools.ozone.moderation.defs#modEventReport'],
|
|
462
|
-
subjectType: 'record',
|
|
463
|
-
}),
|
|
464
|
-
])
|
|
465
|
-
|
|
466
|
-
assert(
|
|
467
|
-
onlyAccountReports.events.every((e) => !isStrongRef(e.subject)),
|
|
468
|
-
'only account reports are returned, no event has a uri',
|
|
469
|
-
)
|
|
470
|
-
|
|
471
|
-
assert(
|
|
472
|
-
onlyRecordReports.events.every(
|
|
473
|
-
(e) => isStrongRef(e.subject) && e.subject.uri,
|
|
474
|
-
),
|
|
475
|
-
'only record reports are returned, all events have a uri',
|
|
476
|
-
)
|
|
477
|
-
|
|
478
|
-
assert(
|
|
479
|
-
onlyReportsOnBobsAccount.events.every(
|
|
480
|
-
(e) => isRepoRef(e.subject) && e.subject.did === sc.dids.bob,
|
|
481
|
-
),
|
|
482
|
-
"only bob's account reports are returned, no events have a URI even though the subjectType is record",
|
|
483
|
-
)
|
|
484
|
-
})
|
|
485
|
-
|
|
486
|
-
it('queries events by creator', async () => {
|
|
487
|
-
const now = new Date()
|
|
488
|
-
const startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000) // 1 day ago
|
|
489
|
-
const endDate = new Date(now.getTime() + 24 * 60 * 60 * 1000) // 1 day from now
|
|
490
|
-
|
|
491
|
-
const events = await modClient.queryEvents({
|
|
492
|
-
createdBy: network.ozone.moderatorAccnt.did,
|
|
493
|
-
createdAfter: startDate.toISOString(),
|
|
494
|
-
createdBefore: endDate.toISOString(),
|
|
495
|
-
limit: 25,
|
|
496
|
-
sortDirection: 'desc',
|
|
497
|
-
})
|
|
498
|
-
|
|
499
|
-
expect(events.events.length).toBeGreaterThan(0)
|
|
500
|
-
expect(events.events.length).toBeLessThanOrEqual(25)
|
|
501
|
-
|
|
502
|
-
// Verify sorting
|
|
503
|
-
for (let i = 1; i < events.events.length; i++) {
|
|
504
|
-
const prev = events.events[i - 1]
|
|
505
|
-
const curr = events.events[i]
|
|
506
|
-
const prevTime = new Date(prev.createdAt).getTime()
|
|
507
|
-
const currTime = new Date(curr.createdAt).getTime()
|
|
508
|
-
|
|
509
|
-
if (prevTime === currTime) {
|
|
510
|
-
expect(prev.id).toBeGreaterThan(curr.id)
|
|
511
|
-
} else {
|
|
512
|
-
expect(prevTime).toBeGreaterThan(currTime)
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// Verify createdBy is correct
|
|
517
|
-
events.events.forEach((event) => {
|
|
518
|
-
expect(event.createdBy).toEqual(network.ozone.moderatorAccnt.did)
|
|
519
|
-
})
|
|
520
|
-
})
|
|
521
|
-
|
|
522
|
-
it('queries events by conversation', async () => {
|
|
523
|
-
const convoId1 = 'conversation-123'
|
|
524
|
-
const convoId2 = 'conversation-456'
|
|
525
|
-
|
|
526
|
-
// create reports
|
|
527
|
-
await sc.createReport({
|
|
528
|
-
reasonType: REASONSPAM,
|
|
529
|
-
reason: 'spam in convo 1',
|
|
530
|
-
subject: {
|
|
531
|
-
$type: 'chat.bsky.convo.defs#convoRef',
|
|
532
|
-
did: sc.dids.carol,
|
|
533
|
-
convoId: convoId1,
|
|
534
|
-
},
|
|
535
|
-
reportedBy: sc.dids.alice,
|
|
536
|
-
})
|
|
537
|
-
await sc.createReport({
|
|
538
|
-
reasonType: REASONMISLEADING,
|
|
539
|
-
reason: 'misleading in convo 1',
|
|
540
|
-
subject: {
|
|
541
|
-
$type: 'chat.bsky.convo.defs#convoRef',
|
|
542
|
-
did: sc.dids.carol,
|
|
543
|
-
convoId: convoId1,
|
|
544
|
-
},
|
|
545
|
-
reportedBy: sc.dids.bob,
|
|
546
|
-
})
|
|
547
|
-
await sc.createReport({
|
|
548
|
-
reasonType: REASONSPAM,
|
|
549
|
-
reason: 'spam in convo 2',
|
|
550
|
-
subject: {
|
|
551
|
-
$type: 'chat.bsky.convo.defs#convoRef',
|
|
552
|
-
did: sc.dids.carol,
|
|
553
|
-
convoId: convoId2,
|
|
554
|
-
},
|
|
555
|
-
reportedBy: sc.dids.alice,
|
|
556
|
-
})
|
|
557
|
-
|
|
558
|
-
// Query events (filter by report type since auto-tagging creates extra events)
|
|
559
|
-
const convo1Events = await modClient.queryEvents({
|
|
560
|
-
subject: `at://${sc.dids.carol}/chat.bsky.convo/${convoId1}`,
|
|
561
|
-
includeAllUserRecords: false,
|
|
562
|
-
types: ['tools.ozone.moderation.defs#modEventReport'],
|
|
563
|
-
})
|
|
564
|
-
const convo2Events = await modClient.queryEvents({
|
|
565
|
-
subject: `at://${sc.dids.carol}/chat.bsky.convo/${convoId2}`,
|
|
566
|
-
includeAllUserRecords: false,
|
|
567
|
-
types: ['tools.ozone.moderation.defs#modEventReport'],
|
|
568
|
-
})
|
|
569
|
-
|
|
570
|
-
// Verify conversation 1 events are correct
|
|
571
|
-
expect(convo1Events.events.length).toBeGreaterThan(0)
|
|
572
|
-
convo1Events.events.forEach((e) => {
|
|
573
|
-
// All events should be conversation refs
|
|
574
|
-
expect(e.subject.$type).toEqual('chat.bsky.convo.defs#convoRef')
|
|
575
|
-
// All events should be for conversation 1
|
|
576
|
-
const subject = e.subject as any
|
|
577
|
-
expect(subject.convoId).toEqual(convoId1)
|
|
578
|
-
expect(subject.did).toEqual(sc.dids.carol)
|
|
579
|
-
// All events should be reports
|
|
580
|
-
expect(e.event.$type).toEqual(
|
|
581
|
-
'tools.ozone.moderation.defs#modEventReport',
|
|
582
|
-
)
|
|
583
|
-
})
|
|
584
|
-
// Verify we got both reports we created
|
|
585
|
-
const convo1Comments = convo1Events.events.map(
|
|
586
|
-
(e) => (e.event as any).comment,
|
|
587
|
-
)
|
|
588
|
-
expect(convo1Comments).toContain('spam in convo 1')
|
|
589
|
-
expect(convo1Comments).toContain('misleading in convo 1')
|
|
590
|
-
|
|
591
|
-
// Verify conversation 2 events are correct
|
|
592
|
-
expect(convo2Events.events.length).toBeGreaterThan(0)
|
|
593
|
-
convo2Events.events.forEach((e) => {
|
|
594
|
-
// All events should be conversation refs
|
|
595
|
-
expect(e.subject.$type).toEqual('chat.bsky.convo.defs#convoRef')
|
|
596
|
-
// All events should be for conversation 2
|
|
597
|
-
const subject = e.subject as any
|
|
598
|
-
expect(subject.convoId).toEqual(convoId2)
|
|
599
|
-
expect(subject.did).toEqual(sc.dids.carol)
|
|
600
|
-
// All events should be reports
|
|
601
|
-
expect(e.event.$type).toEqual(
|
|
602
|
-
'tools.ozone.moderation.defs#modEventReport',
|
|
603
|
-
)
|
|
604
|
-
})
|
|
605
|
-
// Verify we got the report we created
|
|
606
|
-
const convo2Comments = convo2Events.events.map(
|
|
607
|
-
(e) => (e.event as any).comment,
|
|
608
|
-
)
|
|
609
|
-
expect(convo2Comments).toContain('spam in convo 2')
|
|
610
|
-
})
|
|
611
|
-
})
|
|
612
|
-
|
|
613
|
-
describe('get event', () => {
|
|
614
|
-
it('gets an event by specific id', async () => {
|
|
615
|
-
const data = await modClient.getEvent(1)
|
|
616
|
-
expect(forSnapshot(data)).toMatchSnapshot()
|
|
617
|
-
})
|
|
618
|
-
})
|
|
619
|
-
|
|
620
|
-
describe('deduping by external id', () => {
|
|
621
|
-
it('fails on events with duplicate external id', async () => {
|
|
622
|
-
const externalId = 'external-id-1'
|
|
623
|
-
await modClient.emitEvent({
|
|
624
|
-
event: {
|
|
625
|
-
$type: 'tools.ozone.moderation.defs#ageAssuranceEvent',
|
|
626
|
-
status: 'pending',
|
|
627
|
-
createdAt: new Date().toISOString(),
|
|
628
|
-
attemptId: 'attempt-1',
|
|
629
|
-
},
|
|
630
|
-
subject: {
|
|
631
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
632
|
-
did: sc.dids.alice,
|
|
633
|
-
},
|
|
634
|
-
externalId,
|
|
635
|
-
})
|
|
636
|
-
await expect(
|
|
637
|
-
modClient.emitEvent({
|
|
638
|
-
event: {
|
|
639
|
-
$type: 'tools.ozone.moderation.defs#ageAssuranceEvent',
|
|
640
|
-
status: 'pending',
|
|
641
|
-
createdAt: new Date().toISOString(),
|
|
642
|
-
attemptId: 'attempt-1',
|
|
643
|
-
},
|
|
644
|
-
subject: {
|
|
645
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
646
|
-
did: sc.dids.alice,
|
|
647
|
-
},
|
|
648
|
-
externalId,
|
|
649
|
-
}),
|
|
650
|
-
).rejects.toThrow(
|
|
651
|
-
'An event with the same external ID already exists for the subject.',
|
|
652
|
-
)
|
|
653
|
-
})
|
|
654
|
-
})
|
|
655
|
-
|
|
656
|
-
describe('blobs', () => {
|
|
657
|
-
it('are tracked on takedown event', async () => {
|
|
658
|
-
const post = sc.posts[sc.dids.carol][0]
|
|
659
|
-
assert(post.images.length > 1)
|
|
660
|
-
await modClient.emitEvent({
|
|
661
|
-
event: {
|
|
662
|
-
$type: 'tools.ozone.moderation.defs#modEventTakedown',
|
|
663
|
-
},
|
|
664
|
-
subject: {
|
|
665
|
-
$type: 'com.atproto.repo.strongRef',
|
|
666
|
-
uri: post.ref.uriStr,
|
|
667
|
-
cid: post.ref.cidStr,
|
|
668
|
-
},
|
|
669
|
-
subjectBlobCids: [post.images[0].image.ref.toString()],
|
|
670
|
-
})
|
|
671
|
-
const result = await modClient.queryEvents({
|
|
672
|
-
subject: post.ref.uriStr,
|
|
673
|
-
types: ['tools.ozone.moderation.defs#modEventTakedown'],
|
|
674
|
-
})
|
|
675
|
-
expect(result.events[0]).toMatchObject({
|
|
676
|
-
createdBy: network.ozone.moderatorAccnt.did,
|
|
677
|
-
event: {
|
|
678
|
-
$type: 'tools.ozone.moderation.defs#modEventTakedown',
|
|
679
|
-
},
|
|
680
|
-
subjectBlobCids: [post.images[0].image.ref.toString()],
|
|
681
|
-
})
|
|
682
|
-
})
|
|
683
|
-
|
|
684
|
-
it("are tracked on reverse-takedown event even if they aren't specified", async () => {
|
|
685
|
-
const post = sc.posts[sc.dids.carol][0]
|
|
686
|
-
await modClient.emitEvent({
|
|
687
|
-
event: {
|
|
688
|
-
$type: 'tools.ozone.moderation.defs#modEventReverseTakedown',
|
|
689
|
-
},
|
|
690
|
-
subject: {
|
|
691
|
-
$type: 'com.atproto.repo.strongRef',
|
|
692
|
-
uri: post.ref.uriStr,
|
|
693
|
-
cid: post.ref.cidStr,
|
|
694
|
-
},
|
|
695
|
-
})
|
|
696
|
-
const result = await modClient.queryEvents({
|
|
697
|
-
subject: post.ref.uriStr,
|
|
698
|
-
})
|
|
699
|
-
expect(result.events[0]).toMatchObject({
|
|
700
|
-
createdBy: network.ozone.moderatorAccnt.did,
|
|
701
|
-
event: {
|
|
702
|
-
$type: 'tools.ozone.moderation.defs#modEventReverseTakedown',
|
|
703
|
-
},
|
|
704
|
-
subjectBlobCids: [post.images[0].image.ref.toString()],
|
|
705
|
-
})
|
|
706
|
-
})
|
|
707
|
-
})
|
|
708
|
-
|
|
709
|
-
describe('email event', () => {
|
|
710
|
-
let sendMailOriginal
|
|
711
|
-
const mailCatcher = new EventEmitter()
|
|
712
|
-
const getMailFrom = async (
|
|
713
|
-
promise,
|
|
714
|
-
): Promise<{ to: string; subject: string; from: string }> => {
|
|
715
|
-
const result = await Promise.all([once(mailCatcher, 'mail'), promise])
|
|
716
|
-
return result[0][0]
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
beforeAll(() => {
|
|
720
|
-
const mailer = network.pds.ctx.moderationMailer
|
|
721
|
-
// Catch emails for use in tests
|
|
722
|
-
sendMailOriginal = mailer.transporter.sendMail
|
|
723
|
-
mailer.transporter.sendMail = async (opts) => {
|
|
724
|
-
const result = await sendMailOriginal.call(mailer.transporter, opts)
|
|
725
|
-
mailCatcher.emit('mail', opts)
|
|
726
|
-
return result
|
|
727
|
-
}
|
|
728
|
-
})
|
|
729
|
-
|
|
730
|
-
afterAll(() => {
|
|
731
|
-
network.pds.ctx.moderationMailer.transporter.sendMail = sendMailOriginal
|
|
732
|
-
})
|
|
733
|
-
|
|
734
|
-
it('sends email via pds.', async () => {
|
|
735
|
-
const mail = await getMailFrom(
|
|
736
|
-
modClient.emitEvent({
|
|
737
|
-
event: {
|
|
738
|
-
$type: 'tools.ozone.moderation.defs#modEventEmail',
|
|
739
|
-
comment: 'Reaching out to Alice',
|
|
740
|
-
subjectLine: 'Hello',
|
|
741
|
-
content: 'Hey Alice, how are you?',
|
|
742
|
-
},
|
|
743
|
-
subject: {
|
|
744
|
-
$type: 'com.atproto.admin.defs#repoRef',
|
|
745
|
-
did: sc.dids.alice,
|
|
746
|
-
},
|
|
747
|
-
}),
|
|
748
|
-
)
|
|
749
|
-
expect(mail).toEqual({
|
|
750
|
-
to: 'alice@test.com',
|
|
751
|
-
subject: 'Hello',
|
|
752
|
-
html: 'Hey Alice, how are you?',
|
|
753
|
-
})
|
|
754
|
-
})
|
|
755
|
-
})
|
|
756
|
-
})
|