CommonAPI: Extend api with conversation replies.

This commit is contained in:
lain 2019-08-02 15:05:27 +02:00
parent f88560accd
commit 56b1c3af13
4 changed files with 70 additions and 13 deletions

View File

@ -93,4 +93,10 @@ def for_user_with_last_activity_id(user, params \\ %{}) do
end) end)
|> Enum.filter(& &1.last_activity_id) |> Enum.filter(& &1.last_activity_id)
end end
def get(nil), do: nil
def get(id) do
Repo.get(__MODULE__, id)
end
end end

View File

@ -4,6 +4,7 @@
defmodule Pleroma.Web.CommonAPI do defmodule Pleroma.Web.CommonAPI do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Conversation.Participation
alias Pleroma.Formatter alias Pleroma.Formatter
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.ThreadMute alias Pleroma.ThreadMute
@ -171,21 +172,25 @@ defp normalize_and_validate_choice_indices(choices, count) do
end) end)
end end
def get_visibility(%{"visibility" => visibility}, in_reply_to) def get_visibility(_, _, %Participation{}) do
{"direct", "direct"}
end
def get_visibility(%{"visibility" => visibility}, in_reply_to, _)
when visibility in ~w{public unlisted private direct}, when visibility in ~w{public unlisted private direct},
do: {visibility, get_replied_to_visibility(in_reply_to)} do: {visibility, get_replied_to_visibility(in_reply_to)}
def get_visibility(%{"visibility" => "list:" <> list_id}, in_reply_to) do def get_visibility(%{"visibility" => "list:" <> list_id}, in_reply_to, _) do
visibility = {:list, String.to_integer(list_id)} visibility = {:list, String.to_integer(list_id)}
{visibility, get_replied_to_visibility(in_reply_to)} {visibility, get_replied_to_visibility(in_reply_to)}
end end
def get_visibility(_, in_reply_to) when not is_nil(in_reply_to) do def get_visibility(_, in_reply_to, _) when not is_nil(in_reply_to) do
visibility = get_replied_to_visibility(in_reply_to) visibility = get_replied_to_visibility(in_reply_to)
{visibility, visibility} {visibility, visibility}
end end
def get_visibility(_, in_reply_to), do: {"public", get_replied_to_visibility(in_reply_to)} def get_visibility(_, in_reply_to, _), do: {"public", get_replied_to_visibility(in_reply_to)}
def get_replied_to_visibility(nil), do: nil def get_replied_to_visibility(nil), do: nil
@ -201,7 +206,9 @@ def post(user, %{"status" => status} = data) do
with status <- String.trim(status), with status <- String.trim(status),
attachments <- attachments_from_ids(data), attachments <- attachments_from_ids(data),
in_reply_to <- get_replied_to_activity(data["in_reply_to_status_id"]), in_reply_to <- get_replied_to_activity(data["in_reply_to_status_id"]),
{visibility, in_reply_to_visibility} <- get_visibility(data, in_reply_to), in_reply_to_conversation <- Participation.get(data["in_reply_to_conversation_id"]),
{visibility, in_reply_to_visibility} <-
get_visibility(data, in_reply_to, in_reply_to_conversation),
{_, false} <- {_, false} <-
{:private_to_public, in_reply_to_visibility == "direct" && visibility != "direct"}, {:private_to_public, in_reply_to_visibility == "direct" && visibility != "direct"},
{content_html, mentions, tags} <- {content_html, mentions, tags} <-
@ -214,7 +221,8 @@ def post(user, %{"status" => status} = data) do
mentioned_users <- for({_, mentioned_user} <- mentions, do: mentioned_user.ap_id), mentioned_users <- for({_, mentioned_user} <- mentions, do: mentioned_user.ap_id),
addressed_users <- get_addressed_users(mentioned_users, data["to"]), addressed_users <- get_addressed_users(mentioned_users, data["to"]),
{poll, poll_emoji} <- make_poll_data(data), {poll, poll_emoji} <- make_poll_data(data),
{to, cc} <- get_to_and_cc(user, addressed_users, in_reply_to, visibility), {to, cc} <-
get_to_and_cc(user, addressed_users, in_reply_to, visibility, in_reply_to_conversation),
context <- make_context(in_reply_to), context <- make_context(in_reply_to),
cw <- data["spoiler_text"] || "", cw <- data["spoiler_text"] || "",
sensitive <- data["sensitive"] || Enum.member?(tags, {"#nsfw", "nsfw"}), sensitive <- data["sensitive"] || Enum.member?(tags, {"#nsfw", "nsfw"}),

View File

@ -8,6 +8,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
alias Calendar.Strftime alias Calendar.Strftime
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Config alias Pleroma.Config
alias Pleroma.Conversation.Participation
alias Pleroma.Formatter alias Pleroma.Formatter
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Plugs.AuthenticationPlug alias Pleroma.Plugs.AuthenticationPlug
@ -64,9 +65,21 @@ def attachments_from_ids_descs(ids, descs_str) do
end) end)
end end
@spec get_to_and_cc(User.t(), list(String.t()), Activity.t() | nil, String.t()) :: @spec get_to_and_cc(
User.t(),
list(String.t()),
Activity.t() | nil,
String.t(),
Participation.t() | nil
) ::
{list(String.t()), list(String.t())} {list(String.t()), list(String.t())}
def get_to_and_cc(user, mentioned_users, inReplyTo, "public") do
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] to = [Pleroma.Constants.as_public() | mentioned_users]
cc = [user.follower_address] cc = [user.follower_address]
@ -77,7 +90,7 @@ def get_to_and_cc(user, mentioned_users, inReplyTo, "public") do
end end
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] to = [user.follower_address | mentioned_users]
cc = [Pleroma.Constants.as_public()] cc = [Pleroma.Constants.as_public()]
@ -88,12 +101,12 @@ def get_to_and_cc(user, mentioned_users, inReplyTo, "unlisted") do
end end
end end
def get_to_and_cc(user, mentioned_users, inReplyTo, "private") do def get_to_and_cc(user, mentioned_users, inReplyTo, "private", _) do
{to, cc} = get_to_and_cc(user, mentioned_users, inReplyTo, "direct") {to, cc} = get_to_and_cc(user, mentioned_users, inReplyTo, "direct", nil)
{[user.follower_address | to], cc} {[user.follower_address | to], cc}
end 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 if inReplyTo do
{Enum.uniq([inReplyTo.data["actor"] | mentioned_users]), []} {Enum.uniq([inReplyTo.data["actor"] | mentioned_users]), []}
else else
@ -101,7 +114,7 @@ def get_to_and_cc(_user, mentioned_users, inReplyTo, "direct") do
end end
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 def get_addressed_users(_, to) when is_list(to) do
User.get_ap_ids_by_nicknames(to) User.get_ap_ids_by_nicknames(to)

View File

@ -5,6 +5,7 @@
defmodule Pleroma.Web.CommonAPITest do defmodule Pleroma.Web.CommonAPITest do
use Pleroma.DataCase use Pleroma.DataCase
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Conversation.Participation
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@ -12,6 +13,35 @@ defmodule Pleroma.Web.CommonAPITest do
import Pleroma.Factory import Pleroma.Factory
test "when replying to a conversation / participation, it only mentions the recipients explicitly declared in the participation" do
har = insert(:user)
jafnhar = insert(:user)
tridi = insert(:user)
{:ok, activity} =
CommonAPI.post(har, %{
"status" => "@#{jafnhar.nickname} hey",
"visibility" => "direct"
})
assert har.ap_id in activity.recipients
assert jafnhar.ap_id in activity.recipients
[participation] = Participation.for_user(har)
{:ok, activity} =
CommonAPI.post(har, %{
"status" => "I don't really like @#{tridi.nickname}",
"visibility" => "direct",
"in_reply_to_status_id" => activity.id,
"in_reply_to_conversation_id" => participation.id
})
assert har.ap_id in activity.recipients
assert jafnhar.ap_id in activity.recipients
refute tridi.ap_id in activity.recipients
end
test "with the safe_dm_mention option set, it does not mention people beyond the initial tags" do test "with the safe_dm_mention option set, it does not mention people beyond the initial tags" do
har = insert(:user) har = insert(:user)
jafnhar = insert(:user) jafnhar = insert(:user)