Search through users and hashtags as well
[akkoma] / lib / pleroma / search / elasticsearch.ex
1 defmodule Pleroma.Search.Elasticsearch do
2 @behaviour Pleroma.Search
3
4 alias Pleroma.Web.MastodonAPI.StatusView
5 alias Pleroma.Web.MastodonAPI.AccountView
6 alias Pleroma.Web.ActivityPub.Visibility
7 alias Pleroma.Search.Elasticsearch.Parsers
8 alias Pleroma.Web.Endpoint
9
10 defp es_query(:activity, query) do
11 %{
12 query: %{
13 bool: %{
14 must: Parsers.Activity.parse(query)
15 }
16 }
17 }
18 end
19
20 defp es_query(:user, query) do
21 %{
22 query: %{
23 bool: %{
24 must: Parsers.User.parse(query)
25 }
26 }
27 }
28 end
29
30 defp es_query(:hashtag, query) do
31 %{
32 query: %{
33 bool: %{
34 must: Parsers.Hashtag.parse(query)
35 }
36 }
37 }
38 end
39
40 @impl Pleroma.Search
41 def search(%{assigns: %{user: user}} = _conn, %{q: query} = _params, _options) do
42 parsed_query =
43 query
44 |> String.trim()
45 |> SearchParser.parse!()
46
47 activity_task =
48 Task.async(fn ->
49 q = es_query(:activity, parsed_query)
50
51 Pleroma.Elasticsearch.search(:activities, q)
52 |> Enum.filter(fn x -> Visibility.visible_for_user?(x, user) end)
53 end)
54
55 user_task =
56 Task.async(fn ->
57 q = es_query(:user, parsed_query)
58
59 Pleroma.Elasticsearch.search(:users, q)
60 |> Enum.filter(fn x -> Pleroma.User.visible_for(x, user) == :visible end)
61 end)
62
63 hashtag_task =
64 Task.async(fn ->
65 q = es_query(:hashtag, parsed_query)
66
67 Pleroma.Elasticsearch.search(:hashtags, q)
68 end)
69
70 activity_results = Task.await(activity_task)
71 user_results = Task.await(user_task)
72 hashtag_results = Task.await(hashtag_task)
73
74 %{
75 "accounts" =>
76 AccountView.render("index.json",
77 users: user_results,
78 for: user
79 ),
80 "hashtags" =>
81 Enum.map(hashtag_results, fn x ->
82 %{
83 url: Endpoint.url() <> "/tag/" <> x,
84 name: x
85 }
86 end),
87 "statuses" =>
88 StatusView.render("index.json",
89 activities: activity_results,
90 for: user,
91 as: :activity
92 )
93 }
94 end
95 end