mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import {
2 AppBskyFeedDefs,
3 AppBskyFeedGetAuthorFeed as GetAuthorFeed,
4} from '@atproto/api'
5import {FeedAPI, FeedAPIResponse} from './types'
6import {getAgent} from '#/state/session'
7
8export class AuthorFeedAPI implements FeedAPI {
9 constructor(public params: GetAuthorFeed.QueryParams) {}
10
11 async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
12 const res = await getAgent().getAuthorFeed({
13 ...this.params,
14 limit: 1,
15 })
16 return res.data.feed[0]
17 }
18
19 async fetch({
20 cursor,
21 limit,
22 }: {
23 cursor: string | undefined
24 limit: number
25 }): Promise<FeedAPIResponse> {
26 const res = await getAgent().getAuthorFeed({
27 ...this.params,
28 cursor,
29 limit,
30 })
31 if (res.success) {
32 return {
33 cursor: res.data.cursor,
34 feed: this._filter(res.data.feed),
35 }
36 }
37 return {
38 feed: [],
39 }
40 }
41
42 _filter(feed: AppBskyFeedDefs.FeedViewPost[]) {
43 if (this.params.filter === 'posts_and_author_threads') {
44 return feed.filter(post => {
45 const isReply = post.reply
46 const isRepost = AppBskyFeedDefs.isReasonRepost(post.reason)
47 if (!isReply) return true
48 if (isRepost) return true
49 return isReply && isAuthorReplyChain(this.params.actor, post, feed)
50 })
51 }
52
53 return feed
54 }
55}
56
57function isAuthorReplyChain(
58 actor: string,
59 post: AppBskyFeedDefs.FeedViewPost,
60 posts: AppBskyFeedDefs.FeedViewPost[],
61): boolean {
62 // current post is by a different user (shouldn't happen)
63 if (post.post.author.did !== actor) return false
64
65 const replyParent = post.reply?.parent
66
67 if (AppBskyFeedDefs.isPostView(replyParent)) {
68 // reply parent is by a different user
69 if (replyParent.author.did !== actor) return false
70
71 // A top-level post that matches the parent of the current post.
72 const parentPost = posts.find(p => p.post.uri === replyParent.uri)
73
74 /*
75 * Either we haven't fetched the parent at the top level, or the only
76 * record we have is on feedItem.reply.parent, which we've already checked
77 * above.
78 */
79 if (!parentPost) return true
80
81 // Walk up to parent
82 return isAuthorReplyChain(actor, parentPost, posts)
83 }
84
85 // Just default to showing it
86 return true
87}