@atproto/ozone 0.1.46 → 0.1.48

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 (95) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/api/index.d.ts.map +1 -1
  3. package/dist/api/index.js +4 -0
  4. package/dist/api/index.js.map +1 -1
  5. package/dist/api/moderation/getRecord.d.ts.map +1 -1
  6. package/dist/api/moderation/getRecord.js +5 -4
  7. package/dist/api/moderation/getRecord.js.map +1 -1
  8. package/dist/api/moderation/getRecords.d.ts +4 -0
  9. package/dist/api/moderation/getRecords.d.ts.map +1 -0
  10. package/dist/api/moderation/getRecords.js +37 -0
  11. package/dist/api/moderation/getRecords.js.map +1 -0
  12. package/dist/api/moderation/getRepo.d.ts.map +1 -1
  13. package/dist/api/moderation/getRepo.js +5 -4
  14. package/dist/api/moderation/getRepo.js.map +1 -1
  15. package/dist/api/moderation/getRepos.d.ts +4 -0
  16. package/dist/api/moderation/getRepos.d.ts.map +1 -0
  17. package/dist/api/moderation/getRepos.js +36 -0
  18. package/dist/api/moderation/getRepos.js.map +1 -0
  19. package/dist/api/proxied.d.ts.map +1 -1
  20. package/dist/api/proxied.js +39 -0
  21. package/dist/api/proxied.js.map +1 -1
  22. package/dist/api/util.d.ts +1 -1
  23. package/dist/api/util.d.ts.map +1 -1
  24. package/dist/api/util.js +13 -9
  25. package/dist/api/util.js.map +1 -1
  26. package/dist/db/migrations/20241001T205730722Z-subject-status-review-state-index.d.ts +4 -0
  27. package/dist/db/migrations/20241001T205730722Z-subject-status-review-state-index.d.ts.map +1 -0
  28. package/dist/db/migrations/20241001T205730722Z-subject-status-review-state-index.js +18 -0
  29. package/dist/db/migrations/20241001T205730722Z-subject-status-review-state-index.js.map +1 -0
  30. package/dist/db/migrations/index.d.ts +1 -0
  31. package/dist/db/migrations/index.d.ts.map +1 -1
  32. package/dist/db/migrations/index.js +2 -1
  33. package/dist/db/migrations/index.js.map +1 -1
  34. package/dist/lexicon/index.d.ts +15 -0
  35. package/dist/lexicon/index.d.ts.map +1 -1
  36. package/dist/lexicon/index.js +40 -1
  37. package/dist/lexicon/index.js.map +1 -1
  38. package/dist/lexicon/lexicons.d.ts +261 -0
  39. package/dist/lexicon/lexicons.d.ts.map +1 -1
  40. package/dist/lexicon/lexicons.js +269 -0
  41. package/dist/lexicon/lexicons.js.map +1 -1
  42. package/dist/lexicon/types/com/atproto/repo/getRecord.d.ts +1 -0
  43. package/dist/lexicon/types/com/atproto/repo/getRecord.d.ts.map +1 -1
  44. package/dist/lexicon/types/tools/ozone/moderation/getRecords.d.ts +39 -0
  45. package/dist/lexicon/types/tools/ozone/moderation/getRecords.d.ts.map +1 -0
  46. package/dist/lexicon/types/tools/ozone/moderation/getRecords.js +3 -0
  47. package/dist/lexicon/types/tools/ozone/moderation/getRecords.js.map +1 -0
  48. package/dist/lexicon/types/tools/ozone/moderation/getRepos.d.ts +39 -0
  49. package/dist/lexicon/types/tools/ozone/moderation/getRepos.d.ts.map +1 -0
  50. package/dist/lexicon/types/tools/ozone/moderation/getRepos.js +3 -0
  51. package/dist/lexicon/types/tools/ozone/moderation/getRepos.js.map +1 -0
  52. package/dist/lexicon/types/tools/ozone/signature/defs.d.ts +12 -0
  53. package/dist/lexicon/types/tools/ozone/signature/defs.d.ts.map +1 -0
  54. package/dist/lexicon/types/tools/ozone/signature/defs.js +16 -0
  55. package/dist/lexicon/types/tools/ozone/signature/defs.js.map +1 -0
  56. package/dist/lexicon/types/tools/ozone/signature/findCorrelation.d.ts +36 -0
  57. package/dist/lexicon/types/tools/ozone/signature/findCorrelation.d.ts.map +1 -0
  58. package/dist/lexicon/types/tools/ozone/signature/findCorrelation.js +3 -0
  59. package/dist/lexicon/types/tools/ozone/signature/findCorrelation.js.map +1 -0
  60. package/dist/lexicon/types/tools/ozone/signature/findRelatedAccounts.d.ts +48 -0
  61. package/dist/lexicon/types/tools/ozone/signature/findRelatedAccounts.d.ts.map +1 -0
  62. package/dist/lexicon/types/tools/ozone/signature/findRelatedAccounts.js +16 -0
  63. package/dist/lexicon/types/tools/ozone/signature/findRelatedAccounts.js.map +1 -0
  64. package/dist/lexicon/types/tools/ozone/signature/searchAccounts.d.ts +39 -0
  65. package/dist/lexicon/types/tools/ozone/signature/searchAccounts.d.ts.map +1 -0
  66. package/dist/lexicon/types/tools/ozone/signature/searchAccounts.js +3 -0
  67. package/dist/lexicon/types/tools/ozone/signature/searchAccounts.js.map +1 -0
  68. package/dist/mod-service/views.d.ts +5 -5
  69. package/dist/mod-service/views.d.ts.map +1 -1
  70. package/dist/mod-service/views.js +75 -48
  71. package/dist/mod-service/views.js.map +1 -1
  72. package/package.json +5 -5
  73. package/src/api/index.ts +4 -0
  74. package/src/api/moderation/getRecord.ts +7 -5
  75. package/src/api/moderation/getRecords.ts +50 -0
  76. package/src/api/moderation/getRepo.ts +7 -5
  77. package/src/api/moderation/getRepos.ts +41 -0
  78. package/src/api/proxied.ts +51 -0
  79. package/src/api/util.ts +16 -9
  80. package/src/db/migrations/20241001T205730722Z-subject-status-review-state-index.ts +15 -0
  81. package/src/db/migrations/index.ts +1 -0
  82. package/src/lexicon/index.ts +70 -0
  83. package/src/lexicon/lexicons.ts +273 -0
  84. package/src/lexicon/types/com/atproto/repo/getRecord.ts +1 -0
  85. package/src/lexicon/types/tools/ozone/moderation/getRecords.ts +50 -0
  86. package/src/lexicon/types/tools/ozone/moderation/getRepos.ts +50 -0
  87. package/src/lexicon/types/tools/ozone/signature/defs.ts +25 -0
  88. package/src/lexicon/types/tools/ozone/signature/findCorrelation.ts +46 -0
  89. package/src/lexicon/types/tools/ozone/signature/findRelatedAccounts.ts +71 -0
  90. package/src/lexicon/types/tools/ozone/signature/searchAccounts.ts +49 -0
  91. package/src/mod-service/views.ts +93 -52
  92. package/tests/__snapshots__/get-records.test.ts.snap +153 -0
  93. package/tests/__snapshots__/get-repos.test.ts.snap +108 -0
  94. package/tests/get-records.test.ts +87 -0
  95. package/tests/get-repos.test.ts +87 -0
@@ -223,25 +223,33 @@ export class ModerationViews {
223
223
  }
224
224
  }
225
225
 
226
- async repoDetail(
227
- did: string,
226
+ async repoDetails(
227
+ dids: string[],
228
228
  labelers?: ParsedLabelers,
229
- ): Promise<RepoViewDetail | undefined> {
229
+ ): Promise<Map<string, RepoView>> {
230
+ const results = new Map<string, RepoView>()
230
231
  const [repos, localLabels, externalLabels] = await Promise.all([
231
- this.repos([did]),
232
- this.labels(did),
233
- this.getExternalLabels([did], labelers),
232
+ this.repos(dids),
233
+ this.labels(dids),
234
+ this.getExternalLabels(dids, labelers),
234
235
  ])
235
- const repo = repos.get(did)
236
- if (!repo) return
237
236
 
238
- return {
239
- ...repo,
240
- moderation: {
241
- ...repo.moderation,
242
- },
243
- labels: [...localLabels, ...externalLabels],
244
- }
237
+ repos.forEach((repo, did) => {
238
+ const labels = [
239
+ ...(localLabels.get(did) || []),
240
+ ...(externalLabels.get(did) || []),
241
+ ]
242
+ const repoView = {
243
+ ...repo,
244
+ labels,
245
+ moderation: {
246
+ ...repo.moderation,
247
+ },
248
+ }
249
+ results.set(did, repoView)
250
+ })
251
+
252
+ return results
245
253
  }
246
254
 
247
255
  async fetchRecords(
@@ -308,47 +316,59 @@ export class ModerationViews {
308
316
  }, new Map<string, RecordView>())
309
317
  }
310
318
 
311
- async recordDetail(
312
- subject: RecordSubject,
319
+ async recordDetails(
320
+ subjects: RecordSubject[],
313
321
  labelers?: ParsedLabelers,
314
- ): Promise<RecordViewDetail | undefined> {
315
- const [records, subjectStatusesResult] = await Promise.all([
316
- this.records([subject]),
317
- this.getSubjectStatus([subject.uri]),
318
- ])
319
- const record = records.get(subject.uri)
320
- if (!record) return undefined
322
+ ): Promise<Map<string, RecordViewDetail>> {
323
+ const subjectUris = subjects.map((s) => s.uri)
324
+ const [records, subjectStatusesResult, localLabels, externalLabels] =
325
+ await Promise.all([
326
+ this.records(subjects),
327
+ this.getSubjectStatus(subjectUris),
328
+ this.labels(subjectUris),
329
+ this.getExternalLabels(subjectUris, labelers),
330
+ ])
331
+
332
+ const results = new Map<string, RecordViewDetail>()
333
+
334
+ await Promise.all(
335
+ Array.from(records.entries()).map(async ([uri, record]) => {
336
+ const selfLabels = getSelfLabels({
337
+ uri: record.uri,
338
+ cid: record.cid,
339
+ record: record.value,
340
+ })
321
341
 
322
- const status = subjectStatusesResult.get(subject.uri)
342
+ const status = subjectStatusesResult.get(uri)
343
+ const blobs = await this.blob(findBlobRefs(record.value))
323
344
 
324
- const [blobs, labels, externalLabels, subjectStatus] = await Promise.all([
325
- this.blob(findBlobRefs(record.value)),
326
- this.labels(record.uri),
327
- this.getExternalLabels([record.uri], labelers),
328
- status ? this.formatSubjectStatus(status) : Promise.resolve(undefined),
329
- ])
330
- const selfLabels = getSelfLabels({
331
- uri: record.uri,
332
- cid: record.cid,
333
- record: record.value,
334
- })
345
+ results.set(uri, {
346
+ ...record,
347
+ blobs,
348
+ moderation: {
349
+ ...record.moderation,
350
+ subjectStatus: status
351
+ ? this.formatSubjectStatus(status)
352
+ : undefined,
353
+ },
354
+ labels: [
355
+ ...(localLabels.get(uri) || []),
356
+ ...selfLabels,
357
+ ...(externalLabels.get(uri) || []),
358
+ ],
359
+ })
360
+ }),
361
+ )
335
362
 
336
- return {
337
- ...record,
338
- blobs,
339
- moderation: {
340
- ...record.moderation,
341
- subjectStatus,
342
- },
343
- labels: [...labels, ...selfLabels, ...externalLabels],
344
- }
363
+ return results
345
364
  }
346
365
 
347
366
  async getExternalLabels(
348
367
  subjects: string[],
349
368
  labelers?: ParsedLabelers,
350
- ): Promise<Label[]> {
351
- if (!labelers?.dids.length && !labelers?.redact.size) return []
369
+ ): Promise<Map<string, Label[]>> {
370
+ const results = new Map<string, Label[]>()
371
+ if (!labelers?.dids.length && !labelers?.redact.size) return results
352
372
  try {
353
373
  const {
354
374
  data: { labels },
@@ -356,13 +376,20 @@ export class ModerationViews {
356
376
  uriPatterns: subjects,
357
377
  sources: labelers.dids,
358
378
  })
359
- return labels
379
+ labels.forEach((label) => {
380
+ if (!results.has(label.uri)) {
381
+ results.set(label.uri, [label])
382
+ return
383
+ }
384
+ results.get(label.uri)?.push(label)
385
+ })
386
+ return results
360
387
  } catch (err) {
361
388
  httpLogger.error(
362
389
  { err, subjects, labelers },
363
390
  'failed to resolve labels from appview',
364
391
  )
365
- return []
392
+ return results
366
393
  }
367
394
  }
368
395
 
@@ -452,14 +479,28 @@ export class ModerationViews {
452
479
  })
453
480
  }
454
481
 
455
- async labels(subject: string, includeNeg?: boolean): Promise<Label[]> {
482
+ async labels(
483
+ subjects: string[],
484
+ includeNeg?: boolean,
485
+ ): Promise<Map<string, Label[]>> {
486
+ const labels = new Map<string, Label[]>()
456
487
  const res = await this.db.db
457
488
  .selectFrom('label')
458
- .where('label.uri', '=', subject)
489
+ .where('label.uri', 'in', subjects)
459
490
  .if(!includeNeg, (qb) => qb.where('neg', '=', false))
460
491
  .selectAll()
461
492
  .execute()
462
- return Promise.all(res.map((l) => this.formatLabelAndEnsureSig(l)))
493
+
494
+ await Promise.all(
495
+ res.map(async (labelRow) => {
496
+ const signedLabel = await this.formatLabelAndEnsureSig(labelRow)
497
+ if (!labels.has(labelRow.uri)) {
498
+ labels.set(labelRow.uri, [])
499
+ }
500
+ labels.get(labelRow.uri)?.push(signedLabel)
501
+ }),
502
+ )
503
+ return labels
463
504
  }
464
505
 
465
506
  async formatLabelAndEnsureSig(row: LabelRow) {
@@ -0,0 +1,153 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`admin get records view get multiple records by uris 1`] = `
4
+ Object {
5
+ "records": Array [
6
+ Object {
7
+ "$type": "tools.ozone.moderation.defs#recordViewDetail",
8
+ "blobCids": Array [],
9
+ "blobs": Array [],
10
+ "cid": "cids(0)",
11
+ "indexedAt": "1970-01-01T00:00:00.000Z",
12
+ "labels": Array [
13
+ Object {
14
+ "cid": "cids(0)",
15
+ "cts": "1970-01-01T00:00:00.000Z",
16
+ "sig": Object {
17
+ "$bytes": "sig(0)",
18
+ },
19
+ "src": "user(2)",
20
+ "uri": "record(0)",
21
+ "val": "!takedown",
22
+ "ver": 1,
23
+ },
24
+ Object {
25
+ "cid": "cids(0)",
26
+ "cts": "1970-01-01T00:00:00.000Z",
27
+ "src": "user(0)",
28
+ "uri": "record(0)",
29
+ "val": "self-label",
30
+ },
31
+ ],
32
+ "moderation": Object {
33
+ "subjectStatus": Object {
34
+ "createdAt": "1970-01-01T00:00:00.000Z",
35
+ "id": 1,
36
+ "lastReportedAt": "1970-01-01T00:00:00.000Z",
37
+ "lastReviewedAt": "1970-01-01T00:00:00.000Z",
38
+ "lastReviewedBy": "user(1)",
39
+ "reviewState": "tools.ozone.moderation.defs#reviewClosed",
40
+ "subject": Object {
41
+ "$type": "com.atproto.repo.strongRef",
42
+ "cid": "cids(0)",
43
+ "uri": "record(0)",
44
+ },
45
+ "subjectBlobCids": Array [],
46
+ "subjectRepoHandle": "alice.test",
47
+ "tags": Array [
48
+ "lang:en",
49
+ ],
50
+ "takendown": true,
51
+ "updatedAt": "1970-01-01T00:00:00.000Z",
52
+ },
53
+ },
54
+ "repo": Object {
55
+ "did": "user(0)",
56
+ "email": "alice@test.com",
57
+ "handle": "alice.test",
58
+ "indexedAt": "1970-01-01T00:00:00.000Z",
59
+ "invitesDisabled": false,
60
+ "moderation": Object {},
61
+ "relatedRecords": Array [
62
+ Object {
63
+ "$type": "app.bsky.actor.profile",
64
+ "avatar": Object {
65
+ "$type": "blob",
66
+ "mimeType": "image/jpeg",
67
+ "ref": Object {
68
+ "$link": "cids(1)",
69
+ },
70
+ "size": 3976,
71
+ },
72
+ "createdAt": "1970-01-01T00:00:00.000Z",
73
+ "description": "its me!",
74
+ "displayName": "ali",
75
+ "labels": Object {
76
+ "$type": "com.atproto.label.defs#selfLabels",
77
+ "values": Array [
78
+ Object {
79
+ "val": "self-label-a",
80
+ },
81
+ Object {
82
+ "val": "self-label-b",
83
+ },
84
+ ],
85
+ },
86
+ },
87
+ ],
88
+ },
89
+ "uri": "record(0)",
90
+ "value": Object {
91
+ "$type": "app.bsky.feed.post",
92
+ "createdAt": "1970-01-01T00:00:00.000Z",
93
+ "labels": Object {
94
+ "$type": "com.atproto.label.defs#selfLabels",
95
+ "values": Array [
96
+ Object {
97
+ "val": "self-label",
98
+ },
99
+ ],
100
+ },
101
+ "text": "hey there",
102
+ },
103
+ },
104
+ Object {
105
+ "$type": "tools.ozone.moderation.defs#recordViewDetail",
106
+ "blobCids": Array [],
107
+ "blobs": Array [],
108
+ "cid": "cids(2)",
109
+ "indexedAt": "1970-01-01T00:00:00.000Z",
110
+ "labels": Array [],
111
+ "moderation": Object {},
112
+ "repo": Object {
113
+ "did": "user(3)",
114
+ "email": "bob@test.com",
115
+ "handle": "bob.test",
116
+ "indexedAt": "1970-01-01T00:00:00.000Z",
117
+ "invitesDisabled": false,
118
+ "moderation": Object {},
119
+ "relatedRecords": Array [
120
+ Object {
121
+ "$type": "app.bsky.actor.profile",
122
+ "avatar": Object {
123
+ "$type": "blob",
124
+ "mimeType": "image/jpeg",
125
+ "ref": Object {
126
+ "$link": "cids(1)",
127
+ },
128
+ "size": 3976,
129
+ },
130
+ "createdAt": "1970-01-01T00:00:00.000Z",
131
+ "description": "hi im bob label_me",
132
+ "displayName": "bobby",
133
+ },
134
+ ],
135
+ },
136
+ "uri": "record(1)",
137
+ "value": Object {
138
+ "$type": "app.bsky.feed.post",
139
+ "createdAt": "1970-01-01T00:00:00.000Z",
140
+ "langs": Array [
141
+ "en-US",
142
+ "i-klingon",
143
+ ],
144
+ "text": "bob back at it again!",
145
+ },
146
+ },
147
+ Object {
148
+ "$type": "tools.ozone.moderation.defs#recordViewNotFound",
149
+ "uri": "record(2)",
150
+ },
151
+ ],
152
+ }
153
+ `;
@@ -0,0 +1,108 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`admin get multiple repos gets multiple repos by did 1`] = `
4
+ Object {
5
+ "repos": Array [
6
+ Object {
7
+ "$type": "tools.ozone.moderation.defs#repoViewDetail",
8
+ "did": "user(0)",
9
+ "email": "alice@test.com",
10
+ "handle": "alice.test",
11
+ "indexedAt": "1970-01-01T00:00:00.000Z",
12
+ "invites": Array [],
13
+ "invitesDisabled": false,
14
+ "labels": Array [
15
+ Object {
16
+ "cts": "1970-01-01T00:00:00.000Z",
17
+ "sig": Object {
18
+ "$bytes": "sig(0)",
19
+ },
20
+ "src": "user(2)",
21
+ "uri": "user(0)",
22
+ "val": "!takedown",
23
+ "ver": 1,
24
+ },
25
+ ],
26
+ "moderation": Object {
27
+ "subjectStatus": Object {
28
+ "createdAt": "1970-01-01T00:00:00.000Z",
29
+ "id": 1,
30
+ "lastReportedAt": "1970-01-01T00:00:00.000Z",
31
+ "lastReviewedAt": "1970-01-01T00:00:00.000Z",
32
+ "lastReviewedBy": "user(1)",
33
+ "reviewState": "tools.ozone.moderation.defs#reviewClosed",
34
+ "subject": Object {
35
+ "$type": "com.atproto.admin.defs#repoRef",
36
+ "did": "user(0)",
37
+ },
38
+ "subjectBlobCids": Array [],
39
+ "subjectRepoHandle": "alice.test",
40
+ "tags": Array [
41
+ "lang:und",
42
+ ],
43
+ "takendown": true,
44
+ "updatedAt": "1970-01-01T00:00:00.000Z",
45
+ },
46
+ },
47
+ "relatedRecords": Array [
48
+ Object {
49
+ "$type": "app.bsky.actor.profile",
50
+ "avatar": Object {
51
+ "$type": "blob",
52
+ "mimeType": "image/jpeg",
53
+ "ref": Object {
54
+ "$link": "cids(0)",
55
+ },
56
+ "size": 3976,
57
+ },
58
+ "createdAt": "1970-01-01T00:00:00.000Z",
59
+ "description": "its me!",
60
+ "displayName": "ali",
61
+ "labels": Object {
62
+ "$type": "com.atproto.label.defs#selfLabels",
63
+ "values": Array [
64
+ Object {
65
+ "val": "self-label-a",
66
+ },
67
+ Object {
68
+ "val": "self-label-b",
69
+ },
70
+ ],
71
+ },
72
+ },
73
+ ],
74
+ },
75
+ Object {
76
+ "$type": "tools.ozone.moderation.defs#repoViewDetail",
77
+ "did": "user(3)",
78
+ "email": "bob@test.com",
79
+ "handle": "bob.test",
80
+ "indexedAt": "1970-01-01T00:00:00.000Z",
81
+ "invites": Array [],
82
+ "invitesDisabled": false,
83
+ "labels": Array [],
84
+ "moderation": Object {},
85
+ "relatedRecords": Array [
86
+ Object {
87
+ "$type": "app.bsky.actor.profile",
88
+ "avatar": Object {
89
+ "$type": "blob",
90
+ "mimeType": "image/jpeg",
91
+ "ref": Object {
92
+ "$link": "cids(0)",
93
+ },
94
+ "size": 3976,
95
+ },
96
+ "createdAt": "1970-01-01T00:00:00.000Z",
97
+ "description": "hi im bob label_me",
98
+ "displayName": "bobby",
99
+ },
100
+ ],
101
+ },
102
+ Object {
103
+ "$type": "tools.ozone.moderation.defs#repoViewNotFound",
104
+ "did": "did:web:xyz",
105
+ },
106
+ ],
107
+ }
108
+ `;
@@ -0,0 +1,87 @@
1
+ import {
2
+ SeedClient,
3
+ TestNetwork,
4
+ basicSeed,
5
+ TestOzone,
6
+ ModeratorClient,
7
+ } from '@atproto/dev-env'
8
+ import { AtpAgent } from '@atproto/api'
9
+ import {
10
+ REASONOTHER,
11
+ REASONSPAM,
12
+ } from '../src/lexicon/types/com/atproto/moderation/defs'
13
+ import { forSnapshot } from './_util'
14
+ import { ids } from '../src/lexicon/lexicons'
15
+
16
+ describe('admin get records view', () => {
17
+ let network: TestNetwork
18
+ let ozone: TestOzone
19
+ let agent: AtpAgent
20
+ let sc: SeedClient
21
+ let modClient: ModeratorClient
22
+
23
+ beforeAll(async () => {
24
+ network = await TestNetwork.create({
25
+ dbPostgresSchema: 'ozone_admin_get_records',
26
+ })
27
+ ozone = network.ozone
28
+ agent = ozone.getClient()
29
+ sc = network.getSeedClient()
30
+ modClient = ozone.getModClient()
31
+ await basicSeed(sc)
32
+ await network.processAll()
33
+ })
34
+
35
+ afterAll(async () => {
36
+ await network.close()
37
+ })
38
+
39
+ beforeAll(async () => {
40
+ await sc.createReport({
41
+ reportedBy: sc.dids.bob,
42
+ reasonType: REASONSPAM,
43
+ subject: {
44
+ $type: 'com.atproto.repo.strongRef',
45
+ uri: sc.posts[sc.dids.alice][0].ref.uriStr,
46
+ cid: sc.posts[sc.dids.alice][0].ref.cidStr,
47
+ },
48
+ })
49
+ await sc.createReport({
50
+ reportedBy: sc.dids.carol,
51
+ reasonType: REASONOTHER,
52
+ reason: 'defamation',
53
+ subject: {
54
+ $type: 'com.atproto.repo.strongRef',
55
+ uri: sc.posts[sc.dids.alice][0].ref.uriStr,
56
+ cid: sc.posts[sc.dids.alice][0].ref.cidStr,
57
+ },
58
+ })
59
+ await modClient.emitEvent({
60
+ event: { $type: 'tools.ozone.moderation.defs#modEventTakedown' },
61
+ subject: {
62
+ $type: 'com.atproto.repo.strongRef',
63
+ uri: sc.posts[sc.dids.alice][0].ref.uriStr,
64
+ cid: sc.posts[sc.dids.alice][0].ref.cidStr,
65
+ },
66
+ })
67
+ await network.bsky.ctx.dataplane.takedownRecord({
68
+ recordUri: sc.posts[sc.dids.alice][0].ref.uriStr,
69
+ })
70
+ })
71
+
72
+ it('get multiple records by uris', async () => {
73
+ const { data } = await agent.tools.ozone.moderation.getRecords(
74
+ {
75
+ uris: [
76
+ sc.posts[sc.dids.alice][0].ref.uriStr,
77
+ sc.posts[sc.dids.bob][0].ref.uriStr,
78
+ // create a uri for a non-existent collection
79
+ sc.posts[sc.dids.bob][0].ref.uriStr.replace('.post', '.test'),
80
+ ],
81
+ },
82
+ { headers: await ozone.modHeaders(ids.ToolsOzoneModerationGetRecords) },
83
+ )
84
+
85
+ expect(forSnapshot(data)).toMatchSnapshot()
86
+ })
87
+ })
@@ -0,0 +1,87 @@
1
+ import {
2
+ SeedClient,
3
+ TestNetwork,
4
+ TestOzone,
5
+ basicSeed,
6
+ ModeratorClient,
7
+ } from '@atproto/dev-env'
8
+ import { AtpAgent } from '@atproto/api'
9
+ import {
10
+ REASONOTHER,
11
+ REASONSPAM,
12
+ } from '../src/lexicon/types/com/atproto/moderation/defs'
13
+ import { forSnapshot } from './_util'
14
+ import { ids } from '../src/lexicon/lexicons'
15
+
16
+ describe('admin get multiple repos', () => {
17
+ let network: TestNetwork
18
+ let ozone: TestOzone
19
+ let agent: AtpAgent
20
+ let pdsAgent: AtpAgent
21
+ let sc: SeedClient
22
+ let modClient: ModeratorClient
23
+
24
+ beforeAll(async () => {
25
+ network = await TestNetwork.create({
26
+ dbPostgresSchema: 'ozone_admin_get_repos',
27
+ })
28
+ ozone = network.ozone
29
+ agent = ozone.getClient()
30
+ pdsAgent = network.pds.getClient()
31
+ sc = network.getSeedClient()
32
+ modClient = ozone.getModClient()
33
+ await basicSeed(sc)
34
+ await pdsAgent.com.atproto.server.deactivateAccount(
35
+ {},
36
+ { encoding: 'application/json', headers: sc.getHeaders(sc.dids.dan) },
37
+ )
38
+ await network.processAll()
39
+ })
40
+
41
+ afterAll(async () => {
42
+ await network.close()
43
+ })
44
+
45
+ beforeAll(async () => {
46
+ await modClient.emitEvent({
47
+ event: { $type: 'tools.ozone.moderation.defs#modEventAcknowledge' },
48
+ subject: {
49
+ $type: 'com.atproto.admin.defs#repoRef',
50
+ did: sc.dids.alice,
51
+ },
52
+ })
53
+ await sc.createReport({
54
+ reportedBy: sc.dids.bob,
55
+ reasonType: REASONSPAM,
56
+ subject: {
57
+ $type: 'com.atproto.admin.defs#repoRef',
58
+ did: sc.dids.alice,
59
+ },
60
+ })
61
+ await sc.createReport({
62
+ reportedBy: sc.dids.carol,
63
+ reasonType: REASONOTHER,
64
+ reason: 'defamation',
65
+ subject: {
66
+ $type: 'com.atproto.admin.defs#repoRef',
67
+ did: sc.dids.alice,
68
+ },
69
+ })
70
+ await modClient.emitEvent({
71
+ event: { $type: 'tools.ozone.moderation.defs#modEventTakedown' },
72
+ subject: {
73
+ $type: 'com.atproto.admin.defs#repoRef',
74
+ did: sc.dids.alice,
75
+ },
76
+ })
77
+ })
78
+
79
+ it('gets multiple repos by did', async () => {
80
+ const { data } = await agent.tools.ozone.moderation.getRepos(
81
+ { dids: [sc.dids.alice, sc.dids.bob, 'did:web:xyz'] },
82
+ { headers: await ozone.modHeaders(ids.ToolsOzoneModerationGetRepos) },
83
+ )
84
+
85
+ expect(forSnapshot(data)).toMatchSnapshot()
86
+ })
87
+ })