forked from AkkomaGang/akkoma
Add addressable lists
This commit is contained in:
parent
8c9227c1f1
commit
a3dc02d282
5 changed files with 92 additions and 38 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue