@atproto/ozone 0.0.9 → 0.0.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.
Files changed (80) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/api/moderation/util.d.ts +1 -1
  3. package/dist/db/index.js +20 -1
  4. package/dist/db/index.js.map +3 -3
  5. package/dist/db/migrations/20240208T213404429Z-add-tags-column-to-moderation-subject.d.ts +3 -0
  6. package/dist/db/migrations/index.d.ts +1 -0
  7. package/dist/db/schema/moderation_event.d.ts +3 -1
  8. package/dist/db/schema/moderation_subject_status.d.ts +1 -0
  9. package/dist/index.js +1458 -596
  10. package/dist/index.js.map +3 -3
  11. package/dist/lexicon/index.d.ts +20 -6
  12. package/dist/lexicon/lexicons.d.ts +449 -110
  13. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +20 -0
  14. package/dist/lexicon/types/com/atproto/admin/defs.d.ts +9 -0
  15. package/dist/lexicon/types/com/atproto/admin/emitModerationEvent.d.ts +1 -1
  16. package/dist/lexicon/types/com/atproto/admin/queryModerationEvents.d.ts +2 -0
  17. package/dist/lexicon/types/com/atproto/admin/queryModerationStatuses.d.ts +2 -0
  18. package/dist/lexicon/types/com/atproto/identity/getRecommendedDidCredentials.d.ts +33 -0
  19. package/dist/lexicon/types/com/atproto/identity/requestPlcOperationSignature.d.ts +19 -0
  20. package/dist/lexicon/types/com/atproto/{temp/transferAccount.d.ts → identity/signPlcOperation.d.ts} +6 -8
  21. package/dist/lexicon/types/com/atproto/identity/submitPlcOperation.d.ts +25 -0
  22. package/dist/lexicon/types/com/atproto/{temp/pushBlob.d.ts → repo/importRepo.d.ts} +1 -2
  23. package/dist/lexicon/types/com/atproto/repo/listMissingBlobs.d.ts +41 -0
  24. package/dist/lexicon/types/com/atproto/server/activateAccount.d.ts +19 -0
  25. package/dist/lexicon/types/com/atproto/server/checkAccountStatus.d.ts +38 -0
  26. package/dist/lexicon/types/com/atproto/server/deactivateAccount.d.ts +25 -0
  27. package/dist/lexicon/types/com/atproto/server/describeServer.d.ts +1 -0
  28. package/dist/lexicon/types/com/atproto/{temp/importRepo.d.ts → server/getServiceAuth.d.ts} +8 -9
  29. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.d.ts +9 -1
  30. package/dist/logger.d.ts +1 -0
  31. package/dist/mod-service/index.d.ts +18 -4
  32. package/dist/mod-service/lang.d.ts +15 -0
  33. package/dist/mod-service/status.d.ts +1 -1
  34. package/dist/mod-service/types.d.ts +1 -1
  35. package/dist/mod-service/views.d.ts +2 -1
  36. package/package.json +6 -6
  37. package/src/api/admin/emitModerationEvent.ts +22 -10
  38. package/src/api/admin/queryModerationEvents.ts +4 -0
  39. package/src/api/admin/queryModerationStatuses.ts +4 -0
  40. package/src/api/moderation/createReport.ts +15 -4
  41. package/src/api/moderation/util.ts +1 -0
  42. package/src/db/migrations/20240208T213404429Z-add-tags-column-to-moderation-subject.ts +31 -0
  43. package/src/db/migrations/index.ts +1 -0
  44. package/src/db/schema/moderation_event.ts +3 -0
  45. package/src/db/schema/moderation_subject_status.ts +1 -0
  46. package/src/lexicon/index.ts +124 -36
  47. package/src/lexicon/lexicons.ts +491 -138
  48. package/src/lexicon/types/app/bsky/actor/defs.ts +59 -0
  49. package/src/lexicon/types/app/bsky/feed/post.ts +1 -1
  50. package/src/lexicon/types/com/atproto/admin/defs.ts +24 -0
  51. package/src/lexicon/types/com/atproto/admin/emitModerationEvent.ts +1 -0
  52. package/src/lexicon/types/com/atproto/admin/queryModerationEvents.ts +4 -0
  53. package/src/lexicon/types/com/atproto/admin/queryModerationStatuses.ts +2 -0
  54. package/src/lexicon/types/com/atproto/identity/getRecommendedDidCredentials.ts +47 -0
  55. package/src/lexicon/types/com/atproto/identity/requestPlcOperationSignature.ts +31 -0
  56. package/src/lexicon/types/com/atproto/{temp/transferAccount.ts → identity/signPlcOperation.ts} +8 -15
  57. package/src/lexicon/types/com/atproto/identity/submitPlcOperation.ts +38 -0
  58. package/src/lexicon/types/com/atproto/{temp/pushBlob.ts → repo/importRepo.ts} +2 -5
  59. package/src/lexicon/types/com/atproto/repo/listMissingBlobs.ts +65 -0
  60. package/src/lexicon/types/com/atproto/server/activateAccount.ts +31 -0
  61. package/src/lexicon/types/com/atproto/server/checkAccountStatus.ts +51 -0
  62. package/src/lexicon/types/com/atproto/server/deactivateAccount.ts +39 -0
  63. package/src/lexicon/types/com/atproto/server/describeServer.ts +1 -0
  64. package/src/lexicon/types/com/atproto/{temp/importRepo.ts → server/getServiceAuth.ts} +10 -9
  65. package/src/lexicon/types/com/atproto/sync/subscribeRepos.ts +24 -3
  66. package/src/logger.ts +2 -0
  67. package/src/mod-service/index.ts +60 -10
  68. package/src/mod-service/lang.ts +82 -0
  69. package/src/mod-service/status.ts +18 -4
  70. package/src/mod-service/types.ts +1 -0
  71. package/src/mod-service/views.ts +21 -2
  72. package/tests/__snapshots__/get-record.test.ts.snap +6 -0
  73. package/tests/__snapshots__/get-repo.test.ts.snap +3 -0
  74. package/tests/__snapshots__/moderation-events.test.ts.snap +45 -4
  75. package/tests/__snapshots__/moderation-statuses.test.ts.snap +59 -3
  76. package/tests/__snapshots__/moderation.test.ts.snap +3 -3
  77. package/tests/get-record.test.ts +0 -8
  78. package/tests/moderation-events.test.ts +57 -5
  79. package/tests/moderation-status-tags.test.ts +92 -0
  80. package/tests/moderation-statuses.test.ts +20 -3
@@ -148,7 +148,7 @@ describe('moderation-events', () => {
148
148
 
149
149
  expect(
150
150
  [...new Set(allEvents.data.events.map((e) => e.event.$type))].length,
151
- ).toEqual(3)
151
+ ).toEqual(4)
152
152
  })
153
153
 
154
154
  it('returns events for all content by user', async () => {
@@ -203,10 +203,11 @@ describe('moderation-events', () => {
203
203
  const defaultEvents = await getPaginatedEvents()
204
204
  const reversedEvents = await getPaginatedEvents('asc')
205
205
 
206
- expect(allEvents.data.events.length).toEqual(5)
206
+ expect(allEvents.data.events.length).toEqual(7)
207
207
  expect(defaultEvents.length).toEqual(allEvents.data.events.length)
208
208
  expect(reversedEvents.length).toEqual(allEvents.data.events.length)
209
- expect(reversedEvents[0].id).toEqual(defaultEvents[4].id)
209
+ // First event in the reversed list is the last item in the default list
210
+ expect(reversedEvents[0].id).toEqual(defaultEvents[6].id)
210
211
  })
211
212
 
212
213
  it('returns report events matching reportType filters', async () => {
@@ -242,7 +243,7 @@ describe('moderation-events', () => {
242
243
  expect(eventsWithComment.data.events.length).toEqual(12)
243
244
  })
244
245
 
245
- it('returns events matching filter params for columns', async () => {
246
+ it('returns events matching filter params for labels', async () => {
246
247
  const [negatedLabelEvent, createdLabelEvent] = await Promise.all([
247
248
  emitModerationEvent({
248
249
  event: {
@@ -301,6 +302,54 @@ describe('moderation-events', () => {
301
302
  withoutOneLabel.data.events[0].id,
302
303
  )
303
304
  })
305
+ it('returns events matching filter params for tags', async () => {
306
+ const tagEvent = async ({
307
+ add,
308
+ remove,
309
+ }: {
310
+ add: string[]
311
+ remove: string[]
312
+ }) =>
313
+ emitModerationEvent({
314
+ event: {
315
+ $type: 'com.atproto.admin.defs#modEventTag',
316
+ comment: 'X',
317
+ add,
318
+ remove,
319
+ },
320
+ subject: {
321
+ $type: 'com.atproto.admin.defs#repoRef',
322
+ did: sc.dids.carol,
323
+ },
324
+ createdBy: sc.dids.bob,
325
+ })
326
+ const addEvent = await tagEvent({ add: ['L1', 'L2'], remove: [] })
327
+ const addAndRemoveEvent = await tagEvent({ add: ['L3'], remove: ['L2'] })
328
+ const [addFinder, addAndRemoveFinder, removeFinder] = await Promise.all([
329
+ queryModerationEvents({
330
+ addedTags: ['L1'],
331
+ }),
332
+ queryModerationEvents({
333
+ addedTags: ['L3'],
334
+ removedTags: ['L2'],
335
+ }),
336
+ queryModerationEvents({
337
+ removedTags: ['L2'],
338
+ }),
339
+ ])
340
+
341
+ expect(addFinder.data.events.length).toEqual(1)
342
+ expect(addEvent.data.id).toEqual(addFinder.data.events[0].id)
343
+
344
+ expect(addAndRemoveEvent.data.id).toEqual(
345
+ addAndRemoveFinder.data.events[0].id,
346
+ )
347
+ expect(addAndRemoveEvent.data.id).toEqual(
348
+ addAndRemoveFinder.data.events[0].id,
349
+ )
350
+ expect(addAndRemoveEvent.data.event.add).toEqual(['L3'])
351
+ expect(addAndRemoveEvent.data.event.remove).toEqual(['L2'])
352
+ })
304
353
  })
305
354
 
306
355
  describe('get event', () => {
@@ -331,7 +380,10 @@ describe('moderation-events', () => {
331
380
  })
332
381
  const { data: result } =
333
382
  await pdsAgent.api.com.atproto.admin.queryModerationEvents(
334
- { subject: post.ref.uriStr },
383
+ {
384
+ subject: post.ref.uriStr,
385
+ types: ['com.atproto.admin.defs#modEventTakedown'],
386
+ },
335
387
  { headers: network.ozone.adminAuthHeaders('moderator') },
336
388
  )
337
389
  expect(result.events[0]).toMatchObject({
@@ -0,0 +1,92 @@
1
+ import { TestNetwork, SeedClient, basicSeed } from '@atproto/dev-env'
2
+ import AtpAgent from '@atproto/api'
3
+ import { REASONSPAM } from '../src/lexicon/types/com/atproto/moderation/defs'
4
+
5
+ describe('moderation-status-tags', () => {
6
+ let network: TestNetwork
7
+ let agent: AtpAgent
8
+ let pdsAgent: AtpAgent
9
+ let sc: SeedClient
10
+
11
+ const emitModerationEvent = async (eventData) => {
12
+ return pdsAgent.api.com.atproto.admin.emitModerationEvent(eventData, {
13
+ encoding: 'application/json',
14
+ headers: network.bsky.adminAuthHeaders('moderator'),
15
+ })
16
+ }
17
+
18
+ const queryModerationStatuses = (statusQuery) =>
19
+ agent.api.com.atproto.admin.queryModerationStatuses(statusQuery, {
20
+ headers: network.bsky.adminAuthHeaders('moderator'),
21
+ })
22
+
23
+ beforeAll(async () => {
24
+ network = await TestNetwork.create({
25
+ dbPostgresSchema: 'ozone_moderation_status_tags',
26
+ })
27
+ agent = network.ozone.getClient()
28
+ pdsAgent = network.pds.getClient()
29
+ sc = network.getSeedClient()
30
+ await basicSeed(sc)
31
+ await network.processAll()
32
+ })
33
+
34
+ afterAll(async () => {
35
+ await network.close()
36
+ })
37
+
38
+ describe('manage tags on subject status', () => {
39
+ it('adds and removes tags on a subject', async () => {
40
+ const bobsAccount = {
41
+ $type: 'com.atproto.admin.defs#repoRef',
42
+ did: sc.dids.bob,
43
+ }
44
+ await emitModerationEvent({
45
+ subject: bobsAccount,
46
+ event: {
47
+ $type: 'com.atproto.admin.defs#modEventReport',
48
+ comment: 'X',
49
+ reportType: REASONSPAM,
50
+ },
51
+ createdBy: sc.dids.alice,
52
+ })
53
+ await emitModerationEvent({
54
+ subject: bobsAccount,
55
+ event: {
56
+ $type: 'com.atproto.admin.defs#modEventTag',
57
+ add: ['interaction-churn'],
58
+ remove: [],
59
+ },
60
+ createdBy: sc.dids.alice,
61
+ })
62
+ const { data: statusAfterInteractionTag } = await queryModerationStatuses(
63
+ {
64
+ subject: bobsAccount.did,
65
+ },
66
+ )
67
+ expect(statusAfterInteractionTag.subjectStatuses[0].tags).toContain(
68
+ 'interaction-churn',
69
+ )
70
+
71
+ await emitModerationEvent({
72
+ subject: bobsAccount,
73
+ event: {
74
+ $type: 'com.atproto.admin.defs#modEventTag',
75
+ remove: ['interaction-churn'],
76
+ add: ['follow-churn'],
77
+ },
78
+ createdBy: sc.dids.alice,
79
+ })
80
+ const { data: statusAfterFollowTag } = await queryModerationStatuses({
81
+ subject: bobsAccount.did,
82
+ })
83
+
84
+ expect(statusAfterFollowTag.subjectStatuses[0].tags).not.toContain(
85
+ 'interaction-churn',
86
+ )
87
+ expect(statusAfterFollowTag.subjectStatuses[0].tags).toContain(
88
+ 'follow-churn',
89
+ )
90
+ })
91
+ })
92
+ })
@@ -39,8 +39,8 @@ describe('moderation-statuses', () => {
39
39
  }
40
40
  const bobsPost = {
41
41
  $type: 'com.atproto.repo.strongRef',
42
- uri: sc.posts[sc.dids.bob][1].ref.uriStr,
43
- cid: sc.posts[sc.dids.bob][1].ref.cidStr,
42
+ uri: sc.posts[sc.dids.bob][0].ref.uriStr,
43
+ cid: sc.posts[sc.dids.bob][0].ref.cidStr,
44
44
  }
45
45
  const alicesPost = {
46
46
  $type: 'com.atproto.repo.strongRef',
@@ -95,6 +95,23 @@ describe('moderation-statuses', () => {
95
95
  expect(forSnapshot(response.data.subjectStatuses)).toMatchSnapshot()
96
96
  })
97
97
 
98
+ it('returns statuses filtered by subject language', async () => {
99
+ const klingonQueue = await queryModerationStatuses({
100
+ tags: ['lang:i'],
101
+ })
102
+
103
+ expect(forSnapshot(klingonQueue.data.subjectStatuses)).toMatchSnapshot()
104
+
105
+ const nonKlingonQueue = await queryModerationStatuses({
106
+ excludeTags: ['lang:i'],
107
+ })
108
+
109
+ // Verify that the klingon tagged subject is not returned when excluding klingon
110
+ expect(
111
+ nonKlingonQueue.data.subjectStatuses.map((s) => s.id),
112
+ ).not.toContain(klingonQueue.data.subjectStatuses[0].id)
113
+ })
114
+
98
115
  it('returns paginated statuses', async () => {
99
116
  // We know there will be exactly 4 statuses in db
100
117
  const getPaginatedStatuses = async (
@@ -119,7 +136,7 @@ describe('moderation-statuses', () => {
119
136
  }
120
137
 
121
138
  const list = await getPaginatedStatuses({})
122
- expect(list[0].id).toEqual(4)
139
+ expect(list[0].id).toEqual(7)
123
140
  expect(list[list.length - 1].id).toEqual(1)
124
141
 
125
142
  await emitModerationEvent({