ActivityPub: Make fake Create activities for objects without one.
authorlain <lain@soykaf.club>
Sun, 18 Feb 2018 10:24:54 +0000 (11:24 +0100)
committerlain <lain@soykaf.club>
Sun, 18 Feb 2018 10:24:54 +0000 (11:24 +0100)
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
test/web/activity_pub/activity_pub_test.exs
test/web/activity_pub/transmogrifier_test.exs

index 7c9ddcfe750de84bd604d218e7d2b17c31e9d6a3..a5e8b98e9f27c49e64fc7bd4e3d51c8618c0b75e 100644 (file)
@@ -273,6 +273,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     end
   end
 
+  # TODO:
+  # This will create a Create activity, which we need internally at the moment.
   def fetch_object_from_id(id) do
     if object = Object.get_cached_by_ap_id(id) do
       {:ok, object}
@@ -280,8 +282,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
       with {:ok, %{body: body, status_code: code}} when code in 200..299 <- @httpoison.get(id, [Accept: "application/activity+json"], follow_redirect: true, timeout: 10000, recv_timeout: 20000),
            {:ok, data} <- Poison.decode(body),
            data <- Transmogrifier.fix_object(data),
-           %User{} <- User.get_or_fetch_by_ap_id(data["attributedTo"]) do
-        Object.create(data)
+           nil <- Object.get_by_ap_id(data["id"]),
+           %User{} = user <- User.get_or_fetch_by_ap_id(data["attributedTo"]),
+           {:ok, activity} = create(%{to: data["to"], actor: user, context: data["context"], object: data, local: false, additional: %{"cc" => data["cc"]}}) do
+        {:ok, Object.get_by_ap_id(activity.data["object"]["id"])}
+      else
+        object = %Object{} -> {:ok, object}
+        e -> e
       end
     end
   end
index 1dc86fa8538802009c69957cecd00cf79261a4b2..62e43526ec55f0fc30a6a5b9ed8e364d98815d01 100644 (file)
@@ -4,6 +4,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   """
   alias Pleroma.User
   alias Pleroma.Object
+  alias Pleroma.Activity
   alias Pleroma.Web.ActivityPub.ActivityPub
 
   @doc """
@@ -75,7 +76,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
 
   def handle_incoming(%{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data) do
     with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
-         {:ok, object} <- ActivityPub.fetch_object_from_id(object_id),
+         {:ok, object} <- get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
          {:ok, activity, object} <- ActivityPub.announce(actor, object, id, false) do
       {:ok, activity}
     else
@@ -89,6 +90,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
 
   def handle_incoming(_), do: :error
 
+  def get_obj_helper(id) do
+    if object = Object.get_by_ap_id(id), do: {:ok, object}, else: nil
+  end
+
   @doc
   """
   internal -> Mastodon
index be81e75aa5d7c73f2e5b7928abecfb98991d1905..1debdddd4b880bc744db9b2bd257e55cced0a5d8 100644 (file)
@@ -266,8 +266,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
   end
 
   describe "fetching an object" do
-    test "it fetches an existing object" do
+    test "it fetches an object" do
       {:ok, object} = ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
+      assert Activity.get_create_activity_by_object_ap_id(object.data["id"])
+      {:ok, object_again} = ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
+
+      assert object == object_again
     end
   end
 
index 1728360eaecd811c2131db9b367c4c52d5bcae45..a39f4c1390069c97f2c93b9f709a66c1bc180ffa 100644 (file)
@@ -72,6 +72,26 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       assert data["type"] == "Announce"
       assert data["id"] == "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
       assert data["object"] == "http://mastodon.example.org/users/admin/statuses/99541947525187367"
+
+      assert Activity.get_create_activity_by_object_ap_id(data["object"])
+    end
+
+    test "it works for incoming announces with an existing activity" do
+      user = insert(:user)
+      {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
+
+      data = File.read!("test/fixtures/mastodon-announce.json")
+      |> Poison.decode!
+      |> Map.put("object", activity.data["object"]["id"])
+
+      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+      assert data["actor"] == "http://mastodon.example.org/users/admin"
+      assert data["type"] == "Announce"
+      assert data["id"] == "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
+      assert data["object"] == activity.data["object"]["id"]
+
+      assert Activity.get_create_activity_by_object_ap_id(data["object"]).id == activity.id
     end
   end