Mastodon API: Add support for posting polls
authorrinpatch <rinpatch@sdf.org>
Sat, 18 May 2019 10:29:28 +0000 (13:29 +0300)
committerrinpatch <rinpatch@sdf.org>
Sat, 18 May 2019 10:29:28 +0000 (13:29 +0300)
lib/pleroma/web/common_api/common_api.ex
lib/pleroma/web/common_api/utils.ex
test/web/mastodon_api/mastodon_api_controller_test.exs
test/web/mastodon_api/status_view_test.exs

index b53869c7582899eebfbad8bc188a4f2bcb47a730..335ae70b023b4413459513d80adabe7a273a4a49 100644 (file)
@@ -149,6 +149,7 @@ defmodule Pleroma.Web.CommonAPI do
              data,
              visibility
            ),
+         {poll, mentions, tags} <- make_poll_data(data, mentions, tags),
          {to, cc} <- to_for_user_and_mentions(user, mentions, in_reply_to, visibility),
          context <- make_context(in_reply_to),
          cw <- data["spoiler_text"] || "",
@@ -164,7 +165,8 @@ defmodule Pleroma.Web.CommonAPI do
              in_reply_to,
              tags,
              cw,
-             cc
+             cc,
+             poll
            ),
          object <-
            Map.put(
index 1dfe50b408266efd29f341ac37f5dc3b7b652d53..13cdffbbd00eeb394174f114596f0e1e35d8f4a6 100644 (file)
@@ -102,6 +102,48 @@ defmodule Pleroma.Web.CommonAPI.Utils do
     end
   end
 
+  def make_poll_data(
+        %{"poll" => %{"options" => options, "expires_in" => expires_in}} = data,
+        mentions,
+        tags
+      )
+      when is_list(options) and is_integer(expires_in) do
+    content_type = get_content_type(data["content_type"])
+    # XXX: There is probably a more performant/cleaner way to do this
+    {poll, {mentions, tags}} =
+      Enum.map_reduce(options, {mentions, tags}, fn option, {mentions, tags} ->
+        # TODO: Custom emoji
+        {option, mentions_merge, tags_merge} = format_input(option, content_type)
+        mentions = mentions ++ mentions_merge
+        tags = tags ++ tags_merge
+
+        {%{
+           "name" => option,
+           "type" => "Note",
+           "replies" => %{"type" => "Collection", "totalItems" => 0}
+         }, {mentions, tags}}
+      end)
+
+    end_time =
+      NaiveDateTime.utc_now()
+      |> NaiveDateTime.add(expires_in)
+      |> NaiveDateTime.to_iso8601()
+
+    poll =
+      if Pleroma.Web.ControllerHelper.truthy_param?(data["poll"]["multiple"]) do
+        %{"type" => "Question", "anyOf" => poll, "closed" => end_time}
+      else
+        %{"type" => "Question", "oneOf" => poll, "closed" => end_time}
+      end
+
+    {poll, mentions, tags}
+  end
+
+  def make_poll_data(data, mentions, tags) do
+    IO.inspect(data, label: "data")
+    {%{}, mentions, tags}
+  end
+
   def make_content_html(
         status,
         attachments,
@@ -223,8 +265,11 @@ defmodule Pleroma.Web.CommonAPI.Utils do
         in_reply_to,
         tags,
         cw \\ nil,
-        cc \\ []
+        cc \\ [],
+        merge \\ %{}
       ) do
+    IO.inspect(merge, label: "merge")
+
     object = %{
       "type" => "Note",
       "to" => to,
@@ -237,14 +282,17 @@ defmodule Pleroma.Web.CommonAPI.Utils do
       "tag" => tags |> Enum.map(fn {_, tag} -> tag end) |> Enum.uniq()
     }
 
-    if in_reply_to do
-      in_reply_to_object = Object.normalize(in_reply_to)
+    object =
+      if in_reply_to do
+        in_reply_to_object = Object.normalize(in_reply_to)
 
-      object
-      |> Map.put("inReplyTo", in_reply_to_object.data["id"])
-    else
-      object
-    end
+        object
+        |> Map.put("inReplyTo", in_reply_to_object.data["id"])
+      else
+        object
+      end
+
+    Map.merge(object, merge)
   end
 
   def format_naive_asctime(date) do
index 505e450106b637b548e8ce83464946b7e1b8d97b..ce581c0925fd75856f66f7e61e8759a507892ed6 100644 (file)
@@ -132,6 +132,28 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     refute id == third_id
   end
 
+  test "posting a poll", %{conn: conn} do
+    user = insert(:user)
+    time = NaiveDateTime.utc_now()
+
+    conn =
+      conn
+      |> assign(:user, user)
+      |> post("/api/v1/statuses", %{
+        "status" => "Who is the best girl?",
+        "poll" => %{"options" => ["Rei", "Asuka", "Misato"], "expires_in" => 420}
+      })
+
+    response = json_response(conn, 200)
+
+    assert Enum.all?(response["poll"]["options"], fn %{"title" => title} ->
+             title in ["Rei", "Asuka", "Misato"]
+           end)
+
+    assert NaiveDateTime.diff(NaiveDateTime.from_iso8601!(response["poll"]["expires_at"]), time) in 420..430
+    refute response["poll"]["expred"]
+  end
+
   test "posting a sensitive status", %{conn: conn} do
     user = insert(:user)
 
index d7c800e83a54d04a210d7f8894a6583af74bb66e..9f2ebda4e7c2db85b060279074535450d16a94c0 100644 (file)
@@ -103,6 +103,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
       muted: false,
       pinned: false,
       sensitive: false,
+      poll: nil,
       spoiler_text: HtmlSanitizeEx.basic_html(note.data["object"]["summary"]),
       visibility: "public",
       media_attachments: [],