aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEgor Kislitsyn <egor@kislitsyn.com>2019-10-01 11:44:34 +0700
committerEgor Kislitsyn <egor@kislitsyn.com>2019-10-01 11:44:34 +0700
commit36a34c36fe518dae23fb19d02ccb43de8c2621dd (patch)
tree2b269d3914bd89300751b95c31ce03e4fbe91492 /lib
parent703deb66d9346e0c8a160ec6c138b3b53b5183b6 (diff)
downloadpleroma-36a34c36fe518dae23fb19d02ccb43de8c2621dd.tar.gz
Extract poll actions from `MastodonAPIController` to `PollController`
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/web/controller_helper.ex12
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex64
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/poll_controller.ex53
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/status_controller.ex2
-rw-r--r--lib/pleroma/web/mastodon_api/views/poll_view.ex74
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex72
-rw-r--r--lib/pleroma/web/router.ex4
7 files changed, 144 insertions, 137 deletions
diff --git a/lib/pleroma/web/controller_helper.ex b/lib/pleroma/web/controller_helper.ex
index 83b884ba9..9a4e322c9 100644
--- a/lib/pleroma/web/controller_helper.ex
+++ b/lib/pleroma/web/controller_helper.ex
@@ -75,4 +75,16 @@ defmodule Pleroma.Web.ControllerHelper do
nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt()
end
end
+
+ def try_render(conn, target, params)
+ when is_binary(target) do
+ case render(conn, target, params) do
+ nil -> render_error(conn, :not_implemented, "Can't display this activity")
+ res -> res
+ end
+ end
+
+ def try_render(conn, _, _) do
+ render_error(conn, :not_implemented, "Can't display this activity")
+ end
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
index 1484a0174..912dd181f 100644
--- a/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex
@@ -7,7 +7,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
- alias Pleroma.Activity
alias Pleroma.Bookmark
alias Pleroma.Config
alias Pleroma.HTTP
@@ -19,7 +18,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
alias Pleroma.User
alias Pleroma.Web
alias Pleroma.Web.ActivityPub.ActivityPub
- alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MastodonAPI.AppView
@@ -117,56 +115,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
json(conn, mastodon_emoji)
end
- def get_poll(%{assigns: %{user: user}} = conn, %{"id" => id}) do
- with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
- %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
- true <- Visibility.visible_for_user?(activity, user) do
- conn
- |> put_view(StatusView)
- |> try_render("poll.json", %{object: object, for: user})
- else
- error when is_nil(error) or error == false ->
- render_error(conn, :not_found, "Record not found")
- end
- end
-
- defp get_cached_vote_or_vote(user, object, choices) do
- idempotency_key = "polls:#{user.id}:#{object.data["id"]}"
-
- {_, res} =
- Cachex.fetch(:idempotency_cache, idempotency_key, fn _ ->
- case CommonAPI.vote(user, object, choices) do
- {:error, _message} = res -> {:ignore, res}
- res -> {:commit, res}
- end
- end)
-
- res
- end
-
- def poll_vote(%{assigns: %{user: user}} = conn, %{"id" => id, "choices" => choices}) do
- with %Object{} = object <- Object.get_by_id(id),
- true <- object.data["type"] == "Question",
- %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
- true <- Visibility.visible_for_user?(activity, user),
- {:ok, _activities, object} <- get_cached_vote_or_vote(user, object, choices) do
- conn
- |> put_view(StatusView)
- |> try_render("poll.json", %{object: object, for: user})
- else
- nil ->
- render_error(conn, :not_found, "Record not found")
-
- false ->
- render_error(conn, :not_found, "Record not found")
-
- {:error, message} ->
- conn
- |> put_status(:unprocessable_entity)
- |> json(%{error: message})
- end
- end
-
def update_media(
%{assigns: %{user: user}} = conn,
%{"id" => id, "description" => description} = _
@@ -511,18 +459,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
end
- def try_render(conn, target, params)
- when is_binary(target) do
- case render(conn, target, params) do
- nil -> render_error(conn, :not_implemented, "Can't display this activity")
- res -> res
- end
- end
-
- def try_render(conn, _, _) do
- render_error(conn, :not_implemented, "Can't display this activity")
- end
-
defp present?(nil), do: false
defp present?(false), do: false
defp present?(_), do: true
diff --git a/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex b/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex
new file mode 100644
index 000000000..fbf7f8673
--- /dev/null
+++ b/lib/pleroma/web/mastodon_api/controllers/poll_controller.ex
@@ -0,0 +1,53 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.PollController do
+ use Pleroma.Web, :controller
+
+ import Pleroma.Web.ControllerHelper, only: [try_render: 3, json_response: 3]
+
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.Visibility
+ alias Pleroma.Web.CommonAPI
+
+ action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
+
+ @doc "GET /api/v1/polls/:id"
+ def show(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+ with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
+ %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
+ true <- Visibility.visible_for_user?(activity, user) do
+ try_render(conn, "show.json", %{object: object, for: user})
+ else
+ error when is_nil(error) or error == false ->
+ render_error(conn, :not_found, "Record not found")
+ end
+ end
+
+ @doc "POST /api/v1/polls/:id/votes"
+ def vote(%{assigns: %{user: user}} = conn, %{"id" => id, "choices" => choices}) do
+ with %Object{data: %{"type" => "Question"}} = object <- Object.get_by_id(id),
+ %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
+ true <- Visibility.visible_for_user?(activity, user),
+ {:ok, _activities, object} <- get_cached_vote_or_vote(user, object, choices) do
+ try_render(conn, "show.json", %{object: object, for: user})
+ else
+ nil -> render_error(conn, :not_found, "Record not found")
+ false -> render_error(conn, :not_found, "Record not found")
+ {:error, message} -> json_response(conn, :unprocessable_entity, %{error: message})
+ end
+ end
+
+ defp get_cached_vote_or_vote(user, object, choices) do
+ idempotency_key = "polls:#{user.id}:#{object.data["id"]}"
+
+ Cachex.fetch!(:idempotency_cache, idempotency_key, fn ->
+ case CommonAPI.vote(user, object, choices) do
+ {:error, _message} = res -> {:ignore, res}
+ res -> {:commit, res}
+ end
+ end)
+ end
+end
diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
index 3c6987a5f..fb6fd7676 100644
--- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
@@ -5,7 +5,7 @@
defmodule Pleroma.Web.MastodonAPI.StatusController do
use Pleroma.Web, :controller
- import Pleroma.Web.MastodonAPI.MastodonAPIController, only: [try_render: 3]
+ import Pleroma.Web.ControllerHelper, only: [try_render: 3]
require Ecto.Query
diff --git a/lib/pleroma/web/mastodon_api/views/poll_view.ex b/lib/pleroma/web/mastodon_api/views/poll_view.ex
new file mode 100644
index 000000000..753039da3
--- /dev/null
+++ b/lib/pleroma/web/mastodon_api/views/poll_view.ex
@@ -0,0 +1,74 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.PollView do
+ use Pleroma.Web, :view
+
+ alias Pleroma.HTML
+ alias Pleroma.Web.CommonAPI.Utils
+
+ def render("show.json", %{object: object, multiple: multiple, options: options} = params) do
+ {end_time, expired} = end_time_and_expired(object)
+ {options, votes_count} = options_and_votes_count(options)
+
+ %{
+ # Mastodon uses separate ids for polls, but an object can't have
+ # more than one poll embedded so object id is fine
+ id: to_string(object.id),
+ expires_at: end_time,
+ expired: expired,
+ multiple: multiple,
+ votes_count: votes_count,
+ options: options,
+ voted: voted?(params),
+ emojis: Pleroma.Web.MastodonAPI.StatusView.build_emojis(object.data["emoji"])
+ }
+ end
+
+ def render("show.json", %{object: object} = params) do
+ case object.data do
+ %{"anyOf" => options} when is_list(options) ->
+ render(__MODULE__, "show.json", Map.merge(params, %{multiple: true, options: options}))
+
+ %{"oneOf" => options} when is_list(options) ->
+ render(__MODULE__, "show.json", Map.merge(params, %{multiple: false, options: options}))
+
+ _ ->
+ nil
+ end
+ end
+
+ defp end_time_and_expired(object) do
+ case object.data["closed"] || object.data["endTime"] do
+ end_time when is_binary(end_time) ->
+ end_time = NaiveDateTime.from_iso8601!(end_time)
+ expired = NaiveDateTime.compare(end_time, NaiveDateTime.utc_now()) == :lt
+
+ {Utils.to_masto_date(end_time), expired}
+
+ _ ->
+ {nil, false}
+ end
+ end
+
+ defp options_and_votes_count(options) do
+ Enum.map_reduce(options, 0, fn %{"name" => name} = option, count ->
+ current_count = option["replies"]["totalItems"] || 0
+
+ {%{
+ title: HTML.strip_tags(name),
+ votes_count: current_count
+ }, current_count + count}
+ end)
+ end
+
+ defp voted?(%{object: object} = opts) do
+ if opts[:for] do
+ existing_votes = Pleroma.Web.ActivityPub.Utils.get_existing_votes(opts[:for].ap_id, object)
+ existing_votes != [] or opts[:for].ap_id == object.data["actor"]
+ else
+ false
+ end
+ end
+end
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index bc527ad1b..3262427ec 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -18,6 +18,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MastodonAPI.AccountView
+ alias Pleroma.Web.MastodonAPI.PollView
alias Pleroma.Web.MastodonAPI.StatusView
alias Pleroma.Web.MediaProxy
@@ -277,7 +278,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]}),
+ poll: render(PollView, "show.json", object: object, for: opts[:for]),
mentions: mentions,
tags: build_tags(tags),
application: %{
@@ -389,75 +390,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
safe_render_many(opts.activities, StatusView, "listen.json", opts)
end
- 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, expired} =
- case object.data["closed"] || object.data["endTime"] do
- end_time when is_binary(end_time) ->
- end_time =
- (object.data["closed"] || object.data["endTime"])
- |> NaiveDateTime.from_iso8601!()
-
- expired =
- end_time
- |> NaiveDateTime.compare(NaiveDateTime.utc_now())
- |> case do
- :lt -> true
- _ -> false
- end
-
- end_time = Utils.to_masto_date(end_time)
-
- {end_time, expired}
-
- _ ->
- {nil, false}
- end
-
- voted =
- if opts[:for] do
- existing_votes =
- Pleroma.Web.ActivityPub.Utils.get_existing_votes(opts[:for].ap_id, object)
-
- existing_votes != [] or opts[:for].ap_id == object.data["actor"]
- else
- false
- end
-
- {options, votes_count} =
- Enum.map_reduce(options, 0, fn %{"name" => name} = option, count ->
- current_count = option["replies"]["totalItems"] || 0
-
- {%{
- title: HTML.strip_tags(name),
- votes_count: current_count
- }, current_count + count}
- end)
-
- %{
- # Mastodon uses separate ids for polls, but an object can't have
- # more than one poll embedded so object id is fine
- id: to_string(object.id),
- expires_at: end_time,
- expired: expired,
- multiple: multiple,
- votes_count: votes_count,
- options: options,
- voted: voted,
- emojis: build_emojis(object.data["emoji"])
- }
- else
- nil
- end
- end
-
def render("context.json", %{activity: activity, activities: activities, user: user}) do
%{ancestors: ancestors, descendants: descendants} =
activities
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index eab55a27c..7af44c6be 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -403,7 +403,7 @@ defmodule Pleroma.Web.Router do
put("/scheduled_statuses/:id", ScheduledActivityController, :update)
delete("/scheduled_statuses/:id", ScheduledActivityController, :delete)
- post("/polls/:id/votes", MastodonAPIController, :poll_vote)
+ post("/polls/:id/votes", PollController, :vote)
post("/media", MastodonAPIController, :upload)
put("/media/:id", MastodonAPIController, :update_media)
@@ -488,7 +488,7 @@ defmodule Pleroma.Web.Router do
get("/statuses/:id", StatusController, :show)
get("/statuses/:id/context", StatusController, :context)
- get("/polls/:id", MastodonAPIController, :get_poll)
+ get("/polls/:id", PollController, :show)
get("/accounts/:id/statuses", AccountController, :statuses)
get("/accounts/:id/followers", AccountController, :followers)