commit: fe2d4778eee5e8b4fe24f8e1d16d1065e9430027
parent 72ac940618efe56e14f02e23e5af75ae275a5c26
Author: Tusooa Zhu <tusooa@kazv.moe>
Date:   Sat,  4 Jun 2022 12:56:56 -0400
Expose content type of status sources
Diffstat:
6 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/docs/development/API/differences_in_mastoapi_responses.md b/docs/development/API/differences_in_mastoapi_responses.md
@@ -40,6 +40,10 @@ Has these additional fields under the `pleroma` object:
 - `parent_visible`: If the parent of this post is visible to the user or not.
 - `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise.
 
+The `GET /api/v1/statuses/:id/source` endpoint additionally has the following attributes:
+
+- `content_type`: The content type of the status source.
+
 ## Scheduled statuses
 
 Has these additional fields in `params`:
diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex
@@ -761,6 +761,10 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
             type: :string,
             description:
               "Subject or summary line, below which status content is collapsed until expanded"
+          },
+          content_type: %Schema{
+            type: :string,
+            description: "The content type of the source"
           }
         }
       }
diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex
@@ -224,7 +224,10 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
     object =
       note_data
       |> Map.put("emoji", emoji)
-      |> Map.put("source", draft.status)
+      |> Map.put("source", %{
+        "content" => draft.status,
+        "mediaType" => Utils.get_content_type(draft.params[:content_type])
+      })
       |> Map.put("generator", draft.params[:generator])
 
     %__MODULE__{draft | object: object}
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
@@ -219,7 +219,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
     |> maybe_add_attachments(draft.attachments, attachment_links)
   end
 
-  defp get_content_type(content_type) do
+  def get_content_type(content_type) do
     if Enum.member?(Config.get([:instance, :allowed_post_formats]), content_type) do
       content_type
     else
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -354,7 +354,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
       reblog: nil,
       card: card,
       content: content_html,
-      text: opts[:with_source] && object.data["source"],
+      text: opts[:with_source] && get_source_text(object.data["source"]),
       created_at: created_at,
       edited_at: edited_at,
       reblogs_count: announcement_count,
@@ -465,8 +465,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
 
     %{
       id: activity.id,
-      text: Map.get(object.data, "source", ""),
-      spoiler_text: Map.get(object.data, "summary", "")
+      text: get_source_text(Map.get(object.data, "source", "")),
+      spoiler_text: Map.get(object.data, "summary", ""),
+      content_type: get_source_content_type(object.data["source"])
     }
   end
 
@@ -687,4 +688,24 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
   end
 
   defp build_image_url(_, _), do: nil
+
+  defp get_source_text(%{"content" => content} = _source) do
+    content
+  end
+
+  defp get_source_text(source) when is_binary(source) do
+    source
+  end
+
+  defp get_source_text(_) do
+    ""
+  end
+
+  defp get_source_content_type(%{"mediaType" => type} = _source) do
+    type
+  end
+
+  defp get_source_content_type(_source) do
+    Utils.get_content_type(nil)
+  end
 end
diff --git a/test/pleroma/web/mastodon_api/views/status_view_test.exs b/test/pleroma/web/mastodon_api/views/status_view_test.exs
@@ -724,4 +724,40 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
     status = StatusView.render("show.json", activity: edited)
     assert status.edited_at
   end
+
+  test "with a source object" do
+    note =
+      insert(:note,
+        data: %{"source" => %{"content" => "object source", "mediaType" => "text/markdown"}}
+      )
+
+    activity = insert(:note_activity, note: note)
+
+    status = StatusView.render("show.json", activity: activity, with_source: true)
+    assert status.text == "object source"
+  end
+
+  describe "source.json" do
+    test "with a source object, renders both source and content type" do
+      note =
+        insert(:note,
+          data: %{"source" => %{"content" => "object source", "mediaType" => "text/markdown"}}
+        )
+
+      activity = insert(:note_activity, note: note)
+
+      status = StatusView.render("source.json", activity: activity)
+      assert status.text == "object source"
+      assert status.content_type == "text/markdown"
+    end
+
+    test "with a source string, renders source and put text/plain as the content type" do
+      note = insert(:note, data: %{"source" => "string source"})
+      activity = insert(:note_activity, note: note)
+
+      status = StatusView.render("source.json", activity: activity)
+      assert status.text == "string source"
+      assert status.content_type == "text/plain"
+    end
+  end
 end