@@ -93,4 +93,10 @@ defmodule Pleroma.Conversation.Participation do | |||
end) | |||
|> Enum.filter(& &1.last_activity_id) | |||
end | |||
def get(nil), do: nil | |||
def get(id) do | |||
Repo.get(__MODULE__, id) | |||
end | |||
end |
@@ -4,6 +4,7 @@ | |||
defmodule Pleroma.Web.CommonAPI do | |||
alias Pleroma.Activity | |||
alias Pleroma.Conversation.Participation | |||
alias Pleroma.Formatter | |||
alias Pleroma.Object | |||
alias Pleroma.ThreadMute | |||
@@ -171,21 +172,25 @@ defmodule Pleroma.Web.CommonAPI do | |||
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}, | |||
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, get_replied_to_visibility(in_reply_to)} | |||
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, visibility} | |||
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 | |||
@@ -201,7 +206,9 @@ defmodule Pleroma.Web.CommonAPI do | |||
with status <- String.trim(status), | |||
attachments <- attachments_from_ids(data), | |||
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} <- | |||
{:private_to_public, in_reply_to_visibility == "direct" && visibility != "direct"}, | |||
{content_html, mentions, tags} <- | |||
@@ -214,7 +221,8 @@ defmodule Pleroma.Web.CommonAPI do | |||
mentioned_users <- for({_, mentioned_user} <- mentions, do: mentioned_user.ap_id), | |||
addressed_users <- get_addressed_users(mentioned_users, data["to"]), | |||
{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), | |||
cw <- data["spoiler_text"] || "", | |||
sensitive <- data["sensitive"] || Enum.member?(tags, {"#nsfw", "nsfw"}), | |||
@@ -8,6 +8,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do | |||
alias Calendar.Strftime | |||
alias Pleroma.Activity | |||
alias Pleroma.Config | |||
alias Pleroma.Conversation.Participation | |||
alias Pleroma.Formatter | |||
alias Pleroma.Object | |||
alias Pleroma.Plugs.AuthenticationPlug | |||
@@ -64,9 +65,21 @@ defmodule Pleroma.Web.CommonAPI.Utils do | |||
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())} | |||
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] | |||
cc = [user.follower_address] | |||
@@ -77,7 +90,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()] | |||
@@ -88,12 +101,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 | |||
@@ -101,7 +114,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) | |||
@@ -5,6 +5,7 @@ | |||
defmodule Pleroma.Web.CommonAPITest do | |||
use Pleroma.DataCase | |||
alias Pleroma.Activity | |||
alias Pleroma.Conversation.Participation | |||
alias Pleroma.Object | |||
alias Pleroma.User | |||
alias Pleroma.Web.ActivityPub.ActivityPub | |||
@@ -12,6 +13,35 @@ defmodule Pleroma.Web.CommonAPITest do | |||
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 | |||
har = insert(:user) | |||
jafnhar = insert(:user) | |||