Accept multilang polls on MastoAPI
This commit is contained in:
parent
72a2b3329e
commit
b1bdbdcf05
4 changed files with 102 additions and 14 deletions
|
@ -735,18 +735,23 @@ def poll_params do
|
|||
%Schema{
|
||||
nullable: true,
|
||||
type: :object,
|
||||
required: [:options, :expires_in],
|
||||
required: [:expires_in],
|
||||
properties: %{
|
||||
options: %Schema{
|
||||
type: :array,
|
||||
items: %Schema{type: :string},
|
||||
description: "Array of possible answers. Must be provided with `poll[expires_in]`."
|
||||
},
|
||||
options_map: %Schema{
|
||||
type: :array,
|
||||
items: Helpers.multilang_map_of(%Schema{type: :string}),
|
||||
description: "Array of possible answers. Must be provided with `poll[expires_in]`."
|
||||
},
|
||||
expires_in: %Schema{
|
||||
type: :integer,
|
||||
nullable: true,
|
||||
description:
|
||||
"Duration the poll should be open, in seconds. Must be provided with `poll[options]`"
|
||||
"Duration the poll should be open, in seconds. Must be provided with `poll[options]` or `poll[options_map]`"
|
||||
},
|
||||
multiple: %Schema{
|
||||
allOf: [BooleanLike],
|
||||
|
|
|
@ -147,22 +147,34 @@ def make_poll_data(%{"poll" => %{"expires_in" => expires_in}} = data)
|
|||
|> make_poll_data()
|
||||
end
|
||||
|
||||
def make_poll_data(%{poll: %{options: options, expires_in: expires_in}} = data)
|
||||
when is_list(options) do
|
||||
def make_poll_data(%{poll: %{options_map: options_map, expires_in: expires_in}} = data)
|
||||
when is_list(options_map) do
|
||||
limits = Config.get([:instance, :poll_limits])
|
||||
is_single_language = data.poll[:is_single_language]
|
||||
|
||||
options = options |> Enum.uniq()
|
||||
|
||||
with :ok <- validate_poll_expiration(expires_in, limits),
|
||||
:ok <- validate_poll_options_amount(options, limits),
|
||||
:ok <- validate_poll_options_length(options, limits) do
|
||||
:ok <- validate_poll_options_amount(options_map, limits),
|
||||
:ok <- validate_poll_options_length(options_map, limits) do
|
||||
{option_notes, emoji} =
|
||||
Enum.map_reduce(options, %{}, fn option, emoji ->
|
||||
note = %{
|
||||
"name" => option,
|
||||
"type" => "Note",
|
||||
"replies" => %{"type" => "Collection", "totalItems" => 0}
|
||||
}
|
||||
Enum.map_reduce(options_map, %{}, fn option, emoji ->
|
||||
name_attrs =
|
||||
if is_single_language do
|
||||
%{"name" => option["und"]}
|
||||
else
|
||||
%{
|
||||
"name" => Pleroma.MultiLanguage.map_to_str(option, multiline: false),
|
||||
"nameMap" => option
|
||||
}
|
||||
end
|
||||
|
||||
note =
|
||||
%{
|
||||
"type" => "Note",
|
||||
"replies" => %{"type" => "Collection", "totalItems" => 0}
|
||||
}
|
||||
|> Map.merge(name_attrs)
|
||||
|
||||
{note, Map.merge(emoji, Pleroma.Emoji.Formatter.get_emoji_map(option))}
|
||||
end)
|
||||
|
@ -179,6 +191,15 @@ def make_poll_data(%{poll: %{options: options, expires_in: expires_in}} = data)
|
|||
end
|
||||
end
|
||||
|
||||
def make_poll_data(%{poll: %{options: options}} = data) when is_list(options) do
|
||||
new_poll = Map.put(data.poll, :options_map, Enum.map(options, &%{"und" => &1}))
|
||||
|
||||
data
|
||||
|> Map.put(:poll, new_poll)
|
||||
|> Map.put(:is_single_language, true)
|
||||
|> make_poll_data()
|
||||
end
|
||||
|
||||
def make_poll_data(%{"poll" => poll}) when is_map(poll) do
|
||||
{:error, "Invalid poll"}
|
||||
end
|
||||
|
@ -200,8 +221,11 @@ defp validate_poll_options_amount(options, %{max_options: max_options}) do
|
|||
end
|
||||
end
|
||||
|
||||
defp validate_poll_options_length(options, %{max_option_chars: max_option_chars}) do
|
||||
if Enum.any?(options, &(String.length(&1) > max_option_chars)) do
|
||||
defp validate_poll_options_length(options_map, %{max_option_chars: max_option_chars}) do
|
||||
if Enum.any?(options_map, fn option ->
|
||||
Enum.reduce(option, 0, fn {_lang, cur}, acc -> acc + String.length(cur) end)
|
||||
|> Kernel.>(max_option_chars)
|
||||
end) do
|
||||
{:error, "Poll options cannot be longer than #{max_option_chars} characters each"}
|
||||
else
|
||||
:ok
|
||||
|
|
|
@ -729,4 +729,26 @@ test "adds attachments to parsed results" do
|
|||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "make_poll_data/1" do
|
||||
test "multilang support" do
|
||||
{:ok, {poll, _}} =
|
||||
Utils.make_poll_data(%{
|
||||
poll: %{
|
||||
options_map: [
|
||||
%{"a" => "foo", "b" => "1"},
|
||||
%{"a" => "bar", "c" => "2"}
|
||||
],
|
||||
expires_in: 600
|
||||
}
|
||||
})
|
||||
|
||||
assert %{"oneOf" => choices} = poll
|
||||
|
||||
assert [
|
||||
%{"name" => _, "nameMap" => %{"a" => "foo", "b" => "1"}},
|
||||
%{"name" => _, "nameMap" => %{"a" => "bar", "c" => "2"}}
|
||||
] = choices
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -676,6 +676,43 @@ test "posting a poll", %{conn: conn} do
|
|||
assert question.data["closed"] =~ "Z"
|
||||
end
|
||||
|
||||
test "posting a multilang poll", %{conn: conn} do
|
||||
time = NaiveDateTime.utc_now()
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/statuses", %{
|
||||
"status" => "Who is the #bestgrill?",
|
||||
"poll" => %{
|
||||
"options_map" => [
|
||||
%{"a" => "Rei", "b" => "1"},
|
||||
%{"a" => "Asuka", "b" => "2"},
|
||||
%{"a" => "Misato", "b" => "3"}
|
||||
],
|
||||
"expires_in" => 420
|
||||
}
|
||||
})
|
||||
|
||||
response = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
assert Enum.all?(response["poll"]["options"], fn %{"title_map" => title} ->
|
||||
title in [
|
||||
%{"a" => "Rei", "b" => "1"},
|
||||
%{"a" => "Asuka", "b" => "2"},
|
||||
%{"a" => "Misato", "b" => "3"}
|
||||
]
|
||||
end)
|
||||
|
||||
assert NaiveDateTime.diff(NaiveDateTime.from_iso8601!(response["poll"]["expires_at"]), time) in 420..430
|
||||
assert response["poll"]["expired"] == false
|
||||
|
||||
question = Object.get_by_id(response["poll"]["id"])
|
||||
|
||||
# closed contains utc timezone
|
||||
assert question.data["closed"] =~ "Z"
|
||||
end
|
||||
|
||||
test "option limit is enforced", %{conn: conn} do
|
||||
limit = Config.get([:instance, :poll_limits, :max_options])
|
||||
|
||||
|
|
Loading…
Reference in a new issue