aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex2
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex2
-rw-r--r--lib/pleroma/web/common_api/common_api.ex4
-rw-r--r--lib/pleroma/web/common_api/utils.ex59
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex52
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)