@atproto/bsky 0.0.28 → 0.0.29

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 (78) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE.txt +1 -1
  3. package/dist/auto-moderator/index.d.ts +1 -14
  4. package/dist/context.d.ts +0 -3
  5. package/dist/db/index.js +34593 -3478
  6. package/dist/db/index.js.map +3 -3
  7. package/dist/db/pagination.d.ts +1 -0
  8. package/dist/index.d.ts +0 -4
  9. package/dist/index.js +1531 -1723
  10. package/dist/index.js.map +3 -3
  11. package/dist/indexer/config.d.ts +0 -8
  12. package/dist/lexicon/index.d.ts +0 -2
  13. package/dist/lexicon/lexicons.d.ts +38 -47
  14. package/dist/lexicon/types/com/atproto/admin/defs.d.ts +2 -2
  15. package/dist/lexicon/types/com/atproto/admin/queryModerationEvents.d.ts +7 -0
  16. package/package.json +7 -6
  17. package/src/api/app/bsky/actor/getSuggestions.ts +1 -1
  18. package/src/api/app/bsky/actor/searchActors.ts +1 -0
  19. package/src/api/app/bsky/feed/getActorFeeds.ts +6 -0
  20. package/src/api/app/bsky/feed/getActorLikes.ts +4 -0
  21. package/src/api/app/bsky/feed/getAuthorFeed.ts +4 -0
  22. package/src/api/app/bsky/feed/getFeed.ts +8 -5
  23. package/src/api/app/bsky/feed/getLikes.ts +4 -0
  24. package/src/api/app/bsky/feed/getListFeed.ts +4 -0
  25. package/src/api/app/bsky/feed/getRepostedBy.ts +4 -0
  26. package/src/api/app/bsky/feed/getSuggestedFeeds.ts +1 -1
  27. package/src/api/app/bsky/feed/getTimeline.ts +4 -0
  28. package/src/api/app/bsky/feed/searchPosts.ts +1 -0
  29. package/src/api/app/bsky/graph/getBlocks.ts +7 -0
  30. package/src/api/app/bsky/graph/getFollowers.ts +4 -0
  31. package/src/api/app/bsky/graph/getFollows.ts +4 -0
  32. package/src/api/app/bsky/graph/getList.ts +4 -0
  33. package/src/api/app/bsky/graph/getListBlocks.ts +4 -0
  34. package/src/api/app/bsky/graph/getListMutes.ts +7 -0
  35. package/src/api/app/bsky/graph/getLists.ts +7 -0
  36. package/src/api/app/bsky/graph/getMutes.ts +7 -0
  37. package/src/api/app/bsky/notification/listNotifications.ts +3 -0
  38. package/src/api/app/bsky/unspecced/getPopularFeedGenerators.ts +7 -1
  39. package/src/api/index.ts +0 -6
  40. package/src/auto-moderator/index.ts +9 -176
  41. package/src/context.ts +0 -6
  42. package/src/db/pagination.ts +3 -0
  43. package/src/index.ts +1 -6
  44. package/src/indexer/config.ts +0 -29
  45. package/src/lexicon/index.ts +0 -12
  46. package/src/lexicon/lexicons.ts +43 -50
  47. package/src/lexicon/types/com/atproto/admin/defs.ts +2 -0
  48. package/src/lexicon/types/com/atproto/admin/queryModerationEvents.ts +13 -0
  49. package/src/logger.ts +32 -0
  50. package/tests/auto-moderator/labeler.test.ts +2 -0
  51. package/tests/feed-generation.test.ts +0 -6
  52. package/tests/views/notifications.test.ts +9 -0
  53. package/tests/views/timeline.test.ts +8 -0
  54. package/dist/api/app/bsky/feed/describeFeedGenerator.d.ts +0 -3
  55. package/dist/api/app/bsky/feed/getFeedSkeleton.d.ts +0 -3
  56. package/dist/api/app/bsky/unspecced/getTimelineSkeleton.d.ts +0 -3
  57. package/dist/auto-moderator/abyss.d.ts +0 -48
  58. package/dist/auto-moderator/fuzzy-matcher.d.ts +0 -14
  59. package/dist/feed-gen/bsky-team.d.ts +0 -3
  60. package/dist/feed-gen/hot-classic.d.ts +0 -3
  61. package/dist/feed-gen/index.d.ts +0 -2
  62. package/dist/feed-gen/mutuals.d.ts +0 -3
  63. package/dist/feed-gen/types.d.ts +0 -15
  64. package/dist/lexicon/types/app/bsky/unspecced/getTimelineSkeleton.d.ts +0 -35
  65. package/src/api/app/bsky/feed/describeFeedGenerator.ts +0 -21
  66. package/src/api/app/bsky/feed/getFeedSkeleton.ts +0 -30
  67. package/src/api/app/bsky/unspecced/getTimelineSkeleton.ts +0 -26
  68. package/src/auto-moderator/abyss.ts +0 -114
  69. package/src/auto-moderator/fuzzy-matcher.ts +0 -126
  70. package/src/feed-gen/bsky-team.ts +0 -42
  71. package/src/feed-gen/hot-classic.ts +0 -55
  72. package/src/feed-gen/index.ts +0 -17
  73. package/src/feed-gen/mutuals.ts +0 -57
  74. package/src/feed-gen/types.ts +0 -32
  75. package/src/lexicon/types/app/bsky/unspecced/getTimelineSkeleton.ts +0 -49
  76. package/tests/algos/hot-classic.test.ts +0 -87
  77. package/tests/auto-moderator/fuzzy-matcher.test.ts +0 -163
  78. package/tests/auto-moderator/takedowns.test.ts +0 -202
@@ -12,11 +12,7 @@ export interface IndexerConfigValues {
12
12
  didCacheMaxTTL: number;
13
13
  handleResolveNameservers?: string[];
14
14
  hiveApiKey?: string;
15
- abyssEndpoint?: string;
16
- abyssPassword?: string;
17
15
  imgUriEndpoint?: string;
18
- fuzzyMatchB64?: string;
19
- fuzzyFalsePositiveB64?: string;
20
16
  labelerKeywords: Record<string, string>;
21
17
  moderationPushUrl: string;
22
18
  courierUrl?: string;
@@ -54,8 +50,6 @@ export declare class IndexerConfig {
54
50
  get courierHttpVersion(): "2" | "1.1" | undefined;
55
51
  get courierIgnoreBadTls(): boolean | undefined;
56
52
  get hiveApiKey(): string | undefined;
57
- get abyssEndpoint(): string | undefined;
58
- get abyssPassword(): string | undefined;
59
53
  get imgUriEndpoint(): string | undefined;
60
54
  get indexerConcurrency(): number | undefined;
61
55
  get indexerPartitionIds(): number[];
@@ -65,7 +59,5 @@ export declare class IndexerConfig {
65
59
  get indexerPort(): number | undefined;
66
60
  get ingesterPartitionCount(): number;
67
61
  get labelerKeywords(): Record<string, string>;
68
- get fuzzyMatchB64(): string | undefined;
69
- get fuzzyFalsePositiveB64(): string | undefined;
70
62
  get pushNotificationEndpoint(): string | undefined;
71
63
  }
@@ -117,7 +117,6 @@ import * as AppBskyNotificationRegisterPush from './types/app/bsky/notification/
117
117
  import * as AppBskyNotificationUpdateSeen from './types/app/bsky/notification/updateSeen';
118
118
  import * as AppBskyUnspeccedGetPopularFeedGenerators from './types/app/bsky/unspecced/getPopularFeedGenerators';
119
119
  import * as AppBskyUnspeccedGetTaggedSuggestions from './types/app/bsky/unspecced/getTaggedSuggestions';
120
- import * as AppBskyUnspeccedGetTimelineSkeleton from './types/app/bsky/unspecced/getTimelineSkeleton';
121
120
  import * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton';
122
121
  import * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton';
123
122
  export declare const COM_ATPROTO_ADMIN: {
@@ -355,7 +354,6 @@ export declare class AppBskyUnspeccedNS {
355
354
  constructor(server: Server);
356
355
  getPopularFeedGenerators<AV extends AuthVerifier>(cfg: ConfigOf<AV, AppBskyUnspeccedGetPopularFeedGenerators.Handler<ExtractAuth<AV>>, AppBskyUnspeccedGetPopularFeedGenerators.HandlerReqCtx<ExtractAuth<AV>>>): void;
357
356
  getTaggedSuggestions<AV extends AuthVerifier>(cfg: ConfigOf<AV, AppBskyUnspeccedGetTaggedSuggestions.Handler<ExtractAuth<AV>>, AppBskyUnspeccedGetTaggedSuggestions.HandlerReqCtx<ExtractAuth<AV>>>): void;
358
- getTimelineSkeleton<AV extends AuthVerifier>(cfg: ConfigOf<AV, AppBskyUnspeccedGetTimelineSkeleton.Handler<ExtractAuth<AV>>, AppBskyUnspeccedGetTimelineSkeleton.HandlerReqCtx<ExtractAuth<AV>>>): void;
359
357
  searchActorsSkeleton<AV extends AuthVerifier>(cfg: ConfigOf<AV, AppBskyUnspeccedSearchActorsSkeleton.Handler<ExtractAuth<AV>>, AppBskyUnspeccedSearchActorsSkeleton.HandlerReqCtx<ExtractAuth<AV>>>): void;
360
358
  searchPostsSkeleton<AV extends AuthVerifier>(cfg: ConfigOf<AV, AppBskyUnspeccedSearchPostsSkeleton.Handler<ExtractAuth<AV>>, AppBskyUnspeccedSearchPostsSkeleton.HandlerReqCtx<ExtractAuth<AV>>>): void;
361
359
  }
@@ -1296,6 +1296,16 @@ export declare const schemaDict: {
1296
1296
  enum: string[];
1297
1297
  description: string;
1298
1298
  };
1299
+ createdAfter: {
1300
+ type: string;
1301
+ format: string;
1302
+ description: string;
1303
+ };
1304
+ createdBefore: {
1305
+ type: string;
1306
+ format: string;
1307
+ description: string;
1308
+ };
1299
1309
  subject: {
1300
1310
  type: string;
1301
1311
  format: string;
@@ -1311,6 +1321,34 @@ export declare const schemaDict: {
1311
1321
  maximum: number;
1312
1322
  default: number;
1313
1323
  };
1324
+ hasComment: {
1325
+ type: string;
1326
+ description: string;
1327
+ };
1328
+ comment: {
1329
+ type: string;
1330
+ description: string;
1331
+ };
1332
+ addedLabels: {
1333
+ type: string;
1334
+ items: {
1335
+ type: string;
1336
+ };
1337
+ description: string;
1338
+ };
1339
+ removedLabels: {
1340
+ type: string;
1341
+ items: {
1342
+ type: string;
1343
+ };
1344
+ description: string;
1345
+ };
1346
+ reportTypes: {
1347
+ type: string;
1348
+ items: {
1349
+ type: string;
1350
+ };
1351
+ };
1314
1352
  cursor: {
1315
1353
  type: string;
1316
1354
  };
@@ -7602,52 +7640,6 @@ export declare const schemaDict: {
7602
7640
  };
7603
7641
  };
7604
7642
  };
7605
- AppBskyUnspeccedGetTimelineSkeleton: {
7606
- lexicon: number;
7607
- id: string;
7608
- defs: {
7609
- main: {
7610
- type: string;
7611
- description: string;
7612
- parameters: {
7613
- type: string;
7614
- properties: {
7615
- limit: {
7616
- type: string;
7617
- minimum: number;
7618
- maximum: number;
7619
- default: number;
7620
- };
7621
- cursor: {
7622
- type: string;
7623
- };
7624
- };
7625
- };
7626
- output: {
7627
- encoding: string;
7628
- schema: {
7629
- type: string;
7630
- required: string[];
7631
- properties: {
7632
- cursor: {
7633
- type: string;
7634
- };
7635
- feed: {
7636
- type: string;
7637
- items: {
7638
- type: string;
7639
- ref: string;
7640
- };
7641
- };
7642
- };
7643
- };
7644
- };
7645
- errors: {
7646
- name: string;
7647
- }[];
7648
- };
7649
- };
7650
- };
7651
7643
  AppBskyUnspeccedSearchActorsSkeleton: {
7652
7644
  lexicon: number;
7653
7645
  id: string;
@@ -7911,7 +7903,6 @@ export declare const ids: {
7911
7903
  AppBskyUnspeccedDefs: string;
7912
7904
  AppBskyUnspeccedGetPopularFeedGenerators: string;
7913
7905
  AppBskyUnspeccedGetTaggedSuggestions: string;
7914
- AppBskyUnspeccedGetTimelineSkeleton: string;
7915
7906
  AppBskyUnspeccedSearchActorsSkeleton: string;
7916
7907
  AppBskyUnspeccedSearchPostsSkeleton: string;
7917
7908
  };
@@ -12,7 +12,7 @@ export declare function isStatusAttr(v: unknown): v is StatusAttr;
12
12
  export declare function validateStatusAttr(v: unknown): ValidationResult;
13
13
  export interface ModEventView {
14
14
  id: number;
15
- event: ModEventTakedown | ModEventReverseTakedown | ModEventComment | ModEventReport | ModEventLabel | ModEventAcknowledge | ModEventEscalate | ModEventMute | ModEventEmail | {
15
+ event: ModEventTakedown | ModEventReverseTakedown | ModEventComment | ModEventReport | ModEventLabel | ModEventAcknowledge | ModEventEscalate | ModEventMute | ModEventEmail | ModEventResolveAppeal | {
16
16
  $type: string;
17
17
  [k: string]: unknown;
18
18
  };
@@ -31,7 +31,7 @@ export declare function isModEventView(v: unknown): v is ModEventView;
31
31
  export declare function validateModEventView(v: unknown): ValidationResult;
32
32
  export interface ModEventViewDetail {
33
33
  id: number;
34
- event: ModEventTakedown | ModEventReverseTakedown | ModEventComment | ModEventReport | ModEventLabel | ModEventAcknowledge | ModEventEscalate | ModEventMute | ModEventResolveAppeal | {
34
+ event: ModEventTakedown | ModEventReverseTakedown | ModEventComment | ModEventReport | ModEventLabel | ModEventAcknowledge | ModEventEscalate | ModEventMute | ModEventEmail | ModEventResolveAppeal | {
35
35
  $type: string;
36
36
  [k: string]: unknown;
37
37
  };
@@ -5,9 +5,16 @@ export interface QueryParams {
5
5
  types?: string[];
6
6
  createdBy?: string;
7
7
  sortDirection: 'asc' | 'desc';
8
+ createdAfter?: string;
9
+ createdBefore?: string;
8
10
  subject?: string;
9
11
  includeAllUserRecords: boolean;
10
12
  limit: number;
13
+ hasComment?: boolean;
14
+ comment?: string;
15
+ addedLabels?: string[];
16
+ removedLabels?: string[];
17
+ reportTypes?: string[];
11
18
  cursor?: string;
12
19
  }
13
20
  export type InputSchema = undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/bsky",
3
- "version": "0.0.28",
3
+ "version": "0.0.29",
4
4
  "license": "MIT",
5
5
  "description": "Reference implementation of app.bsky App View (Bluesky API)",
6
6
  "keywords": [
@@ -29,6 +29,7 @@
29
29
  "http-errors": "^2.0.0",
30
30
  "http-terminator": "^3.2.0",
31
31
  "ioredis": "^5.3.2",
32
+ "jose": "^5.0.1",
32
33
  "kysely": "^0.22.0",
33
34
  "multiformats": "^9.9.0",
34
35
  "murmurhash": "^2.0.1",
@@ -39,11 +40,11 @@
39
40
  "sharp": "^0.32.6",
40
41
  "typed-emitter": "^2.1.0",
41
42
  "uint8arrays": "3.0.0",
42
- "@atproto/api": "^0.9.5",
43
+ "@atproto/api": "^0.9.6",
43
44
  "@atproto/common": "^0.3.3",
44
45
  "@atproto/crypto": "^0.3.0",
45
- "@atproto/lexicon": "^0.3.1",
46
46
  "@atproto/identity": "^0.3.2",
47
+ "@atproto/lexicon": "^0.3.1",
47
48
  "@atproto/repo": "^0.3.6",
48
49
  "@atproto/syntax": "^0.1.5",
49
50
  "@atproto/xrpc-server": "^0.4.2"
@@ -59,10 +60,10 @@
59
60
  "@types/pg": "^8.6.6",
60
61
  "@types/qs": "^6.9.7",
61
62
  "axios": "^0.27.2",
62
- "@atproto/api": "^0.9.5",
63
- "@atproto/dev-env": "^0.2.28",
63
+ "@atproto/api": "^0.9.6",
64
+ "@atproto/dev-env": "^0.2.29",
64
65
  "@atproto/lex-cli": "^0.3.0",
65
- "@atproto/pds": "^0.3.16",
66
+ "@atproto/pds": "^0.3.17",
66
67
  "@atproto/xrpc": "^0.4.1"
67
68
  },
68
69
  "scripts": {
@@ -43,7 +43,7 @@ const skeleton = async (
43
43
  ): Promise<SkeletonState> => {
44
44
  const { db } = ctx
45
45
  const { viewer } = params
46
- const alreadyIncluded = parseCursor(params.cursor)
46
+ const alreadyIncluded = parseCursor(params.cursor) // @NOTE handles bad cursor e.g. on appview swap
47
47
  const { ref } = db.db.dynamic
48
48
  const suggestions = await db.db
49
49
  .selectFrom('suggested_follow')
@@ -15,6 +15,7 @@ export default function (server: Server, ctx: AppContext) {
15
15
  let results: string[]
16
16
  let resCursor: string | undefined
17
17
  if (ctx.searchAgent) {
18
+ // @NOTE cursors wont change on appview swap
18
19
  const res =
19
20
  await ctx.searchAgent.api.app.bsky.unspecced.searchActorsSkeleton({
20
21
  q: query,
@@ -10,6 +10,12 @@ export default function (server: Server, ctx: AppContext) {
10
10
  handler: async ({ auth, params }) => {
11
11
  const { actor, limit, cursor } = params
12
12
  const viewer = auth.credentials.iss
13
+ if (TimeCidKeyset.clearlyBad(cursor)) {
14
+ return {
15
+ encoding: 'application/json',
16
+ body: { feeds: [] },
17
+ }
18
+ }
13
19
 
14
20
  const db = ctx.db.getReplica()
15
21
  const actorService = ctx.services.actor(db)
@@ -67,6 +67,10 @@ const skeleton = async (
67
67
  throw new InvalidRequestError('Profile not found')
68
68
  }
69
69
 
70
+ if (FeedKeyset.clearlyBad(cursor)) {
71
+ return { params, feedItems: [] }
72
+ }
73
+
70
74
  let feedItemsQb = feedService
71
75
  .selectFeedItemQb()
72
76
  .innerJoin('like', 'like.subject', 'feed_item.uri')
@@ -81,6 +81,10 @@ export const skeleton = async (
81
81
  }
82
82
  }
83
83
 
84
+ if (FeedKeyset.clearlyBad(cursor)) {
85
+ return { params, feedItems: [] }
86
+ }
87
+
84
88
  // defaults to posts, reposts, and replies
85
89
  let feedItemsQb = feedService
86
90
  .selectFeedItemQb()
@@ -17,7 +17,6 @@ import { OutputSchema as SkeletonOutput } from '../../../../lexicon/types/app/bs
17
17
  import { SkeletonFeedPost } from '../../../../lexicon/types/app/bsky/feed/defs'
18
18
  import { Server } from '../../../../lexicon'
19
19
  import AppContext from '../../../../context'
20
- import { AlgoResponse } from '../../../../feed-gen/types'
21
20
  import { Database } from '../../../../db'
22
21
  import {
23
22
  FeedHydrationState,
@@ -43,6 +42,7 @@ export default function (server: Server, ctx: AppContext) {
43
42
  authorization: req.headers['authorization'],
44
43
  'accept-language': req.headers['accept-language'],
45
44
  })
45
+ // @NOTE feed cursors should not be affected by appview swap
46
46
  const { timerSkele, timerHydr, resHeaders, ...result } = await getFeed(
47
47
  { ...params, viewer },
48
48
  {
@@ -70,16 +70,13 @@ const skeleton = async (
70
70
  ctx: Context,
71
71
  ): Promise<SkeletonState> => {
72
72
  const timerSkele = new ServerTimer('skele').start()
73
- const localAlgo = ctx.appCtx.algos[params.feed]
74
73
  const feedParams: GetFeedParams = {
75
74
  feed: params.feed,
76
75
  limit: params.limit,
77
76
  cursor: params.cursor,
78
77
  }
79
78
  const { feedItems, cursor, resHeaders, ...passthrough } =
80
- localAlgo !== undefined
81
- ? await localAlgo(ctx.appCtx, params, params.viewer)
82
- : await skeletonFromFeedGen(ctx, feedParams)
79
+ await skeletonFromFeedGen(ctx, feedParams)
83
80
  return {
84
81
  params,
85
82
  cursor,
@@ -151,6 +148,12 @@ type SkeletonState = {
151
148
  type HydrationState = SkeletonState &
152
149
  FeedHydrationState & { feedItems: FeedRow[]; timerHydr: ServerTimer }
153
150
 
151
+ type AlgoResponse = {
152
+ feedItems: FeedRow[]
153
+ resHeaders?: Record<string, string>
154
+ cursor?: string
155
+ }
156
+
154
157
  const skeletonFromFeedGen = async (
155
158
  ctx: Context,
156
159
  params: GetFeedParams,
@@ -41,6 +41,10 @@ const skeleton = async (
41
41
  const { uri, cid, limit, cursor } = params
42
42
  const { ref } = db.db.dynamic
43
43
 
44
+ if (TimeCidKeyset.clearlyBad(cursor)) {
45
+ return { params, likes: [] }
46
+ }
47
+
44
48
  let builder = db.db
45
49
  .selectFrom('like')
46
50
  .where('like.subject', '=', uri)
@@ -56,6 +56,10 @@ export const skeleton = async (
56
56
  const { db } = ctx
57
57
  const { ref } = db.db.dynamic
58
58
 
59
+ if (FeedKeyset.clearlyBad(cursor)) {
60
+ return { params, feedItems: [] }
61
+ }
62
+
59
63
  const keyset = new FeedKeyset(ref('post.sortAt'), ref('post.cid'))
60
64
  const sortFrom = keyset.unpack(cursor)?.primary
61
65
 
@@ -46,6 +46,10 @@ const skeleton = async (
46
46
  const { limit, cursor, uri, cid } = params
47
47
  const { ref } = db.db.dynamic
48
48
 
49
+ if (TimeCidKeyset.clearlyBad(cursor)) {
50
+ return { params, repostedBy: [] }
51
+ }
52
+
49
53
  let builder = db.db
50
54
  .selectFrom('repost')
51
55
  .where('repost.subject', '=', uri)
@@ -6,8 +6,8 @@ export default function (server: Server, ctx: AppContext) {
6
6
  server.app.bsky.feed.getSuggestedFeeds({
7
7
  auth: ctx.authVerifier.standardOptional,
8
8
  handler: async ({ auth }) => {
9
+ // @NOTE ignores cursor, doesn't matter for appview swap
9
10
  const viewer = auth.credentials.iss
10
-
11
11
  const db = ctx.db.getReplica()
12
12
  const feedService = ctx.services.feed(db)
13
13
  const actorService = ctx.services.actor(db)
@@ -61,6 +61,10 @@ export const skeleton = async (
61
61
  return skeletonLimit1(params, ctx)
62
62
  }
63
63
 
64
+ if (FeedKeyset.clearlyBad(cursor)) {
65
+ return { params, feedItems: [] }
66
+ }
67
+
64
68
  const keyset = new FeedKeyset(ref('feed_item.sortAt'), ref('feed_item.cid'))
65
69
  const sortFrom = keyset.unpack(cursor)?.primary
66
70
 
@@ -49,6 +49,7 @@ const skeleton = async (
49
49
  params: Params,
50
50
  ctx: Context,
51
51
  ): Promise<SkeletonState> => {
52
+ // @NOTE cursors wont change on appview swap
52
53
  const res = await ctx.searchAgent.api.app.bsky.unspecced.searchPostsSkeleton({
53
54
  q: params.q,
54
55
  cursor: params.cursor,
@@ -9,6 +9,13 @@ export default function (server: Server, ctx: AppContext) {
9
9
  handler: async ({ params, auth }) => {
10
10
  const { limit, cursor } = params
11
11
  const requester = auth.credentials.iss
12
+ if (TimeCidKeyset.clearlyBad(cursor)) {
13
+ return {
14
+ encoding: 'application/json',
15
+ body: { blocks: [] },
16
+ }
17
+ }
18
+
12
19
  const db = ctx.db.getReplica()
13
20
  const { ref } = db.db.dynamic
14
21
 
@@ -52,6 +52,10 @@ const skeleton = async (
52
52
  throw new InvalidRequestError(`Actor not found: ${actor}`)
53
53
  }
54
54
 
55
+ if (TimeCidKeyset.clearlyBad(cursor)) {
56
+ return { params, followers: [], subject }
57
+ }
58
+
55
59
  let followersReq = db.db
56
60
  .selectFrom('follow')
57
61
  .where('follow.subjectDid', '=', subject.did)
@@ -52,6 +52,10 @@ const skeleton = async (
52
52
  throw new InvalidRequestError(`Actor not found: ${actor}`)
53
53
  }
54
54
 
55
+ if (TimeCidKeyset.clearlyBad(cursor)) {
56
+ return { params, follows: [], creator }
57
+ }
58
+
55
59
  let followsReq = db.db
56
60
  .selectFrom('follow')
57
61
  .where('follow.creator', '=', creator.did)
@@ -49,6 +49,10 @@ const skeleton = async (
49
49
  throw new InvalidRequestError(`List not found: ${list}`)
50
50
  }
51
51
 
52
+ if (TimeCidKeyset.clearlyBad(cursor)) {
53
+ return { params, list: listRes, listItems: [] }
54
+ }
55
+
52
56
  let itemsReq = graphService
53
57
  .getListItemsQb()
54
58
  .where('list_item.listUri', '=', list)
@@ -45,6 +45,10 @@ const skeleton = async (
45
45
  const { limit, cursor, viewer } = params
46
46
  const { ref } = db.db.dynamic
47
47
 
48
+ if (TimeCidKeyset.clearlyBad(cursor)) {
49
+ return { params, listInfos: [] }
50
+ }
51
+
48
52
  let listsReq = graphService
49
53
  .getListsQb(viewer)
50
54
  .whereExists(
@@ -9,6 +9,13 @@ export default function (server: Server, ctx: AppContext) {
9
9
  handler: async ({ params, auth }) => {
10
10
  const { limit, cursor } = params
11
11
  const requester = auth.credentials.iss
12
+ if (TimeCidKeyset.clearlyBad(cursor)) {
13
+ return {
14
+ encoding: 'application/json',
15
+ body: { lists: [] },
16
+ }
17
+ }
18
+
12
19
  const db = ctx.db.getReplica()
13
20
  const { ref } = db.db.dynamic
14
21
 
@@ -10,6 +10,13 @@ export default function (server: Server, ctx: AppContext) {
10
10
  handler: async ({ params, auth }) => {
11
11
  const { actor, limit, cursor } = params
12
12
  const requester = auth.credentials.iss
13
+ if (TimeCidKeyset.clearlyBad(cursor)) {
14
+ return {
15
+ encoding: 'application/json',
16
+ body: { lists: [] },
17
+ }
18
+ }
19
+
13
20
  const db = ctx.db.getReplica()
14
21
  const { ref } = db.db.dynamic
15
22
 
@@ -9,6 +9,13 @@ export default function (server: Server, ctx: AppContext) {
9
9
  handler: async ({ params, auth }) => {
10
10
  const { limit, cursor } = params
11
11
  const requester = auth.credentials.iss
12
+ if (TimeCidKeyset.clearlyBad(cursor)) {
13
+ return {
14
+ encoding: 'application/json',
15
+ body: { mutes: [] },
16
+ }
17
+ }
18
+
12
19
  const db = ctx.db.getReplica()
13
20
  const { ref } = db.db.dynamic
14
21
 
@@ -51,6 +51,9 @@ const skeleton = async (
51
51
  if (params.seenAt) {
52
52
  throw new InvalidRequestError('The seenAt parameter is unsupported')
53
53
  }
54
+ if (NotifsKeyset.clearlyBad(cursor)) {
55
+ return { params, notifs: [] }
56
+ }
54
57
  let notifBuilder = db.db
55
58
  .selectFrom('notification as notif')
56
59
  .where('notif.did', '=', viewer)
@@ -12,11 +12,17 @@ export default function (server: Server, ctx: AppContext) {
12
12
  handler: async ({ auth, params }) => {
13
13
  const { limit, cursor, query } = params
14
14
  const requester = auth.credentials.iss
15
+ if (LikeCountKeyset.clearlyBad(cursor)) {
16
+ return {
17
+ encoding: 'application/json',
18
+ body: { feeds: [] },
19
+ }
20
+ }
21
+
15
22
  const db = ctx.db.getReplica()
16
23
  const { ref } = db.db.dynamic
17
24
  const feedService = ctx.services.feed(db)
18
25
  const actorService = ctx.services.actor(db)
19
-
20
26
  let inner = db.db
21
27
  .selectFrom('feed_generator')
22
28
  .select([
package/src/api/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { Server } from '../lexicon'
2
2
  import AppContext from '../context'
3
- import describeFeedGenerator from './app/bsky/feed/describeFeedGenerator'
4
3
  import getTimeline from './app/bsky/feed/getTimeline'
5
4
  import getActorFeeds from './app/bsky/feed/getActorFeeds'
6
5
  import getSuggestedFeeds from './app/bsky/feed/getSuggestedFeeds'
@@ -8,7 +7,6 @@ import getAuthorFeed from './app/bsky/feed/getAuthorFeed'
8
7
  import getFeed from './app/bsky/feed/getFeed'
9
8
  import getFeedGenerator from './app/bsky/feed/getFeedGenerator'
10
9
  import getFeedGenerators from './app/bsky/feed/getFeedGenerators'
11
- import getFeedSkeleton from './app/bsky/feed/getFeedSkeleton'
12
10
  import getLikes from './app/bsky/feed/getLikes'
13
11
  import getListFeed from './app/bsky/feed/getListFeed'
14
12
  import getPostThread from './app/bsky/feed/getPostThread'
@@ -40,7 +38,6 @@ import listNotifications from './app/bsky/notification/listNotifications'
40
38
  import updateSeen from './app/bsky/notification/updateSeen'
41
39
  import registerPush from './app/bsky/notification/registerPush'
42
40
  import getPopularFeedGenerators from './app/bsky/unspecced/getPopularFeedGenerators'
43
- import getTimelineSkeleton from './app/bsky/unspecced/getTimelineSkeleton'
44
41
  import getTaggedSuggestions from './app/bsky/unspecced/getTaggedSuggestions'
45
42
  import getSubjectStatus from './com/atproto/admin/getSubjectStatus'
46
43
  import updateSubjectStatus from './com/atproto/admin/updateSubjectStatus'
@@ -57,7 +54,6 @@ export * as blobResolver from './blob-resolver'
57
54
 
58
55
  export default function (server: Server, ctx: AppContext) {
59
56
  // app.bsky
60
- describeFeedGenerator(server, ctx)
61
57
  getTimeline(server, ctx)
62
58
  getActorFeeds(server, ctx)
63
59
  getSuggestedFeeds(server, ctx)
@@ -65,7 +61,6 @@ export default function (server: Server, ctx: AppContext) {
65
61
  getFeed(server, ctx)
66
62
  getFeedGenerator(server, ctx)
67
63
  getFeedGenerators(server, ctx)
68
- getFeedSkeleton(server, ctx)
69
64
  getLikes(server, ctx)
70
65
  getListFeed(server, ctx)
71
66
  getPostThread(server, ctx)
@@ -97,7 +92,6 @@ export default function (server: Server, ctx: AppContext) {
97
92
  updateSeen(server, ctx)
98
93
  registerPush(server, ctx)
99
94
  getPopularFeedGenerators(server, ctx)
100
- getTimelineSkeleton(server, ctx)
101
95
  getTaggedSuggestions(server, ctx)
102
96
  // com.atproto
103
97
  getSubjectStatus(server, ctx)