X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fuser%2Fsearch.ex;h=adbef7fb8c45abf7ca989d57f4f4c1bdf1593f6e;hb=ee67c98e550310813cfdb9242e5fab2e566e1e2a;hp=b1bb9d4da0aa65ad14c14a1fe131f88380ecdc19;hpb=49bb0a130f93476d32d3177d7a989b7a98a063f2;p=akkoma
diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex
index b1bb9d4da..adbef7fb8 100644
--- a/lib/pleroma/user/search.ex
+++ b/lib/pleroma/user/search.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors
+# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.User.Search do
@@ -33,9 +33,15 @@ defmodule Pleroma.User.Search 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/[!-\-|@|[-`|{-~|\/|:|\s]+/, "") do
- name <> "@" <> to_string(:idna.encode(formatted_domain))
+ with [name, domain] <- String.split(query_string, "@") do
+ encoded_domain =
+ domain
+ |> String.replace(~r/[!-\-|@|[-`|{-~|\/|:|\s]+/, "")
+ |> String.to_charlist()
+ |> :idna.encode()
+ |> to_string()
+
+ name <> "@" <> encoded_domain
else
_ -> query_string
end
@@ -46,6 +52,7 @@ defmodule Pleroma.User.Search do
|> base_query(following)
|> filter_blocked_user(for_user)
|> filter_invisible_users()
+ |> filter_internal_users()
|> filter_blocked_domains(for_user)
|> fts_search(query_string)
|> trigram_rank(query_string)
@@ -62,11 +69,15 @@ defmodule Pleroma.User.Search do
u in query,
where:
fragment(
+ # The fragment must _exactly_ match `users_fts_index`, otherwise the index won't work
"""
- (to_tsvector('simple', ?) || to_tsvector('simple', ?)) @@ to_tsquery('simple', ?)
+ (
+ setweight(to_tsvector('simple', regexp_replace(?, '\\W', ' ', 'g')), 'A') ||
+ setweight(to_tsvector('simple', regexp_replace(coalesce(?, ''), '\\W', ' ', 'g')), 'B')
+ ) @@ to_tsquery('simple', ?)
""",
- u.name,
u.nickname,
+ u.name,
^query_string
)
)
@@ -81,15 +92,23 @@ defmodule Pleroma.User.Search do
|> Enum.join(" | ")
end
+ # Considers nickname match, localized nickname match, name match; preferences nickname match
defp trigram_rank(query, query_string) do
from(
u in query,
select_merge: %{
search_rank:
fragment(
- "similarity(?, trim(? || ' ' || coalesce(?, '')))",
+ """
+ similarity(?, ?) +
+ similarity(?, regexp_replace(?, '@.+', '')) +
+ similarity(?, trim(coalesce(?, '')))
+ """,
^query_string,
u.nickname,
+ ^query_string,
+ u.nickname,
+ ^query_string,
u.name
)
}
@@ -97,15 +116,23 @@ defmodule Pleroma.User.Search do
end
defp base_query(_user, false), do: User
- defp base_query(user, true), do: User.get_followers_query(user)
+ defp base_query(user, true), do: User.get_friends_query(user)
defp filter_invisible_users(query) do
from(q in query, where: q.invisible == false)
end
- defp filter_blocked_user(query, %User{blocks: blocks})
- when length(blocks) > 0 do
- from(q in query, where: not (q.ap_id in ^blocks))
+ defp filter_internal_users(query) do
+ from(q in query, where: q.actor_type != "Application")
+ end
+
+ defp filter_blocked_user(query, %User{} = blocker) do
+ query
+ |> join(:left, [u], b in Pleroma.UserRelationship,
+ as: :blocks,
+ on: b.relationship_type == ^:block and b.source_id == ^blocker.id and u.id == b.target_id
+ )
+ |> where([blocks: b], is_nil(b.target_id))
end
defp filter_blocked_user(query, _), do: query