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

View file

@ -231,7 +231,7 @@ def make_content_html(
no_attachment_links =
data
|> 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"])
@ -431,12 +431,14 @@ def confirm_current_password(user, password) do
end
end
def emoji_from_profile(%{info: _info} = user) do
(Emoji.Formatter.get_emoji(user.bio) ++ Emoji.Formatter.get_emoji(user.name))
|> Enum.map(fn {shortcode, %Emoji{file: url}} ->
def emoji_from_profile(%User{bio: bio, name: name}) do
[bio, name]
|> Enum.map(&Emoji.Formatter.get_emoji/1)
|> Enum.concat()
|> Enum.map(fn {shortcode, %Emoji{file: path}} ->
%{
"type" => "Emoji",
"icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}#{url}"},
"icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}#{path}"},
"name" => ":#{shortcode}:"
}
end)