forked from AkkomaGang/akkoma
ActivityPub: Add undo for emoji reactions.
This commit is contained in:
parent
557223b2b5
commit
dfe5c958eb
4 changed files with 75 additions and 9 deletions
|
@ -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.
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue