fix emoji tests
[akkoma] / lib / pleroma / elasticsearch / store.ex
1 # Akkoma: A lightweight social networking server
2 # Copyright © 2022-2022 Akkoma Authors <https://git.ihatebeinga.live/IHBAGang/akkoma/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Elasticsearch do
6 alias Pleroma.Activity
7 alias Pleroma.User
8 alias Pleroma.Object
9 alias Pleroma.Elasticsearch.DocumentMappings
10 alias Pleroma.Config
11 require Logger
12
13 defp url do
14 Config.get([:elasticsearch, :url])
15 end
16
17 defp enabled? do
18 Config.get([:search, :provider]) == Pleroma.Search.Elasticsearch
19 end
20
21 def delete_by_id(:activity, id) do
22 if enabled?() do
23 Elastix.Document.delete(url(), "activities", "activity", id)
24 end
25 end
26
27 def put_by_id(:activity, id) do
28 id
29 |> Activity.get_by_id_with_object()
30 |> maybe_put_into_elasticsearch()
31 end
32
33 def maybe_put_into_elasticsearch({:ok, item}) do
34 maybe_put_into_elasticsearch(item)
35 end
36
37 def maybe_put_into_elasticsearch(
38 %{data: %{"type" => "Create"}, object: %{data: %{"type" => "Note"}}} = activity
39 ) do
40 if enabled?() do
41 actor = Pleroma.Activity.user_actor(activity)
42
43 activity
44 |> Map.put(:user_actor, actor)
45 |> put()
46 end
47 end
48
49 def maybe_put_into_elasticsearch(%User{actor_type: "Person"} = user) do
50 if enabled?() do
51 put(user)
52 end
53 end
54
55 def maybe_put_into_elasticsearch(_) do
56 {:ok, :skipped}
57 end
58
59 def maybe_bulk_post(data, type) do
60 if enabled?() do
61 bulk_post(data, type)
62 end
63 end
64
65 def put(%Activity{} = activity) do
66 with {:ok, _} <-
67 Elastix.Document.index(
68 url(),
69 "activities",
70 "activity",
71 DocumentMappings.Activity.id(activity),
72 DocumentMappings.Activity.encode(activity)
73 ) do
74 activity
75 |> Map.get(:object)
76 |> Object.hashtags()
77 |> Enum.map(fn x ->
78 %{id: x, name: x, timestamp: DateTime.to_iso8601(DateTime.utc_now())}
79 end)
80 |> bulk_post(:hashtags)
81 else
82 {:error, %{reason: err}} ->
83 Logger.error("Could not put activity: #{err}")
84 :skipped
85 end
86 end
87
88 def put(%User{} = user) do
89 with {:ok, _} <-
90 Elastix.Document.index(
91 url(),
92 "users",
93 "user",
94 DocumentMappings.User.id(user),
95 DocumentMappings.User.encode(user)
96 ) do
97 :ok
98 else
99 {:error, %{reason: err}} ->
100 Logger.error("Could not put user: #{err}")
101 :skipped
102 end
103 end
104
105 def bulk_post(data, :activities) do
106 d =
107 data
108 |> Enum.filter(fn x ->
109 t =
110 x.object
111 |> Map.get(:data, %{})
112 |> Map.get("type", "")
113
114 t == "Note"
115 end)
116 |> Enum.map(fn d ->
117 [
118 %{index: %{_id: DocumentMappings.Activity.id(d)}},
119 DocumentMappings.Activity.encode(d)
120 ]
121 end)
122 |> List.flatten()
123
124 with {:ok, %{body: %{"errors" => false}}} <-
125 Elastix.Bulk.post(
126 url(),
127 d,
128 index: "activities",
129 type: "activity"
130 ) do
131 :ok
132 else
133 {:error, %{reason: err}} ->
134 Logger.error("Could not bulk put activity: #{err}")
135 :skipped
136
137 {:ok, %{body: _}} ->
138 :skipped
139 end
140 end
141
142 def bulk_post(data, :users) do
143 d =
144 data
145 |> Enum.filter(fn x -> x.actor_type == "Person" end)
146 |> Enum.map(fn d ->
147 [
148 %{index: %{_id: DocumentMappings.User.id(d)}},
149 DocumentMappings.User.encode(d)
150 ]
151 end)
152 |> List.flatten()
153
154 with {:ok, %{body: %{"errors" => false}}} <-
155 Elastix.Bulk.post(
156 url(),
157 d,
158 index: "users",
159 type: "user"
160 ) do
161 :ok
162 else
163 {:error, %{reason: err}} ->
164 Logger.error("Could not bulk put users: #{err}")
165 :skipped
166
167 {:ok, %{body: _}} ->
168 :skipped
169 end
170 end
171
172 def bulk_post(data, :hashtags) when is_list(data) do
173 d =
174 data
175 |> Enum.map(fn d ->
176 [
177 %{index: %{_id: DocumentMappings.Hashtag.id(d)}},
178 DocumentMappings.Hashtag.encode(d)
179 ]
180 end)
181 |> List.flatten()
182
183 with {:ok, %{body: %{"errors" => false}}} <-
184 Elastix.Bulk.post(
185 url(),
186 d,
187 index: "hashtags",
188 type: "hashtag"
189 ) do
190 :ok
191 else
192 {:error, %{reason: err}} ->
193 Logger.error("Could not bulk put hashtags: #{err}")
194 :skipped
195
196 {:ok, %{body: _}} ->
197 :skipped
198 end
199 end
200
201 def bulk_post(_, :hashtags), do: {:ok, nil}
202
203 def search(_, _, _, :skip), do: []
204
205 def search(:raw, index, type, q) do
206 with {:ok, raw_results} <- Elastix.Search.search(url(), index, [type], q) do
207 results =
208 raw_results
209 |> Map.get(:body, %{})
210 |> Map.get("hits", %{})
211 |> Map.get("hits", [])
212
213 {:ok, results}
214 else
215 {:error, e} ->
216 Logger.error(e)
217 {:error, e}
218 end
219 end
220
221 def search(:activities, q) do
222 with {:ok, results} <- search(:raw, "activities", "activity", q) do
223 results
224 |> Enum.map(fn result -> result["_id"] end)
225 |> Pleroma.Activity.all_by_ids_with_object()
226 |> Enum.sort(&(&1.inserted_at >= &2.inserted_at))
227 else
228 e ->
229 Logger.error(e)
230 []
231 end
232 end
233
234 def search(:users, q) do
235 with {:ok, results} <- search(:raw, "users", "user", q) do
236 results
237 |> Enum.map(fn result -> result["_id"] end)
238 |> Pleroma.User.get_all_by_ids()
239 else
240 e ->
241 Logger.error(e)
242 []
243 end
244 end
245
246 def search(:hashtags, q) do
247 with {:ok, results} <- search(:raw, "hashtags", "hashtag", q) do
248 results
249 |> Enum.map(fn result -> result["_source"]["hashtag"] end)
250 else
251 e ->
252 Logger.error(e)
253 []
254 end
255 end
256 end