diff options
| -rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 72 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 5 | ||||
| -rw-r--r-- | lib/pleroma/web/common_api/common_api.ex | 28 | ||||
| -rw-r--r-- | lib/pleroma/web/common_api/utils.ex | 15 | ||||
| -rw-r--r-- | lib/pleroma/web/salmon/salmon.ex | 8 | 
5 files changed, 91 insertions, 37 deletions
| diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 604ffae7b..84d7f47b1 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -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) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index b1e859d7c..3b7193eaa 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -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 diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index cfbc5dc10..4ca59110f 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -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"} -          }, -          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 diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index 887f878c4..83a745b58 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -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, diff --git a/lib/pleroma/web/salmon/salmon.ex b/lib/pleroma/web/salmon/salmon.ex index 0a9e51656..4d89f4bdb 100644 --- a/lib/pleroma/web/salmon/salmon.ex +++ b/lib/pleroma/web/salmon/salmon.ex @@ -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 | 
