Skip to content

Commit

Permalink
Appview: support handles in post threads, remove deleted reply placeh…
Browse files Browse the repository at this point in the history
…olders (#2498)

* appview: strip deleted post placeholders from threads

* appview: support handle in post thread uris

* tidy
  • Loading branch information
devinivy authored May 20, 2024
1 parent 06d2328 commit 010cf3d
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 16 deletions.
16 changes: 13 additions & 3 deletions packages/bsky/src/api/app/bsky/feed/getPostThread.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { InvalidRequestError } from '@atproto/xrpc-server'
import { AtUri } from '@atproto/syntax'
import { Server } from '../../../../lexicon'
import { isNotFoundPost } from '../../../../lexicon/types/app/bsky/feed/defs'
import {
Expand Down Expand Up @@ -59,20 +60,21 @@ export default function (server: Server, ctx: AppContext) {

const skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {
const { ctx, params } = inputs
const anchor = await resolveUri(ctx, params.uri)
try {
const res = await ctx.dataplane.getThread({
postUri: params.uri,
postUri: anchor,
above: params.parentHeight,
below: params.depth,
})
return {
anchor: params.uri,
anchor,
uris: res.uris,
}
} catch (err) {
if (isDataplaneError(err, Code.NotFound)) {
return {
anchor: params.uri,
anchor,
uris: [],
}
} else {
Expand Down Expand Up @@ -118,3 +120,11 @@ type Skeleton = {
anchor: string
uris: string[]
}

const resolveUri = async (ctx: Context, uriStr: string) => {
const uri = new AtUri(uriStr)
const [did] = await ctx.hydrator.actor.getDids([uri.host])
if (!did) return uriStr
uri.host = did
return uri.toString()
}
9 changes: 7 additions & 2 deletions packages/bsky/src/views/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ export class Views {
childrenByParentUri: Record<string, string[]>,
state: HydrationState,
depth: number,
): (ThreadViewPost | NotFoundPost | BlockedPost)[] | undefined {
): (ThreadViewPost | BlockedPost)[] | undefined {
if (depth < 1) return undefined
const childrenUris = childrenByParentUri[parentUri] ?? []
return mapDefined(childrenUris, (uri) => {
Expand All @@ -666,7 +666,12 @@ export class Views {
return undefined
}
const post = this.post(uri, state)
if (!postInfo || !post) return this.notFoundPost(uri)
if (!postInfo || !post) {
// in the future we might consider keeping a placeholder for deleted
// posts that have replies under them, but not supported at the moment.
// this case is mostly likely hit when a takedown was applied to a post.
return undefined
}
if (rootUri !== getRootUri(uri, postInfo)) return // outside thread boundary
if (this.viewerBlockExists(post.author.did, state)) {
return this.blockedPost(uri, post.author.did, state)
Expand Down
188 changes: 177 additions & 11 deletions packages/bsky/tests/views/__snapshots__/thread.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,177 @@ Object {
}
`;

exports[`pds thread views fetches thread with handle in uri 1`] = `
Object {
"$type": "app.bsky.feed.defs#threadViewPost",
"post": Object {
"author": Object {
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)@jpeg",
"did": "user(0)",
"displayName": "ali",
"handle": "alice.test",
"labels": Array [
Object {
"cid": "cids(2)",
"cts": "1970-01-01T00:00:00.000Z",
"src": "user(0)",
"uri": "record(3)",
"val": "self-label-a",
},
Object {
"cid": "cids(2)",
"cts": "1970-01-01T00:00:00.000Z",
"src": "user(0)",
"uri": "record(3)",
"val": "self-label-b",
},
],
"viewer": Object {
"blockedBy": false,
"followedBy": "record(2)",
"following": "record(1)",
"muted": false,
},
},
"cid": "cids(0)",
"indexedAt": "1970-01-01T00:00:00.000Z",
"labels": Array [],
"likeCount": 3,
"record": Object {
"$type": "app.bsky.feed.post",
"createdAt": "1970-01-01T00:00:00.000000Z",
"text": "again",
},
"replyCount": 2,
"repostCount": 1,
"uri": "record(0)",
"viewer": Object {
"like": "record(4)",
},
},
"replies": Array [
Object {
"$type": "app.bsky.feed.defs#threadViewPost",
"post": Object {
"author": Object {
"did": "user(2)",
"handle": "carol.test",
"labels": Array [],
"viewer": Object {
"blockedBy": false,
"following": "record(6)",
"muted": false,
},
},
"cid": "cids(3)",
"indexedAt": "1970-01-01T00:00:00.000Z",
"labels": Array [],
"likeCount": 0,
"record": Object {
"$type": "app.bsky.feed.post",
"createdAt": "1970-01-01T00:00:00.000Z",
"reply": Object {
"parent": Object {
"cid": "cids(0)",
"uri": "record(0)",
},
"root": Object {
"cid": "cids(0)",
"uri": "record(0)",
},
},
"text": "of course",
},
"replyCount": 0,
"repostCount": 0,
"uri": "record(5)",
"viewer": Object {},
},
},
Object {
"$type": "app.bsky.feed.defs#threadViewPost",
"post": Object {
"author": Object {
"avatar": "https://bsky.public.url/img/avatar/plain/user(4)/cids(1)@jpeg",
"did": "user(3)",
"displayName": "bobby",
"handle": "bob.test",
"labels": Array [],
"viewer": Object {
"blockedBy": false,
"muted": false,
},
},
"cid": "cids(4)",
"embed": Object {
"$type": "app.bsky.embed.images#view",
"images": Array [
Object {
"alt": "../dev-env/src/seed/img/key-landscape-small.jpg",
"fullsize": "https://bsky.public.url/img/feed_fullsize/plain/user(4)/cids(5)@jpeg",
"thumb": "https://bsky.public.url/img/feed_thumbnail/plain/user(4)/cids(5)@jpeg",
},
],
},
"indexedAt": "1970-01-01T00:00:00.000Z",
"labels": Array [
Object {
"cid": "cids(4)",
"cts": "1970-01-01T00:00:00.000Z",
"src": "did:example:labeler",
"uri": "record(7)",
"val": "test-label",
},
Object {
"cid": "cids(4)",
"cts": "1970-01-01T00:00:00.000Z",
"src": "did:example:labeler",
"uri": "record(7)",
"val": "test-label-2",
},
],
"likeCount": 0,
"record": Object {
"$type": "app.bsky.feed.post",
"createdAt": "1970-01-01T00:00:00.000Z",
"embed": Object {
"$type": "app.bsky.embed.images",
"images": Array [
Object {
"alt": "../dev-env/src/seed/img/key-landscape-small.jpg",
"image": Object {
"$type": "blob",
"mimeType": "image/jpeg",
"ref": Object {
"$link": "cids(5)",
},
"size": 4114,
},
},
],
},
"reply": Object {
"parent": Object {
"cid": "cids(0)",
"uri": "record(0)",
},
"root": Object {
"cid": "cids(0)",
"uri": "record(0)",
},
},
"text": "hear that label_me label_me_2",
},
"replyCount": 1,
"repostCount": 0,
"uri": "record(7)",
"viewer": Object {},
},
},
],
}
`;

exports[`pds thread views handles deleted posts correctly 1`] = `
Object {
"$type": "app.bsky.feed.defs#threadViewPost",
Expand Down Expand Up @@ -1041,11 +1212,6 @@ Object {
},
},
"replies": Array [
Object {
"$type": "app.bsky.feed.defs#notFoundPost",
"notFound": true,
"uri": "record(5)",
},
Object {
"$type": "app.bsky.feed.defs#threadViewPost",
"post": Object {
Expand Down Expand Up @@ -1077,14 +1243,14 @@ Object {
"cid": "cids(3)",
"cts": "1970-01-01T00:00:00.000Z",
"src": "did:example:labeler",
"uri": "record(6)",
"uri": "record(5)",
"val": "test-label",
},
Object {
"cid": "cids(3)",
"cts": "1970-01-01T00:00:00.000Z",
"src": "did:example:labeler",
"uri": "record(6)",
"uri": "record(5)",
"val": "test-label-2",
},
],
Expand Down Expand Up @@ -1122,7 +1288,7 @@ Object {
},
"replyCount": 1,
"repostCount": 0,
"uri": "record(6)",
"uri": "record(5)",
"viewer": Object {},
},
"replies": Array [
Expand Down Expand Up @@ -1167,7 +1333,7 @@ Object {
"reply": Object {
"parent": Object {
"cid": "cids(3)",
"uri": "record(6)",
"uri": "record(5)",
},
"root": Object {
"cid": "cids(0)",
Expand All @@ -1178,9 +1344,9 @@ Object {
},
"replyCount": 0,
"repostCount": 2,
"uri": "record(7)",
"uri": "record(6)",
"viewer": Object {
"repost": "record(8)",
"repost": "record(7)",
},
},
"replies": Array [],
Expand Down
15 changes: 15 additions & 0 deletions packages/bsky/tests/views/thread.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ describe('pds thread views', () => {
expect(forSnapshot(thread.data.thread)).toMatchSnapshot()
})

it('fetches thread with handle in uri', async () => {
const thread = await agent.api.app.bsky.feed.getPostThread(
{
depth: 1,
uri: sc.posts[alice][1].ref.uriStr.replace(
`at://${alice}`,
`at://${sc.accounts[alice].handle}`,
),
},
{ headers: await network.serviceHeaders(bob) },
)

expect(forSnapshot(thread.data.thread)).toMatchSnapshot()
})

it('fetches ancestors', async () => {
const thread = await agent.api.app.bsky.feed.getPostThread(
{ depth: 1, uri: sc.replies[alice][0].ref.uriStr },
Expand Down

0 comments on commit 010cf3d

Please sign in to comment.