logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

poll_view.ex (3113B)


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