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 # 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. # that match actual users. See issue #164 for more information about why this is necessary.
defp get_recipients(%{"type" => "Announce"} = data) do defp get_recipients(%{"type" => "Announce"} = data) do
to = data["to"] || [] to = Map.get(data, "to", [])
cc = data["cc"] || [] cc = Map.get(data, "cc", [])
bcc = Map.get(data, "bcc", [])
actor = User.get_cached_by_ap_id(data["actor"]) actor = User.get_cached_by_ap_id(data["actor"])
recipients = recipients =
(to ++ cc) Enum.filter(Enum.concat([to, cc, bcc]), fn recipient ->
|> Enum.filter(fn recipient ->
case User.get_cached_by_ap_id(recipient) do case User.get_cached_by_ap_id(recipient) do
nil -> nil -> true
true user -> User.following?(user, actor)
user ->
User.following?(user, actor)
end end
end) end)
@ -48,17 +45,19 @@ defp get_recipients(%{"type" => "Announce"} = data) do
end end
defp get_recipients(%{"type" => "Create"} = data) do defp get_recipients(%{"type" => "Create"} = data) do
to = data["to"] || [] to = Map.get(data, "to", [])
cc = data["cc"] || [] cc = Map.get(data, "cc", [])
actor = data["actor"] || [] bcc = Map.get(data, "bcc", [])
recipients = (to ++ cc ++ [actor]) |> Enum.uniq() actor = Map.get(data, "actor", [])
recipients = [to, cc, bcc, [actor]] |> Enum.concat() |> Enum.uniq()
{recipients, to, cc} {recipients, to, cc}
end end
defp get_recipients(data) do defp get_recipients(data) do
to = data["to"] || [] to = Map.get(data, "to", [])
cc = data["cc"] || [] cc = Map.get(data, "cc", [])
recipients = to ++ cc bcc = Map.get(data, "bcc", [])
recipients = Enum.concat([to, cc, bcc])
{recipients, to, cc} {recipients, to, cc}
end end
@ -917,22 +916,55 @@ def should_federate?(inbox, public) do
end end
end end
def publish(actor, activity) do defp recipients(actor, activity) do
remote_followers = Pleroma.Web.Salmon.remote_users(activity) ++
if actor.follower_address in activity.recipients do if actor.follower_address in activity.recipients do
{:ok, followers} = User.get_followers(actor) {:ok, followers} = User.get_followers(actor)
followers |> Enum.filter(&(!&1.local)) followers |> Enum.filter(&(!&1.local))
else else
[] []
end end
end
def publish(actor, %{data: %{"bcc" => bcc}} = activity) when is_list(bcc) and bcc != [] do
public = is_public?(activity) public = is_public?(activity)
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data) {: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) json = Jason.encode!(data)
(Pleroma.Web.Salmon.remote_users(activity) ++ remote_followers) recipients(actor, activity)
|> Enum.filter(fn user -> User.ap_enabled?(user) end) |> Enum.filter(&User.ap_enabled?/1)
|> Enum.map(fn %{info: %{source_data: data}} -> |> Enum.map(fn %{info: %{source_data: data}} ->
(is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"] (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"]
end) end)

View file

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

View file

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

View file

@ -8,6 +8,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Config alias Pleroma.Config
alias Pleroma.Formatter alias Pleroma.Formatter
alias Pleroma.List
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.User alias Pleroma.User
@ -102,6 +103,20 @@ def to_for_user_and_mentions(_user, mentions, inReplyTo, "direct") do
end end
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( def make_content_html(
status, status,
attachments, attachments,

View file

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