@@ -4,11 +4,12 @@ import type { AppContext } from '@/app';
44import { isHandle } from '@/helpers/activitypub/actor' ;
55import { isUri } from '@/helpers/uri' ;
66import type { AccountDTO } from '@/http/api/types' ;
7+ import type { AccountSearchView } from '@/http/api/views/account.search.view' ;
78import type { AccountView } from '@/http/api/views/account.view' ;
89import { APIRoute , RequireRoles } from '@/http/decorators/route.decorator' ;
910import { GhostRole } from '@/http/middleware/role-guard' ;
1011
11- type AccountSearchResult = Pick <
12+ export type AccountSearchResult = Pick <
1213 AccountDTO ,
1314 | 'id'
1415 | 'name'
@@ -38,7 +39,10 @@ interface SearchResults {
3839}
3940
4041export class SearchController {
41- constructor ( private readonly accountView : AccountView ) { }
42+ constructor (
43+ private readonly accountView : AccountView ,
44+ private readonly accountSearchView : AccountSearchView ,
45+ ) { }
4246
4347 /**
4448 * Handle a search request
@@ -53,30 +57,60 @@ export class SearchController {
5357 const queryQuery = ctx . req . query ( 'query' ) ;
5458 const query = queryQuery ? decodeURIComponent ( queryQuery ) : '' ;
5559
56- // Init search results - At the moment we only support searching for an actor (account)
60+ // Init search results
5761 const results : SearchResults = {
5862 accounts : [ ] ,
5963 } ;
6064
65+ const account = ctx . get ( 'account' ) ;
6166 const requestUserContext = {
62- requestUserAccount : ctx . get ( ' account' ) ,
67+ requestUserAccount : account ,
6368 } ;
6469
65- let dto : AccountDTO | null = null ;
66-
70+ // Account handle search (exact match, single result)
6771 if ( isHandle ( query ) ) {
68- dto = await this . accountView . viewByHandle (
72+ const dto = await this . accountView . viewByHandle (
6973 query ,
7074 requestUserContext ,
7175 ) ;
76+
77+ if ( dto !== null ) {
78+ results . accounts . push ( toSearchResult ( dto ) ) ;
79+ }
80+
81+ return new Response ( JSON . stringify ( results ) , {
82+ headers : {
83+ 'Content-Type' : 'application/json' ,
84+ } ,
85+ status : 200 ,
86+ } ) ;
7287 }
7388
89+ // Account URI search (exact match, single result)
7490 if ( isUri ( query ) ) {
75- dto = await this . accountView . viewByApId ( query , requestUserContext ) ;
91+ const dto = await this . accountView . viewByApId (
92+ query ,
93+ requestUserContext ,
94+ ) ;
95+
96+ if ( dto !== null ) {
97+ results . accounts . push ( toSearchResult ( dto ) ) ;
98+ }
99+
100+ return new Response ( JSON . stringify ( results ) , {
101+ headers : {
102+ 'Content-Type' : 'application/json' ,
103+ } ,
104+ status : 200 ,
105+ } ) ;
76106 }
77107
78- if ( dto !== null ) {
79- results . accounts . push ( toSearchResult ( dto ) ) ;
108+ // Account name search (partial match, multiple results)
109+ if ( query . trim ( ) . length >= 2 ) {
110+ results . accounts = await this . accountSearchView . searchByName (
111+ query ,
112+ account . id ,
113+ ) ;
80114 }
81115
82116 return new Response ( JSON . stringify ( results ) , {
0 commit comments