Skip to content

Commit

Permalink
Merge pull request #1982 from bluesky-social/bav-v2-drop-pg
Browse files Browse the repository at this point in the history
Cull appview v2 down to frontend service
  • Loading branch information
devinivy authored Dec 29, 2023
2 parents 22b3c2f + 9b2153f commit 1d8a4f1
Show file tree
Hide file tree
Showing 280 changed files with 1,712 additions and 16,931 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-and-push-bsky-ghcr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ on:
push:
branches:
- main
- bav-v2-drop-pg
env:
REGISTRY: ghcr.io
USERNAME: ${{ github.actor }}
Expand Down
2 changes: 1 addition & 1 deletion packages/bsky/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const buildShallow =

require('esbuild').build({
logLevel: 'info',
entryPoints: ['src/index.ts', 'src/db/index.ts'],
entryPoints: ['src/index.ts'],
bundle: true,
sourcemap: true,
outdir: 'dist',
Expand Down
36 changes: 36 additions & 0 deletions packages/bsky/proto/bsky.proto
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,22 @@ message GetMutesResponse {
string cursor = 2;
}

// mute another user
message MuteActorRequest {
string actor_did = 1;
string subject_did = 2;
}

message MuteActorResponse {}

// unmute another user
message UnmuteActorRequest {
string actor_did = 1;
string subject_did = 2;
}

message UnmuteActorResponse {}

//
// Mutelists
//
Expand Down Expand Up @@ -495,6 +511,22 @@ message GetMutelistSubscriptionsResponse {
string cursor = 2;
}

// mute a list
message MuteActorListRequest {
string actor_did = 1;
string list_uri = 2;
}

message MuteActorListResponse {}

// unmute a list
message UnmuteActorListRequest {
string actor_did = 1;
string list_uri = 2;
}

message UnmuteActorListResponse {}

//
// Blocks
//
Expand Down Expand Up @@ -905,11 +937,15 @@ service Service {
// Mutes
rpc GetActorMutesActor(GetActorMutesActorRequest) returns (GetActorMutesActorResponse);
rpc GetMutes(GetMutesRequest) returns (GetMutesResponse);
rpc MuteActor(MuteActorRequest) returns (MuteActorResponse);
rpc UnmuteActor(UnmuteActorRequest) returns (UnmuteActorResponse);

// Mutelists
rpc GetActorMutesActorViaList(GetActorMutesActorViaListRequest) returns (GetActorMutesActorViaListResponse);
rpc GetMutelistSubscription(GetMutelistSubscriptionRequest) returns (GetMutelistSubscriptionResponse);
rpc GetMutelistSubscriptions(GetMutelistSubscriptionsRequest) returns (GetMutelistSubscriptionsResponse);
rpc MuteActorList(MuteActorListRequest) returns (MuteActorListResponse);
rpc UnmuteActorList(UnmuteActorListRequest) returns (UnmuteActorListResponse);

// Blocks
rpc GetBidirectionalBlock(GetBidirectionalBlockRequest) returns (GetBidirectionalBlockResponse);
Expand Down
4 changes: 1 addition & 3 deletions packages/bsky/src/api/app/bsky/actor/getProfiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ export default function (server: Server, ctx: AppContext) {
server.app.bsky.actor.getProfiles({
auth: ctx.authOptionalVerifier,
handler: async ({ auth, params, res }) => {
const db = ctx.db.getReplica()
const actorService = ctx.services.actor(db)
const viewer = auth.credentials.did

const [result, repoRev] = await Promise.all([
getProfile({ ...params, viewer }, ctx),
actorService.getRepoRev(viewer),
ctx.hydrator.actor.getRepoRevSafe(viewer),
])

setRepoRev(res, repoRev)
Expand Down
4 changes: 1 addition & 3 deletions packages/bsky/src/api/app/bsky/actor/searchActors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { Hydrator } from '../../../../hydration/hydrator'
import { Views } from '../../../../views'
import { DataPlaneClient } from '../../../../data-plane'
import { parseString } from '../../../../hydration/util'
import { cleanQuery } from '../../../../services/util/search'

export default function (server: Server, ctx: AppContext) {
const searchActors = createPipeline(
Expand All @@ -37,8 +36,7 @@ export default function (server: Server, ctx: AppContext) {

const skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {
const { ctx, params } = inputs
const rawQuery = params.q ?? params.term
const term = cleanQuery(rawQuery || '')
const term = params.q ?? params.term

// @TODO
// add hits total
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { Hydrator } from '../../../../hydration/hydrator'
import { Views } from '../../../../views'
import { DataPlaneClient } from '../../../../data-plane'
import { parseString } from '../../../../hydration/util'
import { cleanQuery } from '../../../../services/util/search'

export default function (server: Server, ctx: AppContext) {
const searchActorsTypeahead = createPipeline(
Expand All @@ -37,8 +36,7 @@ export default function (server: Server, ctx: AppContext) {

const skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {
const { ctx, params } = inputs
const rawQuery = params.q ?? params.term
const term = cleanQuery(rawQuery || '')
const term = params.q ?? params.term

// @TODO
// add typeahead option
Expand Down
2 changes: 1 addition & 1 deletion packages/bsky/src/api/app/bsky/feed/getFeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { QueryParams as GetFeedParams } from '../../../../lexicon/types/app/bsky
import { OutputSchema as SkeletonOutput } from '../../../../lexicon/types/app/bsky/feed/getFeedSkeleton'
import { Server } from '../../../../lexicon'
import AppContext from '../../../../context'
import { AlgoResponse, AlgoResponseItem } from '../../../../feed-gen/types'
import { AlgoResponse, AlgoResponseItem } from '../../../feed-gen/types'
import {
HydrationFnInput,
PresentationFnInput,
Expand Down
2 changes: 1 addition & 1 deletion packages/bsky/src/api/app/bsky/feed/getFeedSkeleton.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { InvalidRequestError } from '@atproto/xrpc-server'
import { Server } from '../../../../lexicon'
import AppContext from '../../../../context'
import { toSkeletonItem } from '../../../../feed-gen/types'
import { toSkeletonItem } from '../../../feed-gen/types'

export default function (server: Server, ctx: AppContext) {
server.app.bsky.feed.getFeedSkeleton({
Expand Down
217 changes: 0 additions & 217 deletions packages/bsky/src/api/app/bsky/feed/getPostThread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,223 +82,6 @@ const presentation = (
return { thread }
}

// @TODO tidy
// const composeThread = (
// threadData: PostThread,
// actors: ActorInfoMap,
// state: HydrationState,
// ctx: Context,
// viewer: string | null,
// ) => {
// const { feedService } = ctx
// const { posts, threadgates, embeds, blocks, labels, lists } = state

// const post = feedService.views.formatPostView(
// threadData.post.postUri,
// actors,
// posts,
// threadgates,
// embeds,
// labels,
// lists,
// viewer,
// )

// // replies that are invalid due to reply-gating:
// // a. may appear as the anchor post, but without any parent or replies.
// // b. may not appear anywhere else in the thread.
// const isAnchorPost = state.threadData.post.uri === threadData.post.postUri
// const info = posts[threadData.post.postUri]
// // @TODO re-enable invalidReplyRoot check
// // const badReply = !!info?.invalidReplyRoot || !!info?.violatesThreadGate
// const badReply = !!info?.violatesThreadGate
// const omitBadReply = !isAnchorPost && badReply

// if (!post || blocks[post.uri]?.reply || omitBadReply) {
// return {
// $type: 'app.bsky.feed.defs#notFoundPost',
// uri: threadData.post.postUri,
// notFound: true,
// }
// }

// if (post.author.viewer?.blocking || post.author.viewer?.blockedBy) {
// return {
// $type: 'app.bsky.feed.defs#blockedPost',
// uri: threadData.post.postUri,
// blocked: true,
// author: {
// did: post.author.did,
// viewer: post.author.viewer
// ? {
// blockedBy: post.author.viewer?.blockedBy,
// blocking: post.author.viewer?.blocking,
// }
// : undefined,
// },
// }
// }

// let parent
// if (threadData.parent && !badReply) {
// if (threadData.parent instanceof ParentNotFoundError) {
// parent = {
// $type: 'app.bsky.feed.defs#notFoundPost',
// uri: threadData.parent.uri,
// notFound: true,
// }
// } else {
// parent = composeThread(threadData.parent, actors, state, ctx, viewer)
// }
// }

// let replies: (ThreadViewPost | NotFoundPost | BlockedPost)[] | undefined
// if (threadData.replies && !badReply) {
// replies = threadData.replies.flatMap((reply) => {
// const thread = composeThread(reply, actors, state, ctx, viewer)
// // e.g. don't bother including #postNotFound reply placeholders for takedowns. either way matches api contract.
// const skip = []
// return isNotFoundPost(thread) ? skip : thread
// })
// }

// return {
// $type: 'app.bsky.feed.defs#threadViewPost',
// post,
// parent,
// replies,
// }
// }

// const getRelevantIds = (
// thread: PostThread,
// ): { dids: Set<string>; uris: Set<string> } => {
// const dids = new Set<string>()
// const uris = new Set<string>()
// if (thread.parent && !(thread.parent instanceof ParentNotFoundError)) {
// const fromParent = getRelevantIds(thread.parent)
// fromParent.dids.forEach((did) => dids.add(did))
// fromParent.uris.forEach((uri) => uris.add(uri))
// }
// if (thread.replies) {
// for (const reply of thread.replies) {
// const fromChild = getRelevantIds(reply)
// fromChild.dids.forEach((did) => dids.add(did))
// fromChild.uris.forEach((uri) => uris.add(uri))
// }
// }
// dids.add(thread.post.postAuthorDid)
// uris.add(thread.post.postUri)
// if (thread.post.replyRoot) {
// // ensure root is included for checking interactions
// uris.add(thread.post.replyRoot)
// dids.add(new AtUri(thread.post.replyRoot).hostname)
// }
// return { dids, uris }
// }

// const getThreadData = async (
// params: Params,
// ctx: Context,
// ): Promise<PostThread | null> => {
// const { db, feedService } = ctx
// const { uri, depth, parentHeight } = params

// const [parents, children] = await Promise.all([
// getAncestorsAndSelfQb(db.db, { uri, parentHeight })
// .selectFrom('ancestor')
// .innerJoin(
// feedService.selectPostQb().as('post'),
// 'post.uri',
// 'ancestor.uri',
// )
// .selectAll('post')
// .execute(),
// getDescendentsQb(db.db, { uri, depth })
// .selectFrom('descendent')
// .innerJoin(
// feedService.selectPostQb().as('post'),
// 'post.uri',
// 'descendent.uri',
// )
// .selectAll('post')
// .orderBy('sortAt', 'desc')
// .execute(),
// ])
// // prevent self-referential loops
// const includedPosts = new Set<string>([uri])
// const parentsByUri = parents.reduce((acc, post) => {
// return Object.assign(acc, { [post.uri]: post })
// }, {} as Record<string, FeedRow>)
// const childrenByParentUri = children.reduce((acc, child) => {
// if (!child.replyParent) return acc
// if (includedPosts.has(child.uri)) return acc
// includedPosts.add(child.uri)
// acc[child.replyParent] ??= []
// acc[child.replyParent].push(child)
// return acc
// }, {} as Record<string, FeedRow[]>)
// const post = parentsByUri[uri]
// if (!post) return null
// return {
// post,
// parent: post.replyParent
// ? getParentData(
// parentsByUri,
// includedPosts,
// post.replyParent,
// parentHeight,
// )
// : undefined,
// replies: getChildrenData(childrenByParentUri, uri, depth),
// }
// }

// const getParentData = (
// postsByUri: Record<string, FeedRow>,
// includedPosts: Set<string>,
// uri: string,
// depth: number,
// ): PostThread | ParentNotFoundError | undefined => {
// if (depth < 1) return undefined
// if (includedPosts.has(uri)) return undefined
// includedPosts.add(uri)
// const post = postsByUri[uri]
// if (!post) return new ParentNotFoundError(uri)
// return {
// post,
// parent: post.replyParent
// ? getParentData(postsByUri, includedPosts, post.replyParent, depth - 1)
// : undefined,
// replies: [],
// }
// }

// const getChildrenData = (
// childrenByParentUri: Record<string, FeedRow[]>,
// uri: string,
// depth: number,
// ): PostThread[] | undefined => {
// if (depth === 0) return undefined
// const children = childrenByParentUri[uri] ?? []
// return children.map((row) => ({
// post: row,
// replies: getChildrenData(childrenByParentUri, row.postUri, depth - 1),
// }))
// }

// class ParentNotFoundError extends Error {
// constructor(public uri: string) {
// super(`Parent not found: ${uri}`)
// }
// }

// type PostThread = {
// post: FeedRow
// parent?: PostThread | ParentNotFoundError
// replies?: PostThread[]
// }

type Context = {
dataplane: DataPlaneClient
hydrator: Hydrator
Expand Down
19 changes: 4 additions & 15 deletions packages/bsky/src/api/app/bsky/graph/muteActor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,10 @@ export default function (server: Server, ctx: AppContext) {
auth: ctx.authVerifier,
handler: async ({ auth, input }) => {
const { actor } = input.body
const requester = auth.credentials.did
const db = ctx.db.getPrimary()

const subjectDid = await ctx.services.actor(db).getActorDid(actor)
if (!subjectDid) {
throw new InvalidRequestError(`Actor not found: ${actor}`)
}
if (subjectDid === requester) {
throw new InvalidRequestError('Cannot mute oneself')
}

await ctx.services.graph(db).muteActor({
subjectDid,
mutedByDid: requester,
})
const viewer = auth.credentials.did
const [did] = await ctx.hydrator.actor.getDids([actor])
if (!did) throw new InvalidRequestError('Actor not found')
await ctx.dataplane.muteActor({ actorDid: viewer, subjectDid: did })
},
})
}
Loading

0 comments on commit 1d8a4f1

Please sign in to comment.