diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/utils.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/common_api/common_api.ex | 4 | ||||
-rw-r--r-- | lib/pleroma/web/common_api/utils.ex | 59 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/views/status_view.ex | 52 |
5 files changed, 109 insertions, 10 deletions
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 5edd8ccc7..8b2427258 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -398,7 +398,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do # - tags # - emoji def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data) - when objtype in ["Article", "Note", "Video", "Page"] do + when objtype in ["Article", "Note", "Video", "Page", "Question"] do actor = Containment.get_actor(data) data = diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index ca8a0844b..63454e3f7 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -19,7 +19,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do require Logger - @supported_object_types ["Article", "Note", "Video", "Page"] + @supported_object_types ["Article", "Note", "Video", "Page", "Question"] @supported_report_states ~w(open closed resolved) @valid_visibilities ~w(public unlisted private direct) diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 5a312d673..bc8f80389 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -154,6 +154,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"] || "", @@ -171,7 +172,8 @@ defmodule Pleroma.Web.CommonAPI do tags, cw, cc, - sensitive + sensitive, + poll ), object <- Map.put( diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index d93c0d46e..2ea997789 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -102,6 +102,47 @@ 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 + {%{}, mentions, tags} + end + def make_content_html( status, attachments, @@ -224,7 +265,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do tags, cw \\ nil, cc \\ [], - sensitive \\ false + sensitive \\ false, + merge \\ %{} ) do object = %{ "type" => "Note", @@ -239,12 +281,15 @@ defmodule Pleroma.Web.CommonAPI.Utils do "tag" => tags |> Enum.map(fn {_, tag} -> tag end) |> Enum.uniq() } - with false <- is_nil(in_reply_to), - %Object{} = in_reply_to_object <- Object.normalize(in_reply_to) do - Map.put(object, "inReplyTo", in_reply_to_object.data["id"]) - else - _ -> object - end + object = + with false <- is_nil(in_reply_to), + %Object{} = in_reply_to_object <- Object.normalize(in_reply_to) do + Map.put(object, "inReplyTo", in_reply_to_object.data["id"]) + else + _ -> object + end + + Map.merge(object, merge) end def format_naive_asctime(date) do diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index c93d915e5..2a5691e1f 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -234,6 +234,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do spoiler_text: summary_html, visibility: get_visibility(object), media_attachments: attachments, + poll: render("poll.json", %{object: object, for: opts[:for]}), mentions: mentions, tags: build_tags(tags), application: %{ @@ -323,6 +324,57 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do } end + # TODO: Add tests for this view + def render("poll.json", %{object: object} = opts) do + {multiple, options} = + case object.data do + %{"anyOf" => options} when is_list(options) -> {true, options} + %{"oneOf" => options} when is_list(options) -> {false, options} + _ -> {nil, nil} + end + + if options do + end_time = + (object.data["closed"] || object.data["endTime"]) + |> NaiveDateTime.from_iso8601!() + + votes_count = object.data["votes_count"] || 0 + + expired = + end_time + |> NaiveDateTime.compare(NaiveDateTime.utc_now()) + |> case do + :lt -> true + _ -> false + end + + options = + Enum.map(options, fn %{"name" => name} = option -> + name = + HTML.filter_tags( + name, + User.html_filter_policy(opts[:for]) + ) + + %{title: name, votes_count: option["replies"]["votes_count"] || 0} + end) + + %{ + # Mastodon uses separate ids for polls, but an object can't have more than one poll embedded so object id is fine + id: object.id, + expires_at: Utils.to_masto_date(end_time), + expired: expired, + multiple: multiple, + votes_count: votes_count, + options: options, + voted: false, + emojis: build_emojis(object.data["emoji"]) + } + else + nil + end + end + def get_reply_to(activity, %{replied_to_activities: replied_to_activities}) do object = Object.normalize(activity) |