Encapsulation of tags / hashtags fetching from objects.
authorIvan Tashkinov <ivantashkinov@gmail.com>
Mon, 21 Dec 2020 19:54:26 +0000 (22:54 +0300)
committerIvan Tashkinov <ivantashkinov@gmail.com>
Mon, 21 Dec 2020 19:54:26 +0000 (22:54 +0300)
12 files changed:
lib/pleroma/activity/ir/topics.ex
lib/pleroma/object.ex
lib/pleroma/web/activity_pub/mrf/simple_policy.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
lib/pleroma/web/feed/feed_view.ex
lib/pleroma/web/mastodon_api/views/status_view.ex
lib/pleroma/web/templates/feed/feed/_activity.atom.eex
lib/pleroma/web/templates/feed/feed/_activity.rss.eex
lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs
test/pleroma/web/common_api_test.exs
test/pleroma/web/mastodon_api/views/status_view_test.exs

index fe2e8cb5c900d7b84f0e92bc1ba42a74c85d685b..2c74ac2bf9459912dd660b9a6531db66aa69e5d7 100644 (file)
@@ -48,14 +48,12 @@ defmodule Pleroma.Activity.Ir.Topics do
     tags
   end
 
-  defp hashtags_to_topics(%{data: %{"tag" => tags}}) do
-    tags
-    |> Enum.filter(&is_bitstring(&1))
-    |> Enum.map(fn tag -> "hashtag:" <> tag end)
+  defp hashtags_to_topics(object) do
+    object
+    |> Object.hashtags()
+    |> Enum.map(fn hashtag -> "hashtag:" <> hashtag end)
   end
 
-  defp hashtags_to_topics(_), do: []
-
   defp remote_topics(%{local: true}), do: []
 
   defp remote_topics(%{actor: actor}) when is_binary(actor),
index 052ad413bd6c7b2897b3b5823a60f1b884f96394..2088c765615ed7fc1e352371adcf315504f6156c 100644 (file)
@@ -47,17 +47,33 @@ defmodule Pleroma.Object do
   end
 
   def create(data) do
-    Object.change(%Object{}, %{data: data})
+    %Object{}
+    |> Object.change(%{data: data})
     |> Repo.insert()
   end
 
   def change(struct, params \\ %{}) do
-    struct
-    |> cast(params, [:data])
-    |> validate_required([:data])
-    |> unique_constraint(:ap_id, name: :objects_unique_apid_index)
+    changeset =
+      struct
+      |> cast(params, [:data])
+      |> validate_required([:data])
+      |> unique_constraint(:ap_id, name: :objects_unique_apid_index)
+
+    if hashtags_changed?(struct, get_change(changeset, :data)) do
+      # TODO: modify assoc once it's introduced
+      changeset
+    else
+      changeset
+    end
+  end
+
+  defp hashtags_changed?(%Object{} = struct, %{"tag" => _} = data) do
+    Enum.sort(embedded_hashtags(struct)) !=
+      Enum.sort(object_data_hashtags(data))
   end
 
+  defp hashtags_changed?(_, _), do: false
+
   def get_by_id(nil), do: nil
   def get_by_id(id), do: Repo.get(Object, id)
 
@@ -344,4 +360,23 @@ defmodule Pleroma.Object do
 
   def self_replies(object, opts \\ []),
     do: replies(object, Keyword.put(opts, :self_only, true))
+
+  def tags(%Object{data: %{"tag" => tags}}) when is_list(tags), do: tags
+
+  def tags(_), do: []
+
+  def hashtags(object), do: embedded_hashtags(object)
+
+  defp embedded_hashtags(%Object{data: data}) do
+    object_data_hashtags(data)
+  end
+
+  defp embedded_hashtags(_), do: []
+
+  defp object_data_hashtags(%{"tag" => tags}) when is_list(tags) do
+    # Note: AS2 map-type elements are ignored
+    Enum.filter(tags, &is_bitstring(&1))
+  end
+
+  defp object_data_hashtags(_), do: []
 end
index 6cd91826db178ba72f9cc0859fe7eac5c7397eca..e92091d6687959f7f294f5fa5eacda2de7ea2cec 100644 (file)
@@ -74,9 +74,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
 
     object =
       if MRF.subdomain_match?(media_nsfw, actor_host) do
-        tags = (child_object["tag"] || []) ++ ["nsfw"]
-        child_object = Map.put(child_object, "tag", tags)
-        child_object = Map.put(child_object, "sensitive", true)
+        child_object =
+          child_object
+          |> Map.put("tag", (child_object["tag"] || []) ++ ["nsfw"])
+          |> Map.put("sensitive", true)
+
         Map.put(object, "object", child_object)
       else
         object
index 565d324330b751ca35bc65dfbdb3589e993f6a4c..fd17793d016489e61e9a973adf9e33dd99443ed6 100644 (file)
@@ -32,18 +32,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   """
   def fix_object(object, options \\ []) do
     object
-    |> strip_internal_fields
-    |> fix_actor
-    |> fix_url
-    |> fix_attachments
-    |> fix_context
+    |> strip_internal_fields()
+    |> fix_actor()
+    |> fix_url()
+    |> fix_attachments()
+    |> fix_context()
     |> fix_in_reply_to(options)
-    |> fix_emoji
-    |> fix_tag
-    |> set_sensitive
-    |> fix_content_map
-    |> fix_addressing
-    |> fix_summary
+    |> fix_emoji()
+    |> fix_tag()
+    |> set_sensitive()
+    |> fix_content_map()
+    |> fix_addressing()
+    |> fix_summary()
     |> fix_type(options)
   end
 
@@ -315,10 +315,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     tags =
       tag
       |> Enum.filter(fn data -> data["type"] == "Hashtag" and data["name"] end)
-      |> Enum.map(fn %{"name" => name} ->
-        name
-        |> String.slice(1..-1)
-        |> String.downcase()
+      |> Enum.map(fn
+        %{"name" => "#" <> hashtag} -> String.downcase(hashtag)
+        %{"name" => hashtag} -> String.downcase(hashtag)
       end)
 
     Map.put(object, "tag", tag ++ tags)
index 30e0a2a55b69228b470ed0a35a8111ff80c6149e..1155c6a398e6db0ce183a7dcf07ee95588cf48db 100644 (file)
@@ -32,6 +32,7 @@ defmodule Pleroma.Web.Feed.FeedView do
 
     %{
       activity: activity,
+      object: object,
       data: Map.get(object, :data),
       actor: actor
     }
index 2301e21cfaf2d56b760fe35fa733dd2be502eeba..bd08aa2031c47895568e9ffea30a5d999e1766ec 100644 (file)
@@ -201,8 +201,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
     like_count = object.data["like_count"] || 0
     announcement_count = object.data["announcement_count"] || 0
 
-    tags = object.data["tag"] || []
-    sensitive = object.data["sensitive"] || Enum.member?(tags, "nsfw")
+    hashtags = Object.hashtags(object)
+    sensitive = object.data["sensitive"] || Enum.member?(hashtags, "nsfw")
+
+    tags = Object.tags(object)
 
     tag_mentions =
       tags
index 3fd150c4e7570b6d54e449a87ffac7d1adc74d7a..6688830baa954d081ac736703fe870e514535259 100644 (file)
@@ -22,7 +22,7 @@
     <link type="text/html" href='<%= @data["external_url"] %>' rel="alternate"/>
   <% end %>
 
-  <%= for tag <- @data["tag"] || [] do %>
+  <%= for tag <- Pleroma.Object.hashtags(@object) do %>
     <category term="<%= tag %>"></category>
   <% end %>
 
index 42960de7d45f58926546a23145a8d1db60ad108f..fc6d74b42f1d9aab417d6e99f5eb9a57085c106d 100644 (file)
@@ -21,7 +21,7 @@
     <link><%= @data["external_url"] %></link>
   <% end %>
 
-  <%= for tag <- @data["tag"] || [] do %>
+  <%= for tag <- Pleroma.Object.hashtags(@object) do %>
     <category term="<%= tag %>"></category>
   <% end %>
 
index cf5874a91341cb8108631829aa150ec9fd70e15b..c2de28fe48888bea7d8f3fc8c71d6a576cc5a89b 100644 (file)
@@ -41,7 +41,7 @@
       <% end %>
     <% end %>
 
-    <%= for tag <- @data["tag"] || [] do %>
+    <%= for tag <- Pleroma.Object.hashtags(@object) do %>
       <category term="<%= tag %>"></category>
     <% end %>
 
index b4a006aec7f75048b26d17b64a184f90fb2b5837..a33959d9fa8c606e4b3b78fe55194cfff89fe12a 100644 (file)
@@ -39,7 +39,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
       {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
       object = Object.normalize(data["object"])
 
-      assert "test" in object.data["tag"]
+      assert "test" in Object.tags(object)
+      assert Object.hashtags(object) == ["test"]
     end
 
     test "it cleans up incoming notices which are not really DMs" do
@@ -220,7 +221,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
       {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
       object = Object.normalize(data["object"])
 
-      assert Enum.at(object.data["tag"], 2) == "moo"
+      assert Enum.at(Object.tags(object), 2) == "moo"
+      assert Object.hashtags(object) == ["moo"]
     end
 
     test "it works for incoming notices with contentMap" do
index 585b2c174c9564c4aa2ccb408c7847f39374b671..1e98208fb8d996b3268bf0ec7da3de71b9c4a57d 100644 (file)
@@ -493,7 +493,7 @@ defmodule Pleroma.Web.CommonAPITest do
 
     object = Object.normalize(activity)
 
-    assert object.data["tag"] == ["2hu"]
+    assert Object.tags(object) == ["2hu"]
   end
 
   test "it adds emoji in the object" do
index f2a7469edb436ab1459d26572b4ec6278cdfb041..6b8afc960a900e6135821a5a10668b97a6c6c2be 100644 (file)
@@ -262,8 +262,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
       mentions: [],
       tags: [
         %{
-          name: "#{object_data["tag"]}",
-          url: "/tag/#{object_data["tag"]}"
+          name: "#{hd(object_data["tag"])}",
+          url: "/tag/#{hd(object_data["tag"])}"
         }
       ],
       application: %{