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