ActivityPub: Add undo for emoji reactions.

This commit is contained in:
lain 2019-10-02 15:08:20 +02:00
parent 557223b2b5
commit dfe5c958eb
4 changed files with 75 additions and 9 deletions

View file

@ -319,11 +319,18 @@ def react_with_emoji(user, object, emoji, options \\ []) do
end end
end end
def unreact_with_emoji(user, reaction_id, option \\ []) do def unreact_with_emoji(user, reaction_id, options \\ []) do
with local <- Keyword.get(options, :local, true), with local <- Keyword.get(options, :local, true),
activity_id <- Keyword.get(options, :activity_id, nil), activity_id <- Keyword.get(options, :activity_id, nil),
%Activity{actor: ^user.ap_id} = reaction_activity <- Activity.get_by_ap_id(reaction_id), user_ap_id <- user.ap_id,
unreact_data %Activity{actor: ^user_ap_id} = reaction_activity <- Activity.get_by_ap_id(reaction_id),
object <- Object.normalize(reaction_activity),
unreact_data <- make_undo_data(user, reaction_activity, activity_id),
{:ok, activity} <- insert(unreact_data, local),
{:ok, object} <- remove_emoji_reaction_from_object(reaction_activity, object),
:ok <- maybe_federate(activity) do
{:ok, activity, object}
end
end end
# TODO: This is weird, maybe we shouldn't check here if we can make the activity. # TODO: This is weird, maybe we shouldn't check here if we can make the activity.

View file

@ -337,6 +337,24 @@ def add_emoji_reaction_to_object(
update_element_in_object("reaction", new_reactions, object) update_element_in_object("reaction", new_reactions, object)
end end
def remove_emoji_reaction_from_object(
%Activity{data: %{"content" => emoji, "actor" => actor}},
object
) do
reactions = object.data["reactions"] || %{}
emoji_actors = reactions[emoji] || []
new_emoji_actors = List.delete(emoji_actors, actor)
new_reactions =
if new_emoji_actors == [] do
Map.delete(reactions, emoji)
else
Map.put(reactions, emoji, new_emoji_actors)
end
update_element_in_object("reaction", new_reactions, object)
end
@spec add_like_to_object(Activity.t(), Object.t()) :: @spec add_like_to_object(Activity.t(), Object.t()) ::
{:ok, Object.t()} | {:error, Ecto.Changeset.t()} {:ok, Object.t()} | {:error, Ecto.Changeset.t()}
def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do
@ -522,6 +540,25 @@ def make_unlike_data(
|> maybe_put("id", activity_id) |> maybe_put("id", activity_id)
end end
def make_undo_data(
%User{ap_id: actor, follower_address: follower_address},
%Activity{
data: %{"id" => undone_activity_id, "context" => context},
actor: undone_activity_actor
},
activity_id \\ nil
) do
%{
"type" => "Undo",
"actor" => actor,
"object" => undone_activity_id,
"to" => [follower_address, undone_activity_actor],
"cc" => [Pleroma.Constants.as_public()],
"context" => context
}
|> maybe_put("id", activity_id)
end
@spec add_announce_to_object(Activity.t(), Object.t()) :: @spec add_announce_to_object(Activity.t(), Object.t()) ::
{:ok, Object.t()} | {:error, Ecto.Changeset.t()} {:ok, Object.t()} | {:error, Ecto.Changeset.t()}
def add_announce_to_object( def add_announce_to_object(

View file

@ -293,8 +293,6 @@ defmodule Pleroma.Web.Router do
end end
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
pipe_through(:authenticated_api)
scope [] do scope [] do
pipe_through(:authenticated_api) pipe_through(:authenticated_api)
pipe_through(:oauth_read) pipe_through(:oauth_read)

View file

@ -761,16 +761,40 @@ test "adds an emoji reaction activity to the db" do
end end
describe "unreacting to an object" do describe "unreacting to an object" do
test "adds an emoji reaction activity to the db" do test_with_mock "sends an activity to federation", Pleroma.Web.Federator, [:passthrough], [] do
Pleroma.Config.put([:instance, :federating], true)
user = insert(:user) user = insert(:user)
reactor = insert(:user) reactor = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"}) {:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
assert object = Object.normalize(activity) assert object = Object.normalize(activity)
{:ok, reaction_activity, object} = ActivityPub.react_with_emoji(reactor, object, "🔥") {:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
{:ok, unreaction_activity} = ActivityPub.unreact_with_emoji(reactor, reaction_activity.id)
IO.inspect(object) assert called(Pleroma.Web.Federator.publish(reaction_activity))
{:ok, unreaction_activity, _object} =
ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
assert called(Pleroma.Web.Federator.publish(unreaction_activity))
end
test "adds an undo activity to the db" do
user = insert(:user)
reactor = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "YASSSS queen slay"})
assert object = Object.normalize(activity)
{:ok, reaction_activity, _object} = ActivityPub.react_with_emoji(reactor, object, "🔥")
{:ok, unreaction_activity, _object} =
ActivityPub.unreact_with_emoji(reactor, reaction_activity.data["id"])
assert unreaction_activity.actor == reactor.ap_id
assert unreaction_activity.data["object"] == reaction_activity.data["id"]
object = Object.get_by_ap_id(object.data["id"])
assert object.data["reaction_count"] == 0
assert object.data["reactions"] == %{}
end end
end end