mirror of
https://framagit.org/framasoft/mobilizon.git
synced 2024-12-24 00:43:02 +00:00
9c9f1385fb
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
165 lines
4.5 KiB
Elixir
165 lines
4.5 KiB
Elixir
defmodule Mobilizon.Federation.ActivityStream.Converter.Utils do
|
|
@moduledoc """
|
|
Various utils for converters.
|
|
"""
|
|
|
|
alias Mobilizon.Actors.Actor
|
|
alias Mobilizon.Events
|
|
alias Mobilizon.Events.Tag
|
|
alias Mobilizon.Mention
|
|
alias Mobilizon.Storage.Repo
|
|
|
|
alias Mobilizon.Federation.ActivityPub
|
|
|
|
alias Mobilizon.Web.Endpoint
|
|
|
|
require Logger
|
|
|
|
@spec fetch_tags([String.t()]) :: [Tag.t()]
|
|
def fetch_tags(tags) when is_list(tags) do
|
|
Logger.debug("fetching tags")
|
|
Logger.debug(inspect(tags))
|
|
|
|
tags |> Enum.flat_map(&fetch_tag/1) |> Enum.uniq() |> Enum.map(&existing_tag_or_data/1)
|
|
end
|
|
|
|
def fetch_tags(_), do: []
|
|
|
|
@spec fetch_mentions([map()]) :: [map()]
|
|
def fetch_mentions(mentions) when is_list(mentions) do
|
|
Logger.debug("fetching mentions")
|
|
|
|
Enum.reduce(mentions, [], fn mention, acc -> create_mention(mention, acc) end)
|
|
end
|
|
|
|
def fetch_mentions(_), do: []
|
|
|
|
def fetch_address(%{id: id}) do
|
|
with {id, ""} <- Integer.parse(id), do: %{id: id}
|
|
end
|
|
|
|
def fetch_address(address) when is_map(address) do
|
|
address
|
|
end
|
|
|
|
@spec build_tags([Tag.t()]) :: [map()]
|
|
def build_tags(tags) do
|
|
Enum.map(tags, fn %Tag{} = tag ->
|
|
%{
|
|
"href" => Endpoint.url() <> "/tags/#{tag.slug}",
|
|
"name" => "##{tag.title}",
|
|
"type" => "Hashtag"
|
|
}
|
|
end)
|
|
end
|
|
|
|
def build_mentions(mentions) do
|
|
Enum.map(mentions, fn %Mention{} = mention ->
|
|
if Ecto.assoc_loaded?(mention.actor) do
|
|
build_mention(mention.actor)
|
|
else
|
|
build_mention(Repo.preload(mention, [:actor]).actor)
|
|
end
|
|
end)
|
|
end
|
|
|
|
defp build_mention(%Actor{} = actor) do
|
|
%{
|
|
"href" => actor.url,
|
|
"name" => "@#{Actor.preferred_username_and_domain(actor)}",
|
|
"type" => "Mention"
|
|
}
|
|
end
|
|
|
|
defp fetch_tag(%{title: title}), do: [title]
|
|
|
|
defp fetch_tag(tag) when is_map(tag) do
|
|
case tag["type"] do
|
|
"Hashtag" ->
|
|
[tag_without_hash(tag["name"])]
|
|
|
|
_err ->
|
|
[]
|
|
end
|
|
end
|
|
|
|
defp fetch_tag(tag) when is_bitstring(tag), do: [tag_without_hash(tag)]
|
|
|
|
defp tag_without_hash("#" <> tag_title), do: tag_title
|
|
defp tag_without_hash(tag_title), do: tag_title
|
|
|
|
defp existing_tag_or_data(tag_title) do
|
|
case Events.get_tag_by_title(tag_title) do
|
|
%Tag{} = tag -> %{title: tag.title, id: tag.id}
|
|
nil -> %{title: tag_title}
|
|
end
|
|
end
|
|
|
|
@spec create_mention(map(), list()) :: list()
|
|
defp create_mention(%Actor{id: actor_id} = _mention, acc) do
|
|
acc ++ [%{actor_id: actor_id}]
|
|
end
|
|
|
|
@spec create_mention(map(), list()) :: list()
|
|
defp create_mention(mention, acc) when is_map(mention) do
|
|
with true <- mention["type"] == "Mention",
|
|
{:ok, %Actor{id: actor_id}} <- ActivityPub.get_or_fetch_actor_by_url(mention["href"]) do
|
|
acc ++ [%{actor_id: actor_id}]
|
|
else
|
|
_err ->
|
|
acc
|
|
end
|
|
end
|
|
|
|
@spec create_mention({String.t(), map()}, list()) :: list()
|
|
defp create_mention({_, mention}, acc) when is_map(mention) do
|
|
create_mention(mention, acc)
|
|
end
|
|
|
|
@spec maybe_fetch_actor_and_attributed_to_id(map()) :: {Actor.t() | nil, Actor.t() | nil}
|
|
def maybe_fetch_actor_and_attributed_to_id(%{
|
|
"actor" => actor_url,
|
|
"attributedTo" => attributed_to_url
|
|
})
|
|
when is_nil(attributed_to_url) do
|
|
{fetch_actor(actor_url), nil}
|
|
end
|
|
|
|
@spec maybe_fetch_actor_and_attributed_to_id(map()) :: {Actor.t() | nil, Actor.t() | nil}
|
|
def maybe_fetch_actor_and_attributed_to_id(%{
|
|
"actor" => actor_url,
|
|
"attributedTo" => attributed_to_url
|
|
})
|
|
when is_nil(actor_url) do
|
|
{fetch_actor(attributed_to_url), nil}
|
|
end
|
|
|
|
# Only when both actor and attributedTo fields are both filled is when we can return both
|
|
def maybe_fetch_actor_and_attributed_to_id(%{
|
|
"actor" => actor_url,
|
|
"attributedTo" => attributed_to_url
|
|
})
|
|
when actor_url != attributed_to_url do
|
|
with actor <- fetch_actor(actor_url),
|
|
attributed_to <- fetch_actor(attributed_to_url) do
|
|
{actor, attributed_to}
|
|
end
|
|
end
|
|
|
|
# If we only have attributedTo and no actor, take attributedTo as the actor
|
|
def maybe_fetch_actor_and_attributed_to_id(%{
|
|
"attributedTo" => attributed_to_url
|
|
}) do
|
|
{fetch_actor(attributed_to_url), nil}
|
|
end
|
|
|
|
def maybe_fetch_actor_and_attributed_to_id(_), do: {nil, nil}
|
|
|
|
@spec fetch_actor(String.t()) :: Actor.t()
|
|
defp fetch_actor(actor_url) do
|
|
with {:ok, %Actor{suspended: false} = actor} <-
|
|
ActivityPub.get_or_fetch_actor_by_url(actor_url) do
|
|
actor
|
|
end
|
|
end
|
|
end
|