Drill agent into feed apis
This commit is contained in:
@@ -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<AppBskyFeedDefs.FeedViewPost> {
|
||||
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<FeedAPIResponse> {
|
||||
const res = await getAgent().getAuthorFeed({
|
||||
const res = await this.agent.getAuthorFeed({
|
||||
...this.params,
|
||||
cursor,
|
||||
limit,
|
||||
|
||||
@@ -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<AppBskyFeedDefs.FeedViewPost> {
|
||||
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<FeedAPIResponse> {
|
||||
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) {
|
||||
|
||||
@@ -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<AppBskyFeedDefs.FeedViewPost> {
|
||||
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<FeedAPIResponse> {
|
||||
const res = await getAgent().getTimeline({
|
||||
const res = await this.agent.getTimeline({
|
||||
cursor,
|
||||
limit,
|
||||
})
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<AppBskyFeedDefs.FeedViewPost> {
|
||||
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<FeedAPIResponse> {
|
||||
const res = await getAgent().getActorLikes({
|
||||
const res = await this.agent.getActorLikes({
|
||||
...this.params,
|
||||
cursor,
|
||||
limit,
|
||||
|
||||
@@ -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<AppBskyFeedDefs.FeedViewPost> {
|
||||
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<FeedAPIResponse> {
|
||||
const res = await getAgent().app.bsky.feed.getListFeed({
|
||||
const res = await this.agent.app.bsky.feed.getListFeed({
|
||||
...this.params,
|
||||
cursor,
|
||||
limit,
|
||||
|
||||
+72
-17
@@ -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<AppBskyFeedDefs.FeedViewPost> {
|
||||
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<AppBskyFeedGetTimeline.Response> {
|
||||
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<AppBskyFeedGetTimeline.Response> {
|
||||
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
|
||||
|
||||
@@ -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})
|
||||
|
||||
Reference in New Issue
Block a user