mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at ruby-v 107 lines 2.6 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 = params.filter !== 'posts_with_media' 27 return params 28 } 29 30 async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> { 31 const res = await this.agent.getAuthorFeed({ 32 ...this.params, 33 limit: 1, 34 }) 35 return res.data.feed[0] 36 } 37 38 async fetch({ 39 cursor, 40 limit, 41 }: { 42 cursor: string | undefined 43 limit: number 44 }): Promise<FeedAPIResponse> { 45 const res = await this.agent.getAuthorFeed({ 46 ...this.params, 47 cursor, 48 limit, 49 }) 50 if (res.success) { 51 return { 52 cursor: res.data.cursor, 53 feed: this._filter(res.data.feed), 54 } 55 } 56 return { 57 feed: [], 58 } 59 } 60 61 _filter(feed: AppBskyFeedDefs.FeedViewPost[]) { 62 if (this.params.filter === 'posts_and_author_threads') { 63 return feed.filter(post => { 64 const isReply = post.reply 65 const isRepost = AppBskyFeedDefs.isReasonRepost(post.reason) 66 const isPin = AppBskyFeedDefs.isReasonPin(post.reason) 67 if (!isReply) return true 68 if (isRepost || isPin) return true 69 return isReply && isAuthorReplyChain(this.params.actor, post, feed) 70 }) 71 } 72 73 return feed 74 } 75} 76 77function isAuthorReplyChain( 78 actor: string, 79 post: AppBskyFeedDefs.FeedViewPost, 80 posts: AppBskyFeedDefs.FeedViewPost[], 81): boolean { 82 // current post is by a different user (shouldn't happen) 83 if (post.post.author.did !== actor) return false 84 85 const replyParent = post.reply?.parent 86 87 if (AppBskyFeedDefs.isPostView(replyParent)) { 88 // reply parent is by a different user 89 if (replyParent.author.did !== actor) return false 90 91 // A top-level post that matches the parent of the current post. 92 const parentPost = posts.find(p => p.post.uri === replyParent.uri) 93 94 /* 95 * Either we haven't fetched the parent at the top level, or the only 96 * record we have is on feedItem.reply.parent, which we've already checked 97 * above. 98 */ 99 if (!parentPost) return true 100 101 // Walk up to parent 102 return isAuthorReplyChain(actor, parentPost, posts) 103 } 104 105 // Just default to showing it 106 return true 107}