From 0bbcd4065f0d48cb1c0a5e2990002692655170c1 Mon Sep 17 00:00:00 2001 From: itepechi <72330683+itepechi@users.noreply.github.com> Date: Wed, 15 Nov 2023 08:45:53 +0900 Subject: [PATCH] Support for searching local posts/users only --- config/config.exs | 3 ++- lib/pleroma/search/database_search.ex | 16 ++++++++------ lib/pleroma/search/elasticsearch.ex | 6 +++++ lib/pleroma/search/meilisearch.ex | 3 ++- lib/pleroma/user/search.ex | 22 +++++++++++++++++-- .../api_spec/operations/search_operation.ex | 12 ++++++++++ .../controllers/search_controller.ex | 1 + .../web/mastodon_api/views/instance_view.ex | 3 +++ 8 files changed, 55 insertions(+), 11 deletions(-) diff --git a/config/config.exs b/config/config.exs index 15d448196..669c9e770 100644 --- a/config/config.exs +++ b/config/config.exs @@ -871,7 +871,8 @@ # these features are placed in the ':extensions' section for clarity # as they are not in the upstream, at least not yet search_type_media: true, - search_option_following: true + search_option_following: true, + search_option_local: true } config :pleroma, Pleroma.Search.Meilisearch, diff --git a/lib/pleroma/search/database_search.ex b/lib/pleroma/search/database_search.ex index 3d5372d35..6532dc4ef 100644 --- a/lib/pleroma/search/database_search.ex +++ b/lib/pleroma/search/database_search.ex @@ -31,6 +31,7 @@ def search(user, search_query, options \\ []) do author = Keyword.get(options, :author) following = can_search_following && Keyword.get(options, :following, false) only_media = Keyword.get(options, :only_media, false) + only_local = Keyword.get(options, :local, false) search_function = if :persistent_term.get({Pleroma.Repo, :postgres_version}) >= 11 do @@ -45,7 +46,7 @@ def search(user, search_query, options \\ []) do |> Activity.restrict_deactivated_users() |> restrict_public() |> query_with(index_type, search_query, search_function) - |> maybe_restrict_local(user) + |> maybe_restrict_local(user, only_local) |> maybe_restrict_author(author) |> maybe_restrict_blocked(user) |> maybe_restrict_following(user, following) @@ -163,14 +164,15 @@ def query_with(q, :pgroonga, search_query, _) do ) end - def maybe_restrict_local(q, user) do + def maybe_restrict_local(q, user, only_local) do limit = Pleroma.Config.get([:instance, :limit_to_local_content], :unauthenticated) - case {limit, user} do - {:all, _} -> restrict_local(q) - {:unauthenticated, %User{}} -> q - {:unauthenticated, _} -> restrict_local(q) - {false, _} -> q + case {only_local, limit, user} do + {true, _, _} -> restrict_local(q) + {_, :all, _} -> restrict_local(q) + {_, :unauthenticated, %User{}} -> q + {_, :unauthenticated, _} -> restrict_local(q) + {_, false, _} -> q end end diff --git a/lib/pleroma/search/elasticsearch.ex b/lib/pleroma/search/elasticsearch.ex index 60b40fb46..162325992 100644 --- a/lib/pleroma/search/elasticsearch.ex +++ b/lib/pleroma/search/elasticsearch.ex @@ -55,6 +55,7 @@ def search(user, query, options) do offset = Keyword.get(options, :offset, 0) following = can_search_following && Keyword.get(options, :following, false) only_media = Keyword.get(options, :only_media, false) + only_local = Keyword.get(options, :local, false) parsed_query = query @@ -86,6 +87,11 @@ def search(user, query, options) do Enum.member?(User.following_ap_ids(user), x.object.data["actor"]) else true + end, + if only_local do + x.local == true + else + true end ]) end) diff --git a/lib/pleroma/search/meilisearch.ex b/lib/pleroma/search/meilisearch.ex index 467234a9e..47265844b 100644 --- a/lib/pleroma/search/meilisearch.ex +++ b/lib/pleroma/search/meilisearch.ex @@ -84,6 +84,7 @@ def search(user, query, options \\ []) do author = Keyword.get(options, :author) following = can_search_following && Keyword.get(options, :following, false) only_media = Keyword.get(options, :only_media, false) + only_local = Keyword.get(options, :local, false) res = meili_post( @@ -99,7 +100,7 @@ def search(user, query, options \\ []) do |> Activity.create_by_object_ap_id() |> Activity.with_preloaded_object() |> Activity.restrict_deactivated_users() - |> maybe_restrict_local(user) + |> maybe_restrict_local(user, only_local) |> maybe_restrict_author(author) |> maybe_restrict_blocked(user) |> maybe_restrict_following(user, following) diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index c0cbc8b57..9c4b8f066 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -21,6 +21,7 @@ def search(query_string, opts \\ []) do resolve = Keyword.get(opts, :resolve, false) following = Keyword.get(opts, :following, false) + only_local = Keyword.get(opts, :local, false) result_limit = Keyword.get(opts, :limit, @limit) offset = Keyword.get(opts, :offset, 0) @@ -39,7 +40,7 @@ def search(query_string, opts \\ []) do results = query_string - |> search_query(query_type, for_user, following, top_user_ids) + |> search_query(query_type, for_user, following, only_local, top_user_ids) |> Pagination.fetch_paginated(%{"offset" => offset, "limit" => result_limit}, :offset) results @@ -92,13 +93,21 @@ defp format_query(query_string) do end end - defp search_query(query_string, query_type, for_user, following, top_user_ids) do + defp search_query( + query_string, + query_type, + for_user, + following, + only_local, + top_user_ids + ) do for_user |> base_query(following) |> filter_blocked_user(for_user) |> filter_invisible_users() |> filter_internal_users() |> filter_blocked_domains(for_user) + |> filter_local_user(only_local) |> query_with(query_type, query_string) |> select_top_users(top_user_ids) |> trigram_rank(query_string) @@ -233,6 +242,15 @@ defp filter_blocked_domains(query, %User{domain_blocks: domain_blocks}) defp filter_blocked_domains(query, _), do: query + defp filter_local_user(query, true) do + from( + q in query, + where: q.local == true + ) + end + + defp filter_local_user(query, _), do: query + defp maybe_resolve(true, user, query) do case {limit(), user} do {:all, _} -> :noop diff --git a/lib/pleroma/web/api_spec/operations/search_operation.ex b/lib/pleroma/web/api_spec/operations/search_operation.ex index 8d5e35841..5dcc7a273 100644 --- a/lib/pleroma/web/api_spec/operations/search_operation.ex +++ b/lib/pleroma/web/api_spec/operations/search_operation.ex @@ -46,6 +46,12 @@ def account_search_operation do :query, %Schema{allOf: [BooleanLike], default: false}, "Only include accounts that the user is following" + ), + Operation.parameter( + :local, + :query, + %Schema{allOf: [BooleanLike], default: false}, + "Only include local accounts" ) ], responses: %{ @@ -93,6 +99,12 @@ def search2_operation do %Schema{allOf: [BooleanLike], default: false}, "Only include accounts that the user is following" ), + Operation.parameter( + :local, + :query, + %Schema{allOf: [BooleanLike], default: false}, + "Only include local accounts" + ), with_relationships_param() | pagination_params() ], responses: %{ diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex index ef69e84f8..b0301fc24 100644 --- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex @@ -89,6 +89,7 @@ defp search_options(params, user) do [ resolve: params[:resolve], following: params[:following], + local: params[:local], limit: min(params[:limit], @search_limit), offset: params[:offset], type: params[:type], diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index 23647a187..d5c484561 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -95,6 +95,9 @@ def features do if Config.get([Pleroma.Search, :extensions, :search_option_following], true) do "bnakkoma:search_option_following" end, + if Config.get([Pleroma.Search, :extensions, :search_option_local], true) do + "bnakkoma:search_option_local" + end, "bnakkoma:opensearch_protocol", "custom_emoji_reactions", "pleroma:get:main/ostatus"