Merge remote-tracking branch 'pleroma/develop' into features/poll-validation
[akkoma] / lib / pleroma / web / mastodon_api / views / poll_view.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.MastodonAPI.PollView do
6 use Pleroma.Web, :view
7
8 alias Pleroma.Web.CommonAPI.Utils
9
10 def render("show.json", %{object: object, multiple: multiple, options: options} = params) do
11 {end_time, expired} = end_time_and_expired(object)
12 {options, votes_count} = options_and_votes_count(options)
13
14 %{
15 # Mastodon uses separate ids for polls, but an object can't have
16 # more than one poll embedded so object id is fine
17 id: to_string(object.id),
18 expires_at: end_time,
19 expired: expired,
20 multiple: multiple,
21 votes_count: votes_count,
22 voters_count: (multiple || nil) && voters_count(object),
23 options: options,
24 voted: voted?(params),
25 emojis: Pleroma.Web.MastodonAPI.StatusView.build_emojis(object.data["emoji"])
26 }
27 end
28
29 def render("show.json", %{object: object} = params) do
30 case object.data do
31 %{"anyOf" => options} when is_list(options) and options != [] ->
32 render(__MODULE__, "show.json", Map.merge(params, %{multiple: true, options: options}))
33
34 %{"oneOf" => options} when is_list(options) and options != [] ->
35 render(__MODULE__, "show.json", Map.merge(params, %{multiple: false, options: options}))
36
37 _ ->
38 nil
39 end
40 end
41
42 defp end_time_and_expired(object) do
43 if object.data["closed"] do
44 end_time = NaiveDateTime.from_iso8601!(object.data["closed"])
45 expired = NaiveDateTime.compare(end_time, NaiveDateTime.utc_now()) == :lt
46
47 {Utils.to_masto_date(end_time), expired}
48 else
49 {nil, false}
50 end
51 end
52
53 defp options_and_votes_count(options) do
54 Enum.map_reduce(options, 0, fn %{"name" => name} = option, count ->
55 current_count = option["replies"]["totalItems"] || 0
56
57 {%{
58 title: name,
59 votes_count: current_count
60 }, current_count + count}
61 end)
62 end
63
64 defp voters_count(%{data: %{"voters" => [_ | _] = voters}}) do
65 length(voters)
66 end
67
68 defp voters_count(_), do: 0
69
70 defp voted?(%{object: object} = opts) do
71 if opts[:for] do
72 existing_votes = Pleroma.Web.ActivityPub.Utils.get_existing_votes(opts[:for].ap_id, object)
73 existing_votes != [] or opts[:for].ap_id == object.data["actor"]
74 else
75 false
76 end
77 end
78 end