257 lines
5.8 KiB
Elixir
257 lines
5.8 KiB
Elixir
# Akkoma: A lightweight social networking server
|
|
# Copyright © 2022-2022 Akkoma Authors <https://git.ihatebeinga.live/IHBAGang/akkoma/>
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
defmodule Pleroma.Elasticsearch do
|
|
alias Pleroma.Activity
|
|
alias Pleroma.User
|
|
alias Pleroma.Object
|
|
alias Pleroma.Elasticsearch.DocumentMappings
|
|
alias Pleroma.Config
|
|
require Logger
|
|
|
|
defp url do
|
|
Config.get([:elasticsearch, :url])
|
|
end
|
|
|
|
defp enabled? do
|
|
Config.get([:search, :provider]) == Pleroma.Search.Elasticsearch
|
|
end
|
|
|
|
def delete_by_id(:activity, id) do
|
|
if enabled?() do
|
|
Elastix.Document.delete(url(), "activities", "activity", id)
|
|
end
|
|
end
|
|
|
|
def put_by_id(:activity, id) do
|
|
id
|
|
|> Activity.get_by_id_with_object()
|
|
|> maybe_put_into_elasticsearch()
|
|
end
|
|
|
|
def maybe_put_into_elasticsearch({:ok, item}) do
|
|
maybe_put_into_elasticsearch(item)
|
|
end
|
|
|
|
def maybe_put_into_elasticsearch(
|
|
%{data: %{"type" => "Create"}, object: %{data: %{"type" => "Note"}}} = activity
|
|
) do
|
|
if enabled?() do
|
|
actor = Pleroma.Activity.user_actor(activity)
|
|
|
|
activity
|
|
|> Map.put(:user_actor, actor)
|
|
|> put()
|
|
end
|
|
end
|
|
|
|
def maybe_put_into_elasticsearch(%User{actor_type: "Person"} = user) do
|
|
if enabled?() do
|
|
put(user)
|
|
end
|
|
end
|
|
|
|
def maybe_put_into_elasticsearch(_) do
|
|
{:ok, :skipped}
|
|
end
|
|
|
|
def maybe_bulk_post(data, type) do
|
|
if enabled?() do
|
|
bulk_post(data, type)
|
|
end
|
|
end
|
|
|
|
def put(%Activity{} = activity) do
|
|
with {:ok, _} <-
|
|
Elastix.Document.index(
|
|
url(),
|
|
"activities",
|
|
"activity",
|
|
DocumentMappings.Activity.id(activity),
|
|
DocumentMappings.Activity.encode(activity)
|
|
) do
|
|
activity
|
|
|> Map.get(:object)
|
|
|> Object.hashtags()
|
|
|> Enum.map(fn x ->
|
|
%{id: x, name: x, timestamp: DateTime.to_iso8601(DateTime.utc_now())}
|
|
end)
|
|
|> bulk_post(:hashtags)
|
|
else
|
|
{:error, %{reason: err}} ->
|
|
Logger.error("Could not put activity: #{err}")
|
|
:skipped
|
|
end
|
|
end
|
|
|
|
def put(%User{} = user) do
|
|
with {:ok, _} <-
|
|
Elastix.Document.index(
|
|
url(),
|
|
"users",
|
|
"user",
|
|
DocumentMappings.User.id(user),
|
|
DocumentMappings.User.encode(user)
|
|
) do
|
|
:ok
|
|
else
|
|
{:error, %{reason: err}} ->
|
|
Logger.error("Could not put user: #{err}")
|
|
:skipped
|
|
end
|
|
end
|
|
|
|
def bulk_post(data, :activities) do
|
|
d =
|
|
data
|
|
|> Enum.filter(fn x ->
|
|
t =
|
|
x.object
|
|
|> Map.get(:data, %{})
|
|
|> Map.get("type", "")
|
|
|
|
t == "Note"
|
|
end)
|
|
|> Enum.map(fn d ->
|
|
[
|
|
%{index: %{_id: DocumentMappings.Activity.id(d)}},
|
|
DocumentMappings.Activity.encode(d)
|
|
]
|
|
end)
|
|
|> List.flatten()
|
|
|
|
with {:ok, %{body: %{"errors" => false}}} <-
|
|
Elastix.Bulk.post(
|
|
url(),
|
|
d,
|
|
index: "activities",
|
|
type: "activity"
|
|
) do
|
|
:ok
|
|
else
|
|
{:error, %{reason: err}} ->
|
|
Logger.error("Could not bulk put activity: #{err}")
|
|
:skipped
|
|
|
|
{:ok, %{body: _}} ->
|
|
:skipped
|
|
end
|
|
end
|
|
|
|
def bulk_post(data, :users) do
|
|
d =
|
|
data
|
|
|> Enum.filter(fn x -> x.actor_type == "Person" end)
|
|
|> Enum.map(fn d ->
|
|
[
|
|
%{index: %{_id: DocumentMappings.User.id(d)}},
|
|
DocumentMappings.User.encode(d)
|
|
]
|
|
end)
|
|
|> List.flatten()
|
|
|
|
with {:ok, %{body: %{"errors" => false}}} <-
|
|
Elastix.Bulk.post(
|
|
url(),
|
|
d,
|
|
index: "users",
|
|
type: "user"
|
|
) do
|
|
:ok
|
|
else
|
|
{:error, %{reason: err}} ->
|
|
Logger.error("Could not bulk put users: #{err}")
|
|
:skipped
|
|
|
|
{:ok, %{body: _}} ->
|
|
:skipped
|
|
end
|
|
end
|
|
|
|
def bulk_post(data, :hashtags) when is_list(data) do
|
|
d =
|
|
data
|
|
|> Enum.map(fn d ->
|
|
[
|
|
%{index: %{_id: DocumentMappings.Hashtag.id(d)}},
|
|
DocumentMappings.Hashtag.encode(d)
|
|
]
|
|
end)
|
|
|> List.flatten()
|
|
|
|
with {:ok, %{body: %{"errors" => false}}} <-
|
|
Elastix.Bulk.post(
|
|
url(),
|
|
d,
|
|
index: "hashtags",
|
|
type: "hashtag"
|
|
) do
|
|
:ok
|
|
else
|
|
{:error, %{reason: err}} ->
|
|
Logger.error("Could not bulk put hashtags: #{err}")
|
|
:skipped
|
|
|
|
{:ok, %{body: _}} ->
|
|
:skipped
|
|
end
|
|
end
|
|
|
|
def bulk_post(_, :hashtags), do: {:ok, nil}
|
|
|
|
def search(_, _, _, :skip), do: []
|
|
|
|
def search(:raw, index, type, q) do
|
|
with {:ok, raw_results} <- Elastix.Search.search(url(), index, [type], q) do
|
|
results =
|
|
raw_results
|
|
|> Map.get(:body, %{})
|
|
|> Map.get("hits", %{})
|
|
|> Map.get("hits", [])
|
|
|
|
{:ok, results}
|
|
else
|
|
{:error, e} ->
|
|
Logger.error(e)
|
|
{:error, e}
|
|
end
|
|
end
|
|
|
|
def search(:activities, q) do
|
|
with {:ok, results} <- search(:raw, "activities", "activity", q) do
|
|
results
|
|
|> Enum.map(fn result -> result["_id"] end)
|
|
|> Pleroma.Activity.all_by_ids_with_object()
|
|
|> Enum.sort(&(&1.inserted_at >= &2.inserted_at))
|
|
else
|
|
e ->
|
|
Logger.error(e)
|
|
[]
|
|
end
|
|
end
|
|
|
|
def search(:users, q) do
|
|
with {:ok, results} <- search(:raw, "users", "user", q) do
|
|
results
|
|
|> Enum.map(fn result -> result["_id"] end)
|
|
|> Pleroma.User.get_all_by_ids()
|
|
else
|
|
e ->
|
|
Logger.error(e)
|
|
[]
|
|
end
|
|
end
|
|
|
|
def search(:hashtags, q) do
|
|
with {:ok, results} <- search(:raw, "hashtags", "hashtag", q) do
|
|
results
|
|
|> Enum.map(fn result -> result["_source"]["hashtag"] end)
|
|
else
|
|
e ->
|
|
Logger.error(e)
|
|
[]
|
|
end
|
|
end
|
|
end
|