# 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)
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
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)
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 ->
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"] || "")),
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"}
- },
- Pleroma.Web.ControllerHelper.truthy_param?(data["preview"]) || false
- )
-
- res
+ ActivityPub.create(
+ %{
+ to: to,
+ actor: user,
+ context: context,
+ object: object,
+ additional: %{"cc" => cc, "bcc" => bcc, "directMessage" => visibility == "direct"}
+ },
+ Pleroma.Web.ControllerHelper.truthy_param?(data["preview"]) || false
+ )
end
end
alias Pleroma.Activity
alias Pleroma.Config
alias Pleroma.Formatter
+ alias Pleroma.List
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
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,