@atproto/bsky 0.0.15 → 0.0.16

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 (170) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/api/com/atproto/moderation/util.d.ts +4 -3
  3. package/dist/context.d.ts +15 -0
  4. package/dist/db/index.js +26 -1
  5. package/dist/db/index.js.map +3 -3
  6. package/dist/db/migrations/20231003T202833377Z-create-moderation-subject-status.d.ts +3 -0
  7. package/dist/db/migrations/index.d.ts +1 -0
  8. package/dist/db/pagination.d.ts +2 -1
  9. package/dist/db/{periodic-moderation-action-reversal.d.ts → periodic-moderation-event-reversal.d.ts} +3 -5
  10. package/dist/db/tables/moderation.d.ts +24 -34
  11. package/dist/feed-gen/types.d.ts +1 -1
  12. package/dist/index.d.ts +2 -1
  13. package/dist/index.js +2750 -2121
  14. package/dist/index.js.map +3 -3
  15. package/dist/lexicon/index.d.ts +11 -18
  16. package/dist/lexicon/lexicons.d.ts +414 -399
  17. package/dist/lexicon/types/app/bsky/feed/defs.d.ts +1 -7
  18. package/dist/lexicon/types/app/bsky/graph/defs.d.ts +1 -0
  19. package/dist/lexicon/types/com/atproto/admin/defs.d.ts +114 -48
  20. package/dist/lexicon/types/com/atproto/admin/{takeModerationAction.d.ts → emitModerationEvent.d.ts} +5 -6
  21. package/dist/lexicon/types/com/atproto/admin/{getModerationAction.d.ts → getModerationEvent.d.ts} +1 -1
  22. package/dist/lexicon/types/com/atproto/admin/{getModerationActions.d.ts → queryModerationEvents.d.ts} +5 -1
  23. package/dist/lexicon/types/com/atproto/admin/{getModerationReports.d.ts → queryModerationStatuses.d.ts} +12 -6
  24. package/dist/lexicon/types/com/atproto/admin/sendEmail.d.ts +1 -0
  25. package/dist/migrate-moderation-data.d.ts +1 -0
  26. package/dist/services/actor/views.d.ts +2 -5
  27. package/dist/services/feed/index.d.ts +1 -0
  28. package/dist/services/feed/util.d.ts +9 -1
  29. package/dist/services/feed/views.d.ts +6 -17
  30. package/dist/services/graph/index.d.ts +5 -29
  31. package/dist/services/graph/types.d.ts +1 -0
  32. package/dist/services/moderation/index.d.ts +135 -72
  33. package/dist/services/moderation/pagination.d.ts +36 -0
  34. package/dist/services/moderation/status.d.ts +13 -0
  35. package/dist/services/moderation/types.d.ts +35 -0
  36. package/dist/services/moderation/views.d.ts +18 -14
  37. package/dist/util/debug.d.ts +1 -1
  38. package/package.json +11 -11
  39. package/src/api/app/bsky/feed/getActorFeeds.ts +2 -1
  40. package/src/api/app/bsky/feed/getActorLikes.ts +1 -3
  41. package/src/api/app/bsky/feed/getAuthorFeed.ts +1 -3
  42. package/src/api/app/bsky/feed/getFeed.ts +9 -9
  43. package/src/api/app/bsky/feed/getFeedGenerator.ts +3 -0
  44. package/src/api/app/bsky/feed/getFeedGenerators.ts +2 -1
  45. package/src/api/app/bsky/feed/getListFeed.ts +1 -3
  46. package/src/api/app/bsky/feed/getPostThread.ts +15 -54
  47. package/src/api/app/bsky/feed/getPosts.ts +21 -18
  48. package/src/api/app/bsky/feed/getSuggestedFeeds.ts +2 -1
  49. package/src/api/app/bsky/feed/getTimeline.ts +1 -3
  50. package/src/api/app/bsky/feed/searchPosts.ts +20 -17
  51. package/src/api/app/bsky/graph/getList.ts +6 -3
  52. package/src/api/app/bsky/graph/getListBlocks.ts +3 -2
  53. package/src/api/app/bsky/graph/getListMutes.ts +2 -1
  54. package/src/api/app/bsky/graph/getLists.ts +2 -1
  55. package/src/api/app/bsky/unspecced/getPopularFeedGenerators.ts +3 -1
  56. package/src/api/blob-resolver.ts +6 -11
  57. package/src/api/com/atproto/admin/emitModerationEvent.ts +220 -0
  58. package/src/api/com/atproto/admin/{getModerationActions.ts → getModerationEvent.ts} +5 -11
  59. package/src/api/com/atproto/admin/getRecord.ts +1 -0
  60. package/src/api/com/atproto/admin/{getModerationReports.ts → queryModerationEvents.ts} +13 -16
  61. package/src/api/com/atproto/admin/queryModerationStatuses.ts +55 -0
  62. package/src/api/com/atproto/moderation/createReport.ts +9 -7
  63. package/src/api/com/atproto/moderation/util.ts +38 -20
  64. package/src/api/index.ts +8 -14
  65. package/src/auth.ts +29 -21
  66. package/src/auto-moderator/index.ts +26 -19
  67. package/src/context.ts +4 -0
  68. package/src/db/migrations/20231003T202833377Z-create-moderation-subject-status.ts +123 -0
  69. package/src/db/migrations/index.ts +1 -0
  70. package/src/db/pagination.ts +26 -3
  71. package/src/db/{periodic-moderation-action-reversal.ts → periodic-moderation-event-reversal.ts} +50 -46
  72. package/src/db/tables/moderation.ts +35 -52
  73. package/src/feed-gen/best-of-follows.ts +6 -3
  74. package/src/feed-gen/bsky-team.ts +1 -1
  75. package/src/feed-gen/hot-classic.ts +1 -1
  76. package/src/feed-gen/mutuals.ts +6 -2
  77. package/src/feed-gen/types.ts +1 -1
  78. package/src/feed-gen/whats-hot.ts +1 -1
  79. package/src/feed-gen/with-friends.ts +7 -3
  80. package/src/index.ts +2 -1
  81. package/src/lexicon/index.ts +30 -67
  82. package/src/lexicon/lexicons.ts +526 -491
  83. package/src/lexicon/types/app/bsky/feed/defs.ts +1 -18
  84. package/src/lexicon/types/app/bsky/graph/defs.ts +1 -0
  85. package/src/lexicon/types/com/atproto/admin/defs.ts +276 -84
  86. package/src/lexicon/types/com/atproto/admin/{takeModerationAction.ts → emitModerationEvent.ts} +13 -11
  87. package/src/lexicon/types/com/atproto/admin/{getModerationReport.ts → getModerationEvent.ts} +1 -1
  88. package/src/lexicon/types/com/atproto/admin/{getModerationActions.ts → queryModerationEvents.ts} +8 -1
  89. package/src/lexicon/types/com/atproto/admin/{getModerationReports.ts → queryModerationStatuses.ts} +21 -14
  90. package/src/lexicon/types/com/atproto/admin/sendEmail.ts +1 -0
  91. package/src/migrate-moderation-data.ts +414 -0
  92. package/src/services/actor/views.ts +5 -14
  93. package/src/services/feed/index.ts +26 -7
  94. package/src/services/feed/util.ts +47 -19
  95. package/src/services/feed/views.ts +68 -4
  96. package/src/services/graph/index.ts +21 -3
  97. package/src/services/graph/types.ts +1 -0
  98. package/src/services/indexing/plugins/block.ts +2 -3
  99. package/src/services/indexing/plugins/feed-generator.ts +2 -3
  100. package/src/services/indexing/plugins/follow.ts +2 -3
  101. package/src/services/indexing/plugins/like.ts +2 -3
  102. package/src/services/indexing/plugins/list-block.ts +2 -3
  103. package/src/services/indexing/plugins/list-item.ts +2 -3
  104. package/src/services/indexing/plugins/list.ts +2 -3
  105. package/src/services/indexing/plugins/post.ts +3 -4
  106. package/src/services/indexing/plugins/repost.ts +2 -3
  107. package/src/services/indexing/plugins/thread-gate.ts +2 -3
  108. package/src/services/label/index.ts +2 -3
  109. package/src/services/moderation/index.ts +380 -395
  110. package/src/services/moderation/pagination.ts +96 -0
  111. package/src/services/moderation/status.ts +244 -0
  112. package/src/services/moderation/types.ts +49 -0
  113. package/src/services/moderation/views.ts +278 -329
  114. package/src/util/debug.ts +2 -2
  115. package/tests/__snapshots__/feed-generation.test.ts.snap +322 -6
  116. package/tests/__snapshots__/indexing.test.ts.snap +0 -6
  117. package/tests/admin/__snapshots__/get-record.test.ts.snap +30 -132
  118. package/tests/admin/__snapshots__/get-repo.test.ts.snap +14 -60
  119. package/tests/admin/__snapshots__/moderation-events.test.ts.snap +146 -0
  120. package/tests/admin/__snapshots__/moderation-statuses.test.ts.snap +64 -0
  121. package/tests/admin/__snapshots__/moderation.test.ts.snap +0 -125
  122. package/tests/admin/get-record.test.ts +5 -9
  123. package/tests/admin/get-repo.test.ts +5 -9
  124. package/tests/admin/moderation-events.test.ts +221 -0
  125. package/tests/admin/moderation-statuses.test.ts +145 -0
  126. package/tests/admin/moderation.test.ts +512 -860
  127. package/tests/admin/repo-search.test.ts +2 -3
  128. package/tests/auto-moderator/fuzzy-matcher.test.ts +2 -1
  129. package/tests/auto-moderator/takedowns.test.ts +45 -18
  130. package/tests/feed-generation.test.ts +57 -9
  131. package/tests/views/__snapshots__/block-lists.test.ts.snap +3 -9
  132. package/tests/views/__snapshots__/blocks.test.ts.snap +0 -9
  133. package/tests/views/__snapshots__/mute-lists.test.ts.snap +5 -5
  134. package/tests/views/__snapshots__/mutes.test.ts.snap +0 -3
  135. package/tests/views/__snapshots__/thread.test.ts.snap +0 -30
  136. package/tests/views/actor-search.test.ts +2 -3
  137. package/tests/views/author-feed.test.ts +42 -36
  138. package/tests/views/follows.test.ts +40 -35
  139. package/tests/views/list-feed.test.ts +17 -9
  140. package/tests/views/notifications.test.ts +13 -9
  141. package/tests/views/profile.test.ts +20 -18
  142. package/tests/views/thread.test.ts +54 -26
  143. package/tests/views/threadgating.test.ts +51 -19
  144. package/tests/views/timeline.test.ts +21 -13
  145. package/dist/api/com/atproto/admin/resolveModerationReports.d.ts +0 -3
  146. package/dist/api/com/atproto/admin/reverseModerationAction.d.ts +0 -3
  147. package/dist/api/com/atproto/admin/takeModerationAction.d.ts +0 -3
  148. package/dist/lexicon/types/com/atproto/admin/getModerationReport.d.ts +0 -29
  149. package/dist/lexicon/types/com/atproto/admin/resolveModerationReports.d.ts +0 -36
  150. package/dist/lexicon/types/com/atproto/admin/reverseModerationAction.d.ts +0 -36
  151. package/src/api/com/atproto/admin/getModerationAction.ts +0 -44
  152. package/src/api/com/atproto/admin/getModerationReport.ts +0 -43
  153. package/src/api/com/atproto/admin/resolveModerationReports.ts +0 -24
  154. package/src/api/com/atproto/admin/reverseModerationAction.ts +0 -115
  155. package/src/api/com/atproto/admin/takeModerationAction.ts +0 -156
  156. package/src/lexicon/types/com/atproto/admin/getModerationAction.ts +0 -41
  157. package/src/lexicon/types/com/atproto/admin/resolveModerationReports.ts +0 -49
  158. package/src/lexicon/types/com/atproto/admin/reverseModerationAction.ts +0 -49
  159. package/tests/admin/__snapshots__/get-moderation-action.test.ts.snap +0 -172
  160. package/tests/admin/__snapshots__/get-moderation-actions.test.ts.snap +0 -178
  161. package/tests/admin/__snapshots__/get-moderation-report.test.ts.snap +0 -177
  162. package/tests/admin/__snapshots__/get-moderation-reports.test.ts.snap +0 -307
  163. package/tests/admin/get-moderation-action.test.ts +0 -100
  164. package/tests/admin/get-moderation-actions.test.ts +0 -164
  165. package/tests/admin/get-moderation-report.test.ts +0 -100
  166. package/tests/admin/get-moderation-reports.test.ts +0 -332
  167. /package/dist/api/com/atproto/admin/{getModerationAction.d.ts → emitModerationEvent.d.ts} +0 -0
  168. /package/dist/api/com/atproto/admin/{getModerationActions.d.ts → getModerationEvent.d.ts} +0 -0
  169. /package/dist/api/com/atproto/admin/{getModerationReport.d.ts → queryModerationEvents.d.ts} +0 -0
  170. /package/dist/api/com/atproto/admin/{getModerationReports.d.ts → queryModerationStatuses.d.ts} +0 -0
@@ -1,13 +1,13 @@
1
- import { Selectable } from 'kysely';
2
1
  import { CID } from 'multiformats/cid';
3
2
  import { AtUri } from '@atproto/syntax';
4
3
  import { PrimaryDatabase } from '../../db';
5
- import { ModerationAction, ModerationReport } from '../../db/tables/moderation';
6
4
  import { ModerationViews } from './views';
7
5
  import { ImageUriBuilder } from '../../image/uri';
6
+ import { Main as StrongRef } from '../../lexicon/types/com/atproto/repo/strongRef';
8
7
  import { ImageInvalidator } from '../../image/invalidator';
9
8
  import { RepoRef, RepoBlobRef } from '../../lexicon/types/com/atproto/admin/defs';
10
- import { Main as StrongRef } from '../../lexicon/types/com/atproto/repo/strongRef';
9
+ import { ModEventType, ModerationEventRow, ModerationEventRowWithHandle, ModerationSubjectStatusRow, ReversibleModerationEvent, SubjectInfo } from './types';
10
+ import { ModerationEvent } from '../../db/tables/moderation';
11
11
  export declare class ModerationService {
12
12
  db: PrimaryDatabase;
13
13
  imgUriBuilder: ImageUriBuilder;
@@ -15,52 +15,52 @@ export declare class ModerationService {
15
15
  constructor(db: PrimaryDatabase, imgUriBuilder: ImageUriBuilder, imgInvalidator: ImageInvalidator);
16
16
  static creator(imgUriBuilder: ImageUriBuilder, imgInvalidator: ImageInvalidator): (db: PrimaryDatabase) => ModerationService;
17
17
  views: ModerationViews;
18
- getAction(id: number): Promise<ModerationActionRow | undefined>;
19
- getActionOrThrow(id: number): Promise<ModerationActionRow>;
20
- getActions(opts: {
18
+ getEvent(id: number): Promise<ModerationEventRow | undefined>;
19
+ getEventOrThrow(id: number): Promise<ModerationEventRow>;
20
+ getEvents(opts: {
21
21
  subject?: string;
22
+ createdBy?: string;
22
23
  limit: number;
23
24
  cursor?: string;
24
- }): Promise<ModerationActionRow[]>;
25
- getReport(id: number): Promise<ModerationReportRow | undefined>;
26
- getReports(opts: {
27
- subject?: string;
28
- resolved?: boolean;
29
- actionType?: string;
30
- limit: number;
25
+ includeAllUserRecords: boolean;
26
+ types: ModerationEvent['action'][];
27
+ sortDirection?: 'asc' | 'desc';
28
+ }): Promise<{
31
29
  cursor?: string;
32
- ignoreSubjects?: string[];
33
- reverse?: boolean;
34
- reporters?: string[];
35
- actionedBy?: string;
36
- }): Promise<ModerationReportRowWithHandle[]>;
37
- getReportOrThrow(id: number): Promise<ModerationReportRow>;
38
- getCurrentActions(subject: {
30
+ events: ModerationEventRowWithHandle[];
31
+ }>;
32
+ getReport(id: number): Promise<ModerationEventRow | undefined>;
33
+ getCurrentStatus(subject: {
39
34
  did: string;
40
35
  } | {
41
36
  uri: AtUri;
42
37
  } | {
43
38
  cids: CID[];
44
39
  }): Promise<{
40
+ did: string;
45
41
  id: number;
46
- action: "com.atproto.admin.defs#takedown" | "com.atproto.admin.defs#flag" | "com.atproto.admin.defs#acknowledge" | "com.atproto.admin.defs#escalate";
47
- reason: string;
48
- createdBy: string;
49
42
  createdAt: string;
50
- durationInHours: number | null;
51
- createLabelVals: string | null;
52
- negateLabelVals: string | null;
53
- subjectCid: string | null;
54
- subjectDid: string;
55
- subjectType: "com.atproto.repo.strongRef" | "com.atproto.admin.defs#repoRef";
56
- subjectUri: string | null;
57
- reversedAt: string | null;
58
- reversedBy: string | null;
59
- reversedReason: string | null;
60
- expiresAt: string | null;
43
+ updatedAt: string;
44
+ reviewState: "com.atproto.admin.defs#reviewOpen" | "com.atproto.admin.defs#reviewEscalated" | "com.atproto.admin.defs#reviewClosed";
45
+ blobCids: string[] | null;
46
+ comment: string | null;
47
+ lastReportedAt: string | null;
48
+ lastReviewedAt: string | null;
49
+ muteUntil: string | null;
50
+ lastReviewedBy: string | null;
51
+ takendown: boolean;
52
+ suspendUntil: string | null;
53
+ recordCid: string | null;
54
+ recordPath: string;
61
55
  }[]>;
62
- logAction(info: {
63
- action: ModerationActionRow['action'];
56
+ buildSubjectInfo(subject: {
57
+ did: string;
58
+ } | {
59
+ uri: AtUri;
60
+ cid: CID;
61
+ }, subjectBlobCids?: CID[]): SubjectInfo;
62
+ logEvent(info: {
63
+ event: ModEventType;
64
64
  subject: {
65
65
  did: string;
66
66
  } | {
@@ -68,19 +68,31 @@ export declare class ModerationService {
68
68
  cid: CID;
69
69
  };
70
70
  subjectBlobCids?: CID[];
71
- reason: string;
72
- createLabelVals?: string[];
73
- negateLabelVals?: string[];
74
71
  createdBy: string;
75
72
  createdAt?: Date;
76
- durationInHours?: number;
77
- }): Promise<ModerationActionRow>;
78
- getActionsDueForReversal(): Promise<ModerationActionRow[]>;
79
- revertAction({ id, createdBy, createdAt, reason, }: ReversibleModerationAction): Promise<{
80
- result: ModerationActionRow;
73
+ }): Promise<ModerationEventRow>;
74
+ getLastReversibleEventForSubject({ did, muteUntil, recordPath, suspendUntil, }: ModerationSubjectStatusRow): Promise<{
75
+ id: number;
76
+ createdBy: string;
77
+ createdAt: string;
78
+ comment: string | null;
79
+ createLabelVals: string | null;
80
+ negateLabelVals: string | null;
81
+ durationInHours: number | null;
82
+ action: "com.atproto.admin.defs#modEventTakedown" | "com.atproto.admin.defs#modEventReverseTakedown" | "com.atproto.admin.defs#modEventComment" | "com.atproto.admin.defs#modEventReport" | "com.atproto.admin.defs#modEventLabel" | "com.atproto.admin.defs#modEventAcknowledge" | "com.atproto.admin.defs#modEventEscalate" | "com.atproto.admin.defs#modEventMute" | "com.atproto.admin.defs#modEventEmail";
83
+ subjectCid: string | null;
84
+ subjectDid: string;
85
+ subjectType: "com.atproto.repo.strongRef" | "com.atproto.admin.defs#repoRef";
86
+ subjectUri: string | null;
87
+ expiresAt: string | null;
88
+ meta: Record<string, string | boolean> | null;
89
+ legacyRefId: number | null;
90
+ } | null | undefined>;
91
+ getSubjectsDueForReversal(): Promise<ModerationSubjectStatusRow[]>;
92
+ revertState({ createdBy, createdAt, comment, action, subject, }: ReversibleModerationEvent): Promise<{
93
+ result: ModerationEventRow;
81
94
  restored?: TakedownSubjects;
82
95
  }>;
83
- logReverseAction(info: ReversibleModerationAction): Promise<ModerationActionRow>;
84
96
  takedownRepo(info: {
85
97
  takedownId: number;
86
98
  did: string;
@@ -97,14 +109,8 @@ export declare class ModerationService {
97
109
  reverseTakedownRecord(info: {
98
110
  uri: AtUri;
99
111
  }): Promise<void>;
100
- resolveReports(info: {
101
- reportIds: number[];
102
- actionId: number;
103
- createdBy: string;
104
- createdAt?: Date;
105
- }): Promise<void>;
106
112
  report(info: {
107
- reasonType: ModerationReportRow['reasonType'];
113
+ reasonType: NonNullable<ModerationEventRow['meta']>['reportType'];
108
114
  reason?: string;
109
115
  subject: {
110
116
  did: string;
@@ -114,28 +120,85 @@ export declare class ModerationService {
114
120
  };
115
121
  reportedBy: string;
116
122
  createdAt?: Date;
117
- }): Promise<ModerationReportRow>;
123
+ }): Promise<ModerationEventRow>;
124
+ getSubjectStatuses({ cursor, limit, takendown, reviewState, reviewedAfter, reviewedBefore, reportedAfter, reportedBefore, includeMuted, ignoreSubjects, sortDirection, lastReviewedBy, sortField, subject, }: {
125
+ cursor?: string;
126
+ limit?: number;
127
+ takendown?: boolean;
128
+ reviewedBefore?: string;
129
+ reviewState?: ModerationSubjectStatusRow['reviewState'];
130
+ reviewedAfter?: string;
131
+ reportedAfter?: string;
132
+ reportedBefore?: string;
133
+ includeMuted?: boolean;
134
+ subject?: string;
135
+ ignoreSubjects?: string[];
136
+ sortDirection: 'asc' | 'desc';
137
+ lastReviewedBy?: string;
138
+ sortField: 'lastReviewedAt' | 'lastReportedAt';
139
+ }): Promise<{
140
+ statuses: (import("kysely").Selection<{
141
+ record: import("../../db/tables/record").Record;
142
+ subscription: import("../../db/tables/subscription").Subscription;
143
+ post: import("../../db/tables/post").Post;
144
+ duplicate_record: import("../../db/tables/duplicate-record").DuplicateRecord;
145
+ profile: import("../../db/tables/profile").Profile;
146
+ profile_agg: import("../../db/tables/profile-agg").ProfileAgg;
147
+ post_embed_image: import("../../db/tables/post-embed").PostEmbedImage;
148
+ post_embed_external: import("../../db/tables/post-embed").PostEmbedExternal;
149
+ post_embed_record: import("../../db/tables/post-embed").PostEmbedRecord;
150
+ post_agg: import("../../db/tables/post-agg").PostAgg;
151
+ repost: import("../../db/tables/repost").Repost;
152
+ thread_gate: import("../../db/tables/thread-gate").ThreadGate;
153
+ feed_item: import("../../db/tables/feed-item").FeedItem;
154
+ follow: import("../../db/tables/follow").Follow;
155
+ like: import("../../db/tables/like").Like;
156
+ list: import("../../db/tables/list").List;
157
+ list_item: import("../../db/tables/list-item").ListItem;
158
+ list_mute: import("../../db/tables/list-mute").ListMute;
159
+ list_block: import("../../db/tables/list-block").ListBlock;
160
+ mute: import("../../db/tables/mute").Mute;
161
+ actor_block: import("../../db/tables/actor-block").ActorBlock;
162
+ feed_generator: import("../../db/tables/feed-generator").FeedGenerator;
163
+ actor: import("kysely/dist/cjs/util/type-utils").Nullable<import("../../db/tables/actor").Actor>;
164
+ actor_state: import("../../db/tables/actor-state").ActorState;
165
+ actor_sync: import("../../db/tables/actor-sync").ActorSync;
166
+ notification: import("../../db/tables/notification").Notification;
167
+ notification_push_token: import("../../db/tables/notification-push-token").NotificationPushToken;
168
+ did_cache: import("../../db/tables/did-cache").DidCache;
169
+ label: import("../../db/tables/label").Label;
170
+ moderation_event: ModerationEvent;
171
+ moderation_subject_status: import("../../db/tables/moderation").ModerationSubjectStatus;
172
+ algo_whats_hot_view: import("../../db/tables/algo").AlgoWhatsHotView;
173
+ view_param: import("../../db/tables/view-param").ViewParam;
174
+ suggested_follow: import("../../db/tables/suggested-follow").SuggestedFollow;
175
+ suggested_feed: import("../../db/tables/suggested-feed").SuggestedFeed;
176
+ }, "actor" | "moderation_subject_status", "actor.handle as handle"> & {
177
+ did: string;
178
+ id: number;
179
+ createdAt: string;
180
+ updatedAt: string;
181
+ reviewState: "com.atproto.admin.defs#reviewOpen" | "com.atproto.admin.defs#reviewEscalated" | "com.atproto.admin.defs#reviewClosed";
182
+ blobCids: string[] | null;
183
+ comment: string | null;
184
+ lastReportedAt: string | null;
185
+ lastReviewedAt: string | null;
186
+ muteUntil: string | null;
187
+ lastReviewedBy: string | null;
188
+ takendown: boolean;
189
+ suspendUntil: string | null;
190
+ recordCid: string | null;
191
+ recordPath: string;
192
+ })[];
193
+ cursor: string | undefined;
194
+ }>;
195
+ isSubjectTakendown(subject: {
196
+ did: string;
197
+ } | {
198
+ uri: AtUri;
199
+ }): Promise<boolean>;
118
200
  }
119
201
  export declare type TakedownSubjects = {
120
202
  did: string;
121
203
  subjects: (RepoRef | RepoBlobRef | StrongRef)[];
122
204
  };
123
- export declare type ModerationActionRow = Selectable<ModerationAction>;
124
- export declare type ReversibleModerationAction = Pick<ModerationActionRow, 'id' | 'createdBy' | 'reason'> & {
125
- createdAt?: Date;
126
- };
127
- export declare type ModerationReportRow = Selectable<ModerationReport>;
128
- export declare type ModerationReportRowWithHandle = ModerationReportRow & {
129
- handle?: string | null;
130
- };
131
- export declare type SubjectInfo = {
132
- subjectType: 'com.atproto.admin.defs#repoRef';
133
- subjectDid: string;
134
- subjectUri: null;
135
- subjectCid: null;
136
- } | {
137
- subjectType: 'com.atproto.repo.strongRef';
138
- subjectDid: string;
139
- subjectUri: string;
140
- subjectCid: string;
141
- };
@@ -0,0 +1,36 @@
1
+ import { Cursor, GenericKeyset } from '../../db/pagination';
2
+ declare type StatusKeysetParam = {
3
+ lastReviewedAt: string | null;
4
+ lastReportedAt: string | null;
5
+ id: number;
6
+ };
7
+ export declare class StatusKeyset extends GenericKeyset<StatusKeysetParam, Cursor> {
8
+ labelResult(result: StatusKeysetParam): Cursor;
9
+ labeledResultToCursor(labeled: Cursor): {
10
+ primary: string;
11
+ secondary: string;
12
+ };
13
+ cursorToLabeledResult(cursor: Cursor): {
14
+ primary: string;
15
+ secondary: string;
16
+ };
17
+ unpackCursor(cursorStr?: string): Cursor | undefined;
18
+ getSql(labeled?: Cursor, direction?: 'asc' | 'desc'): import("kysely").RawBuilder<unknown> | undefined;
19
+ }
20
+ declare type TimeIdKeysetParam = {
21
+ id: number;
22
+ createdAt: string;
23
+ };
24
+ declare type TimeIdResult = TimeIdKeysetParam;
25
+ export declare class TimeIdKeyset extends GenericKeyset<TimeIdKeysetParam, Cursor> {
26
+ labelResult(result: TimeIdResult): Cursor;
27
+ labeledResultToCursor(labeled: Cursor): {
28
+ primary: string;
29
+ secondary: string;
30
+ };
31
+ cursorToLabeledResult(cursor: Cursor): {
32
+ primary: string;
33
+ secondary: string;
34
+ };
35
+ }
36
+ export {};
@@ -0,0 +1,13 @@
1
+ import { AtUri } from '@atproto/syntax';
2
+ import { PrimaryDatabase } from '../../db';
3
+ import { ModerationSubjectStatus } from '../../db/tables/moderation';
4
+ import { ModerationEventRow } from './types';
5
+ import { CID } from 'multiformats/cid';
6
+ export declare const adjustModerationSubjectStatus: (db: PrimaryDatabase, moderationEvent: ModerationEventRow, blobCids?: CID[]) => Promise<import("kysely").InsertResult | null>;
7
+ declare type ModerationSubjectStatusFilter = Pick<ModerationSubjectStatus, 'did'> | Pick<ModerationSubjectStatus, 'did' | 'recordPath'> | Pick<ModerationSubjectStatus, 'did' | 'recordPath' | 'recordCid'>;
8
+ export declare const getModerationSubjectStatus: (db: PrimaryDatabase, filters: ModerationSubjectStatusFilter) => Promise<{} | undefined>;
9
+ export declare const getStatusIdentifierFromSubject: (subject: string | AtUri) => {
10
+ did: string;
11
+ recordPath: string;
12
+ };
13
+ export {};
@@ -0,0 +1,35 @@
1
+ import { Selectable } from 'kysely';
2
+ import { ModerationEvent, ModerationSubjectStatus } from '../../db/tables/moderation';
3
+ import { AtUri } from '@atproto/syntax';
4
+ import { CID } from 'multiformats/cid';
5
+ import { ComAtprotoAdminDefs } from '@atproto/api';
6
+ export declare type SubjectInfo = {
7
+ subjectType: 'com.atproto.admin.defs#repoRef';
8
+ subjectDid: string;
9
+ subjectUri: null;
10
+ subjectCid: null;
11
+ } | {
12
+ subjectType: 'com.atproto.repo.strongRef';
13
+ subjectDid: string;
14
+ subjectUri: string;
15
+ subjectCid: string;
16
+ };
17
+ export declare type ModerationEventRow = Selectable<ModerationEvent>;
18
+ export declare type ReversibleModerationEvent = Pick<ModerationEventRow, 'createdBy' | 'comment' | 'action'> & {
19
+ createdAt?: Date;
20
+ subject: {
21
+ did: string;
22
+ } | {
23
+ uri: AtUri;
24
+ cid: CID;
25
+ };
26
+ };
27
+ export declare type ModerationEventRowWithHandle = ModerationEventRow & {
28
+ subjectHandle?: string | null;
29
+ creatorHandle?: string | null;
30
+ };
31
+ export declare type ModerationSubjectStatusRow = Selectable<ModerationSubjectStatus>;
32
+ export declare type ModerationSubjectStatusRowWithHandle = ModerationSubjectStatusRow & {
33
+ handle: string | null;
34
+ };
35
+ export declare type ModEventType = ComAtprotoAdminDefs.ModEventTakedown | ComAtprotoAdminDefs.ModEventAcknowledge | ComAtprotoAdminDefs.ModEventEscalate | ComAtprotoAdminDefs.ModEventComment | ComAtprotoAdminDefs.ModEventLabel | ComAtprotoAdminDefs.ModEventReport | ComAtprotoAdminDefs.ModEventMute | ComAtprotoAdminDefs.ModEventReverseTakedown;
@@ -1,37 +1,41 @@
1
- import { Selectable } from 'kysely';
2
1
  import { BlobRef } from '@atproto/lexicon';
3
2
  import { Database } from '../../db';
4
3
  import { Actor } from '../../db/tables/actor';
5
4
  import { Record as RecordRow } from '../../db/tables/record';
6
- import { ModerationAction } from '../../db/tables/moderation';
7
- import { RepoView, RepoViewDetail, RecordView, RecordViewDetail, ActionView, ActionViewDetail, ReportView, ReportViewDetail, BlobView } from '../../lexicon/types/com/atproto/admin/defs';
5
+ import { ModEventView, RepoView, RepoViewDetail, RecordView, RecordViewDetail, ReportViewDetail, BlobView, SubjectStatusView, ModEventViewDetail } from '../../lexicon/types/com/atproto/admin/defs';
8
6
  import { OutputSchema as ReportOutput } from '../../lexicon/types/com/atproto/moderation/createReport';
9
7
  import { Label } from '../../lexicon/types/com/atproto/label/defs';
10
- import { ModerationReportRowWithHandle } from '.';
8
+ import { ModerationEventRowWithHandle, ModerationSubjectStatusRowWithHandle } from './types';
11
9
  export declare class ModerationViews {
12
10
  private db;
13
11
  constructor(db: Database);
14
12
  repo(result: RepoResult): Promise<RepoView>;
15
13
  repo(result: RepoResult[]): Promise<RepoView[]>;
14
+ event(result: EventResult): Promise<ModEventView>;
15
+ event(result: EventResult[]): Promise<ModEventView[]>;
16
+ eventDetail(result: EventResult): Promise<ModEventViewDetail>;
16
17
  repoDetail(result: RepoResult): Promise<RepoViewDetail>;
17
18
  record(result: RecordResult): Promise<RecordView>;
18
19
  record(result: RecordResult[]): Promise<RecordView[]>;
19
20
  recordDetail(result: RecordResult): Promise<RecordViewDetail>;
20
- action(result: ActionResult): Promise<ActionView>;
21
- action(result: ActionResult[]): Promise<ActionView[]>;
22
- actionDetail(result: ActionResult): Promise<ActionViewDetail>;
23
- report(result: ReportResult): Promise<ReportView>;
24
- report(result: ReportResult[]): Promise<ReportView[]>;
25
21
  reportPublic(report: ReportResult): ReportOutput;
26
- reportDetail(result: ReportResult): Promise<ReportViewDetail>;
27
22
  subject(result: SubjectResult): Promise<SubjectView>;
28
23
  blob(blobs: BlobRef[]): Promise<BlobView[]>;
29
24
  labels(subject: string, includeNeg?: boolean): Promise<Label[]>;
25
+ getSubjectStatus(subject: {
26
+ did: string;
27
+ recordPath?: string;
28
+ } | {
29
+ did: string;
30
+ recordPath?: string;
31
+ }[]): Promise<ModerationSubjectStatusRowWithHandle[]>;
32
+ subjectStatus(result: ModerationSubjectStatusRowWithHandle): SubjectStatusView;
33
+ subjectStatus(result: ModerationSubjectStatusRowWithHandle[]): SubjectStatusView[];
30
34
  }
31
35
  declare type RepoResult = Actor;
32
- declare type ActionResult = Selectable<ModerationAction>;
33
- declare type ReportResult = ModerationReportRowWithHandle;
36
+ declare type EventResult = ModerationEventRowWithHandle;
37
+ declare type ReportResult = ModerationEventRowWithHandle;
34
38
  declare type RecordResult = RecordRow;
35
- declare type SubjectResult = Pick<ActionResult & ReportResult, 'id' | 'subjectType' | 'subjectDid' | 'subjectUri' | 'subjectCid'>;
36
- declare type SubjectView = ActionViewDetail['subject'] & ReportViewDetail['subject'];
39
+ declare type SubjectResult = Pick<EventResult & ReportResult, 'id' | 'subjectType' | 'subjectDid' | 'subjectUri' | 'subjectCid'>;
40
+ declare type SubjectView = ModEventViewDetail['subject'] & ReportViewDetail['subject'];
37
41
  export {};
@@ -1 +1 @@
1
- export declare const debugCatch: <Func extends (...args: any[]) => any>(fn: Func) => (...args: any[]) => Promise<any>;
1
+ export declare const debugCatch: <Func extends (...args: any[]) => any>(fn: Func) => (...args: Parameters<Func>) => Promise<ReturnType<Func>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/bsky",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "license": "MIT",
5
5
  "description": "Reference implementation of app.bsky App View (Bluesky API)",
6
6
  "keywords": [
@@ -35,14 +35,14 @@
35
35
  "sharp": "^0.32.6",
36
36
  "typed-emitter": "^2.1.0",
37
37
  "uint8arrays": "3.0.0",
38
- "@atproto/api": "^0.6.23",
38
+ "@atproto/api": "^0.6.24",
39
39
  "@atproto/common": "^0.3.3",
40
40
  "@atproto/crypto": "^0.3.0",
41
- "@atproto/syntax": "^0.1.4",
41
+ "@atproto/syntax": "^0.1.5",
42
42
  "@atproto/identity": "^0.3.2",
43
- "@atproto/lexicon": "^0.3.0",
44
- "@atproto/repo": "^0.3.5",
45
- "@atproto/xrpc-server": "^0.4.1"
43
+ "@atproto/lexicon": "^0.3.1",
44
+ "@atproto/repo": "^0.3.6",
45
+ "@atproto/xrpc-server": "^0.4.2"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@did-plc/server": "^0.0.1",
@@ -52,11 +52,11 @@
52
52
  "@types/pg": "^8.6.6",
53
53
  "@types/qs": "^6.9.7",
54
54
  "axios": "^0.27.2",
55
- "@atproto/api": "^0.6.23",
56
- "@atproto/dev-env": "^0.2.15",
57
- "@atproto/lex-cli": "^0.2.4",
58
- "@atproto/pds": "^0.3.3",
59
- "@atproto/xrpc": "^0.4.0"
55
+ "@atproto/api": "^0.6.24",
56
+ "@atproto/dev-env": "^0.2.16",
57
+ "@atproto/lex-cli": "^0.2.5",
58
+ "@atproto/pds": "^0.3.4",
59
+ "@atproto/xrpc": "^0.4.1"
60
60
  },
61
61
  "scripts": {
62
62
  "codegen": "lex gen-server ./src/lexicon ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/*",
@@ -1,4 +1,5 @@
1
1
  import { InvalidRequestError } from '@atproto/xrpc-server'
2
+ import { mapDefined } from '@atproto/common'
2
3
  import { Server } from '../../../../lexicon'
3
4
  import AppContext from '../../../../context'
4
5
  import { TimeCidKeyset, paginate } from '../../../../db/pagination'
@@ -42,7 +43,7 @@ export default function (server: Server, ctx: AppContext) {
42
43
  throw new InvalidRequestError(`Actor not found: ${actor}`)
43
44
  }
44
45
 
45
- const feeds = feedsRes.map((row) => {
46
+ const feeds = mapDefined(feedsRes, (row) => {
46
47
  const feed = {
47
48
  ...row,
48
49
  viewer: viewer ? { like: row.viewerLike } : undefined,
@@ -107,9 +107,7 @@ const noPostBlocks = (state: HydrationState) => {
107
107
  const presentation = (state: HydrationState, ctx: Context) => {
108
108
  const { feedService } = ctx
109
109
  const { feedItems, cursor, params } = state
110
- const feed = feedService.views.formatFeed(feedItems, state, {
111
- viewer: params.viewer,
112
- })
110
+ const feed = feedService.views.formatFeed(feedItems, state, params.viewer)
113
111
  return { feed, cursor }
114
112
  }
115
113
 
@@ -147,9 +147,7 @@ const noBlocksOrMutedReposts = (state: HydrationState) => {
147
147
  const presentation = (state: HydrationState, ctx: Context) => {
148
148
  const { feedService } = ctx
149
149
  const { feedItems, cursor, params } = state
150
- const feed = feedService.views.formatFeed(feedItems, state, {
151
- viewer: params.viewer,
152
- })
150
+ const feed = feedService.views.formatFeed(feedItems, state, params.viewer)
153
151
  return { feed, cursor }
154
152
  }
155
153
 
@@ -33,7 +33,7 @@ export default function (server: Server, ctx: AppContext) {
33
33
  presentation,
34
34
  )
35
35
  server.app.bsky.feed.getFeed({
36
- auth: ctx.authVerifierAnyAudience,
36
+ auth: ctx.authOptionalVerifierAnyAudience,
37
37
  handler: async ({ params, auth, req }) => {
38
38
  const db = ctx.db.getReplica()
39
39
  const feedService = ctx.services.feed(db)
@@ -98,22 +98,22 @@ const hydration = async (state: SkeletonState, ctx: Context) => {
98
98
 
99
99
  const noBlocksOrMutes = (state: HydrationState) => {
100
100
  const { viewer } = state.params
101
- state.feedItems = state.feedItems.filter(
102
- (item) =>
101
+ state.feedItems = state.feedItems.filter((item) => {
102
+ if (!viewer) return true
103
+ return (
103
104
  !state.bam.block([viewer, item.postAuthorDid]) &&
104
105
  !state.bam.block([viewer, item.originatorDid]) &&
105
106
  !state.bam.mute([viewer, item.postAuthorDid]) &&
106
- !state.bam.mute([viewer, item.originatorDid]),
107
- )
107
+ !state.bam.mute([viewer, item.originatorDid])
108
+ )
109
+ })
108
110
  return state
109
111
  }
110
112
 
111
113
  const presentation = (state: HydrationState, ctx: Context) => {
112
114
  const { feedService } = ctx
113
115
  const { feedItems, cursor, passthrough, params } = state
114
- const feed = feedService.views.formatFeed(feedItems, state, {
115
- viewer: params.viewer,
116
- })
116
+ const feed = feedService.views.formatFeed(feedItems, state, params.viewer)
117
117
  return {
118
118
  feed,
119
119
  cursor,
@@ -130,7 +130,7 @@ type Context = {
130
130
  authorization?: string
131
131
  }
132
132
 
133
- type Params = GetFeedParams & { viewer: string }
133
+ type Params = GetFeedParams & { viewer: string | null }
134
134
 
135
135
  type SkeletonState = {
136
136
  params: Params
@@ -55,6 +55,9 @@ export default function (server: Server, ctx: AppContext) {
55
55
  feedInfo,
56
56
  profiles,
57
57
  )
58
+ if (!feedView) {
59
+ throw new InvalidRequestError('could not find feed')
60
+ }
58
61
 
59
62
  return {
60
63
  encoding: 'application/json',
@@ -1,3 +1,4 @@
1
+ import { mapDefined } from '@atproto/common'
1
2
  import { Server } from '../../../../lexicon'
2
3
  import AppContext from '../../../../context'
3
4
  import { FeedGenInfo, FeedService } from '../../../../services/feed'
@@ -60,7 +61,7 @@ const hydration = async (state: SkeletonState, ctx: Context) => {
60
61
 
61
62
  const presentation = (state: HydrationState, ctx: Context) => {
62
63
  const { feedService } = ctx
63
- const feeds = state.generators.map((gen) =>
64
+ const feeds = mapDefined(state.generators, (gen) =>
64
65
  feedService.views.formatFeedGeneratorView(gen, state.profiles),
65
66
  )
66
67
  return { feeds }
@@ -105,9 +105,7 @@ const noBlocksOrMutes = (state: HydrationState) => {
105
105
  const presentation = (state: HydrationState, ctx: Context) => {
106
106
  const { feedService } = ctx
107
107
  const { feedItems, cursor, params } = state
108
- const feed = feedService.views.formatFeed(feedItems, state, {
109
- viewer: params.viewer,
110
- })
108
+ const feed = feedService.views.formatFeed(feedItems, state, params.viewer)
111
109
  return { feed, cursor }
112
110
  }
113
111