mobilizon.chapril.org-mobil.../lib/federation/activity_pub/types/posts.ex

122 lines
4.2 KiB
Elixir

defmodule Mobilizon.Federation.ActivityPub.Types.Posts do
@moduledoc false
alias Mobilizon.{Actors, Posts, Tombstone}
alias Mobilizon.Actors.Actor
alias Mobilizon.Federation.ActivityPub.{Audience, Permission}
alias Mobilizon.Federation.ActivityPub.Types.Entity
alias Mobilizon.Federation.ActivityStream
alias Mobilizon.Federation.ActivityStream.Converter.Utils, as: ConverterUtils
alias Mobilizon.Federation.ActivityStream.Convertible
alias Mobilizon.Posts.Post
alias Mobilizon.Service.Activity.Post, as: PostsActivity
alias Mobilizon.Service.LanguageDetection
require Logger
import Mobilizon.Federation.ActivityPub.Utils, only: [make_create_data: 2, make_update_data: 2]
@behaviour Entity
@public_ap "https://www.w3.org/ns/activitystreams#Public"
@impl Entity
@spec create(map(), map()) :: {:ok, Post.t(), ActivityStream.t()}
def create(args, additional) do
with args <- prepare_args(args),
{:ok, %Post{attributed_to_id: group_id, author_id: creator_id} = post} <-
Posts.create_post(args),
{:ok, _} <- PostsActivity.insert_activity(post, subject: "post_created"),
{:ok, %Actor{} = group} <- Actors.get_group_by_actor_id(group_id),
%Actor{} = creator <- Actors.get_actor(creator_id),
post_as_data <-
Convertible.model_to_as(%{post | attributed_to: group, author: creator}) do
create_data = make_create_data(post_as_data, additional)
{:ok, post, create_data}
else
err ->
Logger.debug(inspect(err))
err
end
end
@impl Entity
@spec update(Post.t(), map(), map()) :: {:ok, Post.t(), ActivityStream.t()}
def update(%Post{} = post, args, additional) do
with args <- prepare_args(args),
{:ok, %Post{attributed_to_id: group_id, author_id: creator_id} = post} <-
Posts.update_post(post, args),
{:ok, _} <- PostsActivity.insert_activity(post, subject: "post_updated"),
{:ok, true} <- Cachex.del(:activity_pub, "post_#{post.slug}"),
{:ok, %Actor{} = group} <- Actors.get_group_by_actor_id(group_id),
%Actor{} = creator <- Actors.get_actor(creator_id),
post_as_data <-
Convertible.model_to_as(%{post | attributed_to: group, author: creator}),
audience <-
Audience.get_audience(post) do
update_data = make_update_data(post_as_data, Map.merge(audience, additional))
{:ok, post, update_data}
else
err ->
Logger.debug(inspect(err))
err
end
end
@impl Entity
@spec delete(Post.t(), Actor.t(), boolean, map) ::
{:ok, ActivityStream.t(), Actor.t(), Post.t()}
def delete(
%Post{
url: url,
attributed_to: %Actor{url: group_url, members_url: members_url}
} = post,
%Actor{url: actor_url} = actor,
_local,
_additionnal
) do
activity_data = %{
"actor" => actor_url,
"type" => "Delete",
"object" => Convertible.model_to_as(post),
"id" => url <> "/delete",
"to" => [group_url, @public_ap, members_url]
}
with {:ok, %Post{} = post} <- Posts.delete_post(post),
{:ok, _} <- PostsActivity.insert_activity(post, subject: "post_deleted"),
{:ok, true} <- Cachex.del(:activity_pub, "post_#{post.slug}"),
{:ok, %Tombstone{} = _tombstone} <-
Tombstone.create_tombstone(%{uri: post.url, actor_id: actor.id}) do
{:ok, activity_data, actor, post}
end
end
@spec actor(Post.t()) :: Actor.t() | nil
def actor(%Post{author_id: author_id}),
do: Actors.get_actor(author_id)
@spec group_actor(Post.t()) :: Actor.t() | nil
def group_actor(%Post{attributed_to_id: attributed_to_id}),
do: Actors.get_actor(attributed_to_id)
@spec permissions(Post.t()) :: Permission.t()
def permissions(%Post{}) do
%Permission{
access: :member,
create: :moderator,
update: :moderator,
delete: :moderator
}
end
@spec prepare_args(map()) :: map
defp prepare_args(args) do
args
|> Map.update(:tags, [], &ConverterUtils.fetch_tags/1)
|> Map.put_new(:language, "und")
|> Map.update!(:language, fn lang ->
if lang == "und", do: LanguageDetection.detect(:post, args), else: lang
end)
end
end