X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fuser%2Fsearch.ex;h=46620b89acf42517429aa6a1e1cb1f77d0d95c73;hb=bbd9ed02576f1599e90f8575573fe6e935d32eae;hp=ed06c2ab92f2f367a90c7176279b12bb408b8b42;hpb=ee4ed87fb47fa6c395e0f77b614f1630f3a12637;p=akkoma diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index ed06c2ab9..46620b89a 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -3,6 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.User.Search do + alias Pleroma.Pagination alias Pleroma.Repo alias Pleroma.User import Ecto.Query @@ -18,8 +19,7 @@ defmodule Pleroma.User.Search do for_user = Keyword.get(opts, :for_user) - # Strip the beginning @ off if there is a query - query_string = String.trim_leading(query_string, "@") + query_string = format_query(query_string) maybe_resolve(resolve, for_user, query_string) @@ -33,16 +33,29 @@ defmodule Pleroma.User.Search do query_string |> search_query(for_user, following) - |> paginate(result_limit, offset) - |> Repo.all() + |> Pagination.fetch_paginated(%{"offset" => offset, "limit" => result_limit}, :offset) end) results end + defp format_query(query_string) do + # Strip the beginning @ off if there is a query + query_string = String.trim_leading(query_string, "@") + + with [name, domain] <- String.split(query_string, "@"), + formatted_domain <- String.replace(domain, ~r/[!-\-|@|[-`|{-~|\/|:]+/, "") do + name <> "@" <> to_string(:idna.encode(formatted_domain)) + else + _ -> query_string + end + end + defp search_query(query_string, for_user, following) do for_user |> base_query(following) + |> filter_blocked_user(for_user) + |> filter_blocked_domains(for_user) |> search_subqueries(query_string) |> union_subqueries |> distinct_query() @@ -55,10 +68,25 @@ defmodule Pleroma.User.Search do defp base_query(_user, false), do: User defp base_query(user, true), do: User.get_followers_query(user) - defp paginate(query, limit, offset) do - from(q in query, limit: ^limit, offset: ^offset) + defp filter_blocked_user(query, %User{info: %{blocks: blocks}}) + when length(blocks) > 0 do + from(q in query, where: not (q.ap_id in ^blocks)) end + defp filter_blocked_user(query, _), do: query + + defp filter_blocked_domains(query, %User{info: %{domain_blocks: domain_blocks}}) + when length(domain_blocks) > 0 do + domains = Enum.join(domain_blocks, ",") + + from( + q in query, + where: fragment("substring(ap_id from '.*://([^/]*)') NOT IN (?)", ^domains) + ) + end + + defp filter_blocked_domains(query, _), do: query + defp union_subqueries({fts_subquery, trigram_subquery}) do from(s in trigram_subquery, union_all: ^fts_subquery) end @@ -129,8 +157,8 @@ defmodule Pleroma.User.Search do @spec fts_search_subquery(User.t() | Ecto.Query.t(), String.t()) :: Ecto.Query.t() defp fts_search_subquery(query, term) do processed_query = - term - |> String.replace(~r/\W+/, " ") + String.trim_trailing(term, "@" <> local_domain()) + |> String.replace(~r/[!-\/|@|[-`|{-~|:-?]+/, " ") |> String.trim() |> String.split() |> Enum.map(&(&1 <> ":*")) @@ -171,6 +199,8 @@ defmodule Pleroma.User.Search do @spec trigram_search_subquery(User.t() | Ecto.Query.t(), String.t()) :: Ecto.Query.t() defp trigram_search_subquery(query, term) do + term = String.trim_trailing(term, "@" <> local_domain()) + from( u in query, select_merge: %{ @@ -188,4 +218,6 @@ defmodule Pleroma.User.Search do ) |> User.restrict_deactivated() end + + defp local_domain, do: Pleroma.Config.get([Pleroma.Web.Endpoint, :url, :host]) end