Skip to content

Commit

Permalink
retrieve feeds from indexing server
Browse files Browse the repository at this point in the history
  • Loading branch information
dholms committed Apr 12, 2022
1 parent c10daa7 commit f469d99
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 14 deletions.
17 changes: 11 additions & 6 deletions cli/src/commands/posts/feed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,28 @@ export default cmd({
category: 'posts',
help: 'List posts in your feed, or the posts of the given user.',
args: [
{ name: 'username/did', optional: true },
{ name: 'username', optional: true },
{ name: 'count', optional: true },
{ name: 'from', optional: true },
],
async command(args) {
const client = await loadDelegate(REPO_PATH)
const nameOrDid = args._[0] || client.did
const username = args._[0] || client.did
const countParsed = parseInt(args._[1])
const count = isNaN(countParsed) ? 100 : countParsed
const fromStr = args._[2]
const from = fromStr ? TID.fromStr(fromStr) : undefined
const posts = await client.listPostsFromUser(nameOrDid, count, from)
const feed = await client.retrieveFeed(username, count, from)
if (!feed) {
console.log('Could not find user: ', username)
return
}
console.log(``)
for (const post of posts) {
console.log(post.text)
for (const post of feed) {
console.log(`"${post.text}" - ${post.author_name}`)
console.log(`Likes: ${post.likes}`)
console.log(chalk.gray(formatDate(post.time)))
console.log(`id: ${chalk.gray(post.tid.formatted())}`)
console.log(chalk.gray(`id: ${post.tid.formatted()}`))
console.log(``)
}
},
Expand Down
22 changes: 22 additions & 0 deletions common/src/microblog/delegator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,28 @@ export class MicroblogDelegator {
}
}

async retrieveFeed(
username: string,
count: number,
from?: TID,
): Promise<Timeline | null> {
const { hostUrl } = this.normalizeUsername(username)
const did = await this.resolveDid(username)
const params = { user: did, count, from: from?.toString() }
try {
const res = await axios.get(`${hostUrl}/indexer/feed`, {
params,
})
return check.assure(schema.timeline, res.data)
} catch (e) {
const err = assureAxiosError(e)
if (err.response?.status === 404) {
return null
}
throw new Error(err.message)
}
}

async retrieveTimeline(count: number, from?: TID): Promise<Timeline> {
const params = { user: this.did, count, from: from?.toString() }
try {
Expand Down
24 changes: 23 additions & 1 deletion common/src/microblog/reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import axios, { AxiosResponse } from 'axios'
import TID from '../repo/tid.js'

import { z } from 'zod'
import { Post, Like, schema, AccountInfo } from './types.js'
import { Post, Like, schema, AccountInfo, Timeline } from './types.js'
import { schema as repoSchema } from '../repo/types.js'
import * as check from '../common/check.js'
import { assureAxiosError } from '../network/util.js'
Expand Down Expand Up @@ -59,6 +59,28 @@ export class MicroblogReader {
}
}

async retrieveFeed(
username: string,
count: number,
from?: TID,
): Promise<Timeline | null> {
const { hostUrl } = this.normalizeUsername(username)
const did = await this.resolveDid(username)
const params = { user: did, count, from: from?.toString() }
try {
const res = await axios.get(`${hostUrl}/indexer/feed`, {
params,
})
return check.assure(schema.timeline, res.data)
} catch (e) {
const err = assureAxiosError(e)
if (err.response?.status === 404) {
return null
}
throw new Error(err.message)
}
}

async getPostFromUser(username: string, tid: TID): Promise<Post | null> {
const { hostUrl } = this.normalizeUsername(username)
const did = await this.resolveDid(username)
Expand Down
38 changes: 31 additions & 7 deletions server/src/db/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
Like,
Post,
Timeline,
AccountInfo,
TimelinePost,
} from '@bluesky/common'
import { Like, Post, Timeline, AccountInfo } from '@bluesky/common'
import { Follow } from '@bluesky/common/dist/repo/types'
import knex from 'knex'
import { CID } from 'multiformats'
Expand Down Expand Up @@ -254,6 +248,36 @@ export class Database {
// INDEXER
// -----------

async retrieveFeed(
user: string,
count: number,
from?: string,
): Promise<Timeline> {
// fallback to a fake TID that is larger than any possible
const username = await this.getUsername(user)
if (!username) {
throw new ServerError(404, `Could not find user ${user}`)
}
const olderThan = from || 'zzzzzzzzzzzzz'
const feed = await this.db('posts')
.where('posts.author', user)
.where('posts.tid', '<', olderThan)
.select('*')
.orderBy('posts.tid', 'desc')
.limit(count)

return Promise.all(
feed.map(async (p) => ({
tid: p.tid,
author: p.author,
author_name: username,
text: p.text,
time: p.time,
likes: await this.likeCount(p.author, p.namespace, p.tid),
})),
)
}

async retrieveTimeline(
user: string,
count: number,
Expand Down
22 changes: 22 additions & 0 deletions server/src/routes/indexer/feed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import express from 'express'
import { z } from 'zod'
import { schema } from '@bluesky/common'
import * as util from '../../util.js'

const router = express.Router()

export const getFeedReq = z.object({
user: z.string(),
count: schema.common.strToInt,
from: schema.repo.strToTid.optional(),
})
export type GetFeedReq = z.infer<typeof getFeedReq>

router.get('/', async (req, res) => {
const { user, count, from } = util.checkReqBody(req.query, getFeedReq)
const db = util.getDB(res)
const feed = await db.retrieveFeed(user, count, from?.toString())
res.status(200).send(feed)
})

export default router
2 changes: 2 additions & 0 deletions server/src/routes/indexer/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import express from 'express'
import Timeline from './timeline.js'
import Feed from './feed.js'
import Count from './count.js'
import Followers from './followers.js'
import AccountInfo from './account-info.js'

const router = express.Router()

router.use('/timeline', Timeline)
router.use('/feed', Feed)
router.use('/count', Count)
router.use('/followers', Followers)
router.use('/account-info', AccountInfo)
Expand Down

0 comments on commit f469d99

Please sign in to comment.