diff options
Diffstat (limited to 'lib/pleroma/web/activity_pub')
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 11 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 25 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/utils.ex | 33 |
3 files changed, 67 insertions, 2 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index d23ec66ac..74663ac97 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -312,6 +312,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end end + def react_with_emoji(user, object, emoji, options \\ []) do + with local <- Keyword.get(options, :local, true), + activity_id <- Keyword.get(options, :activity_id, nil), + Pleroma.Emoji.is_unicode_emoji?(emoji), + reaction_data <- make_emoji_reaction_data(user, object, emoji, activity_id), + {:ok, activity} <- insert(reaction_data, local), + {:ok, object} <- add_emoji_reaction_to_object(activity, object) do + {:ok, activity, object} + end + end + # TODO: This is weird, maybe we shouldn't check here if we can make the activity. def like( %User{ap_id: ap_id} = user, diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 350b83abb..cb5755ccc 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -575,6 +575,27 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end def handle_incoming( + %{ + "type" => "EmojiReaction", + "object" => object_id, + "actor" => _actor, + "id" => id, + "content" => emoji + } = data, + _options + ) do + with actor <- Containment.get_actor(data), + {:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor), + {:ok, object} <- get_obj_helper(object_id), + {:ok, activity, _object} <- + ActivityPub.react_with_emoji(actor, object, emoji, activity_id: id, local: false) do + {:ok, activity} + else + _e -> :error + end + end + + def handle_incoming( %{"type" => "Announce", "object" => object_id, "actor" => _actor, "id" => id} = data, _options ) do @@ -976,9 +997,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> Map.put("attachment", attachments) end - defp strip_internal_fields(object) do + def strip_internal_fields(object) do object |> Map.drop([ + "reactions", + "reaction_count", "likes", "like_count", "announcements", diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index c9c0c3763..95e040c6c 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -277,6 +277,12 @@ defmodule Pleroma.Web.ActivityPub.Utils do |> Repo.all() end + def make_emoji_reaction_data(user, object, emoji, activity_id) do + make_like_data(user, object, activity_id) + |> Map.put("type", "EmojiReaction") + |> Map.put("content", emoji) + end + @spec make_like_data(User.t(), map(), String.t()) :: map() def make_like_data( %User{ap_id: ap_id} = actor, @@ -311,10 +317,21 @@ defmodule Pleroma.Web.ActivityPub.Utils do @spec update_element_in_object(String.t(), list(any), Object.t()) :: {:ok, Object.t()} | {:error, Ecto.Changeset.t()} def update_element_in_object(property, element, object) do + length = + if is_map(element) do + element + |> Map.values() + |> List.flatten() + |> length() + else + element + |> length() + end + data = Map.merge( object.data, - %{"#{property}_count" => length(element), "#{property}s" => element} + %{"#{property}_count" => length, "#{property}s" => element} ) object @@ -322,6 +339,20 @@ defmodule Pleroma.Web.ActivityPub.Utils do |> Object.update_and_set_cache() end + @spec add_emoji_reaction_to_object(Activity.t(), Object.t()) :: + {:ok, Object.t()} | {:error, Ecto.Changeset.t()} + + def add_emoji_reaction_to_object( + %Activity{data: %{"content" => emoji, "actor" => actor}}, + object + ) do + reactions = object.data["reactions"] || %{} + emoji_actors = reactions[emoji] || [] + new_emoji_actors = [actor | emoji_actors] |> Enum.uniq() + new_reactions = Map.put(reactions, emoji, new_emoji_actors) + update_element_in_object("reaction", new_reactions, object) + end + @spec add_like_to_object(Activity.t(), Object.t()) :: {:ok, Object.t()} | {:error, Ecto.Changeset.t()} def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do |