1 defmodule Pleroma.Web.ActivityPub.SideEffects do
3 This module looks at an inserted object and executes the side effects that it
4 implies. For example, a `Like` activity will increase the like count on the
5 liked object, a `Follow` activity will add the user to the follower
10 alias Pleroma.Chat.MessageReference
11 alias Pleroma.Notification
15 alias Pleroma.Web.ActivityPub.ActivityPub
16 alias Pleroma.Web.ActivityPub.Pipeline
17 alias Pleroma.Web.ActivityPub.Utils
18 alias Pleroma.Web.Push
19 alias Pleroma.Web.Streamer
21 def handle(object, meta \\ [])
25 def handle(%{data: %{"type" => "Update", "object" => updated_object}} = object, meta) do
26 {:ok, new_user_data} = ActivityPub.user_data_from_user_object(updated_object)
28 User.get_by_ap_id(updated_object["id"])
29 |> User.remote_user_changeset(new_user_data)
30 |> User.update_and_set_cache()
36 # - Add like to object
37 # - Set up notification
38 def handle(%{data: %{"type" => "Like"}} = object, meta) do
39 liked_object = Object.get_by_ap_id(object.data["object"])
40 Utils.add_like_to_object(object, liked_object)
42 Notification.create_notifications(object)
48 # - Actually create object
49 # - Rollback if we couldn't create it
50 # - Set up notifications
51 def handle(%{data: %{"type" => "Create"}} = activity, meta) do
52 with {:ok, _object, meta} <- handle_object_creation(meta[:object_data], meta) do
53 {:ok, notifications} = Notification.create_notifications(activity, do_send: false)
57 |> add_notifications(notifications)
66 # - Add announce to object
67 # - Set up notification
68 # - Stream out the announce
69 def handle(%{data: %{"type" => "Announce"}} = object, meta) do
70 announced_object = Object.get_by_ap_id(object.data["object"])
71 user = User.get_cached_by_ap_id(object.data["actor"])
73 Utils.add_announce_to_object(object, announced_object)
75 if !User.is_internal_user?(user) do
76 Notification.create_notifications(object)
77 ActivityPub.stream_out(object)
83 def handle(%{data: %{"type" => "Undo", "object" => undone_object}} = object, meta) do
84 with undone_object <- Activity.get_by_ap_id(undone_object),
85 :ok <- handle_undoing(undone_object) do
91 # - Add reaction to object
92 # - Set up notification
93 def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do
94 reacted_object = Object.get_by_ap_id(object.data["object"])
95 Utils.add_emoji_reaction_to_object(object, reacted_object)
97 Notification.create_notifications(object)
102 # Tasks this handles:
103 # - Delete and unpins the create activity
104 # - Replace object with Tombstone
105 # - Set up notification
106 # - Reduce the user note count
107 # - Reduce the reply count
108 # - Stream out the activity
109 def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do
111 Object.normalize(deleted_object, false) || User.get_cached_by_ap_id(deleted_object)
114 case deleted_object do
116 with {:ok, deleted_object, activity} <- Object.delete(deleted_object),
117 %User{} = user <- User.get_cached_by_ap_id(deleted_object.data["actor"]) do
118 User.remove_pinnned_activity(user, activity)
120 {:ok, user} = ActivityPub.decrease_note_count_if_public(user, deleted_object)
122 if in_reply_to = deleted_object.data["inReplyTo"] do
123 Object.decrease_replies_count(in_reply_to)
126 MessageReference.delete_for_object(deleted_object)
128 ActivityPub.stream_out(object)
129 ActivityPub.stream_out_participations(deleted_object, user)
134 with {:ok, _} <- User.delete(deleted_object) do
140 Notification.create_notifications(object)
148 def handle(object, meta) do
152 def handle_object_creation(%{"type" => "ChatMessage"} = object, meta) do
153 with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do
154 actor = User.get_cached_by_ap_id(object.data["actor"])
155 recipient = User.get_cached_by_ap_id(hd(object.data["to"]))
158 [[actor, recipient], [recipient, actor]]
159 |> Enum.map(fn [user, other_user] ->
161 {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id)
162 {:ok, cm_ref} = MessageReference.create(chat, object, user.ap_id != actor.ap_id)
165 ["user", "user:pleroma_chat"],
166 {user, %{cm_ref | chat: chat, object: object}}
174 |> add_streamables(streamables)
181 def handle_object_creation(object) do
185 def handle_undoing(%{data: %{"type" => "Like"}} = object) do
186 with %Object{} = liked_object <- Object.get_by_ap_id(object.data["object"]),
187 {:ok, _} <- Utils.remove_like_from_object(object, liked_object),
188 {:ok, _} <- Repo.delete(object) do
193 def handle_undoing(%{data: %{"type" => "EmojiReact"}} = object) do
194 with %Object{} = reacted_object <- Object.get_by_ap_id(object.data["object"]),
195 {:ok, _} <- Utils.remove_emoji_reaction_from_object(object, reacted_object),
196 {:ok, _} <- Repo.delete(object) do
201 def handle_undoing(%{data: %{"type" => "Announce"}} = object) do
202 with %Object{} = liked_object <- Object.get_by_ap_id(object.data["object"]),
203 {:ok, _} <- Utils.remove_announce_from_object(object, liked_object),
204 {:ok, _} <- Repo.delete(object) do
210 %{data: %{"type" => "Block", "actor" => blocker, "object" => blocked}} = object
212 with %User{} = blocker <- User.get_cached_by_ap_id(blocker),
213 %User{} = blocked <- User.get_cached_by_ap_id(blocked),
214 {:ok, _} <- User.unblock(blocker, blocked),
215 {:ok, _} <- Repo.delete(object) do
220 def handle_undoing(object), do: {:error, ["don't know how to handle", object]}
222 defp send_notifications(meta) do
223 Keyword.get(meta, :notifications, [])
224 |> Enum.each(fn notification ->
225 Streamer.stream(["user", "user:notification"], notification)
226 Push.send(notification)
232 defp send_streamables(meta) do
233 Keyword.get(meta, :streamables, [])
234 |> Enum.each(fn {topics, items} ->
235 Streamer.stream(topics, items)
241 defp add_streamables(meta, streamables) do
242 existing = Keyword.get(meta, :streamables, [])
245 |> Keyword.put(:streamables, streamables ++ existing)
248 defp add_notifications(meta, notifications) do
249 existing = Keyword.get(meta, :notifications, [])
252 |> Keyword.put(:notifications, notifications ++ existing)
255 def handle_after_transaction(meta) do
257 |> send_notifications()
258 |> send_streamables()