diff --git a/lib/search.rb b/lib/search.rb index d8557cc3b85..1e4b136a20f 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -415,6 +415,19 @@ class Search posts.where("EXISTS (SELECT 1 FROM topic_tags WHERE topic_tags.topic_id = posts.topic_id)") end + advanced_filter(/\Ain:bots?\z/i) { |posts| posts.where("posts.user_id < 0") } + advanced_filter(/\Ain:humans?\z/i) { |posts| posts.where("posts.user_id >= 0") } + + advanced_filter(/\Ain:whispers?\z/i) do |posts| + if @guardian.can_see_whispers? + posts.where(post_type: Post.types[:whisper]) + else + posts.where("1 = 0") + end + end + + advanced_filter(/\Ain:regular\z/i) { |posts| posts.where(post_type: Post.types[:regular]) } + advanced_filter(/\Ain:untagged\z/i) do |posts| posts.joins( "LEFT JOIN topic_tags ON @@ -1459,7 +1472,6 @@ class Search def aggregate_search(opts = {}) post_sql = aggregate_post_sql(opts) - added = 0 aggregate_posts(post_sql[:default]).each do |p| diff --git a/spec/lib/search_spec.rb b/spec/lib/search_spec.rb index 2dce8b2cfec..1a716a3dec7 100644 --- a/spec/lib/search_spec.rb +++ b/spec/lib/search_spec.rb @@ -2990,7 +2990,6 @@ RSpec.describe Search do context "when max_duplicate_search_index_terms limits duplication" do before { SearchIndexer.enable } - after { SearchIndexer.disable } it "correctly ranks topics" do @@ -3034,4 +3033,90 @@ RSpec.describe Search do expect(sql).to match(/where.*topics.closed/i) end end + + describe "bot search" do + fab!(:bot) + fab!(:bot_topic) { Fabricate(:topic, title: "this is a topic by a bot") } + fab!(:bot_post) do + Fabricate(:post, user: bot, topic: bot_topic, raw: "this is a regular post by a bot") + end + + fab!(:human_post) { Fabricate(:post, topic: topic, raw: "this is a regular post not by a bot") } + + before do + SearchIndexer.enable + SearchIndexer.index(bot_post, force: true) + SearchIndexer.index(human_post, force: true) + end + + it "works as expected" do + # include bot posts by default + results = Search.execute("bot", guardian: Guardian.new) + expect(results.posts).to contain_exactly(bot_post, human_post) + + # bots only + results = Search.execute("bot in:bot", guardian: Guardian.new) + expect(results.posts).to contain_exactly(bot_post) + + # allows searching for human only + results = Search.execute("bot in:human", guardian: Guardian.new) + expect(results.posts).to contain_exactly(human_post) + end + end + + describe "whisper search" do + fab!(:topic2) { Fabricate(:topic) } + fab!(:user) + fab!(:whisperer) { Fabricate(:user) } + fab!(:whisperers_group) { Fabricate(:group) } + fab!(:regular_post) do + Fabricate(:post, topic: topic, raw: "this is a regular post with whisper content") + end + fab!(:whisper_post) do + Fabricate( + :post, + topic: topic2, + raw: "this is a whisper post", + post_type: Post.types[:whisper], + ) + end + + before do + SiteSetting.whispers_allowed_groups = "#{Group::AUTO_GROUPS[:staff]}|#{whisperers_group.id}" + whisperers_group.add(whisperer) + SearchIndexer.enable + [regular_post, whisper_post].each { |post| SearchIndexer.index(post, force: true) } + end + + it "works as expected" do + # note this is simple enough, saving up on all the reindexing over and over + # by running in a big batch + + # anon + results = Search.execute("whisper", guardian: Guardian.new(user)) + expect(results.posts).to contain_exactly(regular_post) + + # staff + results = Search.execute("whisper", guardian: Guardian.new(admin)) + expect(results.posts).to contain_exactly(regular_post, whisper_post) + + # whisperer + results = Search.execute("whisper", guardian: Guardian.new(whisperer)) + expect(results.posts).to contain_exactly(regular_post, whisper_post) + + # in:whispers + results = Search.execute("whisper in:whispers", guardian: Guardian.new(admin)) + expect(results.posts).to contain_exactly(whisper_post) + + results = Search.execute("whisper in:whispers", guardian: Guardian.new(user)) + expect(results.posts).to be_empty + + # in:regular + results = Search.execute("whisper in:regular", guardian: Guardian.new(admin)) + expect(results.posts).to contain_exactly(regular_post) + + results = Search.execute("content in:regular", guardian: Guardian.new(admin)) + expect(results.posts).to contain_exactly(regular_post) + end + end end