Add compatibility with bookwyrm's weird entities
authorFloatingGhost <hannah@coffee-and-dreams.uk>
Fri, 7 Jan 2022 16:51:04 +0000 (16:51 +0000)
committerFloatingGhost <hannah@coffee-and-dreams.uk>
Fri, 7 Jan 2022 16:51:04 +0000 (16:51 +0000)
lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
lib/pleroma/web/activity_pub/object_validators/tag_validator.ex
test/fixtures/bookwyrm-article.json [new file with mode: 0644]
test/fixtures/bookwyrm-replies-collection.json [new file with mode: 0644]
test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs

index 0aa249c4c1ea089847202ae709e06530aaf9e330..6beeca225d9de189d90c72ffaa05eeec1c0f52b8 100644 (file)
@@ -9,9 +9,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
   alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
   alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
   alias Pleroma.Web.ActivityPub.Transmogrifier
+  alias Pleroma.Object.Fetcher
 
   import Ecto.Changeset
 
+  require Logger
+
   @primary_key false
   @derive Jason.Encoder
 
@@ -63,6 +66,18 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
   defp fix_replies(%{"replies" => replies} = data) when is_bitstring(replies),
     do: Map.drop(data, ["replies"])
 
+  defp fix_replies(%{"replies" => %{"first" => first}} = data) do
+    with {:ok, %{"orderedItems" => replies}} <-
+           Fetcher.fetch_and_contain_remote_object_from_id(first) do
+      Map.put(data, "replies", replies)
+    else
+      {:error, e} ->
+        Logger.error("Could not fetch replies for #{first}")
+        IO.inspect(e)
+        Map.put(data, "replies", [])
+    end
+  end
+
   defp fix_replies(data), do: data
 
   defp fix(data) do
index 7510215851346810f3a86f1e33ae6ff1f7d39620..77aaf7f2962aef2bf2b7ecff4bd9517b6b5f0084 100644 (file)
@@ -68,6 +68,36 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.TagValidator do
     |> validate_required([:type, :name, :icon])
   end
 
+  def changeset(struct, %{"type" => "Book"} = data) do
+    data = Map.put(data, "name", data["title"])
+
+    struct
+    |> cast(data, [:type, :name])
+    |> validate_required([:type, :name])
+  end
+
+  def changeset(struct, %{"type" => "Edition"} = data) do
+    data = Map.put(data, "name", data["work"])
+
+    struct
+    |> cast(data, [:type, :name])
+    |> validate_required([:type, :name])
+  end
+
+  def changeset(struct, %{"type" => "Work"} = data) do
+    data = Map.put(data, "name", data["lccn"])
+
+    struct
+    |> cast(data, [:type, :name])
+    |> validate_required([:type, :name])
+  end
+
+  def changeset(struct, %{"type" => "Author"} = data) do
+    struct
+    |> cast(data, [:type, :name])
+    |> validate_required([:type, :name])
+  end
+
   def icon_changeset(struct, data) do
     struct
     |> cast(data, [:type, :url])
diff --git a/test/fixtures/bookwyrm-article.json b/test/fixtures/bookwyrm-article.json
new file mode 100644 (file)
index 0000000..66b34b6
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  "@context": "https://www.w3.org/ns/activitystreams",
+  "attachment": [
+    {
+      "id": null,
+      "name": "Death's End (The Three-Body Problem) (2018, Head of Zeus)",
+      "type": "Document",
+      "url": "https://bookwyrm.com/images/covers/e7a6a777-b3fa-44be-a819-33f3aa5187dd.jpeg"
+    }
+  ],
+  "attributedTo": "https://bookwyrm.com/user/TestUser",
+  "cc": [
+    "https://bookwyrm.com/user/TestUser/followers"
+  ],
+  "content": "<p>review</p>",
+  "id": "https://bookwyrm.com/user/TestUser/review/17",
+  "inReplyToBook": "https://bookwyrm.com/book/2",
+  "name": "Review of \"Death's End (The Three-Body Problem)\": ab",
+  "published": "2022-01-07T16:07:43.665392+00:00",
+  "replies": {
+    "@context": "https://www.w3.org/ns/activitystreams",
+    "first": "https://bookwyrm.com/user/TestUser/review/17/replies?page=1",
+    "id": "https://bookwyrm.com/user/TestUser/review/17/replies",
+    "last": "https://bookwyrm.com/user/TestUser/review/17/replies?page=1",
+    "totalItems": 0,
+    "type": "OrderedCollection"
+  },
+  "sensitive": false,
+  "tag": [],
+  "to": [
+    "https://www.w3.org/ns/activitystreams#Public"
+  ],
+  "type": "Article",
+  "updated": "2022-01-07T16:14:08.267337+00:00"
+}
diff --git a/test/fixtures/bookwyrm-replies-collection.json b/test/fixtures/bookwyrm-replies-collection.json
new file mode 100644 (file)
index 0000000..3f6d722
--- /dev/null
@@ -0,0 +1,41 @@
+{
+  "id": "https://bookwyrm.com/user/TestUser/review/17/replies?page=1",
+  "type": "OrderedCollectionPage",
+  "partOf": "https://bookwyrm.com/user/TestUser/review/17/replies",
+  "orderedItems": [
+    {
+      "id": "https://bookwyrm.com/user/TestUser/status/18",
+      "type": "Note",
+      "published": "2022-01-07T16:07:51.111523+00:00",
+      "attributedTo": "https://bookwyrm.com/user/TestUser",
+      "content": "<p>reply</p>",
+      "to": [
+        "https://www.w3.org/ns/activitystreams#Public"
+      ],
+      "cc": [
+        "https://bookwyrm.com/user/TestUser/followers",
+        "https://bookwyrm.com/user/TestUser"
+      ],
+      "replies": {
+        "id": "https://bookwyrm.com/user/TestUser/status/18/replies",
+        "type": "OrderedCollection",
+        "totalItems": 0,
+        "first": "https://bookwyrm.com/user/TestUser/status/18/replies?page=1",
+        "last": "https://bookwyrm.com/user/TestUser/status/18/replies?page=1",
+        "@context": "https://www.w3.org/ns/activitystreams"
+      },
+      "inReplyTo": "https://bookwyrm.com/user/TestUser/review/17",
+      "tag": [
+        {
+          "href": "https://bookwyrm.com/user/TestUser",
+          "name": "TestUser@bookwyrm.com",
+          "type": "Mention"
+        }
+      ],
+      "attachment": [],
+      "sensitive": false,
+      "@context": "https://www.w3.org/ns/activitystreams"
+    }
+  ],
+  "@context": "https://www.w3.org/ns/activitystreams"
+}
index 720c17d8da7e731da5c134dfce4699c274ecf48e..2bd1e46c131376f719a5c3ede92940c4e99779cf 100644 (file)
@@ -31,5 +31,26 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
     test "a basic note validates", %{note: note} do
       %{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
     end
+
+    test "a note with a remote replies collection should validate", _ do
+      insert(:user, %{ap_id: "https://bookwyrm.com/user/TestUser"})
+      collection = File.read!("test/fixtures/bookwyrm-replies-collection.json")
+
+      Tesla.Mock.mock(fn %{
+                           method: :get,
+                           url: "https://bookwyrm.com/user/TestUser/review/17/replies?page=1"
+                         } ->
+        %Tesla.Env{
+          status: 200,
+          body: collection,
+          headers: HttpRequestMock.activitypub_object_headers()
+        }
+      end)
+
+      note = Jason.decode!(File.read!("test/fixtures/bookwyrm-article.json"))
+
+      %{valid?: true, changes: %{replies: ["https://bookwyrm.com/user/TestUser/status/18"]}} =
+        ArticleNotePageValidator.cast_and_validate(note)
+    end
   end
 end