Create Object.hashtags/1 wrapper
[akkoma] / lib / pleroma / web / activity_pub / transmogrifier.ex
index 8fe430644de3c23eff23492e73d97fcf8a9f0d60..36ef6a454e54a0cc8ca38c0844532f3a68836a43 100644 (file)
@@ -7,7 +7,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   A module to handle coding from internal to wire ActivityPub and back.
   """
   alias Pleroma.Activity
-  alias Pleroma.EarmarkRenderer
   alias Pleroma.EctoType.ActivityPub.ObjectValidators
   alias Pleroma.Maps
   alias Pleroma.Object
@@ -41,11 +40,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     |> fix_in_reply_to(options)
     |> fix_emoji
     |> fix_tag
+    |> set_sensitive
     |> fix_content_map
     |> fix_addressing
     |> fix_summary
     |> fix_type(options)
-    |> fix_content
   end
 
   def fix_summary(%{"summary" => nil} = object) do
@@ -253,6 +252,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
           }
           |> Maps.put_if_present("mediaType", media_type)
           |> Maps.put_if_present("name", data["name"])
+          |> Maps.put_if_present("blurhash", data["blurhash"])
         else
           nil
         end
@@ -274,24 +274,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     Map.put(object, "url", url["href"])
   end
 
-  def fix_url(%{"type" => "Video", "url" => url} = object) when is_list(url) do
-    attachment =
-      Enum.find(url, fn x ->
-        media_type = x["mediaType"] || x["mimeType"] || ""
-
-        is_map(x) and String.starts_with?(media_type, "video/")
-      end)
-
-    link_element =
-      Enum.find(url, fn x -> is_map(x) and (x["mediaType"] || x["mimeType"]) == "text/html" end)
-
-    object
-    |> Map.put("attachment", [attachment])
-    |> Map.put("url", link_element["href"])
-  end
-
-  def fix_url(%{"type" => object_type, "url" => url} = object)
-      when object_type != "Video" and is_list(url) do
+  def fix_url(%{"url" => url} = object) when is_list(url) do
     first_element = Enum.at(url, 0)
 
     url_string =
@@ -329,22 +312,23 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   def fix_emoji(object), do: object
 
   def fix_tag(%{"tag" => tag} = object) when is_list(tag) do
-    tags =
+    hashtags =
       tag
       |> Enum.filter(fn data -> data["type"] == "Hashtag" and data["name"] end)
-      |> Enum.map(fn data -> String.slice(data["name"], 1..-1) end)
+      |> Enum.map(fn
+        %{"name" => "#" <> hashtag} -> String.downcase(hashtag)
+        %{"name" => hashtag} -> String.downcase(hashtag)
+      end)
 
-    Map.put(object, "tag", tag ++ tags)
+    Map.put(object, "hashtags", hashtags)
   end
 
-  def fix_tag(%{"tag" => %{"type" => "Hashtag", "name" => hashtag} = tag} = object) do
-    combined = [tag, String.slice(hashtag, 1..-1)]
-
-    Map.put(object, "tag", combined)
+  def fix_tag(%{"tag" => %{} = tag} = object) do
+    object
+    |> Map.put("tag", [tag])
+    |> fix_tag
   end
 
-  def fix_tag(%{"tag" => %{} = tag} = object), do: Map.put(object, "tag", [tag])
-
   def fix_tag(object), do: object
 
   # content map usually only has one language so this will do for now.
@@ -371,18 +355,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
 
   def fix_type(object, _), do: object
 
-  defp fix_content(%{"mediaType" => "text/markdown", "content" => content} = object)
-       when is_binary(content) do
-    html_content =
-      content
-      |> Earmark.as_html!(%Earmark.Options{renderer: EarmarkRenderer})
-      |> Pleroma.HTML.filter_tags()
-
-    Map.merge(object, %{"content" => html_content, "mediaType" => "text/html"})
-  end
-
-  defp fix_content(object), do: object
-
   # Reduce the object list to find the reported user.
   defp get_reported(objects) do
     Enum.reduce_while(objects, nil, fn ap_id, _ ->
@@ -455,7 +427,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
         %{"type" => "Create", "object" => %{"type" => objtype} = object} = data,
         options
       )
-      when objtype in ~w{Article Note Video Page} do
+      when objtype in ~w{Note Page} do
     actor = Containment.get_actor(data)
 
     with nil <- Activity.get_create_by_object_ap_id(object["id"]),
@@ -546,13 +518,19 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   end
 
   def handle_incoming(
-        %{"type" => "Create", "object" => %{"type" => objtype}} = data,
+        %{"type" => "Create", "object" => %{"type" => objtype, "id" => obj_id}} = data,
         _options
       )
-      when objtype in ~w{Question Answer ChatMessage Audio Event} do
+      when objtype in ~w{Question Answer ChatMessage Audio Video Event Article} do
+    data = Map.put(data, "object", strip_internal_fields(data["object"]))
+
     with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
+         nil <- Activity.get_create_by_object_ap_id(obj_id),
          {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
       {:ok, activity}
+    else
+      %Activity{} = activity -> {:ok, activity}
+      e -> e
     end
   end
 
@@ -885,23 +863,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   def maybe_fix_object_url(data), do: data
 
   def add_hashtags(object) do
-    tags =
-      (object["tag"] || [])
-      |> Enum.map(fn
-        # Expand internal representation tags into AS2 tags.
-        tag when is_binary(tag) ->
-          %{
-            "href" => Pleroma.Web.Endpoint.url() <> "/tags/#{tag}",
-            "name" => "##{tag}",
-            "type" => "Hashtag"
-          }
-
-        # Do not process tags which are already AS2 tag objects.
-        tag when is_map(tag) ->
-          tag
+    hashtags =
+      object
+      |> Object.hashtags()
+      |> Enum.map(fn tag ->
+        %{
+          "href" => Pleroma.Web.Endpoint.url() <> "/tags/#{tag}",
+          "name" => "##{tag}",
+          "type" => "Hashtag"
+        }
       end)
 
-    Map.put(object, "tag", tags)
+    Map.put(object, "tag", hashtags ++ (object["tag"] || []))
   end
 
   # TODO These should be added on our side on insertion, it doesn't make much
@@ -952,12 +925,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     Map.put(object, "conversation", object["context"])
   end
 
-  def set_sensitive(%{"sensitive" => true} = object) do
+  def set_sensitive(%{"sensitive" => _} = object) do
     object
   end
 
   def set_sensitive(object) do
-    tags = object["tag"] || []
+    tags = object["hashtags"] || object["tag"] || []
     Map.put(object, "sensitive", "nsfw" in tags)
   end