X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Factivity_pub%2Fpublisher.ex;h=4073d3d63455ffa3e4aa7b1a9f554ebd630b6ed2;hb=45180d4c6058f790475d8ff28018c912db105082;hp=0bbe6ee805fdd6b613b2dcf4bb518a9437de7784;hpb=b70e659304ba35f7afc598c3d3d1b96fa16f6cdf;p=akkoma diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex index 0bbe6ee80..4073d3d63 100644 --- a/lib/pleroma/web/activity_pub/publisher.ex +++ b/lib/pleroma/web/activity_pub/publisher.ex @@ -5,12 +5,17 @@ defmodule Pleroma.Web.ActivityPub.Publisher do alias Pleroma.Activity alias Pleroma.Config + alias Pleroma.Delivery alias Pleroma.HTTP alias Pleroma.Instances + alias Pleroma.Object + alias Pleroma.Repo alias Pleroma.User alias Pleroma.Web.ActivityPub.Relay alias Pleroma.Web.ActivityPub.Transmogrifier + require Pleroma.Constants + import Pleroma.Web.ActivityPub.Visibility @behaviour Pleroma.Web.Federator.Publisher @@ -44,16 +49,15 @@ defmodule Pleroma.Web.ActivityPub.Publisher do """ def publish_one(%{inbox: inbox, json: json, actor: %User{} = actor, id: id} = params) do Logger.info("Federating #{id} to #{inbox}") - host = URI.parse(inbox).host + %{host: host, path: path} = URI.parse(inbox) digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64()) - date = - NaiveDateTime.utc_now() - |> Timex.format!("{WDshort}, {0D} {Mshort} {YYYY} {h24}:{m}:{s} GMT") + date = Pleroma.Signature.signed_date() signature = Pleroma.Signature.sign(actor, %{ + "(request-target)": "post #{path}", host: host, "content-length": byte_size(json), digest: digest, @@ -83,6 +87,15 @@ defmodule Pleroma.Web.ActivityPub.Publisher do end end + def publish_one(%{actor_id: actor_id} = params) do + actor = User.get_cached_by_id(actor_id) + + params + |> Map.delete(:actor_id) + |> Map.put(:actor, actor) + |> publish_one() + end + defp should_federate?(inbox, public) do if public do true @@ -97,16 +110,27 @@ defmodule Pleroma.Web.ActivityPub.Publisher do end end + @spec recipients(User.t(), Activity.t()) :: list(User.t()) | [] defp recipients(actor, activity) do followers = if actor.follower_address in activity.recipients do - {:ok, followers} = User.get_followers(actor) - Enum.filter(followers, &(!&1.local)) + User.get_external_followers(actor) else [] end - Pleroma.Web.Salmon.remote_users(actor, activity) ++ followers + fetchers = + with %Activity{data: %{"type" => "Delete"}} <- activity, + %Object{id: object_id} <- Object.normalize(activity), + fetchers <- User.get_delivered_users_by_object_id(object_id), + _ <- Delivery.delete_all_by_object_id(object_id) do + fetchers + else + _ -> + [] + end + + Pleroma.Web.Federator.Publisher.remote_users(actor, activity) ++ followers ++ fetchers end defp get_cc_ap_ids(ap_id, recipients) do @@ -117,9 +141,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do |> Enum.map(& &1.ap_id) end - @as_public "https://www.w3.org/ns/activitystreams#Public" - - defp maybe_use_sharedinbox(%User{info: %{source_data: data}}), + defp maybe_use_sharedinbox(%User{source_data: data}), do: (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"] @doc """ @@ -135,7 +157,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do """ def determine_inbox( %Activity{data: activity_data}, - %User{info: %{source_data: data}} = user + %User{source_data: data} = user ) do to = activity_data["to"] || [] cc = activity_data["cc"] || [] @@ -145,7 +167,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do type == "Delete" -> maybe_use_sharedinbox(user) - @as_public in to || @as_public in cc -> + Pleroma.Constants.as_public() in to || Pleroma.Constants.as_public() in cc -> maybe_use_sharedinbox(user) length(to) + length(cc) > 1 -> @@ -160,37 +182,42 @@ defmodule Pleroma.Web.ActivityPub.Publisher do Publishes an activity with BCC to all relevant peers. """ - def publish(actor, %{data: %{"bcc" => bcc}} = activity) when is_list(bcc) and bcc != [] do + def publish(%User{} = 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: ap_id} = - Enum.find(recipients, fn %{info: %{source_data: data}} -> data["inbox"] == inbox end) - - # Get all the recipients on the same host and add them to cc. Otherwise, a remote - # instance would only accept a first message for the first recipient and ignore the rest. - cc = get_cc_ap_ids(ap_id, recipients) - - json = - data - |> Map.put("cc", cc) - |> Jason.encode!() - - Pleroma.Web.Federator.Publisher.enqueue_one(__MODULE__, %{ - inbox: inbox, - json: json, - actor: actor, - id: activity.data["id"], - unreachable_since: unreachable_since - }) + inboxes = + recipients + |> Enum.filter(&User.ap_enabled?/1) + |> Enum.map(fn %{source_data: data} -> data["inbox"] end) + |> Enum.filter(fn inbox -> should_federate?(inbox, public) end) + |> Instances.filter_reachable() + + Repo.checkout(fn -> + Enum.each(inboxes, fn {inbox, unreachable_since} -> + %User{ap_id: ap_id} = + Enum.find(recipients, fn %{source_data: data} -> data["inbox"] == inbox end) + + # Get all the recipients on the same host and add them to cc. Otherwise, a remote + # instance would only accept a first message for the first recipient and ignore the rest. + cc = get_cc_ap_ids(ap_id, recipients) + + json = + data + |> Map.put("cc", cc) + |> Jason.encode!() + + Pleroma.Web.Federator.Publisher.enqueue_one(__MODULE__, %{ + inbox: inbox, + json: json, + actor_id: actor.id, + id: activity.data["id"], + unreachable_since: unreachable_since + }) + end) end) end @@ -222,7 +249,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do %{ inbox: inbox, json: json, - actor: actor, + actor_id: actor.id, id: activity.data["id"], unreachable_since: unreachable_since }