Announcements: Handle through common pipeline.

This commit is contained in:
lain 2020-05-20 15:44:37 +02:00
commit e42bc5f557
11 changed files with 135 additions and 79 deletions

View file

@ -356,36 +356,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
@spec announce(User.t(), Object.t(), String.t() | nil, boolean(), boolean()) ::
{:ok, Activity.t(), Object.t()} | {:error, any()}
def announce(
%User{ap_id: _} = user,
%Object{data: %{"id" => _}} = object,
activity_id \\ nil,
local \\ true,
public \\ true
) do
with {:ok, result} <-
Repo.transaction(fn -> do_announce(user, object, activity_id, local, public) end) do
result
end
end
defp do_announce(user, object, activity_id, local, public) do
with true <- is_announceable?(object, user, public),
object <- Object.get_by_id(object.id),
announce_data <- make_announce_data(user, object, activity_id, public),
{:ok, activity} <- insert(announce_data, local),
{:ok, object} <- add_announce_to_object(activity, object),
_ <- notify_and_stream(activity),
:ok <- maybe_federate(activity) do
{:ok, activity, object}
else
false -> {:error, false}
{:error, error} -> Repo.rollback(error)
end
end
@spec follow(User.t(), User.t(), String.t() | nil, boolean()) ::
{:ok, Activity.t()} | {:error, any()}
def follow(follower, followed, activity_id \\ nil, local \\ true) do

View file

@ -10,6 +10,8 @@ defmodule Pleroma.Web.ActivityPub.Builder do
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility
require Pleroma.Constants
@spec emoji_react(User.t(), Object.t(), String.t()) :: {:ok, map(), keyword()}
def emoji_react(actor, object, emoji) do
with {:ok, data, meta} <- object_action(actor, object) do
@ -83,9 +85,17 @@ defmodule Pleroma.Web.ActivityPub.Builder do
end
end
def announce(actor, object) do
def announce(actor, object, options \\ []) do
public? = Keyword.get(options, :public, false)
to = [actor.follower_address, object.data["actor"]]
to =
if public? do
[Pleroma.Constants.as_public() | to]
else
to
end
{:ok,
%{
"id" => Utils.generate_activity_id(),
@ -93,7 +103,8 @@ defmodule Pleroma.Web.ActivityPub.Builder do
"object" => object.data["id"],
"to" => to,
"context" => object.data["context"],
"type" => "Announce"
"type" => "Announce",
"published" => Utils.make_date()
}, []}
end

View file

@ -88,7 +88,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
def fetch_actor_and_object(object) do
fetch_actor(object)
Object.normalize(object["object"])
Object.normalize(object["object"], true)
:ok
end
end

View file

@ -18,9 +18,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
field(:type, :string)
field(:object, Types.ObjectID)
field(:actor, Types.ObjectID)
field(:context, :string)
field(:context, :string, autogenerate: {Utils, :generate_context_id, []})
field(:to, Types.Recipients, default: [])
field(:cc, Types.Recipients, default: [])
field(:published, Types.DateTime)
end
def cast_and_validate(data) do
@ -47,7 +48,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
def validate_data(data_cng) do
data_cng
|> validate_inclusion(:type, ["Announce"])
|> validate_required([:id, :type, :object, :actor, :context, :to, :cc])
|> validate_required([:id, :type, :object, :actor, :to, :cc])
|> validate_actor_presence()
|> validate_object_presence()
|> validate_existing_announce()

View file

@ -27,6 +27,18 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
{:ok, object, meta}
end
# Tasks this handles:
# - Add announce to object
# - Set up notification
def handle(%{data: %{"type" => "Announce"}} = object, meta) do
announced_object = Object.get_by_ap_id(object.data["object"])
Utils.add_announce_to_object(object, announced_object)
Notification.create_notifications(object)
{:ok, object, meta}
end
def handle(%{data: %{"type" => "Undo", "object" => undone_object}} = object, meta) do
with undone_object <- Activity.get_by_ap_id(undone_object),
:ok <- handle_undoing(undone_object) do

View file

@ -662,7 +662,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> handle_incoming(options)
end
def handle_incoming(%{"type" => type} = data, _options) when type in ["Like", "EmojiReact"] do
def handle_incoming(%{"type" => type} = data, _options)
when type in ["Like", "EmojiReact", "Announce"] do
with :ok <- ObjectValidator.fetch_actor_and_object(data),
{:ok, activity, _meta} <-
Pipeline.common_pipeline(data, local: false) do
@ -672,22 +673,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
end
def handle_incoming(
%{"type" => "Announce", "object" => object_id, "actor" => _actor, "id" => id} = data,
_options
) do
with actor <- Containment.get_actor(data),
{_, {:ok, %User{} = actor}} <- {:fetch_user, User.get_or_fetch_by_ap_id(actor)},
{_, {:ok, object}} <- {:get_embedded, get_embedded_obj_helper(object_id, actor)},
public <- Visibility.is_public?(data),
{_, {:ok, activity, _object}} <-
{:announce, ActivityPub.announce(actor, object, id, false, public)} do
{:ok, activity}
else
e -> {:error, e}
end
end
def handle_incoming(
%{"type" => "Update", "object" => %{"type" => object_type} = object, "actor" => actor_id} =
data,

View file

@ -127,18 +127,19 @@ defmodule Pleroma.Web.CommonAPI do
end
def repeat(id, user, params \\ %{}) do
with %Activity{data: %{"type" => "Create"}} = activity <- Activity.get_by_id(id) do
object = Object.normalize(activity)
announce_activity = Utils.get_existing_announce(user.ap_id, object)
public = public_announce?(object, params)
if announce_activity do
{:ok, announce_activity, object}
else
ActivityPub.announce(user, object, nil, true, public)
end
with %Activity{data: %{"type" => "Create"}} = activity <- Activity.get_by_id(id),
object = %Object{} <- Object.normalize(activity, false),
{_, nil} <- {:existing_announce, Utils.get_existing_announce(user.ap_id, object)},
public = public_announce?(object, params),
{:ok, announce, _} <- Builder.announce(user, object, public: public),
{:ok, activity, _} <- Pipeline.common_pipeline(announce, local: true) do
{:ok, activity}
else
_ -> {:error, :not_found}
{:existing_announce, %Activity{} = announce} ->
{:ok, announce}
_ ->
{:error, :not_found}
end
end