diff --git a/src/lib/api/feed/author.ts b/src/lib/api/feed/author.ts index 57db061b33..56eff18816 100644 --- a/src/lib/api/feed/author.ts +++ b/src/lib/api/feed/author.ts @@ -1,15 +1,28 @@ import { AppBskyFeedDefs, AppBskyFeedGetAuthorFeed as GetAuthorFeed, + BskyAgent, } from '@atproto/api' + import {FeedAPI, FeedAPIResponse} from './types' -import {getAgent} from '#/state/session' export class AuthorFeedAPI implements FeedAPI { - constructor(public params: GetAuthorFeed.QueryParams) {} + agent: BskyAgent + params: GetAuthorFeed.QueryParams + + constructor({ + agent, + feedParams, + }: { + agent: BskyAgent + feedParams: GetAuthorFeed.QueryParams + }) { + this.agent = agent + this.params = feedParams + } async peekLatest(): Promise { - const res = await getAgent().getAuthorFeed({ + const res = await this.agent.getAuthorFeed({ ...this.params, limit: 1, }) @@ -23,7 +36,7 @@ export class AuthorFeedAPI implements FeedAPI { cursor: string | undefined limit: number }): Promise { - const res = await getAgent().getAuthorFeed({ + const res = await this.agent.getAuthorFeed({ ...this.params, cursor, limit, diff --git a/src/lib/api/feed/custom.ts b/src/lib/api/feed/custom.ts index bd30d58acb..64da5ee0a4 100644 --- a/src/lib/api/feed/custom.ts +++ b/src/lib/api/feed/custom.ts @@ -2,18 +2,30 @@ import { AppBskyFeedDefs, AppBskyFeedGetFeed as GetCustomFeed, AtpAgent, + BskyAgent, } from '@atproto/api' import {getContentLanguages} from '#/state/preferences/languages' -import {getAgent} from '#/state/session' import {FeedAPI, FeedAPIResponse} from './types' export class CustomFeedAPI implements FeedAPI { - constructor(public params: GetCustomFeed.QueryParams) {} + agent: BskyAgent + params: GetCustomFeed.QueryParams + + constructor({ + agent, + feedParams, + }: { + agent: BskyAgent + feedParams: GetCustomFeed.QueryParams + }) { + this.agent = agent + this.params = feedParams + } async peekLatest(): Promise { const contentLangs = getContentLanguages().join(',') - const res = await getAgent().app.bsky.feed.getFeed( + const res = await this.agent.app.bsky.feed.getFeed( { ...this.params, limit: 1, @@ -31,15 +43,19 @@ export class CustomFeedAPI implements FeedAPI { limit: number }): Promise { const contentLangs = getContentLanguages().join(',') - const agent = getAgent() - const res = agent.session - ? await getAgent().app.bsky.feed.getFeed( + + const res = this.agent.session + ? await this.agent.app.bsky.feed.getFeed( { ...this.params, cursor, limit, }, - {headers: {'Accept-Language': contentLangs}}, + { + headers: { + 'Accept-Language': contentLangs, + }, + }, ) : await loggedOutFetch({...this.params, cursor, limit}) if (res.success) { diff --git a/src/lib/api/feed/following.ts b/src/lib/api/feed/following.ts index 24389b5edc..1004ccfb87 100644 --- a/src/lib/api/feed/following.ts +++ b/src/lib/api/feed/following.ts @@ -1,12 +1,16 @@ -import {AppBskyFeedDefs} from '@atproto/api' +import {AppBskyFeedDefs, BskyAgent} from '@atproto/api' + import {FeedAPI, FeedAPIResponse} from './types' -import {getAgent} from '#/state/session' export class FollowingFeedAPI implements FeedAPI { - constructor() {} + agent: BskyAgent + + constructor({agent}: {agent: BskyAgent}) { + this.agent = agent + } async peekLatest(): Promise { - const res = await getAgent().getTimeline({ + const res = await this.agent.getTimeline({ limit: 1, }) return res.data.feed[0] @@ -19,7 +23,7 @@ export class FollowingFeedAPI implements FeedAPI { cursor: string | undefined limit: number }): Promise { - const res = await getAgent().getTimeline({ + const res = await this.agent.getTimeline({ cursor, limit, }) diff --git a/src/lib/api/feed/home.ts b/src/lib/api/feed/home.ts index 436a66d076..6f41dc3a16 100644 --- a/src/lib/api/feed/home.ts +++ b/src/lib/api/feed/home.ts @@ -1,8 +1,9 @@ -import {AppBskyFeedDefs} from '@atproto/api' -import {FeedAPI, FeedAPIResponse} from './types' -import {FollowingFeedAPI} from './following' -import {CustomFeedAPI} from './custom' +import {AppBskyFeedDefs, BskyAgent} from '@atproto/api' + import {PROD_DEFAULT_FEED} from '#/lib/constants' +import {CustomFeedAPI} from './custom' +import {FollowingFeedAPI} from './following' +import {FeedAPI, FeedAPIResponse} from './types' // HACK // the feed API does not include any facilities for passing down @@ -26,19 +27,27 @@ export const FALLBACK_MARKER_POST: AppBskyFeedDefs.FeedViewPost = { } export class HomeFeedAPI implements FeedAPI { + agent: BskyAgent following: FollowingFeedAPI discover: CustomFeedAPI usingDiscover = false itemCursor = 0 - constructor() { - this.following = new FollowingFeedAPI() - this.discover = new CustomFeedAPI({feed: PROD_DEFAULT_FEED('whats-hot')}) + constructor({agent}: {agent: BskyAgent}) { + this.agent = agent + this.following = new FollowingFeedAPI({agent}) + this.discover = new CustomFeedAPI({ + agent, + feedParams: {feed: PROD_DEFAULT_FEED('whats-hot')}, + }) } reset() { - this.following = new FollowingFeedAPI() - this.discover = new CustomFeedAPI({feed: PROD_DEFAULT_FEED('whats-hot')}) + this.following = new FollowingFeedAPI({agent: this.agent}) + this.discover = new CustomFeedAPI({ + agent: this.agent, + feedParams: {feed: PROD_DEFAULT_FEED('whats-hot')}, + }) this.usingDiscover = false this.itemCursor = 0 } diff --git a/src/lib/api/feed/likes.ts b/src/lib/api/feed/likes.ts index 2b0afdf11e..a4e84d8f1f 100644 --- a/src/lib/api/feed/likes.ts +++ b/src/lib/api/feed/likes.ts @@ -1,15 +1,28 @@ import { AppBskyFeedDefs, AppBskyFeedGetActorLikes as GetActorLikes, + BskyAgent, } from '@atproto/api' + import {FeedAPI, FeedAPIResponse} from './types' -import {getAgent} from '#/state/session' export class LikesFeedAPI implements FeedAPI { - constructor(public params: GetActorLikes.QueryParams) {} + agent: BskyAgent + params: GetActorLikes.QueryParams + + constructor({ + agent, + feedParams, + }: { + agent: BskyAgent + feedParams: GetActorLikes.QueryParams + }) { + this.agent = agent + this.params = feedParams + } async peekLatest(): Promise { - const res = await getAgent().getActorLikes({ + const res = await this.agent.getActorLikes({ ...this.params, limit: 1, }) @@ -23,7 +36,7 @@ export class LikesFeedAPI implements FeedAPI { cursor: string | undefined limit: number }): Promise { - const res = await getAgent().getActorLikes({ + const res = await this.agent.getActorLikes({ ...this.params, cursor, limit, diff --git a/src/lib/api/feed/list.ts b/src/lib/api/feed/list.ts index 19f2ff177c..9744e3d4ce 100644 --- a/src/lib/api/feed/list.ts +++ b/src/lib/api/feed/list.ts @@ -1,15 +1,28 @@ import { AppBskyFeedDefs, AppBskyFeedGetListFeed as GetListFeed, + BskyAgent, } from '@atproto/api' + import {FeedAPI, FeedAPIResponse} from './types' -import {getAgent} from '#/state/session' export class ListFeedAPI implements FeedAPI { - constructor(public params: GetListFeed.QueryParams) {} + agent: BskyAgent + params: GetListFeed.QueryParams + + constructor({ + agent, + feedParams, + }: { + agent: BskyAgent + feedParams: GetListFeed.QueryParams + }) { + this.agent = agent + this.params = feedParams + } async peekLatest(): Promise { - const res = await getAgent().app.bsky.feed.getListFeed({ + const res = await this.agent.app.bsky.feed.getListFeed({ ...this.params, limit: 1, }) @@ -23,7 +36,7 @@ export class ListFeedAPI implements FeedAPI { cursor: string | undefined limit: number }): Promise { - const res = await getAgent().app.bsky.feed.getListFeed({ + const res = await this.agent.app.bsky.feed.getListFeed({ ...this.params, cursor, limit, diff --git a/src/lib/api/feed/merge.ts b/src/lib/api/feed/merge.ts index 28bf143cbb..8f5980d194 100644 --- a/src/lib/api/feed/merge.ts +++ b/src/lib/api/feed/merge.ts @@ -1,31 +1,51 @@ -import {AppBskyFeedDefs, AppBskyFeedGetTimeline} from '@atproto/api' +import {AppBskyFeedDefs, AppBskyFeedGetTimeline, BskyAgent} from '@atproto/api' import shuffle from 'lodash.shuffle' -import {timeout} from 'lib/async/timeout' + +import {getContentLanguages} from '#/state/preferences/languages' +import {FeedParams} from '#/state/queries/post-feed' import {bundleAsync} from 'lib/async/bundle' +import {timeout} from 'lib/async/timeout' import {feedUriToHref} from 'lib/strings/url-helpers' import {FeedTuner} from '../feed-manip' -import {FeedAPI, FeedAPIResponse, ReasonFeedSource} from './types' -import {FeedParams} from '#/state/queries/post-feed' import {FeedTunerFn} from '../feed-manip' -import {getAgent} from '#/state/session' -import {getContentLanguages} from '#/state/preferences/languages' +import {FeedAPI, FeedAPIResponse, ReasonFeedSource} from './types' const REQUEST_WAIT_MS = 500 // 500ms const POST_AGE_CUTOFF = 60e3 * 60 * 24 // 24hours export class MergeFeedAPI implements FeedAPI { + agent: BskyAgent + params: FeedParams + feedTuners: FeedTunerFn[] following: MergeFeedSource_Following customFeeds: MergeFeedSource_Custom[] = [] feedCursor = 0 itemCursor = 0 sampleCursor = 0 - constructor(public params: FeedParams, public feedTuners: FeedTunerFn[]) { - this.following = new MergeFeedSource_Following(this.feedTuners) + constructor({ + agent, + feedParams, + feedTuners, + }: { + agent: BskyAgent + feedParams: FeedParams + feedTuners: FeedTunerFn[] + }) { + this.agent = agent + this.params = feedParams + this.feedTuners = feedTuners + this.following = new MergeFeedSource_Following({ + agent: this.agent, + feedTuners: this.feedTuners, + }) } reset() { - this.following = new MergeFeedSource_Following(this.feedTuners) + this.following = new MergeFeedSource_Following({ + agent: this.agent, + feedTuners: this.feedTuners, + }) this.customFeeds = [] this.feedCursor = 0 this.itemCursor = 0 @@ -33,7 +53,12 @@ export class MergeFeedAPI implements FeedAPI { if (this.params.mergeFeedSources) { this.customFeeds = shuffle( this.params.mergeFeedSources.map( - feedUri => new MergeFeedSource_Custom(feedUri, this.feedTuners), + feedUri => + new MergeFeedSource_Custom({ + agent: this.agent, + feedUri, + feedTuners: this.feedTuners, + }), ), ) } else { @@ -42,7 +67,7 @@ export class MergeFeedAPI implements FeedAPI { } async peekLatest(): Promise { - const res = await getAgent().getTimeline({ + const res = await this.agent.getTimeline({ limit: 1, }) return res.data.feed[0] @@ -136,12 +161,23 @@ export class MergeFeedAPI implements FeedAPI { } class MergeFeedSource { + agent: BskyAgent + feedTuners: FeedTunerFn[] sourceInfo: ReasonFeedSource | undefined cursor: string | undefined = undefined queue: AppBskyFeedDefs.FeedViewPost[] = [] hasMore = true - constructor(public feedTuners: FeedTunerFn[]) {} + constructor({ + agent, + feedTuners, + }: { + agent: BskyAgent + feedTuners: FeedTunerFn[] + }) { + this.agent = agent + this.feedTuners = feedTuners + } get numReady() { return this.queue.length @@ -203,7 +239,7 @@ class MergeFeedSource_Following extends MergeFeedSource { cursor: string | undefined, limit: number, ): Promise { - const res = await getAgent().getTimeline({cursor, limit}) + const res = await this.agent.getTimeline({cursor, limit}) // run the tuner pre-emptively to ensure better mixing const slices = this.tuner.tune(res.data.feed, { dryRun: false, @@ -215,10 +251,25 @@ class MergeFeedSource_Following extends MergeFeedSource { } class MergeFeedSource_Custom extends MergeFeedSource { + agent: BskyAgent minDate: Date + feedUri: string - constructor(public feedUri: string, public feedTuners: FeedTunerFn[]) { - super(feedTuners) + constructor({ + agent, + feedUri, + feedTuners, + }: { + agent: BskyAgent + feedUri: string + feedTuners: FeedTunerFn[] + }) { + super({ + agent, + feedTuners, + }) + this.agent = agent + this.feedUri = feedUri this.sourceInfo = { $type: 'reasonFeedSource', uri: feedUri, @@ -233,13 +284,17 @@ class MergeFeedSource_Custom extends MergeFeedSource { ): Promise { try { const contentLangs = getContentLanguages().join(',') - const res = await getAgent().app.bsky.feed.getFeed( + const res = await this.agent.app.bsky.feed.getFeed( { cursor, limit, feed: this.feedUri, }, - {headers: {'Accept-Language': contentLangs}}, + { + headers: { + 'Accept-Language': contentLangs, + }, + }, ) // NOTE // some custom feeds fail to enforce the pagination limit diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts index ecb21f4353..ca35f1ae30 100644 --- a/src/state/queries/post-feed.ts +++ b/src/state/queries/post-feed.ts @@ -379,7 +379,7 @@ function createApi({ feedParams, feedTuners, }: { - agent?: BskyAgent + agent: BskyAgent feedDesc: FeedDescriptor feedParams: FeedParams feedTuners: FeedTunerFn[] @@ -398,10 +398,10 @@ function createApi({ return new FollowingFeedAPI({agent}) } else if (feedDesc.startsWith('author')) { const [_, actor, filter] = feedDesc.split('|') - return new AuthorFeedAPI({agent, actor, filter}) + return new AuthorFeedAPI({agent, feedParams: {actor, filter}}) } else if (feedDesc.startsWith('likes')) { const [_, actor] = feedDesc.split('|') - return new LikesFeedAPI({agent, actor}) + return new LikesFeedAPI({agent, feedParams: {actor}}) } else if (feedDesc.startsWith('feedgen')) { const [_, feed] = feedDesc.split('|') return new CustomFeedAPI({ @@ -410,7 +410,7 @@ function createApi({ }) } else if (feedDesc.startsWith('list')) { const [_, list] = feedDesc.split('|') - return new ListFeedAPI({agent, list}) + return new ListFeedAPI({agent, feedParams: {list}}) } else { // shouldnt happen return new FollowingFeedAPI({agent})