Merge branch 'finmoji-optional' into 'develop'
[akkoma] / lib / pleroma / web / activity_pub / utils.ex
index 8b41a3becbb26cad7af645d8bd6480316bd2a8c0..266667f8109720ee05ae35374800147eaddf3b31 100644 (file)
@@ -19,6 +19,48 @@ defmodule Pleroma.Web.ActivityPub.Utils do
     Map.put(params, "actor", get_ap_id(params["actor"]))
   end
 
+  defp recipient_in_collection(ap_id, coll) when is_binary(coll), do: ap_id == coll
+  defp recipient_in_collection(ap_id, coll) when is_list(coll), do: ap_id in coll
+  defp recipient_in_collection(_, _), do: false
+
+  def recipient_in_message(ap_id, params) do
+    cond do
+      recipient_in_collection(ap_id, params["to"]) ->
+        true
+
+      recipient_in_collection(ap_id, params["cc"]) ->
+        true
+
+      recipient_in_collection(ap_id, params["bto"]) ->
+        true
+
+      recipient_in_collection(ap_id, params["bcc"]) ->
+        true
+
+      true ->
+        false
+    end
+  end
+
+  defp extract_list(target) when is_binary(target), do: [target]
+  defp extract_list(lst) when is_list(lst), do: lst
+  defp extract_list(_), do: []
+
+  def maybe_splice_recipient(ap_id, params) do
+    need_splice =
+      !recipient_in_collection(ap_id, params["to"]) &&
+        !recipient_in_collection(ap_id, params["cc"])
+
+    cc_list = extract_list(params["cc"])
+
+    if need_splice do
+      params
+      |> Map.put("cc", [ap_id | cc_list])
+    else
+      params
+    end
+  end
+
   def make_json_ld_header do
     %{
       "@context" => [
@@ -128,7 +170,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
   Inserts a full object if it is contained in an activity.
   """
   def insert_full_object(%{"object" => %{"type" => type} = object_data})
-      when is_map(object_data) and type in ["Article", "Note"] do
+      when is_map(object_data) and type in ["Article", "Note", "Video"] do
     with {:ok, _} <- Object.create(object_data) do
       :ok
     end
@@ -204,13 +246,17 @@ defmodule Pleroma.Web.ActivityPub.Utils do
   end
 
   def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do
-    with likes <- [actor | object.data["likes"] || []] |> Enum.uniq() do
+    likes = if is_list(object.data["likes"]), do: object.data["likes"], else: []
+
+    with likes <- [actor | likes] |> Enum.uniq() do
       update_likes_in_object(likes, object)
     end
   end
 
   def remove_like_from_object(%Activity{data: %{"actor" => actor}}, object) do
-    with likes <- (object.data["likes"] || []) |> List.delete(actor) do
+    likes = if is_list(object.data["likes"]), do: object.data["likes"], else: []
+
+    with likes <- likes |> List.delete(actor) do
       update_likes_in_object(likes, object)
     end
   end
@@ -243,11 +289,11 @@ defmodule Pleroma.Web.ActivityPub.Utils do
       "actor" => follower_id,
       "to" => [followed_id],
       "cc" => ["https://www.w3.org/ns/activitystreams#Public"],
-      "object" => followed_id
+      "object" => followed_id,
+      "state" => "pending"
     }
 
     data = if activity_id, do: Map.put(data, "id", activity_id), else: data
-    data = if User.locked?(followed), do: Map.put(data, "state", "pending"), else: data
 
     data
   end
@@ -302,6 +348,24 @@ defmodule Pleroma.Web.ActivityPub.Utils do
   @doc """
   Make announce activity data for the given actor and object
   """
+  # for relayed messages, we only want to send to subscribers
+  def make_announce_data(
+        %User{ap_id: ap_id, nickname: nil} = user,
+        %Object{data: %{"id" => id}} = object,
+        activity_id
+      ) do
+    data = %{
+      "type" => "Announce",
+      "actor" => ap_id,
+      "object" => id,
+      "to" => [user.follower_address],
+      "cc" => [],
+      "context" => object.data["context"]
+    }
+
+    if activity_id, do: Map.put(data, "id", activity_id), else: data
+  end
+
   def make_announce_data(
         %User{ap_id: ap_id} = user,
         %Object{data: %{"id" => id}} = object,
@@ -356,14 +420,27 @@ defmodule Pleroma.Web.ActivityPub.Utils do
     if activity_id, do: Map.put(data, "id", activity_id), else: data
   end
 
-  def add_announce_to_object(%Activity{data: %{"actor" => actor}}, object) do
-    with announcements <- [actor | object.data["announcements"] || []] |> Enum.uniq() do
+  def add_announce_to_object(
+        %Activity{
+          data: %{"actor" => actor, "cc" => ["https://www.w3.org/ns/activitystreams#Public"]}
+        },
+        object
+      ) do
+    announcements =
+      if is_list(object.data["announcements"]), do: object.data["announcements"], else: []
+
+    with announcements <- [actor | announcements] |> Enum.uniq() do
       update_element_in_object("announcement", announcements, object)
     end
   end
 
+  def add_announce_to_object(_, object), do: {:ok, object}
+
   def remove_announce_from_object(%Activity{data: %{"actor" => actor}}, object) do
-    with announcements <- (object.data["announcements"] || []) |> List.delete(actor) do
+    announcements =
+      if is_list(object.data["announcements"]), do: object.data["announcements"], else: []
+
+    with announcements <- announcements |> List.delete(actor) do
       update_element_in_object("announcement", announcements, object)
     end
   end