Include own_votes in the poll data
[akkoma] / lib / pleroma / web / mastodon_api / views / poll_view.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 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 {voted, own_votes} = voted_and_own_votes(params, options)
14
15 %{
16 # Mastodon uses separate ids for polls, but an object can't have
17 # more than one poll embedded so object id is fine
18 id: to_string(object.id),
19 expires_at: end_time,
20 expired: expired,
21 multiple: multiple,
22 votes_count: votes_count,
23 voters_count: voters_count(object),
24 options: options,
25 voted: voted,
26 own_votes: own_votes,
27 emojis: Pleroma.Web.MastodonAPI.StatusView.build_emojis(object.data["emoji"])
28 }
29 end
30
31 def render("show.json", %{object: object} = params) do
32 case object.data do
33 %{"anyOf" => [_ | _] = options} ->
34 render(__MODULE__, "show.json", Map.merge(params, %{multiple: true, options: options}))
35
36 %{"oneOf" => [_ | _] = options} ->
37 render(__MODULE__, "show.json", Map.merge(params, %{multiple: false, options: options}))
38
39 _ ->
40 nil
41 end
42 end
43
44 defp end_time_and_expired(object) do
45 if object.data["closed"] do
46 end_time = NaiveDateTime.from_iso8601!(object.data["closed"])
47 expired = NaiveDateTime.compare(end_time, NaiveDateTime.utc_now()) == :lt
48
49 {Utils.to_masto_date(end_time), expired}
50 else
51 {nil, false}
52 end
53 end
54
55 defp options_and_votes_count(options) do
56 Enum.map_reduce(options, 0, fn %{"name" => name} = option, count ->
57 current_count = option["replies"]["totalItems"] || 0
58
59 {%{
60 title: name,
61 votes_count: current_count
62 }, current_count + count}
63 end)
64 end
65
66 defp voters_count(%{data: %{"voters" => [_ | _] = voters}}) do
67 length(voters)
68 end
69
70 defp voters_count(_), do: 0
71
72 defp voted_and_own_votes(%{object: object} = params, options) do
73 options = options |> Enum.map(fn x -> Map.get(x, :title) end)
74
75 if params[:for] do
76 existing_votes =
77 Pleroma.Web.ActivityPub.Utils.get_existing_votes(params[:for].ap_id, object)
78
79 own_votes =
80 for vote <- existing_votes do
81 data = Map.get(vote, :object) |> Map.get(:data)
82
83 Enum.find_index(options, fn x -> x == data["name"] end)
84 end || []
85
86 voted = existing_votes != [] or params[:for].ap_id == object.data["actor"]
87
88 {voted, own_votes}
89 else
90 {false, []}
91 end
92 end
93 end