Cleanup CommonAPI

This commit is contained in:
Egor Kislitsyn 2019-09-24 15:56:20 +07:00
parent de3e90e536
commit c57ad0a402
2 changed files with 79 additions and 92 deletions

View file

@ -17,14 +17,11 @@ defmodule Pleroma.Web.CommonAPI do
import Pleroma.Web.CommonAPI.Utils import Pleroma.Web.CommonAPI.Utils
def follow(follower, followed) do def follow(follower, followed) do
timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout])
with {:ok, follower} <- User.maybe_direct_follow(follower, followed), with {:ok, follower} <- User.maybe_direct_follow(follower, followed),
{:ok, activity} <- ActivityPub.follow(follower, followed), {:ok, activity} <- ActivityPub.follow(follower, followed),
{:ok, follower, followed} <- {:ok, follower, followed} <- User.wait_and_refresh(timeout, follower, followed) do
User.wait_and_refresh(
Pleroma.Config.get([:activitypub, :follow_handshake_timeout]),
follower,
followed
) do
{:ok, follower, followed, activity} {:ok, follower, followed, activity}
end end
end end
@ -75,8 +72,7 @@ def delete(activity_id, user) do
{:ok, delete} <- ActivityPub.delete(object) do {:ok, delete} <- ActivityPub.delete(object) do
{:ok, delete} {:ok, delete}
else else
_ -> _ -> {:error, dgettext("errors", "Could not delete")}
{:error, dgettext("errors", "Could not delete")}
end end
end end
@ -86,18 +82,16 @@ def repeat(id_or_ap_id, user) do
nil <- Utils.get_existing_announce(user.ap_id, object) do nil <- Utils.get_existing_announce(user.ap_id, object) do
ActivityPub.announce(user, object) ActivityPub.announce(user, object)
else else
_ -> _ -> {:error, dgettext("errors", "Could not repeat")}
{:error, dgettext("errors", "Could not repeat")}
end end
end end
def unrepeat(id_or_ap_id, user) do def unrepeat(id_or_ap_id, user) do
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id) do
object <- Object.normalize(activity) do object = Object.normalize(activity)
ActivityPub.unannounce(user, object) ActivityPub.unannounce(user, object)
else else
_ -> _ -> {:error, dgettext("errors", "Could not unrepeat")}
{:error, dgettext("errors", "Could not unrepeat")}
end end
end end
@ -107,30 +101,23 @@ def favorite(id_or_ap_id, user) do
nil <- Utils.get_existing_like(user.ap_id, object) do nil <- Utils.get_existing_like(user.ap_id, object) do
ActivityPub.like(user, object) ActivityPub.like(user, object)
else else
_ -> _ -> {:error, dgettext("errors", "Could not favorite")}
{:error, dgettext("errors", "Could not favorite")}
end end
end end
def unfavorite(id_or_ap_id, user) do def unfavorite(id_or_ap_id, user) do
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id) do
object <- Object.normalize(activity) do object = Object.normalize(activity)
ActivityPub.unlike(user, object) ActivityPub.unlike(user, object)
else else
_ -> _ -> {:error, dgettext("errors", "Could not unfavorite")}
{:error, dgettext("errors", "Could not unfavorite")}
end end
end end
def vote(user, object, choices) do def vote(user, %{data: %{"type" => "Question"}} = object, choices) do
with "Question" <- object.data["type"], with :ok <- validate_not_author(object, user),
{:author, false} <- {:author, object.data["actor"] == user.ap_id}, :ok <- validate_existing_votes(user, object),
{:existing_votes, []} <- {:existing_votes, Utils.get_existing_votes(user.ap_id, object)}, {:ok, options, choices} <- normalize_and_validate_choices(choices, object) do
{options, max_count} <- get_options_and_max_count(object),
option_count <- Enum.count(options),
{:choice_check, {choices, true}} <-
{:choice_check, normalize_and_validate_choice_indices(choices, option_count)},
{:count_check, true} <- {:count_check, Enum.count(choices) <= max_count} do
answer_activities = answer_activities =
Enum.map(choices, fn index -> Enum.map(choices, fn index ->
answer_data = make_answer_data(user, object, Enum.at(options, index)["name"]) answer_data = make_answer_data(user, object, Enum.at(options, index)["name"])
@ -149,27 +136,37 @@ def vote(user, object, choices) do
object = Object.get_cached_by_ap_id(object.data["id"]) object = Object.get_cached_by_ap_id(object.data["id"])
{:ok, answer_activities, object} {:ok, answer_activities, object}
else
{:author, _} -> {:error, dgettext("errors", "Poll's author can't vote")}
{:existing_votes, _} -> {:error, dgettext("errors", "Already voted")}
{:choice_check, {_, false}} -> {:error, dgettext("errors", "Invalid indices")}
{:count_check, false} -> {:error, dgettext("errors", "Too many choices")}
end end
end end
defp get_options_and_max_count(object) do defp validate_not_author(%{data: %{"actor" => ap_id}}, %{ap_id: ap_id}),
if Map.has_key?(object.data, "anyOf") do do: {:error, dgettext("errors", "Poll's author can't vote")}
{object.data["anyOf"], Enum.count(object.data["anyOf"])}
defp validate_not_author(_, _), do: :ok
defp validate_existing_votes(%{ap_id: ap_id}, object) do
if Utils.get_existing_votes(ap_id, object) == [] do
:ok
else else
{object.data["oneOf"], 1} {:error, dgettext("errors", "Already voted")}
end end
end end
defp normalize_and_validate_choice_indices(choices, count) do defp get_options_and_max_count(%{data: %{"anyOf" => any_of}}), do: {any_of, Enum.count(any_of)}
Enum.map_reduce(choices, true, fn index, valid -> defp get_options_and_max_count(%{data: %{"oneOf" => one_of}}), do: {one_of, 1}
index = if is_binary(index), do: String.to_integer(index), else: index
{index, if(valid, do: index < count, else: valid)} defp normalize_and_validate_choices(choices, object) do
end) choices = Enum.map(choices, fn i -> if is_binary(i), do: String.to_integer(i), else: i end)
{options, max_count} = get_options_and_max_count(object)
count = Enum.count(options)
with {_, true} <- {:valid_choice, Enum.all?(choices, &(&1 < count))},
{_, true} <- {:count_check, Enum.count(choices) <= max_count} do
{:ok, options, choices}
else
{:valid_choice, _} -> {:error, dgettext("errors", "Invalid indices")}
{:count_check, _} -> {:error, dgettext("errors", "Too many choices")}
end
end end
def get_visibility(_, _, %Participation{}), do: {"direct", "direct"} def get_visibility(_, _, %Participation{}), do: {"direct", "direct"}
@ -194,7 +191,7 @@ def get_replied_to_visibility(nil), do: nil
def get_replied_to_visibility(activity) do def get_replied_to_visibility(activity) do
with %Object{} = object <- Object.normalize(activity) do with %Object{} = object <- Object.normalize(activity) do
Pleroma.Web.ActivityPub.Visibility.get_visibility(object) Visibility.get_visibility(object)
end end
end end
@ -234,13 +231,12 @@ defp maybe_create_activity_expiration(result, _), do: result
# Updates the emojis for a user based on their profile # Updates the emojis for a user based on their profile
def update(user) do def update(user) do
emoji = emoji_from_profile(user) emoji = emoji_from_profile(user)
source_data = user.info |> Map.get(:source_data, {}) |> Map.put("tag", emoji) source_data = user.info |> Map.get(:source_data, %{}) |> Map.put("tag", emoji)
user = user =
with {:ok, user} <- User.update_info(user, &User.Info.set_source_data(&1, source_data)) do case User.update_info(user, &User.Info.set_source_data(&1, source_data)) do
user {:ok, user} -> user
else _ -> user
_e -> user
end end
ActivityPub.update(%{ ActivityPub.update(%{
@ -255,14 +251,8 @@ def update(user) do
def pin(id_or_ap_id, %{ap_id: user_ap_id} = user) do def pin(id_or_ap_id, %{ap_id: user_ap_id} = user) do
with %Activity{ with %Activity{
actor: ^user_ap_id, actor: ^user_ap_id,
data: %{ data: %{"type" => "Create"},
"type" => "Create" object: %Object{data: %{"type" => "Note"}}
},
object: %Object{
data: %{
"type" => "Note"
}
}
} = activity <- get_by_id_or_ap_id(id_or_ap_id), } = activity <- get_by_id_or_ap_id(id_or_ap_id),
true <- Visibility.is_public?(activity), true <- Visibility.is_public?(activity),
{:ok, _user} <- User.update_info(user, &User.Info.add_pinnned_activity(&1, activity)) do {:ok, _user} <- User.update_info(user, &User.Info.add_pinnned_activity(&1, activity)) do
@ -299,19 +289,13 @@ def remove_mute(user, activity) do
def thread_muted?(%{id: nil} = _user, _activity), do: false def thread_muted?(%{id: nil} = _user, _activity), do: false
def thread_muted?(user, activity) do def thread_muted?(user, activity) do
with [] <- ThreadMute.check_muted(user.id, activity.data["context"]) do ThreadMute.check_muted(user.id, activity.data["context"]) != []
false
else
_ -> true
end
end end
def report(user, data) do def report(user, %{"account_id" => account_id} = data) do
with {:account_id, %{"account_id" => account_id}} <- {:account_id, data}, with {:ok, account} <- get_reported_account(account_id),
{:account, %User{} = account} <- {:account, User.get_cached_by_id(account_id)},
{:ok, {content_html, _, _}} <- make_report_content_html(data["comment"]), {:ok, {content_html, _, _}} <- make_report_content_html(data["comment"]),
{:ok, statuses} <- get_report_statuses(account, data), {:ok, statuses} <- get_report_statuses(account, data) do
{:ok, activity} <-
ActivityPub.flag(%{ ActivityPub.flag(%{
context: Utils.generate_context_id(), context: Utils.generate_context_id(),
actor: user, actor: user,
@ -319,31 +303,32 @@ def report(user, data) do
statuses: statuses, statuses: statuses,
content: content_html, content: content_html,
forward: data["forward"] || false forward: data["forward"] || false
}) do })
{:ok, activity} end
else end
{:error, err} -> {:error, err}
{:account_id, %{}} -> {:error, dgettext("errors", "Valid `account_id` required")} def report(_user, _params), do: {:error, dgettext("errors", "Valid `account_id` required")}
{:account, nil} -> {:error, dgettext("errors", "Account not found")}
defp get_reported_account(account_id) do
case User.get_cached_by_id(account_id) do
%User{} = account -> {:ok, account}
_ -> {:error, dgettext("errors", "Account not found")}
end end
end end
def update_report_state(activity_id, state) do def update_report_state(activity_id, state) do
with %Activity{} = activity <- Activity.get_by_id(activity_id), with %Activity{} = activity <- Activity.get_by_id(activity_id) do
{:ok, activity} <- Utils.update_report_state(activity, state) do Utils.update_report_state(activity, state)
{:ok, activity}
else else
nil -> {:error, :not_found} nil -> {:error, :not_found}
{:error, reason} -> {:error, reason}
_ -> {:error, dgettext("errors", "Could not update state")} _ -> {:error, dgettext("errors", "Could not update state")}
end end
end end
def update_activity_scope(activity_id, opts \\ %{}) do def update_activity_scope(activity_id, opts \\ %{}) do
with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id), with %Activity{} = activity <- Activity.get_by_id_with_object(activity_id),
{:ok, activity} <- toggle_sensitive(activity, opts), {:ok, activity} <- toggle_sensitive(activity, opts) do
{:ok, activity} <- set_visibility(activity, opts) do set_visibility(activity, opts)
{:ok, activity}
else else
nil -> {:error, :not_found} nil -> {:error, :not_found}
{:error, reason} -> {:error, reason} {:error, reason} -> {:error, reason}

View file

@ -231,7 +231,7 @@ def make_content_html(
no_attachment_links = no_attachment_links =
data data
|> Map.get("no_attachment_links", Config.get([:instance, :no_attachment_links])) |> Map.get("no_attachment_links", Config.get([:instance, :no_attachment_links]))
|> Kernel.in([true, "true"]) |> truthy_param?()
content_type = get_content_type(data["content_type"]) content_type = get_content_type(data["content_type"])
@ -431,12 +431,14 @@ def confirm_current_password(user, password) do
end end
end end
def emoji_from_profile(%{info: _info} = user) do def emoji_from_profile(%User{bio: bio, name: name}) do
(Emoji.Formatter.get_emoji(user.bio) ++ Emoji.Formatter.get_emoji(user.name)) [bio, name]
|> Enum.map(fn {shortcode, %Emoji{file: url}} -> |> Enum.map(&Emoji.Formatter.get_emoji/1)
|> Enum.concat()
|> Enum.map(fn {shortcode, %Emoji{file: path}} ->
%{ %{
"type" => "Emoji", "type" => "Emoji",
"icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}#{url}"}, "icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}#{path}"},
"name" => ":#{shortcode}:" "name" => ":#{shortcode}:"
} }
end) end)