From 77c6c424a66b4bfc418e43054eaa695ae3e22231 Mon Sep 17 00:00:00 2001 From: lain Date: Sun, 18 Feb 2018 11:24:54 +0100 Subject: [PATCH] ActivityPub: Make fake Create activities for objects without one. --- lib/pleroma/web/activity_pub/activity_pub.ex | 11 ++++++++-- .../web/activity_pub/transmogrifier.ex | 7 ++++++- test/web/activity_pub/activity_pub_test.exs | 6 +++++- test/web/activity_pub/transmogrifier_test.exs | 20 +++++++++++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 7c9ddcfe7..a5e8b98e9 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -273,6 +273,8 @@ def publish(actor, activity) 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 @@ def fetch_object_from_id(id) 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 diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 1dc86fa85..62e43526e 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -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 @@ def handle_incoming(%{"type" => "Like", "object" => object_id, "actor" => actor, 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 @@ def handle_incoming(%{"type" => "Announce", "object" => object_id, "actor" => ac 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 diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index be81e75aa..1debdddd4 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -266,8 +266,12 @@ test "fetches the latest Follow activity" 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 diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 1728360ea..a39f4c139 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -72,6 +72,26 @@ test "it works for incoming announces" 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