@atproto/ozone 0.0.16 → 0.0.17-next.0

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.
Files changed (66) hide show
  1. package/dist/api/moderation/util.d.ts +1 -1
  2. package/dist/auth-verifier.d.ts +7 -11
  3. package/dist/config/config.d.ts +1 -0
  4. package/dist/config/env.d.ts +1 -2
  5. package/dist/config/secrets.d.ts +0 -2
  6. package/dist/daemon/event-pusher.d.ts +2 -0
  7. package/dist/db/index.js.map +1 -1
  8. package/dist/db/schema/moderation_subject_status.d.ts +2 -2
  9. package/dist/index.js +821 -1055
  10. package/dist/index.js.map +3 -3
  11. package/dist/lexicon/index.d.ts +8 -0
  12. package/dist/lexicon/lexicons.d.ts +298 -0
  13. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +23 -1
  14. package/dist/lexicon/types/app/bsky/embed/record.d.ts +2 -1
  15. package/dist/lexicon/types/app/bsky/labeler/defs.d.ts +41 -0
  16. package/dist/lexicon/types/app/bsky/labeler/getServices.d.ts +36 -0
  17. package/dist/lexicon/types/app/bsky/labeler/service.d.ts +14 -0
  18. package/dist/lexicon/types/com/atproto/admin/defs.d.ts +2 -1
  19. package/dist/lexicon/types/com/atproto/label/defs.d.ts +18 -0
  20. package/dist/mod-service/index.d.ts +2 -2
  21. package/package.json +5 -4
  22. package/src/api/admin/createCommunicationTemplate.ts +1 -1
  23. package/src/api/admin/deleteCommunicationTemplate.ts +1 -1
  24. package/src/api/admin/emitModerationEvent.ts +6 -2
  25. package/src/api/admin/getModerationEvent.ts +1 -1
  26. package/src/api/admin/getRecord.ts +1 -1
  27. package/src/api/admin/getRepo.ts +1 -1
  28. package/src/api/admin/listCommunicationTemplates.ts +1 -1
  29. package/src/api/admin/queryModerationEvents.ts +1 -1
  30. package/src/api/admin/queryModerationStatuses.ts +1 -1
  31. package/src/api/admin/searchRepos.ts +1 -1
  32. package/src/api/admin/updateCommunicationTemplate.ts +1 -1
  33. package/src/api/admin/util.ts +1 -1
  34. package/src/api/moderation/createReport.ts +1 -2
  35. package/src/api/proxied.ts +8 -8
  36. package/src/api/temp/fetchLabels.ts +1 -1
  37. package/src/auth-verifier.ts +19 -29
  38. package/src/config/config.ts +10 -7
  39. package/src/config/env.ts +2 -4
  40. package/src/config/secrets.ts +0 -6
  41. package/src/context.ts +1 -3
  42. package/src/daemon/context.ts +2 -2
  43. package/src/daemon/event-pusher.ts +9 -1
  44. package/src/db/schema/moderation_subject_status.ts +6 -1
  45. package/src/lexicon/index.ts +23 -0
  46. package/src/lexicon/lexicons.ts +327 -1
  47. package/src/lexicon/types/app/bsky/actor/defs.ts +57 -1
  48. package/src/lexicon/types/app/bsky/embed/record.ts +2 -0
  49. package/src/lexicon/types/app/bsky/labeler/defs.ts +93 -0
  50. package/src/lexicon/types/app/bsky/labeler/getServices.ts +51 -0
  51. package/src/lexicon/types/app/bsky/labeler/service.ts +31 -0
  52. package/src/lexicon/types/com/atproto/admin/defs.ts +3 -0
  53. package/src/lexicon/types/com/atproto/label/defs.ts +68 -0
  54. package/src/mod-service/index.ts +4 -3
  55. package/src/mod-service/status.ts +42 -26
  56. package/tests/__snapshots__/get-record.test.ts.snap +4 -4
  57. package/tests/__snapshots__/get-repo.test.ts.snap +2 -2
  58. package/tests/communication-templates.test.ts +7 -7
  59. package/tests/get-record.test.ts +17 -7
  60. package/tests/get-repo.test.ts +24 -12
  61. package/tests/moderation-appeals.test.ts +24 -52
  62. package/tests/moderation-events.test.ts +87 -130
  63. package/tests/moderation-status-tags.test.ts +16 -31
  64. package/tests/moderation-statuses.test.ts +125 -58
  65. package/tests/moderation.test.ts +140 -287
  66. package/tests/repo-search.test.ts +11 -4
@@ -4,12 +4,9 @@ import {
4
4
  RecordRef,
5
5
  SeedClient,
6
6
  basicSeed,
7
+ ModeratorClient,
7
8
  } from '@atproto/dev-env'
8
- import AtpAgent, {
9
- ComAtprotoAdminEmitModerationEvent,
10
- ComAtprotoAdminQueryModerationStatuses,
11
- ComAtprotoModerationCreateReport,
12
- } from '@atproto/api'
9
+ import AtpAgent, { ComAtprotoAdminEmitModerationEvent } from '@atproto/api'
13
10
  import { AtUri } from '@atproto/syntax'
14
11
  import { forSnapshot } from './_util'
15
12
  import {
@@ -19,7 +16,6 @@ import {
19
16
  } from '../src/lexicon/types/com/atproto/moderation/defs'
20
17
  import {
21
18
  ModEventLabel,
22
- ModEventTakedown,
23
19
  REVIEWCLOSED,
24
20
  REVIEWESCALATED,
25
21
  } from '../src/lexicon/types/com/atproto/admin/defs'
@@ -31,16 +27,6 @@ import {
31
27
  UNSPECCED_TAKEDOWN_LABEL,
32
28
  } from '../src/mod-service/types'
33
29
 
34
- type BaseCreateReportParams =
35
- | { account: string }
36
- | { content: { uri: string; cid: string } }
37
- type CreateReportParams = BaseCreateReportParams & {
38
- author: string
39
- } & Omit<ComAtprotoModerationCreateReport.InputSchema, 'subject'>
40
-
41
- type TakedownParams = BaseCreateReportParams &
42
- Omit<ComAtprotoAdminEmitModerationEvent.InputSchema, 'subject'>
43
-
44
30
  describe('moderation', () => {
45
31
  let network: TestNetwork
46
32
  let ozone: TestOzone
@@ -49,102 +35,18 @@ describe('moderation', () => {
49
35
  let bskyAgent: AtpAgent
50
36
  let pdsAgent: AtpAgent
51
37
  let sc: SeedClient
38
+ let modClient: ModeratorClient
52
39
 
53
- const createReport = async (params: CreateReportParams) => {
54
- const { author, ...rest } = params
55
- return agent.api.com.atproto.moderation.createReport(
56
- {
57
- // Set default type to spam
58
- reasonType: REASONSPAM,
59
- ...rest,
60
- subject:
61
- 'account' in params
62
- ? {
63
- $type: 'com.atproto.admin.defs#repoRef',
64
- did: params.account,
65
- }
66
- : {
67
- $type: 'com.atproto.repo.strongRef',
68
- uri: params.content.uri,
69
- cid: params.content.cid,
70
- },
71
- },
72
- {
73
- headers: await network.serviceHeaders(
74
- author,
75
- network.ozone.ctx.cfg.service.did,
76
- ),
77
- encoding: 'application/json',
78
- },
79
- )
80
- }
81
-
82
- const performTakedown = async ({
83
- durationInHours,
84
- ...rest
85
- }: TakedownParams & Pick<ModEventTakedown, 'durationInHours'>) =>
86
- agent.api.com.atproto.admin.emitModerationEvent(
87
- {
88
- event: {
89
- $type: 'com.atproto.admin.defs#modEventTakedown',
90
- durationInHours,
91
- },
92
- subject:
93
- 'account' in rest
94
- ? {
95
- $type: 'com.atproto.admin.defs#repoRef',
96
- did: rest.account,
97
- }
98
- : {
99
- $type: 'com.atproto.repo.strongRef',
100
- uri: rest.content.uri,
101
- cid: rest.content.cid,
102
- },
103
- createdBy: 'did:example:admin',
104
- ...rest,
105
- },
106
- {
107
- encoding: 'application/json',
108
- headers: ozone.adminAuthHeaders(),
109
- },
110
- )
111
-
112
- const performReverseTakedown = async (params: TakedownParams) =>
113
- agent.api.com.atproto.admin.emitModerationEvent(
114
- {
115
- event: {
116
- $type: 'com.atproto.admin.defs#modEventReverseTakedown',
117
- },
118
- subject:
119
- 'account' in params
120
- ? {
121
- $type: 'com.atproto.admin.defs#repoRef',
122
- did: params.account,
123
- }
124
- : {
125
- $type: 'com.atproto.repo.strongRef',
126
- uri: params.content.uri,
127
- cid: params.content.cid,
128
- },
129
- createdBy: 'did:example:admin',
130
- ...params,
131
- },
132
- {
133
- encoding: 'application/json',
134
- headers: ozone.adminAuthHeaders(),
135
- },
136
- )
137
-
138
- const getStatuses = async (
139
- params: ComAtprotoAdminQueryModerationStatuses.QueryParams,
140
- ) => {
141
- const { data } = await agent.api.com.atproto.admin.queryModerationStatuses(
142
- params,
143
- { headers: ozone.adminAuthHeaders() },
144
- )
40
+ const repoSubject = (did: string) => ({
41
+ $type: 'com.atproto.admin.defs#repoRef',
42
+ did,
43
+ })
145
44
 
146
- return data
147
- }
45
+ const recordSubject = (ref: RecordRef) => ({
46
+ $type: 'com.atproto.repo.strongRef',
47
+ uri: ref.uriStr,
48
+ cid: ref.cidStr,
49
+ })
148
50
 
149
51
  const getLabel = async (uri: string, val: string, neg = false) => {
150
52
  return ozone.ctx.db.db
@@ -170,6 +72,7 @@ describe('moderation', () => {
170
72
  bskyAgent = network.bsky.getClient()
171
73
  pdsAgent = network.pds.getClient()
172
74
  sc = network.getSeedClient()
75
+ modClient = network.ozone.getModClient()
173
76
  await basicSeed(sc)
174
77
  await network.processAll()
175
78
  })
@@ -180,25 +83,25 @@ describe('moderation', () => {
180
83
 
181
84
  describe('reporting', () => {
182
85
  it('creates reports of a repo.', async () => {
183
- const { data: reportA } = await createReport({
86
+ const reportA = await sc.createReport({
184
87
  reasonType: REASONSPAM,
185
- account: sc.dids.bob,
186
- author: sc.dids.alice,
88
+ subject: repoSubject(sc.dids.bob),
89
+ reportedBy: sc.dids.alice,
187
90
  })
188
- const { data: reportB } = await createReport({
91
+ const reportB = await sc.createReport({
189
92
  reasonType: REASONOTHER,
190
93
  reason: 'impersonation',
191
- account: sc.dids.bob,
192
- author: sc.dids.carol,
94
+ subject: repoSubject(sc.dids.bob),
95
+ reportedBy: sc.dids.carol,
193
96
  })
194
97
  expect(forSnapshot([reportA, reportB])).toMatchSnapshot()
195
98
  })
196
99
 
197
100
  it("allows reporting a repo that doesn't exist.", async () => {
198
- const promise = createReport({
101
+ const promise = sc.createReport({
199
102
  reasonType: REASONSPAM,
200
- account: 'did:plc:unknown',
201
- author: sc.dids.alice,
103
+ subject: repoSubject('did:plc:unknown'),
104
+ reportedBy: sc.dids.alice,
202
105
  })
203
106
  await expect(promise).resolves.toBeDefined()
204
107
  })
@@ -206,24 +109,16 @@ describe('moderation', () => {
206
109
  it('creates reports of a record.', async () => {
207
110
  const postA = sc.posts[sc.dids.bob][0].ref
208
111
  const postB = sc.posts[sc.dids.bob][1].ref
209
- const { data: reportA } = await createReport({
210
- author: sc.dids.alice,
112
+ const reportA = await sc.createReport({
113
+ reportedBy: sc.dids.alice,
211
114
  reasonType: REASONSPAM,
212
- content: {
213
- $type: 'com.atproto.repo.strongRef',
214
- uri: postA.uriStr,
215
- cid: postA.cidStr,
216
- },
115
+ subject: recordSubject(postA),
217
116
  })
218
- const { data: reportB } = await createReport({
117
+ const reportB = await sc.createReport({
219
118
  reasonType: REASONOTHER,
220
119
  reason: 'defamation',
221
- content: {
222
- $type: 'com.atproto.repo.strongRef',
223
- uri: postB.uriStr,
224
- cid: postB.cidStr,
225
- },
226
- author: sc.dids.carol,
120
+ subject: recordSubject(postB),
121
+ reportedBy: sc.dids.carol,
227
122
  })
228
123
  expect(forSnapshot([reportA, reportB])).toMatchSnapshot()
229
124
  })
@@ -234,26 +129,26 @@ describe('moderation', () => {
234
129
  const postUriBad = new AtUri(postA.uriStr)
235
130
  postUriBad.rkey = 'badrkey'
236
131
 
237
- const promiseA = createReport({
132
+ const promiseA = sc.createReport({
238
133
  reasonType: REASONSPAM,
239
- content: {
134
+ subject: {
240
135
  $type: 'com.atproto.repo.strongRef',
241
136
  uri: postUriBad.toString(),
242
137
  cid: postA.cidStr,
243
138
  },
244
- author: sc.dids.alice,
139
+ reportedBy: sc.dids.alice,
245
140
  })
246
141
  await expect(promiseA).resolves.toBeDefined()
247
142
 
248
- const promiseB = createReport({
143
+ const promiseB = sc.createReport({
249
144
  reasonType: REASONOTHER,
250
145
  reason: 'defamation',
251
- content: {
146
+ subject: {
252
147
  $type: 'com.atproto.repo.strongRef',
253
148
  uri: postB.uri.toString(),
254
149
  cid: postA.cidStr, // bad cid
255
150
  },
256
- author: sc.dids.carol,
151
+ reportedBy: sc.dids.carol,
257
152
  })
258
153
  await expect(promiseB).resolves.toBeDefined()
259
154
  })
@@ -264,29 +159,27 @@ describe('moderation', () => {
264
159
  const post = sc.posts[sc.dids.bob][1].ref
265
160
 
266
161
  await Promise.all([
267
- createReport({
162
+ sc.createReport({
268
163
  reasonType: REASONSPAM,
269
- account: sc.dids.bob,
270
- author: sc.dids.alice,
164
+ subject: repoSubject(sc.dids.bob),
165
+ reportedBy: sc.dids.alice,
271
166
  }),
272
- createReport({
167
+ sc.createReport({
273
168
  reasonType: REASONOTHER,
274
169
  reason: 'defamation',
275
- content: {
276
- uri: post.uri.toString(),
277
- cid: post.cid.toString(),
278
- },
279
- author: sc.dids.carol,
170
+ subject: recordSubject(post),
171
+ reportedBy: sc.dids.carol,
280
172
  }),
281
173
  ])
282
174
 
283
- await performTakedown({
284
- account: sc.dids.bob,
175
+ await modClient.performTakedown({
176
+ subject: repoSubject(sc.dids.bob),
285
177
  })
286
178
 
287
- const moderationStatusOnBobsAccount = await getStatuses({
288
- subject: sc.dids.bob,
289
- })
179
+ const moderationStatusOnBobsAccount =
180
+ await modClient.queryModerationStatuses({
181
+ subject: sc.dids.bob,
182
+ })
290
183
 
291
184
  // Validate that subject status is set to review closed and takendown flag is on
292
185
  expect(moderationStatusOnBobsAccount.subjectStatuses[0]).toMatchObject({
@@ -299,8 +192,8 @@ describe('moderation', () => {
299
192
  })
300
193
 
301
194
  // Cleanup
302
- await performReverseTakedown({
303
- account: sc.dids.bob,
195
+ await modClient.performReverseTakedown({
196
+ subject: repoSubject(sc.dids.bob),
304
197
  })
305
198
  })
306
199
 
@@ -311,7 +204,7 @@ describe('moderation', () => {
311
204
  uri: alicesPostRef.uri.toString(),
312
205
  cid: alicesPostRef.cid.toString(),
313
206
  }
314
- await agent.api.com.atproto.admin.emitModerationEvent(
207
+ await modClient.emitModerationEvent(
315
208
  {
316
209
  event: {
317
210
  $type: 'com.atproto.admin.defs#modEventEscalate',
@@ -320,13 +213,10 @@ describe('moderation', () => {
320
213
  subject: alicesPostSubject,
321
214
  createdBy: 'did:example:admin',
322
215
  },
323
- {
324
- encoding: 'application/json',
325
- headers: ozone.adminAuthHeaders('triage'),
326
- },
216
+ 'triage',
327
217
  )
328
218
 
329
- const alicesPostStatus = await getStatuses({
219
+ const alicesPostStatus = await modClient.queryModerationStatuses({
330
220
  subject: alicesPostRef.uri.toString(),
331
221
  })
332
222
 
@@ -344,7 +234,7 @@ describe('moderation', () => {
344
234
  uri: alicesPostRef.uri.toString(),
345
235
  cid: alicesPostRef.cid.toString(),
346
236
  }
347
- await agent.api.com.atproto.admin.emitModerationEvent(
237
+ await modClient.emitModerationEvent(
348
238
  {
349
239
  event: {
350
240
  $type: 'com.atproto.admin.defs#modEventComment',
@@ -354,13 +244,10 @@ describe('moderation', () => {
354
244
  subject: alicesPostSubject,
355
245
  createdBy: 'did:example:admin',
356
246
  },
357
- {
358
- encoding: 'application/json',
359
- headers: ozone.adminAuthHeaders('triage'),
360
- },
247
+ 'triage',
361
248
  )
362
249
 
363
- const alicesPostStatus = await getStatuses({
250
+ const alicesPostStatus = await modClient.queryModerationStatuses({
364
251
  subject: alicesPostRef.uri.toString(),
365
252
  })
366
253
 
@@ -383,17 +270,11 @@ describe('moderation', () => {
383
270
  },
384
271
  createdBy: 'did:example:admin',
385
272
  }
386
- return agent.api.com.atproto.admin.emitModerationEvent(
387
- {
388
- event,
389
- ...baseAction,
390
- ...overwrites,
391
- },
392
- {
393
- encoding: 'application/json',
394
- headers: ozone.adminAuthHeaders(),
395
- },
396
- )
273
+ return modClient.emitModerationEvent({
274
+ event,
275
+ ...baseAction,
276
+ ...overwrites,
277
+ })
397
278
  }
398
279
  // Validate that subject status is marked as escalated
399
280
  await emitModEvent({
@@ -407,9 +288,10 @@ describe('moderation', () => {
407
288
  await emitModEvent({
408
289
  $type: 'com.atproto.admin.defs#modEventEscalate',
409
290
  })
410
- const alicesPostStatusAfterEscalation = await getStatuses({
411
- subject: alicesPostRef.uriStr,
412
- })
291
+ const alicesPostStatusAfterEscalation =
292
+ await modClient.queryModerationStatuses({
293
+ subject: alicesPostRef.uriStr,
294
+ })
413
295
  expect(
414
296
  alicesPostStatusAfterEscalation.subjectStatuses[0].reviewState,
415
297
  ).toEqual(REVIEWESCALATED)
@@ -425,9 +307,10 @@ describe('moderation', () => {
425
307
  $type: 'com.atproto.admin.defs#modEventTakedown',
426
308
  })
427
309
 
428
- const alicesPostStatusAfterTakedown = await getStatuses({
429
- subject: alicesPostRef.uriStr,
430
- })
310
+ const alicesPostStatusAfterTakedown =
311
+ await modClient.queryModerationStatuses({
312
+ subject: alicesPostRef.uriStr,
313
+ })
431
314
  expect(alicesPostStatusAfterTakedown.subjectStatuses[0]).toMatchObject({
432
315
  reviewState: REVIEWCLOSED,
433
316
  takendown: true,
@@ -436,9 +319,10 @@ describe('moderation', () => {
436
319
  await emitModEvent({
437
320
  $type: 'com.atproto.admin.defs#modEventReverseTakedown',
438
321
  })
439
- const alicesPostStatusAfterRevert = await getStatuses({
440
- subject: alicesPostRef.uriStr,
441
- })
322
+ const alicesPostStatusAfterRevert =
323
+ await modClient.queryModerationStatuses({
324
+ subject: alicesPostRef.uriStr,
325
+ })
442
326
  // Validate that after reverting, the status of the subject is reverted to the last status changing event
443
327
  expect(alicesPostStatusAfterRevert.subjectStatuses[0]).toMatchObject({
444
328
  reviewState: REVIEWCLOSED,
@@ -598,7 +482,7 @@ describe('moderation', () => {
598
482
  })
599
483
 
600
484
  it('does not allow triage moderators to label.', async () => {
601
- const attemptLabel = agent.api.com.atproto.admin.emitModerationEvent(
485
+ const attemptLabel = modClient.emitModerationEvent(
602
486
  {
603
487
  event: {
604
488
  $type: 'com.atproto.admin.defs#modEventLabel',
@@ -612,10 +496,7 @@ describe('moderation', () => {
612
496
  did: sc.dids.bob,
613
497
  },
614
498
  },
615
- {
616
- encoding: 'application/json',
617
- headers: network.ozone.adminAuthHeaders('triage'),
618
- },
499
+ 'triage',
619
500
  )
620
501
  await expect(attemptLabel).rejects.toThrow(
621
502
  'Must be a full moderator to label content',
@@ -623,29 +504,29 @@ describe('moderation', () => {
623
504
  })
624
505
 
625
506
  it('does not allow take down event on takendown post or reverse takedown on available post.', async () => {
626
- await performTakedown({
627
- account: sc.dids.bob,
507
+ await modClient.performTakedown({
508
+ subject: repoSubject(sc.dids.bob),
628
509
  })
629
510
  await expect(
630
- performTakedown({
631
- account: sc.dids.bob,
511
+ modClient.performTakedown({
512
+ subject: repoSubject(sc.dids.bob),
632
513
  }),
633
514
  ).rejects.toThrow('Subject is already taken down')
634
515
 
635
516
  // Cleanup
636
- await performReverseTakedown({
637
- account: sc.dids.bob,
517
+ await modClient.performReverseTakedown({
518
+ subject: repoSubject(sc.dids.bob),
638
519
  })
639
520
  await expect(
640
- performReverseTakedown({
641
- account: sc.dids.bob,
521
+ modClient.performReverseTakedown({
522
+ subject: repoSubject(sc.dids.bob),
642
523
  }),
643
524
  ).rejects.toThrow('Subject is not taken down')
644
525
  })
645
526
 
646
527
  it('fans out repo takedowns', async () => {
647
- await performTakedown({
648
- account: sc.dids.bob,
528
+ await modClient.performTakedown({
529
+ subject: repoSubject(sc.dids.bob),
649
530
  })
650
531
  await ozone.processAll()
651
532
 
@@ -672,7 +553,9 @@ describe('moderation', () => {
672
553
  expect(takedownLabel1).toBeDefined()
673
554
 
674
555
  // cleanup
675
- await performReverseTakedown({ account: sc.dids.bob })
556
+ await modClient.performReverseTakedown({
557
+ subject: repoSubject(sc.dids.bob),
558
+ })
676
559
  await ozone.processAll()
677
560
 
678
561
  const pdsRes2 = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
@@ -699,11 +582,10 @@ describe('moderation', () => {
699
582
  })
700
583
 
701
584
  it('fans out record takedowns', async () => {
702
- const post = sc.posts[sc.dids.bob][0]
703
- const uri = post.ref.uriStr
704
- const cid = post.ref.cidStr
705
- await performTakedown({
706
- content: { uri, cid },
585
+ const post = sc.posts[sc.dids.bob][0].ref
586
+ const uri = post.uriStr
587
+ await modClient.performTakedown({
588
+ subject: recordSubject(post),
707
589
  })
708
590
  await ozone.processAll()
709
591
 
@@ -723,7 +605,7 @@ describe('moderation', () => {
723
605
  expect(takedownLabel1).toBeDefined()
724
606
 
725
607
  // cleanup
726
- await performReverseTakedown({ content: { uri, cid } })
608
+ await modClient.performReverseTakedown({ subject: recordSubject(post) })
727
609
  await ozone.processAll()
728
610
 
729
611
  const pdsRes2 = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
@@ -742,7 +624,7 @@ describe('moderation', () => {
742
624
  })
743
625
 
744
626
  it('allows full moderators to takedown.', async () => {
745
- await agent.api.com.atproto.admin.emitModerationEvent(
627
+ await modClient.emitModerationEvent(
746
628
  {
747
629
  event: {
748
630
  $type: 'com.atproto.admin.defs#modEventTakedown',
@@ -753,10 +635,7 @@ describe('moderation', () => {
753
635
  did: sc.dids.bob,
754
636
  },
755
637
  },
756
- {
757
- encoding: 'application/json',
758
- headers: network.ozone.adminAuthHeaders('moderator'),
759
- },
638
+ 'moderator',
760
639
  )
761
640
  // cleanup
762
641
  await reverse({
@@ -768,47 +647,42 @@ describe('moderation', () => {
768
647
  })
769
648
 
770
649
  it('does not allow non-full moderators to takedown.', async () => {
771
- const attemptTakedownTriage =
772
- agent.api.com.atproto.admin.emitModerationEvent(
773
- {
774
- event: {
775
- $type: 'com.atproto.admin.defs#modEventTakedown',
776
- },
777
- createdBy: 'did:example:moderator',
778
- subject: {
779
- $type: 'com.atproto.admin.defs#repoRef',
780
- did: sc.dids.bob,
781
- },
650
+ const attemptTakedownTriage = modClient.emitModerationEvent(
651
+ {
652
+ event: {
653
+ $type: 'com.atproto.admin.defs#modEventTakedown',
782
654
  },
783
- {
784
- encoding: 'application/json',
785
- headers: network.ozone.adminAuthHeaders('triage'),
655
+ createdBy: 'did:example:moderator',
656
+ subject: {
657
+ $type: 'com.atproto.admin.defs#repoRef',
658
+ did: sc.dids.bob,
786
659
  },
787
- )
660
+ },
661
+ 'triage',
662
+ )
788
663
  await expect(attemptTakedownTriage).rejects.toThrow(
789
664
  'Must be a full moderator to take this type of action',
790
665
  )
791
666
  })
792
667
 
793
668
  it('automatically reverses actions marked with duration', async () => {
794
- await createReport({
669
+ await sc.createReport({
795
670
  reasonType: REASONSPAM,
796
- account: sc.dids.bob,
797
- author: sc.dids.alice,
671
+ subject: repoSubject(sc.dids.bob),
672
+ reportedBy: sc.dids.alice,
798
673
  })
799
- const { data: action } = await performTakedown({
800
- account: sc.dids.bob,
674
+ const action = await modClient.performTakedown({
675
+ subject: repoSubject(sc.dids.bob),
801
676
  // Use negative value to set the expiry time in the past so that the action is automatically reversed
802
677
  // right away without having to wait n number of hours for a successful assertion
803
678
  durationInHours: -1,
804
679
  })
805
680
  await ozone.processAll()
806
681
 
807
- const { data: statusesAfterTakedown } =
808
- await agent.api.com.atproto.admin.queryModerationStatuses(
809
- { subject: sc.dids.bob },
810
- { headers: network.ozone.adminAuthHeaders('moderator') },
811
- )
682
+ const statusesAfterTakedown = await modClient.queryModerationStatuses(
683
+ { subject: sc.dids.bob },
684
+ 'moderator',
685
+ )
812
686
 
813
687
  expect(statusesAfterTakedown.subjectStatuses[0]).toMatchObject({
814
688
  takendown: true,
@@ -822,14 +696,11 @@ describe('moderation', () => {
822
696
  await reverser.findAndRevertDueActions()
823
697
  await ozone.processAll()
824
698
 
825
- const [{ data: eventList }, { data: statuses }] = await Promise.all([
826
- agent.api.com.atproto.admin.queryModerationEvents(
699
+ const [eventList, statuses] = await Promise.all([
700
+ modClient.queryModerationEvents({ subject: sc.dids.bob }, 'moderator'),
701
+ modClient.queryModerationStatuses(
827
702
  { subject: sc.dids.bob },
828
- { headers: network.ozone.adminAuthHeaders('moderator') },
829
- ),
830
- agent.api.com.atproto.admin.queryModerationStatuses(
831
- { subject: sc.dids.bob },
832
- { headers: network.ozone.adminAuthHeaders('moderator') },
703
+ 'moderator',
833
704
  ),
834
705
  ])
835
706
 
@@ -873,22 +744,16 @@ describe('moderation', () => {
873
744
  },
874
745
  ) {
875
746
  const { createLabelVals, negateLabelVals } = opts
876
- const result = await agent.api.com.atproto.admin.emitModerationEvent(
877
- {
878
- event: {
879
- $type: 'com.atproto.admin.defs#modEventLabel',
880
- createLabelVals,
881
- negateLabelVals,
882
- },
883
- createdBy: 'did:example:admin',
884
- reason: 'Y',
885
- ...opts,
886
- },
887
- {
888
- encoding: 'application/json',
889
- headers: network.ozone.adminAuthHeaders(),
747
+ const result = await modClient.emitModerationEvent({
748
+ event: {
749
+ $type: 'com.atproto.admin.defs#modEventLabel',
750
+ createLabelVals,
751
+ negateLabelVals,
890
752
  },
891
- )
753
+ createdBy: 'did:example:admin',
754
+ reason: 'Y',
755
+ ...opts,
756
+ })
892
757
  return result.data
893
758
  }
894
759
 
@@ -897,26 +762,20 @@ describe('moderation', () => {
897
762
  subject: ComAtprotoAdminEmitModerationEvent.InputSchema['subject']
898
763
  },
899
764
  ) {
900
- await agent.api.com.atproto.admin.emitModerationEvent(
901
- {
902
- event: {
903
- $type: 'com.atproto.admin.defs#modEventReverseTakedown',
904
- },
905
- createdBy: 'did:example:admin',
906
- reason: 'Y',
907
- ...opts,
908
- },
909
- {
910
- encoding: 'application/json',
911
- headers: network.ozone.adminAuthHeaders(),
765
+ await modClient.emitModerationEvent({
766
+ event: {
767
+ $type: 'com.atproto.admin.defs#modEventReverseTakedown',
912
768
  },
913
- )
769
+ createdBy: 'did:example:admin',
770
+ reason: 'Y',
771
+ ...opts,
772
+ })
914
773
  }
915
774
 
916
775
  async function getRecordLabels(uri: string) {
917
776
  const result = await agent.api.com.atproto.admin.getRecord(
918
777
  { uri },
919
- { headers: network.ozone.adminAuthHeaders() },
778
+ { headers: await network.ozone.modHeaders() },
920
779
  )
921
780
  const labels = result.data.labels ?? []
922
781
  return labels.map((l) => l.val)
@@ -925,7 +784,7 @@ describe('moderation', () => {
925
784
  async function getRepoLabels(did: string) {
926
785
  const result = await agent.api.com.atproto.admin.getRepo(
927
786
  { did },
928
- { headers: network.ozone.adminAuthHeaders() },
787
+ { headers: await network.ozone.modHeaders() },
929
788
  )
930
789
  const labels = result.data.labels ?? []
931
790
  return labels.map((l) => l.val)
@@ -951,18 +810,15 @@ describe('moderation', () => {
951
810
  await fetch(imageUri)
952
811
  const cached = await fetch(imageUri)
953
812
  expect(cached.headers.get('x-cache')).toEqual('hit')
954
- await performTakedown({
955
- content: {
956
- uri: post.ref.uriStr,
957
- cid: post.ref.cidStr,
958
- },
813
+ await modClient.performTakedown({
814
+ subject: recordSubject(post.ref),
959
815
  subjectBlobCids: [blob.image.ref.toString()],
960
816
  })
961
817
  await ozone.processAll()
962
818
  })
963
819
 
964
820
  it('sets blobCids in moderation status', async () => {
965
- const { subjectStatuses } = await getStatuses({
821
+ const { subjectStatuses } = await modClient.queryModerationStatuses({
966
822
  subject: post.ref.uriStr,
967
823
  })
968
824
 
@@ -1020,11 +876,8 @@ describe('moderation', () => {
1020
876
  })
1021
877
 
1022
878
  it('restores blob when action is reversed.', async () => {
1023
- await performReverseTakedown({
1024
- content: {
1025
- uri: post.ref.uriStr,
1026
- cid: post.ref.cidStr,
1027
- },
879
+ await modClient.performReverseTakedown({
880
+ subject: recordSubject(post.ref),
1028
881
  subjectBlobCids: [blob.image.ref.toString()],
1029
882
  })
1030
883