diff --git a/app/lib/search_query_transformer.rb b/app/lib/search_query_transformer.rb index 89b16c1d2e..9417305ba2 100644 --- a/app/lib/search_query_transformer.rb +++ b/app/lib/search_query_transformer.rb @@ -30,6 +30,8 @@ class SearchQueryTransformer < Parslet::Transform def request search = Chewy::Search::Request.new(*indexes).filter(default_filter) + search = search.filter(flag_following_only) if following_only? + must_clauses.each { |clause| search = search.query.must(clause.to_query) } must_not_clauses.each { |clause| search = search.query.must_not(clause.to_query) } filter_clauses.each { |clause| search = search.filter(**clause.to_query) } @@ -59,6 +61,10 @@ class SearchQueryTransformer < Parslet::Transform @flags = clauses_by_operator.fetch(:flag, []).to_h { |clause| [clause.prefix, clause.term] } end + def following_only? + @flags['following'] + end + def must_clauses clauses_by_operator.fetch(:must, []) end @@ -198,6 +204,16 @@ class SearchQueryTransformer < Parslet::Transform } end + def flag_following_only + { + bool: { + (@flags['following'] == 'following' ? :must : :must_not) => { + terms: { account_id: following_account_ids }, + }, + }, + } + end + def following_account_ids return @following_account_ids if defined?(@following_account_ids) @@ -299,6 +315,10 @@ class SearchQueryTransformer < Parslet::Transform when 'in' @operator = :flag @term = term + if term == 'following' + @prefix = 'following' + @term = @negated ? 'not_following' : 'following' + end when 'my' @type = :term @term = @options[:current_account]&.id diff --git a/spec/search/services/statuses_search_service_spec.rb b/spec/search/services/statuses_search_service_spec.rb index 8bc236e4a6..383fa86eec 100644 --- a/spec/search/services/statuses_search_service_spec.rb +++ b/spec/search/services/statuses_search_service_spec.rb @@ -262,5 +262,32 @@ describe StatusesSearchService do it_behaves_like 'does not hit status', 'when double quote search with multiple letter in word but does not contain half', 'ず ご' it_behaves_like 'hit status', 'when specify user name', 'りんご from:alice' it_behaves_like 'does not hit status', 'when specify not existing user name', 'りんご from:ohagi' + + context 'when in:following is specified' do + let(:following) { Fabricate(:user).account } + let(:other) { Fabricate(:user).account } + + before do + following.follow!(alice) + end + + context 'with myself' do + let(:account) { alice } + + it_behaves_like 'does not hit status', 'when search with following', 'in:following りんご' + end + + context 'with following' do + let(:account) { following } + + it_behaves_like 'hit status', 'when search with following', 'in:following りんご' + end + + context 'without following' do + let(:account) { other } + + it_behaves_like 'does not hit status', 'when search with following', 'in:following りんご' + end + end end end