11import { AtpAgent } from '@atproto/api'
22import { mapDefined } from '@atproto/common'
3+ import { ServerConfig } from '../../../../config'
34import { AppContext } from '../../../../context'
45import { DataPlaneClient } from '../../../../data-plane'
6+ import {
7+ PostSearchQuery ,
8+ parsePostSearchQuery ,
9+ } from '../../../../data-plane/server/util'
510import { HydrateCtx , Hydrator } from '../../../../hydration/hydrator'
611import { parseString } from '../../../../hydration/util'
712import { Server } from '../../../../lexicon'
@@ -21,16 +26,20 @@ export default function (server: Server, ctx: AppContext) {
2126 const searchPosts = createPipeline (
2227 skeleton ,
2328 hydration ,
24- noBlocks ,
29+ noBlocksOrTagged ,
2530 presentation ,
2631 )
2732 server . app . bsky . feed . searchPosts ( {
2833 auth : ctx . authVerifier . standardOptional ,
2934 handler : async ( { auth, params, req } ) => {
30- const viewer = auth . credentials . iss
35+ const { viewer, isModService } = ctx . authVerifier . parseCreds ( auth )
36+
3137 const labelers = ctx . reqLabelers ( req )
3238 const hydrateCtx = await ctx . hydrator . createContext ( { labelers, viewer } )
33- const results = await searchPosts ( { ...params , hydrateCtx } , ctx )
39+ const results = await searchPosts (
40+ { ...params , hydrateCtx, isModService } ,
41+ ctx ,
42+ )
3443 return {
3544 encoding : 'application/json' ,
3645 body : results ,
@@ -42,6 +51,9 @@ export default function (server: Server, ctx: AppContext) {
4251
4352const skeleton = async ( inputs : SkeletonFnInput < Context , Params > ) => {
4453 const { ctx, params } = inputs
54+ const parsedQuery = parsePostSearchQuery ( params . q , {
55+ author : params . author ,
56+ } )
4557
4658 if ( ctx . searchAgent ) {
4759 // @NOTE cursors won't change on appview swap
@@ -64,6 +76,7 @@ const skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {
6476 return {
6577 posts : res . posts . map ( ( { uri } ) => uri ) ,
6678 cursor : parseString ( res . cursor ) ,
79+ parsedQuery,
6780 }
6881 }
6982
@@ -75,6 +88,7 @@ const skeleton = async (inputs: SkeletonFnInput<Context, Params>) => {
7588 return {
7689 posts : res . uris ,
7790 cursor : parseString ( res . cursor ) ,
91+ parsedQuery,
7892 }
7993}
8094
@@ -88,11 +102,30 @@ const hydration = async (
88102 )
89103}
90104
91- const noBlocks = ( inputs : RulesFnInput < Context , Params , Skeleton > ) => {
92- const { ctx, skeleton, hydration } = inputs
105+ const noBlocksOrTagged = ( inputs : RulesFnInput < Context , Params , Skeleton > ) => {
106+ const { ctx, params, skeleton, hydration } = inputs
107+ const { parsedQuery } = skeleton
108+
93109 skeleton . posts = skeleton . posts . filter ( ( uri ) => {
110+ const post = hydration . posts ?. get ( uri )
111+ if ( ! post ) return
112+
94113 const creator = creatorFromUri ( uri )
95- return ! ctx . views . viewerBlockExists ( creator , hydration )
114+ const isCuratedSearch = params . sort === 'top'
115+ const isPostByViewer = creator === params . hydrateCtx . viewer
116+
117+ // Cases to always show.
118+ if ( isPostByViewer ) return true
119+ if ( params . isModService ) return true
120+
121+ // Cases to never show.
122+ if ( ctx . views . viewerBlockExists ( creator , hydration ) ) return false
123+
124+ // Cases to conditionally show based on tagging.
125+ const tagged = [ ...ctx . cfg . searchTagsHide ] . some ( ( t ) => post . tags . has ( t ) )
126+ if ( isCuratedSearch && tagged ) return false
127+ if ( ! parsedQuery . author && tagged ) return false
128+ return true
96129 } )
97130 return skeleton
98131}
@@ -101,9 +134,12 @@ const presentation = (
101134 inputs : PresentationFnInput < Context , Params , Skeleton > ,
102135) => {
103136 const { ctx, skeleton, hydration } = inputs
104- const posts = mapDefined ( skeleton . posts , ( uri ) =>
105- ctx . views . post ( uri , hydration ) ,
106- )
137+ const posts = mapDefined ( skeleton . posts , ( uri ) => {
138+ const post = hydration . posts ?. get ( uri )
139+ if ( ! post ) return
140+
141+ return ctx . views . post ( uri , hydration )
142+ } )
107143 return {
108144 posts,
109145 cursor : skeleton . cursor ,
@@ -112,16 +148,21 @@ const presentation = (
112148}
113149
114150type Context = {
151+ cfg : ServerConfig
115152 dataplane : DataPlaneClient
116153 hydrator : Hydrator
117154 views : Views
118155 searchAgent ?: AtpAgent
119156}
120157
121- type Params = QueryParams & { hydrateCtx : HydrateCtx }
158+ type Params = QueryParams & {
159+ hydrateCtx : HydrateCtx
160+ isModService : boolean
161+ }
122162
123163type Skeleton = {
124164 posts : string [ ]
125165 hitsTotal ?: number
126166 cursor ?: string
167+ parsedQuery : PostSearchQuery
127168}
0 commit comments