X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Fcommon_api%2Futils.ex;h=8093a56a683f134005d414869eae53b221199801;hb=eed774d058bfac2d36fd79faa915394a97baa6db;hp=22c44a0a3927b9d0668c476db67cab86578136d0;hpb=29807ef6a5b43a528ffca08b4f721b251f331c8d;p=akkoma diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 22c44a0a3..8093a56a6 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -4,10 +4,13 @@ defmodule Pleroma.Web.CommonAPI.Utils do import Pleroma.Web.Gettext + import Pleroma.Web.ControllerHelper, only: [truthy_param?: 1] alias Calendar.Strftime alias Pleroma.Activity alias Pleroma.Config + alias Pleroma.Conversation.Participation + alias Pleroma.Emoji alias Pleroma.Formatter alias Pleroma.Object alias Pleroma.Plugs.AuthenticationPlug @@ -24,7 +27,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do # This is a hack for twidere. def get_by_id_or_ap_id(id) do activity = - with true <- Pleroma.FlakeId.is_flake_id?(id), + with true <- FlakeId.flake_id?(id), %Activity{} = activity <- Activity.get_by_id_with_object(id) do activity else @@ -39,14 +42,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do end end - def get_replied_to_activity(""), do: nil - - def get_replied_to_activity(id) when not is_nil(id) do - Activity.get_by_id(id) - end - - def get_replied_to_activity(_), do: nil - def attachments_from_ids(%{"media_ids" => ids, "descriptions" => desc} = _) do attachments_from_ids_descs(ids, desc) end @@ -86,9 +81,20 @@ defmodule Pleroma.Web.CommonAPI.Utils do |> Enum.filter(& &1) end - @spec get_to_and_cc(User.t(), list(String.t()), Activity.t() | nil, String.t()) :: - {list(String.t()), list(String.t())} - def get_to_and_cc(user, mentioned_users, inReplyTo, "public") do + @spec get_to_and_cc( + User.t(), + list(String.t()), + Activity.t() | nil, + String.t(), + Participation.t() | nil + ) :: {list(String.t()), list(String.t())} + + def get_to_and_cc(_, _, _, _, %Participation{} = participation) do + participation = Repo.preload(participation, :recipients) + {Enum.map(participation.recipients, & &1.ap_id), []} + end + + def get_to_and_cc(user, mentioned_users, inReplyTo, "public", _) do to = [Pleroma.Constants.as_public() | mentioned_users] cc = [user.follower_address] @@ -99,7 +105,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do end end - def get_to_and_cc(user, mentioned_users, inReplyTo, "unlisted") do + def get_to_and_cc(user, mentioned_users, inReplyTo, "unlisted", _) do to = [user.follower_address | mentioned_users] cc = [Pleroma.Constants.as_public()] @@ -110,12 +116,12 @@ defmodule Pleroma.Web.CommonAPI.Utils do end end - def get_to_and_cc(user, mentioned_users, inReplyTo, "private") do - {to, cc} = get_to_and_cc(user, mentioned_users, inReplyTo, "direct") + def get_to_and_cc(user, mentioned_users, inReplyTo, "private", _) do + {to, cc} = get_to_and_cc(user, mentioned_users, inReplyTo, "direct", nil) {[user.follower_address | to], cc} end - def get_to_and_cc(_user, mentioned_users, inReplyTo, "direct") do + def get_to_and_cc(_user, mentioned_users, inReplyTo, "direct", _) do if inReplyTo do {Enum.uniq([inReplyTo.data["actor"] | mentioned_users]), []} else @@ -123,7 +129,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do end end - def get_to_and_cc(_user, mentions, _inReplyTo, {:list, _}), do: {mentions, []} + def get_to_and_cc(_user, mentions, _inReplyTo, {:list, _}, _), do: {mentions, []} def get_addressed_users(_, to) when is_list(to) do User.get_ap_ids_by_nicknames(to) @@ -146,70 +152,74 @@ defmodule Pleroma.Web.CommonAPI.Utils do def maybe_add_list_data(activity_params, _, _), do: activity_params + def make_poll_data(%{"poll" => %{"expires_in" => expires_in}} = data) + when is_binary(expires_in) do + # In some cases mastofe sends out strings instead of integers + data + |> put_in(["poll", "expires_in"], String.to_integer(expires_in)) + |> make_poll_data() + end + def make_poll_data(%{"poll" => %{"options" => options, "expires_in" => expires_in}} = data) when is_list(options) do - %{max_expiration: max_expiration, min_expiration: min_expiration} = - limits = Pleroma.Config.get([:instance, :poll_limits]) + limits = Pleroma.Config.get([:instance, :poll_limits]) - # XXX: There is probably a cleaner way of doing this - try do - # In some cases mastofe sends out strings instead of integers - expires_in = if is_binary(expires_in), do: String.to_integer(expires_in), else: expires_in - - if Enum.count(options) > limits.max_options do - raise ArgumentError, message: "Poll can't contain more than #{limits.max_options} options" - end - - {poll, emoji} = + with :ok <- validate_poll_expiration(expires_in, limits), + :ok <- validate_poll_options_amount(options, limits), + :ok <- validate_poll_options_length(options, limits) do + {option_notes, emoji} = Enum.map_reduce(options, %{}, fn option, emoji -> - if String.length(option) > limits.max_option_chars do - raise ArgumentError, - message: - "Poll options cannot be longer than #{limits.max_option_chars} characters each" - end - - {%{ - "name" => option, - "type" => "Note", - "replies" => %{"type" => "Collection", "totalItems" => 0} - }, Map.merge(emoji, Formatter.get_emoji_map(option))} - end) - - case expires_in do - expires_in when expires_in > max_expiration -> - raise ArgumentError, message: "Expiration date is too far in the future" + note = %{ + "name" => option, + "type" => "Note", + "replies" => %{"type" => "Collection", "totalItems" => 0} + } - expires_in when expires_in < min_expiration -> - raise ArgumentError, message: "Expiration date is too soon" - - _ -> - :noop - end + {note, Map.merge(emoji, Emoji.Formatter.get_emoji_map(option))} + end) end_time = NaiveDateTime.utc_now() |> NaiveDateTime.add(expires_in) |> NaiveDateTime.to_iso8601() - poll = - if Pleroma.Web.ControllerHelper.truthy_param?(data["poll"]["multiple"]) do - %{"type" => "Question", "anyOf" => poll, "closed" => end_time} - else - %{"type" => "Question", "oneOf" => poll, "closed" => end_time} - end + key = if truthy_param?(data["poll"]["multiple"]), do: "anyOf", else: "oneOf" + poll = %{"type" => "Question", key => option_notes, "closed" => end_time} - {poll, emoji} - rescue - e in ArgumentError -> e.message + {:ok, {poll, emoji}} end end def make_poll_data(%{"poll" => poll}) when is_map(poll) do - "Invalid poll" + {:error, "Invalid poll"} end def make_poll_data(_data) do - {%{}, %{}} + {:ok, {%{}, %{}}} + end + + defp validate_poll_options_amount(options, %{max_options: max_options}) do + if Enum.count(options) > max_options do + {:error, "Poll can't contain more than #{max_options} options"} + else + :ok + 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 + {:error, "Poll options cannot be longer than #{max_option_chars} characters each"} + else + :ok + end + end + + defp validate_poll_expiration(expires_in, %{min_expiration: min, max_expiration: max}) do + cond do + expires_in > max -> {:error, "Expiration date is too far in the future"} + expires_in < min -> {:error, "Expiration date is too soon"} + true -> :ok + end end def make_content_html( @@ -253,8 +263,12 @@ defmodule Pleroma.Web.CommonAPI.Utils do defp maybe_add_nsfw_tag(data, _), do: data - def make_context(%Activity{data: %{"context" => context}}), do: context - def make_context(_), do: Utils.generate_context_id() + def make_context(_, %Participation{} = participation) do + Repo.preload(participation, :conversation).conversation.ap_id + end + + def make_context(%Activity{data: %{"context" => context}}, _), do: context + def make_context(_, _), do: Utils.generate_context_id() def maybe_add_attachments(parsed, _attachments, true = _no_links), do: parsed @@ -330,25 +344,25 @@ defmodule Pleroma.Web.CommonAPI.Utils do attachments, in_reply_to, tags, - cw \\ nil, + summary \\ nil, cc \\ [], sensitive \\ false, - merge \\ %{} + extra_params \\ %{} ) do %{ "type" => "Note", "to" => to, "cc" => cc, "content" => content_html, - "summary" => cw, - "sensitive" => !Enum.member?(["false", "False", "0", false], sensitive), + "summary" => summary, + "sensitive" => truthy_param?(sensitive), "context" => context, "attachment" => attachments, "actor" => actor, "tag" => Keyword.values(tags) |> Enum.uniq() } |> add_in_reply_to(in_reply_to) - |> Map.merge(merge) + |> Map.merge(extra_params) end defp add_in_reply_to(object, nil), do: object @@ -418,8 +432,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do end def emoji_from_profile(%{info: _info} = user) do - (Formatter.get_emoji(user.bio) ++ Formatter.get_emoji(user.name)) - |> Enum.map(fn {shortcode, url, _} -> + (Emoji.Formatter.get_emoji(user.bio) ++ Emoji.Formatter.get_emoji(user.name)) + |> Enum.map(fn {shortcode, %Emoji{file: url}} -> %{ "type" => "Emoji", "icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}#{url}"}, @@ -554,15 +568,16 @@ defmodule Pleroma.Web.CommonAPI.Utils do } end - def validate_character_limit(full_payload, attachments, limit) do + def validate_character_limit("" = _full_payload, [] = _attachments) do + {:error, dgettext("errors", "Cannot post an empty status without attachments")} + end + + def validate_character_limit(full_payload, _attachments) do + limit = Pleroma.Config.get([:instance, :limit]) length = String.length(full_payload) if length < limit do - if length > 0 or Enum.count(attachments) > 0 do - :ok - else - {:error, dgettext("errors", "Cannot post an empty status without attachments")} - end + :ok else {:error, dgettext("errors", "The status is over the character limit")} end