Add addressable lists

This commit is contained in:
Egor Kislitsyn 2019-05-01 16:11:17 +07:00
parent 8c9227c1f1
commit a3dc02d282
5 changed files with 92 additions and 38 deletions

View File

@ -28,19 +28,16 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
# For Announce activities, we filter the recipients based on following status for any actors
# that match actual users. See issue #164 for more information about why this is necessary.
defp get_recipients(%{"type" => "Announce"} = data) do
to = data["to"] || []
cc = data["cc"] || []
to = Map.get(data, "to", [])
cc = Map.get(data, "cc", [])
bcc = Map.get(data, "bcc", [])
actor = User.get_cached_by_ap_id(data["actor"])
recipients =
(to ++ cc)
|> Enum.filter(fn recipient ->
Enum.filter(Enum.concat([to, cc, bcc]), fn recipient ->
case User.get_cached_by_ap_id(recipient) do
nil ->
true
user ->
User.following?(user, actor)
nil -> true
user -> User.following?(user, actor)
end
end)
@ -48,17 +45,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
defp get_recipients(%{"type" => "Create"} = data) do
to = data["to"] || []
cc = data["cc"] || []
actor = data["actor"] || []
recipients = (to ++ cc ++ [actor]) |> Enum.uniq()
to = Map.get(data, "to", [])
cc = Map.get(data, "cc", [])
bcc = Map.get(data, "bcc", [])
actor = Map.get(data, "actor", [])
recipients = [to, cc, bcc, [actor]] |> Enum.concat() |> Enum.uniq()
{recipients, to, cc}
end
defp get_recipients(data) do
to = data["to"] || []
cc = data["cc"] || []
recipients = to ++ cc
to = Map.get(data, "to", [])
cc = Map.get(data, "cc", [])
bcc = Map.get(data, "bcc", [])
recipients = Enum.concat([to, cc, bcc])
{recipients, to, cc}
end
@ -917,22 +916,55 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
def publish(actor, activity) do
remote_followers =
defp recipients(actor, activity) do
Pleroma.Web.Salmon.remote_users(activity) ++
if actor.follower_address in activity.recipients do
{:ok, followers} = User.get_followers(actor)
followers |> Enum.filter(&(!&1.local))
else
[]
end
end
def publish(actor, %{data: %{"bcc" => bcc}} = activity) when is_list(bcc) and bcc != [] do
public = is_public?(activity)
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
recipients = recipients(actor, activity)
recipients
|> Enum.filter(&User.ap_enabled?/1)
|> Enum.map(fn %{info: %{source_data: data}} -> data["inbox"] end)
|> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
|> Instances.filter_reachable()
|> Enum.each(fn {inbox, unreachable_since} ->
%User{ap_id: cc} =
Enum.find(recipients, fn %{info: %{source_data: data}} -> data["inbox"] == inbox end)
json =
data
|> Map.put("cc", [cc])
|> Map.put("directMessage", true)
|> Jason.encode!()
Federator.publish_single_ap(%{
inbox: inbox,
json: json,
actor: actor,
id: activity.data["id"],
unreachable_since: unreachable_since
})
end)
end
def publish(actor, activity) do
public = is_public?(activity)
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
json = Jason.encode!(data)
(Pleroma.Web.Salmon.remote_users(activity) ++ remote_followers)
|> Enum.filter(fn user -> User.ap_enabled?(user) end)
recipients(actor, activity)
|> Enum.filter(&User.ap_enabled?/1)
|> Enum.map(fn %{info: %{source_data: data}} ->
(is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"]
end)

View File

@ -741,13 +741,16 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def prepare_outgoing(%{"type" => "Create", "object" => object_id} = data) do
object =
Object.normalize(object_id).data
object_id
|> Object.normalize()
|> Map.get(:data)
|> prepare_object
data =
data
|> Map.put("object", object)
|> Map.merge(Utils.make_json_ld_header())
|> Map.delete("bcc")
{:ok, data}
end

View File

@ -119,6 +119,10 @@ defmodule Pleroma.Web.CommonAPI do
when visibility in ~w{public unlisted private direct},
do: visibility
def get_visibility(%{"visibility" => "list:" <> list_id}) do
{:list, String.to_integer(list_id)}
end
def get_visibility(%{"in_reply_to_status_id" => status_id}) when not is_nil(status_id) do
case get_replied_to_activity(status_id) do
nil ->
@ -149,6 +153,7 @@ defmodule Pleroma.Web.CommonAPI do
visibility
),
{to, cc} <- to_for_user_and_mentions(user, mentions, in_reply_to, visibility),
{:ok, bcc} <- bcc_for_list(user, visibility),
context <- make_context(in_reply_to),
cw <- data["spoiler_text"],
full_payload <- String.trim(status <> (data["spoiler_text"] || "")),
@ -174,19 +179,16 @@ defmodule Pleroma.Web.CommonAPI do
Map.put(acc, name, "#{Pleroma.Web.Endpoint.static_url()}#{file}")
end)
) do
res =
ActivityPub.create(
%{
to: to,
actor: user,
context: context,
object: object,
additional: %{"cc" => cc, "directMessage" => visibility == "direct"}
additional: %{"cc" => cc, "bcc" => bcc, "directMessage" => visibility == "direct"}
},
Pleroma.Web.ControllerHelper.truthy_param?(data["preview"]) || false
)
res
end
end

View File

@ -8,6 +8,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
alias Pleroma.Activity
alias Pleroma.Config
alias Pleroma.Formatter
alias Pleroma.List
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
@ -102,6 +103,20 @@ defmodule Pleroma.Web.CommonAPI.Utils do
end
end
def to_for_user_and_mentions(_user, _mentions, _inReplyTo, _), do: {[], []}
def bcc_for_list(user, {:list, list_id}) do
with {_, %List{} = list} <- {:list, List.get(list_id, user)},
{:ok, following} <- List.get_following(list) do
{:ok, Enum.map(following, & &1.ap_id)}
else
{:list, _} -> {:error, "List not found"}
err -> err
end
end
def bcc_for_list(_, _), do: {:ok, []}
def make_content_html(
status,
attachments,

View File

@ -157,10 +157,12 @@ defmodule Pleroma.Web.Salmon do
end
def remote_users(%{data: %{"to" => to} = data}) do
to = to ++ (data["cc"] || [])
cc = Map.get(data, "cc", [])
bcc = Map.get(data, "bcc", [])
to
|> Enum.map(fn id -> User.get_cached_by_ap_id(id) end)
[to, cc, bcc]
|> Enum.concat()
|> Enum.map(&User.get_cached_by_ap_id/1)
|> Enum.filter(fn user -> user && !user.local end)
end