summaryrefslogtreecommitdiff
path: root/lib/pleroma/web/mastodon_api/views/poll_view.ex
blob: 59a5deb28bf360c8b533bac7102a81527aea86bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only

defmodule Pleroma.Web.MastodonAPI.PollView do
  use Pleroma.Web, :view

  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,
      voters_count: (multiple || nil) && voters_count(object),
      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: name,
         votes_count: current_count
       }, current_count + count}
    end)
  end

  defp voters_count(%{data: %{"voters" => [_ | _] = voters}}) do
    length(voters)
  end

  defp voters_count(_), do: 0

  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