Cleanup CommonAPI
This commit is contained in:
parent
de3e90e536
commit
c57ad0a402
|
@ -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}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue