@atproto/bsky 0.0.94 → 0.0.95
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.
- package/CHANGELOG.md +7 -0
- package/dist/api/app/bsky/feed/getFeed.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getFeed.js +5 -1
- package/dist/api/app/bsky/feed/getFeed.js.map +1 -1
- package/dist/api/app/bsky/feed/getPostThread.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getPostThread.js +9 -2
- package/dist/api/app/bsky/feed/getPostThread.js.map +1 -1
- package/dist/api/app/bsky/feed/getQuotes.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getQuotes.js +5 -4
- package/dist/api/app/bsky/feed/getQuotes.js.map +1 -1
- package/dist/api/app/bsky/graph/searchStarterPacks.d.ts +4 -0
- package/dist/api/app/bsky/graph/searchStarterPacks.d.ts.map +1 -0
- package/dist/api/app/bsky/graph/searchStarterPacks.js +76 -0
- package/dist/api/app/bsky/graph/searchStarterPacks.js.map +1 -0
- package/dist/api/app/bsky/notification/listNotifications.js +12 -4
- package/dist/api/app/bsky/notification/listNotifications.js.map +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +2 -0
- package/dist/api/index.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +19 -0
- package/dist/config.js.map +1 -1
- package/dist/data-plane/server/db/migrations/20241114T153108102Z-add-starter-packs-name.d.ts +4 -0
- package/dist/data-plane/server/db/migrations/20241114T153108102Z-add-starter-packs-name.d.ts.map +1 -0
- package/dist/data-plane/server/db/migrations/20241114T153108102Z-add-starter-packs-name.js +21 -0
- package/dist/data-plane/server/db/migrations/20241114T153108102Z-add-starter-packs-name.js.map +1 -0
- package/dist/data-plane/server/db/migrations/index.d.ts +1 -0
- package/dist/data-plane/server/db/migrations/index.d.ts.map +1 -1
- package/dist/data-plane/server/db/migrations/index.js +2 -1
- package/dist/data-plane/server/db/migrations/index.js.map +1 -1
- package/dist/data-plane/server/db/tables/starter-pack.d.ts +1 -0
- package/dist/data-plane/server/db/tables/starter-pack.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/starter-pack.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/starter-pack.js +1 -0
- package/dist/data-plane/server/indexing/plugins/starter-pack.js.map +1 -1
- package/dist/data-plane/server/routes/search.d.ts.map +1 -1
- package/dist/data-plane/server/routes/search.js +21 -0
- package/dist/data-plane/server/routes/search.js.map +1 -1
- package/dist/hydration/actor.d.ts.map +1 -1
- package/dist/hydration/actor.js +6 -2
- package/dist/hydration/actor.js.map +1 -1
- package/dist/hydration/label.d.ts +1 -0
- package/dist/hydration/label.d.ts.map +1 -1
- package/dist/hydration/label.js +7 -0
- package/dist/hydration/label.js.map +1 -1
- package/dist/lexicon/index.d.ts +6 -0
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +12 -0
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +17817 -7728
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +153 -0
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/graph/searchStarterPacks.d.ts +40 -0
- package/dist/lexicon/types/app/bsky/graph/searchStarterPacks.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/searchStarterPacks.js +3 -0
- package/dist/lexicon/types/app/bsky/graph/searchStarterPacks.js.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/defs.d.ts +6 -0
- package/dist/lexicon/types/app/bsky/unspecced/defs.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/defs.js +10 -0
- package/dist/lexicon/types/app/bsky/unspecced/defs.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/searchStarterPacksSkeleton.d.ts +46 -0
- package/dist/lexicon/types/app/bsky/unspecced/searchStarterPacksSkeleton.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/searchStarterPacksSkeleton.js +3 -0
- package/dist/lexicon/types/app/bsky/unspecced/searchStarterPacksSkeleton.js.map +1 -0
- package/dist/lexicon/types/com/atproto/temp/addReservedHandle.d.ts +39 -0
- package/dist/lexicon/types/com/atproto/temp/addReservedHandle.d.ts.map +1 -0
- package/dist/lexicon/types/com/atproto/temp/addReservedHandle.js +3 -0
- package/dist/lexicon/types/com/atproto/temp/addReservedHandle.js.map +1 -0
- package/dist/proto/bsky_connect.d.ts +10 -1
- package/dist/proto/bsky_connect.d.ts.map +1 -1
- package/dist/proto/bsky_connect.js +9 -0
- package/dist/proto/bsky_connect.js.map +1 -1
- package/dist/proto/bsky_pb.d.ts +49 -0
- package/dist/proto/bsky_pb.d.ts.map +1 -1
- package/dist/proto/bsky_pb.js +144 -3
- package/dist/proto/bsky_pb.js.map +1 -1
- package/dist/views/index.d.ts +1 -0
- package/dist/views/index.d.ts.map +1 -1
- package/dist/views/index.js +9 -0
- package/dist/views/index.js.map +1 -1
- package/package.json +4 -4
- package/proto/bsky.proto +14 -0
- package/src/api/app/bsky/feed/getFeed.ts +8 -1
- package/src/api/app/bsky/feed/getPostThread.ts +13 -7
- package/src/api/app/bsky/feed/getQuotes.ts +12 -5
- package/src/api/app/bsky/graph/searchStarterPacks.ts +118 -0
- package/src/api/app/bsky/notification/listNotifications.ts +14 -4
- package/src/api/index.ts +2 -0
- package/src/config.ts +26 -0
- package/src/data-plane/server/db/migrations/20241114T153108102Z-add-starter-packs-name.ts +19 -0
- package/src/data-plane/server/db/migrations/index.ts +1 -0
- package/src/data-plane/server/db/tables/starter-pack.ts +1 -0
- package/src/data-plane/server/indexing/plugins/starter-pack.ts +1 -0
- package/src/data-plane/server/routes/search.ts +30 -0
- package/src/hydration/actor.ts +11 -5
- package/src/hydration/label.ts +10 -0
- package/src/lexicon/index.ts +36 -0
- package/src/lexicon/lexicons.ts +163 -2
- package/src/lexicon/types/app/bsky/graph/searchStarterPacks.ts +50 -0
- package/src/lexicon/types/app/bsky/unspecced/defs.ts +24 -0
- package/src/lexicon/types/app/bsky/unspecced/searchStarterPacksSkeleton.ts +56 -0
- package/src/lexicon/types/com/atproto/temp/addReservedHandle.ts +48 -0
- package/src/proto/bsky_connect.ts +11 -0
- package/src/proto/bsky_pb.ts +137 -0
- package/src/views/index.ts +12 -0
- package/tests/__snapshots__/feed-generation.test.ts.snap +49 -7
- package/tests/feed-generation.test.ts +82 -28
- package/tests/query-labels.test.ts +1 -1
- package/tests/views/known-followers.test.ts +1 -1
- package/tests/views/labels-needs-review.test.ts +168 -0
- package/tests/views/starter-packs.test.ts +62 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.tests.tsbuildinfo +1 -1
- /package/tests/views/{takedown-labels.test.ts → labels-takedown.test.ts} +0 -0
package/src/proto/bsky_pb.ts
CHANGED
|
@@ -9445,6 +9445,143 @@ export class SearchPostsResponse extends Message<SearchPostsResponse> {
|
|
|
9445
9445
|
}
|
|
9446
9446
|
}
|
|
9447
9447
|
|
|
9448
|
+
/**
|
|
9449
|
+
* - Return uris of starter packs matching term, paginated
|
|
9450
|
+
* - `searchStarterPacks` skeleton
|
|
9451
|
+
*
|
|
9452
|
+
* @generated from message bsky.SearchStarterPacksRequest
|
|
9453
|
+
*/
|
|
9454
|
+
export class SearchStarterPacksRequest extends Message<SearchStarterPacksRequest> {
|
|
9455
|
+
/**
|
|
9456
|
+
* @generated from field: string term = 1;
|
|
9457
|
+
*/
|
|
9458
|
+
term = ''
|
|
9459
|
+
|
|
9460
|
+
/**
|
|
9461
|
+
* @generated from field: int32 limit = 2;
|
|
9462
|
+
*/
|
|
9463
|
+
limit = 0
|
|
9464
|
+
|
|
9465
|
+
/**
|
|
9466
|
+
* @generated from field: string cursor = 3;
|
|
9467
|
+
*/
|
|
9468
|
+
cursor = ''
|
|
9469
|
+
|
|
9470
|
+
constructor(data?: PartialMessage<SearchStarterPacksRequest>) {
|
|
9471
|
+
super()
|
|
9472
|
+
proto3.util.initPartial(data, this)
|
|
9473
|
+
}
|
|
9474
|
+
|
|
9475
|
+
static readonly runtime: typeof proto3 = proto3
|
|
9476
|
+
static readonly typeName = 'bsky.SearchStarterPacksRequest'
|
|
9477
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
9478
|
+
{ no: 1, name: 'term', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
|
9479
|
+
{ no: 2, name: 'limit', kind: 'scalar', T: 5 /* ScalarType.INT32 */ },
|
|
9480
|
+
{ no: 3, name: 'cursor', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
|
9481
|
+
])
|
|
9482
|
+
|
|
9483
|
+
static fromBinary(
|
|
9484
|
+
bytes: Uint8Array,
|
|
9485
|
+
options?: Partial<BinaryReadOptions>,
|
|
9486
|
+
): SearchStarterPacksRequest {
|
|
9487
|
+
return new SearchStarterPacksRequest().fromBinary(bytes, options)
|
|
9488
|
+
}
|
|
9489
|
+
|
|
9490
|
+
static fromJson(
|
|
9491
|
+
jsonValue: JsonValue,
|
|
9492
|
+
options?: Partial<JsonReadOptions>,
|
|
9493
|
+
): SearchStarterPacksRequest {
|
|
9494
|
+
return new SearchStarterPacksRequest().fromJson(jsonValue, options)
|
|
9495
|
+
}
|
|
9496
|
+
|
|
9497
|
+
static fromJsonString(
|
|
9498
|
+
jsonString: string,
|
|
9499
|
+
options?: Partial<JsonReadOptions>,
|
|
9500
|
+
): SearchStarterPacksRequest {
|
|
9501
|
+
return new SearchStarterPacksRequest().fromJsonString(jsonString, options)
|
|
9502
|
+
}
|
|
9503
|
+
|
|
9504
|
+
static equals(
|
|
9505
|
+
a:
|
|
9506
|
+
| SearchStarterPacksRequest
|
|
9507
|
+
| PlainMessage<SearchStarterPacksRequest>
|
|
9508
|
+
| undefined,
|
|
9509
|
+
b:
|
|
9510
|
+
| SearchStarterPacksRequest
|
|
9511
|
+
| PlainMessage<SearchStarterPacksRequest>
|
|
9512
|
+
| undefined,
|
|
9513
|
+
): boolean {
|
|
9514
|
+
return proto3.util.equals(SearchStarterPacksRequest, a, b)
|
|
9515
|
+
}
|
|
9516
|
+
}
|
|
9517
|
+
|
|
9518
|
+
/**
|
|
9519
|
+
* @generated from message bsky.SearchStarterPacksResponse
|
|
9520
|
+
*/
|
|
9521
|
+
export class SearchStarterPacksResponse extends Message<SearchStarterPacksResponse> {
|
|
9522
|
+
/**
|
|
9523
|
+
* @generated from field: repeated string uris = 1;
|
|
9524
|
+
*/
|
|
9525
|
+
uris: string[] = []
|
|
9526
|
+
|
|
9527
|
+
/**
|
|
9528
|
+
* @generated from field: string cursor = 2;
|
|
9529
|
+
*/
|
|
9530
|
+
cursor = ''
|
|
9531
|
+
|
|
9532
|
+
constructor(data?: PartialMessage<SearchStarterPacksResponse>) {
|
|
9533
|
+
super()
|
|
9534
|
+
proto3.util.initPartial(data, this)
|
|
9535
|
+
}
|
|
9536
|
+
|
|
9537
|
+
static readonly runtime: typeof proto3 = proto3
|
|
9538
|
+
static readonly typeName = 'bsky.SearchStarterPacksResponse'
|
|
9539
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
9540
|
+
{
|
|
9541
|
+
no: 1,
|
|
9542
|
+
name: 'uris',
|
|
9543
|
+
kind: 'scalar',
|
|
9544
|
+
T: 9 /* ScalarType.STRING */,
|
|
9545
|
+
repeated: true,
|
|
9546
|
+
},
|
|
9547
|
+
{ no: 2, name: 'cursor', kind: 'scalar', T: 9 /* ScalarType.STRING */ },
|
|
9548
|
+
])
|
|
9549
|
+
|
|
9550
|
+
static fromBinary(
|
|
9551
|
+
bytes: Uint8Array,
|
|
9552
|
+
options?: Partial<BinaryReadOptions>,
|
|
9553
|
+
): SearchStarterPacksResponse {
|
|
9554
|
+
return new SearchStarterPacksResponse().fromBinary(bytes, options)
|
|
9555
|
+
}
|
|
9556
|
+
|
|
9557
|
+
static fromJson(
|
|
9558
|
+
jsonValue: JsonValue,
|
|
9559
|
+
options?: Partial<JsonReadOptions>,
|
|
9560
|
+
): SearchStarterPacksResponse {
|
|
9561
|
+
return new SearchStarterPacksResponse().fromJson(jsonValue, options)
|
|
9562
|
+
}
|
|
9563
|
+
|
|
9564
|
+
static fromJsonString(
|
|
9565
|
+
jsonString: string,
|
|
9566
|
+
options?: Partial<JsonReadOptions>,
|
|
9567
|
+
): SearchStarterPacksResponse {
|
|
9568
|
+
return new SearchStarterPacksResponse().fromJsonString(jsonString, options)
|
|
9569
|
+
}
|
|
9570
|
+
|
|
9571
|
+
static equals(
|
|
9572
|
+
a:
|
|
9573
|
+
| SearchStarterPacksResponse
|
|
9574
|
+
| PlainMessage<SearchStarterPacksResponse>
|
|
9575
|
+
| undefined,
|
|
9576
|
+
b:
|
|
9577
|
+
| SearchStarterPacksResponse
|
|
9578
|
+
| PlainMessage<SearchStarterPacksResponse>
|
|
9579
|
+
| undefined,
|
|
9580
|
+
): boolean {
|
|
9581
|
+
return proto3.util.equals(SearchStarterPacksResponse, a, b)
|
|
9582
|
+
}
|
|
9583
|
+
}
|
|
9584
|
+
|
|
9448
9585
|
/**
|
|
9449
9586
|
* - Return DIDs of suggested follows for a user, excluding anyone they already follow
|
|
9450
9587
|
* - `getSuggestions`, `getSuggestedFollowsByActor`
|
package/src/views/index.ts
CHANGED
|
@@ -125,6 +125,15 @@ export class Views {
|
|
|
125
125
|
return actor.muted || !!actor.mutedByList
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
viewerSeesNeedsReview(did: string, state: HydrationState): boolean {
|
|
129
|
+
const { labels, profileViewers, ctx } = state
|
|
130
|
+
return (
|
|
131
|
+
!labels?.get(did)?.needsReview ||
|
|
132
|
+
ctx?.viewer === did ||
|
|
133
|
+
!!profileViewers?.get(did)?.following
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
128
137
|
replyIsHiddenByThreadgate(
|
|
129
138
|
replyUri: string,
|
|
130
139
|
rootPostUri: string,
|
|
@@ -850,6 +859,9 @@ export class Views {
|
|
|
850
859
|
if (this.viewerBlockExists(post.author.did, state)) {
|
|
851
860
|
return this.blockedPost(uri, post.author.did, state)
|
|
852
861
|
}
|
|
862
|
+
if (!this.viewerSeesNeedsReview(post.author.did, state)) {
|
|
863
|
+
return undefined
|
|
864
|
+
}
|
|
853
865
|
return {
|
|
854
866
|
$type: 'app.bsky.feed.defs#threadViewPost',
|
|
855
867
|
post,
|
|
@@ -397,9 +397,9 @@ Array [
|
|
|
397
397
|
"muted": false,
|
|
398
398
|
},
|
|
399
399
|
},
|
|
400
|
-
"description": "
|
|
400
|
+
"description": "Echoes back the same cursor it received",
|
|
401
401
|
"did": "user(0)",
|
|
402
|
-
"displayName": "Bad Pagination",
|
|
402
|
+
"displayName": "Bad Pagination Cursor",
|
|
403
403
|
"indexedAt": "1970-01-01T00:00:00.000Z",
|
|
404
404
|
"labels": Array [],
|
|
405
405
|
"likeCount": 0,
|
|
@@ -439,9 +439,9 @@ Array [
|
|
|
439
439
|
"muted": false,
|
|
440
440
|
},
|
|
441
441
|
},
|
|
442
|
-
"description": "Provides
|
|
442
|
+
"description": "Provides all feed candidates, blindly ignoring pagination limit",
|
|
443
443
|
"did": "user(0)",
|
|
444
|
-
"displayName": "
|
|
444
|
+
"displayName": "Bad Pagination Limit",
|
|
445
445
|
"indexedAt": "1970-01-01T00:00:00.000Z",
|
|
446
446
|
"labels": Array [],
|
|
447
447
|
"likeCount": 0,
|
|
@@ -481,15 +481,57 @@ Array [
|
|
|
481
481
|
"muted": false,
|
|
482
482
|
},
|
|
483
483
|
},
|
|
484
|
+
"description": "Provides even-indexed feed candidates",
|
|
485
|
+
"did": "user(0)",
|
|
486
|
+
"displayName": "Even",
|
|
487
|
+
"indexedAt": "1970-01-01T00:00:00.000Z",
|
|
488
|
+
"labels": Array [],
|
|
489
|
+
"likeCount": 0,
|
|
490
|
+
"uri": "record(7)",
|
|
491
|
+
"viewer": Object {},
|
|
492
|
+
},
|
|
493
|
+
Object {
|
|
494
|
+
"cid": "cids(7)",
|
|
495
|
+
"creator": Object {
|
|
496
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(2)/cids(1)@jpeg",
|
|
497
|
+
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
498
|
+
"description": "its me!",
|
|
499
|
+
"did": "user(1)",
|
|
500
|
+
"displayName": "ali",
|
|
501
|
+
"handle": "alice.test",
|
|
502
|
+
"indexedAt": "1970-01-01T00:00:00.000Z",
|
|
503
|
+
"labels": Array [
|
|
504
|
+
Object {
|
|
505
|
+
"cid": "cids(2)",
|
|
506
|
+
"cts": "1970-01-01T00:00:00.000Z",
|
|
507
|
+
"src": "user(1)",
|
|
508
|
+
"uri": "record(3)",
|
|
509
|
+
"val": "self-label-a",
|
|
510
|
+
},
|
|
511
|
+
Object {
|
|
512
|
+
"cid": "cids(2)",
|
|
513
|
+
"cts": "1970-01-01T00:00:00.000Z",
|
|
514
|
+
"src": "user(1)",
|
|
515
|
+
"uri": "record(3)",
|
|
516
|
+
"val": "self-label-b",
|
|
517
|
+
},
|
|
518
|
+
],
|
|
519
|
+
"viewer": Object {
|
|
520
|
+
"blockedBy": false,
|
|
521
|
+
"followedBy": "record(2)",
|
|
522
|
+
"following": "record(1)",
|
|
523
|
+
"muted": false,
|
|
524
|
+
},
|
|
525
|
+
},
|
|
484
526
|
"description": "Provides all feed candidates",
|
|
485
527
|
"did": "user(0)",
|
|
486
528
|
"displayName": "All",
|
|
487
529
|
"indexedAt": "1970-01-01T00:00:00.000Z",
|
|
488
530
|
"labels": Array [],
|
|
489
531
|
"likeCount": 2,
|
|
490
|
-
"uri": "record(
|
|
532
|
+
"uri": "record(8)",
|
|
491
533
|
"viewer": Object {
|
|
492
|
-
"like": "record(
|
|
534
|
+
"like": "record(9)",
|
|
493
535
|
},
|
|
494
536
|
},
|
|
495
537
|
]
|
|
@@ -1950,7 +1992,7 @@ Object {
|
|
|
1950
1992
|
},
|
|
1951
1993
|
"description": "Provides all feed candidates, blindly ignoring pagination limit",
|
|
1952
1994
|
"did": "user(0)",
|
|
1953
|
-
"displayName": "Bad Pagination",
|
|
1995
|
+
"displayName": "Bad Pagination Limit",
|
|
1954
1996
|
"indexedAt": "1970-01-01T00:00:00.000Z",
|
|
1955
1997
|
"labels": Array [],
|
|
1956
1998
|
"likeCount": 0,
|
|
@@ -30,7 +30,8 @@ describe('feed generation', () => {
|
|
|
30
30
|
let feedUriAllRef: RecordRef
|
|
31
31
|
let feedUriEven: string
|
|
32
32
|
let feedUriOdd: string // Unsupported by feed gen
|
|
33
|
-
let
|
|
33
|
+
let feedUriBadPaginationLimit: string
|
|
34
|
+
let feedUriBadPaginationCursor: string
|
|
34
35
|
let feedUriPrime: string // Taken-down
|
|
35
36
|
let feedUriPrimeRef: RecordRef
|
|
36
37
|
let feedUriNeedsAuth: string
|
|
@@ -47,10 +48,15 @@ describe('feed generation', () => {
|
|
|
47
48
|
await network.processAll()
|
|
48
49
|
alice = sc.dids.alice
|
|
49
50
|
const allUri = AtUri.make(alice, 'app.bsky.feed.generator', 'all')
|
|
50
|
-
const
|
|
51
|
+
const feedUriBadPaginationLimit = AtUri.make(
|
|
51
52
|
alice,
|
|
52
53
|
'app.bsky.feed.generator',
|
|
53
|
-
'bad-pagination',
|
|
54
|
+
'bad-pagination-limit',
|
|
55
|
+
)
|
|
56
|
+
const feedUriBadPaginationCursor = AtUri.make(
|
|
57
|
+
alice,
|
|
58
|
+
'app.bsky.feed.generator',
|
|
59
|
+
'bad-pagination-cursor',
|
|
54
60
|
)
|
|
55
61
|
const evenUri = AtUri.make(alice, 'app.bsky.feed.generator', 'even')
|
|
56
62
|
const primeUri = AtUri.make(alice, 'app.bsky.feed.generator', 'prime')
|
|
@@ -62,7 +68,12 @@ describe('feed generation', () => {
|
|
|
62
68
|
gen = await network.createFeedGen({
|
|
63
69
|
[allUri.toString()]: feedGenHandler('all'),
|
|
64
70
|
[evenUri.toString()]: feedGenHandler('even'),
|
|
65
|
-
[
|
|
71
|
+
[feedUriBadPaginationLimit.toString()]: feedGenHandler(
|
|
72
|
+
'bad-pagination-limit',
|
|
73
|
+
),
|
|
74
|
+
[feedUriBadPaginationCursor.toString()]: feedGenHandler(
|
|
75
|
+
'bad-pagination-cursor',
|
|
76
|
+
),
|
|
66
77
|
[primeUri.toString()]: feedGenHandler('prime'),
|
|
67
78
|
[needsAuthUri.toString()]: feedGenHandler('needs-auth'),
|
|
68
79
|
})
|
|
@@ -70,7 +81,7 @@ describe('feed generation', () => {
|
|
|
70
81
|
const feedSuggestions = [
|
|
71
82
|
{ uri: allUri.toString(), order: 1 },
|
|
72
83
|
{ uri: evenUri.toString(), order: 2 },
|
|
73
|
-
{ uri:
|
|
84
|
+
{ uri: feedUriBadPaginationLimit.toString(), order: 3 },
|
|
74
85
|
{ uri: primeUri.toString(), order: 4 },
|
|
75
86
|
]
|
|
76
87
|
await network.bsky.db.db
|
|
@@ -116,17 +127,31 @@ describe('feed generation', () => {
|
|
|
116
127
|
},
|
|
117
128
|
sc.getHeaders(alice),
|
|
118
129
|
)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
'
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
|
|
131
|
+
const badPaginationLimit =
|
|
132
|
+
await pdsAgent.api.app.bsky.feed.generator.create(
|
|
133
|
+
{ repo: alice, rkey: 'bad-pagination-limit' },
|
|
134
|
+
{
|
|
135
|
+
did: gen.did,
|
|
136
|
+
displayName: 'Bad Pagination Limit',
|
|
137
|
+
description:
|
|
138
|
+
'Provides all feed candidates, blindly ignoring pagination limit',
|
|
139
|
+
createdAt: new Date().toISOString(),
|
|
140
|
+
},
|
|
141
|
+
sc.getHeaders(alice),
|
|
142
|
+
)
|
|
143
|
+
const badPaginationCursor =
|
|
144
|
+
await pdsAgent.api.app.bsky.feed.generator.create(
|
|
145
|
+
{ repo: alice, rkey: 'bad-pagination-cursor' },
|
|
146
|
+
{
|
|
147
|
+
did: gen.did,
|
|
148
|
+
displayName: 'Bad Pagination Cursor',
|
|
149
|
+
description: 'Echoes back the same cursor it received',
|
|
150
|
+
createdAt: new Date().toISOString(),
|
|
151
|
+
},
|
|
152
|
+
sc.getHeaders(alice),
|
|
153
|
+
)
|
|
154
|
+
|
|
130
155
|
// Taken-down
|
|
131
156
|
const prime = await pdsAgent.api.app.bsky.feed.generator.create(
|
|
132
157
|
{ repo: alice, rkey: 'prime' },
|
|
@@ -157,7 +182,8 @@ describe('feed generation', () => {
|
|
|
157
182
|
feedUriAllRef = new RecordRef(all.uri, all.cid)
|
|
158
183
|
feedUriEven = even.uri
|
|
159
184
|
feedUriOdd = odd.uri
|
|
160
|
-
|
|
185
|
+
feedUriBadPaginationLimit = badPaginationLimit.uri
|
|
186
|
+
feedUriBadPaginationCursor = badPaginationCursor.uri
|
|
161
187
|
feedUriPrime = prime.uri
|
|
162
188
|
feedUriPrimeRef = new RecordRef(prime.uri, prime.cid)
|
|
163
189
|
feedUriNeedsAuth = needsAuth.uri
|
|
@@ -203,12 +229,13 @@ describe('feed generation', () => {
|
|
|
203
229
|
|
|
204
230
|
const paginatedAll = results(await paginateAll(paginator))
|
|
205
231
|
|
|
206
|
-
expect(paginatedAll.length).toEqual(
|
|
232
|
+
expect(paginatedAll.length).toEqual(6)
|
|
207
233
|
expect(paginatedAll[0].uri).toEqual(feedUriOdd)
|
|
208
234
|
expect(paginatedAll[1].uri).toEqual(feedUriNeedsAuth)
|
|
209
|
-
expect(paginatedAll[2].uri).toEqual(
|
|
210
|
-
expect(paginatedAll[3].uri).toEqual(
|
|
211
|
-
expect(paginatedAll[4].uri).toEqual(
|
|
235
|
+
expect(paginatedAll[2].uri).toEqual(feedUriBadPaginationCursor)
|
|
236
|
+
expect(paginatedAll[3].uri).toEqual(feedUriBadPaginationLimit)
|
|
237
|
+
expect(paginatedAll[4].uri).toEqual(feedUriEven)
|
|
238
|
+
expect(paginatedAll[5].uri).toEqual(feedUriAll)
|
|
212
239
|
expect(paginatedAll.map((fg) => fg.uri)).not.toContain(feedUriPrime) // taken-down
|
|
213
240
|
expect(forSnapshot(paginatedAll)).toMatchSnapshot()
|
|
214
241
|
})
|
|
@@ -490,7 +517,7 @@ describe('feed generation', () => {
|
|
|
490
517
|
expect(res.data.feeds.map((f) => f.uri)).toEqual([
|
|
491
518
|
feedUriAll,
|
|
492
519
|
feedUriEven,
|
|
493
|
-
|
|
520
|
+
feedUriBadPaginationLimit,
|
|
494
521
|
])
|
|
495
522
|
})
|
|
496
523
|
|
|
@@ -605,7 +632,7 @@ describe('feed generation', () => {
|
|
|
605
632
|
|
|
606
633
|
it('paginates, handling feed not respecting limit.', async () => {
|
|
607
634
|
const res = await agent.api.app.bsky.feed.getFeed(
|
|
608
|
-
{ feed:
|
|
635
|
+
{ feed: feedUriBadPaginationLimit, limit: 3 },
|
|
609
636
|
{
|
|
610
637
|
headers: await network.serviceHeaders(
|
|
611
638
|
alice,
|
|
@@ -640,6 +667,22 @@ describe('feed generation', () => {
|
|
|
640
667
|
})
|
|
641
668
|
})
|
|
642
669
|
|
|
670
|
+
it('returns empty cursor with feeds that echo back the same cursor from the param.', async () => {
|
|
671
|
+
const res = await agent.api.app.bsky.feed.getFeed(
|
|
672
|
+
{ feed: feedUriBadPaginationCursor, cursor: '1', limit: 2 },
|
|
673
|
+
{
|
|
674
|
+
headers: await network.serviceHeaders(
|
|
675
|
+
alice,
|
|
676
|
+
ids.AppBskyFeedGetFeed,
|
|
677
|
+
gen.did,
|
|
678
|
+
),
|
|
679
|
+
},
|
|
680
|
+
)
|
|
681
|
+
|
|
682
|
+
expect(res.data.cursor).toBeUndefined()
|
|
683
|
+
expect(res.data.feed).toHaveLength(2)
|
|
684
|
+
})
|
|
685
|
+
|
|
643
686
|
it('resolves contents of taken-down feed.', async () => {
|
|
644
687
|
const tryGetFeed = agent.api.app.bsky.feed.getFeed(
|
|
645
688
|
{ feed: feedUriPrime },
|
|
@@ -712,7 +755,13 @@ describe('feed generation', () => {
|
|
|
712
755
|
|
|
713
756
|
const feedGenHandler =
|
|
714
757
|
(
|
|
715
|
-
feedName:
|
|
758
|
+
feedName:
|
|
759
|
+
| 'even'
|
|
760
|
+
| 'all'
|
|
761
|
+
| 'prime'
|
|
762
|
+
| 'bad-pagination-limit'
|
|
763
|
+
| 'bad-pagination-cursor'
|
|
764
|
+
| 'needs-auth',
|
|
716
765
|
): SkeletonHandler =>
|
|
717
766
|
async ({ req, params }) => {
|
|
718
767
|
if (feedName === 'needs-auth' && !req.headers.authorization) {
|
|
@@ -753,17 +802,22 @@ describe('feed generation', () => {
|
|
|
753
802
|
return true
|
|
754
803
|
})
|
|
755
804
|
const feedResults =
|
|
756
|
-
feedName === 'bad-pagination'
|
|
805
|
+
feedName === 'bad-pagination-limit'
|
|
757
806
|
? fullFeed.slice(offset) // does not respect limit
|
|
758
807
|
: fullFeed.slice(offset, offset + limit)
|
|
759
808
|
const lastResult = feedResults.at(-1)
|
|
809
|
+
const cursorResult =
|
|
810
|
+
feedName === 'bad-pagination-cursor'
|
|
811
|
+
? cursor
|
|
812
|
+
: lastResult
|
|
813
|
+
? (fullFeed.indexOf(lastResult) + 1).toString()
|
|
814
|
+
: undefined
|
|
815
|
+
|
|
760
816
|
return {
|
|
761
817
|
encoding: 'application/json',
|
|
762
818
|
body: {
|
|
763
819
|
feed: feedResults,
|
|
764
|
-
cursor:
|
|
765
|
-
? (fullFeed.indexOf(lastResult) + 1).toString()
|
|
766
|
-
: undefined,
|
|
820
|
+
cursor: cursorResult,
|
|
767
821
|
$auth: jwtBody(req.headers.authorization), // for testing purposes
|
|
768
822
|
},
|
|
769
823
|
}
|
|
@@ -13,7 +13,7 @@ describe('label hydration', () => {
|
|
|
13
13
|
|
|
14
14
|
beforeAll(async () => {
|
|
15
15
|
network = await TestNetwork.create({
|
|
16
|
-
dbPostgresSchema: '
|
|
16
|
+
dbPostgresSchema: 'bsky_query_labels',
|
|
17
17
|
})
|
|
18
18
|
pdsAgent = network.pds.getClient()
|
|
19
19
|
sc = network.getSeedClient()
|
|
@@ -14,7 +14,7 @@ describe('known followers (social proof)', () => {
|
|
|
14
14
|
|
|
15
15
|
beforeAll(async () => {
|
|
16
16
|
network = await TestNetwork.create({
|
|
17
|
-
dbPostgresSchema: '
|
|
17
|
+
dbPostgresSchema: 'bsky_known_followers',
|
|
18
18
|
})
|
|
19
19
|
agent = network.bsky.getClient()
|
|
20
20
|
pdsAgent = network.pds.getClient()
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { AtpAgent } from '@atproto/api'
|
|
2
|
+
import { TestNetwork, SeedClient, basicSeed } from '@atproto/dev-env'
|
|
3
|
+
import { ids } from '../../src/lexicon/lexicons'
|
|
4
|
+
import assert from 'assert'
|
|
5
|
+
import { isThreadViewPost } from '../../src/lexicon/types/app/bsky/feed/defs'
|
|
6
|
+
|
|
7
|
+
describe('bsky needs-review labels', () => {
|
|
8
|
+
let network: TestNetwork
|
|
9
|
+
let agent: AtpAgent
|
|
10
|
+
let sc: SeedClient
|
|
11
|
+
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
network = await TestNetwork.create({
|
|
14
|
+
dbPostgresSchema: 'bsky_views_needs_review_labels',
|
|
15
|
+
})
|
|
16
|
+
agent = network.bsky.getClient()
|
|
17
|
+
sc = network.getSeedClient()
|
|
18
|
+
await basicSeed(sc)
|
|
19
|
+
|
|
20
|
+
await sc.createAccount('geoff', {
|
|
21
|
+
email: 'geoff@test.com',
|
|
22
|
+
handle: 'geoff.test',
|
|
23
|
+
password: 'geoff',
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
await sc.reply(
|
|
27
|
+
sc.dids.geoff,
|
|
28
|
+
sc.posts[sc.dids.alice][0].ref,
|
|
29
|
+
sc.posts[sc.dids.alice][0].ref,
|
|
30
|
+
'my name geoff',
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
await sc.post(
|
|
34
|
+
sc.dids.geoff,
|
|
35
|
+
'her name alice',
|
|
36
|
+
undefined,
|
|
37
|
+
undefined,
|
|
38
|
+
sc.posts[sc.dids.alice][0].ref,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
await sc.follow(sc.dids.bob, sc.dids.geoff)
|
|
42
|
+
|
|
43
|
+
await network.processAll()
|
|
44
|
+
|
|
45
|
+
AtpAgent.configure({ appLabelers: [network.ozone.ctx.cfg.service.did] })
|
|
46
|
+
await network.bsky.db.db
|
|
47
|
+
.insertInto('label')
|
|
48
|
+
.values({
|
|
49
|
+
src: network.ozone.ctx.cfg.service.did,
|
|
50
|
+
uri: sc.dids.geoff,
|
|
51
|
+
cid: '',
|
|
52
|
+
val: 'needs-review',
|
|
53
|
+
neg: false,
|
|
54
|
+
cts: new Date().toISOString(),
|
|
55
|
+
})
|
|
56
|
+
.execute()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
afterAll(async () => {
|
|
60
|
+
await network.close()
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('applies to thread replies.', async () => {
|
|
64
|
+
const {
|
|
65
|
+
data: { thread },
|
|
66
|
+
} = await agent.app.bsky.feed.getPostThread({
|
|
67
|
+
uri: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
68
|
+
})
|
|
69
|
+
assert(isThreadViewPost(thread))
|
|
70
|
+
expect(
|
|
71
|
+
thread.replies?.some((reply) => {
|
|
72
|
+
return (
|
|
73
|
+
isThreadViewPost(reply) && reply.post.author.did === sc.dids.geoff
|
|
74
|
+
)
|
|
75
|
+
}),
|
|
76
|
+
).toBe(false)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('applies to quote lists.', async () => {
|
|
80
|
+
const {
|
|
81
|
+
data: { posts },
|
|
82
|
+
} = await agent.app.bsky.feed.getQuotes({
|
|
83
|
+
uri: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
84
|
+
})
|
|
85
|
+
expect(
|
|
86
|
+
posts.some((post) => {
|
|
87
|
+
return post.author.did === sc.dids.geoff
|
|
88
|
+
}),
|
|
89
|
+
).toBe(false)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('applies to reply, quote, and mention notifications.', async () => {
|
|
93
|
+
const {
|
|
94
|
+
data: { notifications },
|
|
95
|
+
} = await agent.app.bsky.notification.listNotifications(
|
|
96
|
+
{},
|
|
97
|
+
{
|
|
98
|
+
headers: await network.serviceHeaders(
|
|
99
|
+
sc.dids.alice,
|
|
100
|
+
ids.AppBskyNotificationListNotifications,
|
|
101
|
+
),
|
|
102
|
+
},
|
|
103
|
+
)
|
|
104
|
+
expect(
|
|
105
|
+
notifications.some((notif) => {
|
|
106
|
+
return notif.reason === 'reply' && notif.author.did === sc.dids.geoff
|
|
107
|
+
}),
|
|
108
|
+
).toBe(false)
|
|
109
|
+
expect(
|
|
110
|
+
notifications.some((notif) => {
|
|
111
|
+
return notif.reason === 'quote' && notif.author.did === sc.dids.geoff
|
|
112
|
+
}),
|
|
113
|
+
).toBe(false)
|
|
114
|
+
expect(
|
|
115
|
+
notifications.some((notif) => {
|
|
116
|
+
return notif.reason === 'mention' && notif.author.did === sc.dids.geoff
|
|
117
|
+
}),
|
|
118
|
+
).toBe(false)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('does not apply to self.', async () => {
|
|
122
|
+
const {
|
|
123
|
+
data: { thread },
|
|
124
|
+
} = await agent.app.bsky.feed.getPostThread(
|
|
125
|
+
{
|
|
126
|
+
uri: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
headers: await network.serviceHeaders(
|
|
130
|
+
sc.dids.geoff,
|
|
131
|
+
ids.AppBskyFeedGetPostThread,
|
|
132
|
+
),
|
|
133
|
+
},
|
|
134
|
+
)
|
|
135
|
+
assert(isThreadViewPost(thread))
|
|
136
|
+
expect(
|
|
137
|
+
thread.replies?.some((reply) => {
|
|
138
|
+
return (
|
|
139
|
+
isThreadViewPost(reply) && reply.post.author.did === sc.dids.geoff
|
|
140
|
+
)
|
|
141
|
+
}),
|
|
142
|
+
).toBe(true)
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('does not apply to followers.', async () => {
|
|
146
|
+
const {
|
|
147
|
+
data: { thread },
|
|
148
|
+
} = await agent.app.bsky.feed.getPostThread(
|
|
149
|
+
{
|
|
150
|
+
uri: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
headers: await network.serviceHeaders(
|
|
154
|
+
sc.dids.bob, // follows geoff
|
|
155
|
+
ids.AppBskyFeedGetPostThread,
|
|
156
|
+
),
|
|
157
|
+
},
|
|
158
|
+
)
|
|
159
|
+
assert(isThreadViewPost(thread))
|
|
160
|
+
expect(
|
|
161
|
+
thread.replies?.some((reply) => {
|
|
162
|
+
return (
|
|
163
|
+
isThreadViewPost(reply) && reply.post.author.did === sc.dids.geoff
|
|
164
|
+
)
|
|
165
|
+
}),
|
|
166
|
+
).toBe(true)
|
|
167
|
+
})
|
|
168
|
+
})
|