X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Factivity_pub%2Factivity_pub.ex;h=c46d8233e04aa77dfef3a4da5e0d49d66679454f;hb=6c8d15da110e86f799052c82df8b7b2404f8f722;hp=44c295d658445c4d9777bdd883cd679e3113e166;hpb=8654a591f08c7d8d5d61f075906f0c6907e877bb;p=akkoma diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 44c295d65..c46d8233e 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -3,13 +3,22 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.ActivityPub.ActivityPub do - alias Pleroma.{Activity, Repo, Object, Upload, User, Notification, Instances} - alias Pleroma.Web.ActivityPub.{Transmogrifier, MRF} + alias Pleroma.Activity + alias Pleroma.Repo + alias Pleroma.Object + alias Pleroma.Upload + alias Pleroma.User + alias Pleroma.Notification + alias Pleroma.Instances + alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Web.ActivityPub.MRF alias Pleroma.Web.WebFinger alias Pleroma.Web.Federator alias Pleroma.Web.OStatus + import Ecto.Query import Pleroma.Web.ActivityPub.Utils + require Logger @httpoison Application.get_env(:pleroma, :httpoison) @@ -19,20 +28,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp get_recipients(%{"type" => "Announce"} = data) do to = data["to"] || [] cc = data["cc"] || [] - recipients = to ++ cc actor = User.get_cached_by_ap_id(data["actor"]) - recipients - |> Enum.filter(fn recipient -> - case User.get_cached_by_ap_id(recipient) do - nil -> - true + recipients = + (to ++ cc) + |> Enum.filter(fn recipient -> + case User.get_cached_by_ap_id(recipient) do + nil -> + true + + user -> + User.following?(user, actor) + end + end) - user -> - User.following?(user, actor) - end - end) + {recipients, to, cc} + end + defp get_recipients(%{"type" => "Create"} = data) do + to = data["to"] || [] + cc = data["cc"] || [] + actor = data["actor"] || [] + recipients = (to ++ cc ++ [actor]) |> Enum.uniq() {recipients, to, cc} end @@ -56,7 +73,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end end - defp check_remote_limit(%{"object" => %{"content" => content}}) do + defp check_remote_limit(%{"object" => %{"content" => content}}) when not is_nil(content) do limit = Pleroma.Config.get([:instance, :remote_limit]) String.length(content) <= limit end @@ -80,6 +97,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do recipients: recipients }) + Task.start(fn -> + Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity) + end) + Notification.create_notifications(activity) stream_out(activity) {:ok, activity} @@ -107,7 +128,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do activity.data["object"] |> Map.get("tag", []) |> Enum.filter(fn tag -> is_bitstring(tag) end) - |> Enum.map(fn tag -> Pleroma.Web.Streamer.stream("hashtag:" <> tag, activity) end) + |> Enum.each(fn tag -> Pleroma.Web.Streamer.stream("hashtag:" <> tag, activity) end) if activity.data["object"]["attachment"] != [] do Pleroma.Web.Streamer.stream("public:media", activity) @@ -410,13 +431,42 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> Enum.reverse() end + defp restrict_since(query, %{"since_id" => ""}), do: query + defp restrict_since(query, %{"since_id" => since_id}) do from(activity in query, where: activity.id > ^since_id) end defp restrict_since(query, _), do: query - defp restrict_tag(query, %{"tag" => tag}) do + defp restrict_tag_reject(query, %{"tag_reject" => tag_reject}) + when is_list(tag_reject) and tag_reject != [] do + from( + activity in query, + where: fragment("(not (? #> '{\"object\",\"tag\"}') \\?| ?)", activity.data, ^tag_reject) + ) + end + + defp restrict_tag_reject(query, _), do: query + + defp restrict_tag_all(query, %{"tag_all" => tag_all}) + when is_list(tag_all) and tag_all != [] do + from( + activity in query, + where: fragment("(? #> '{\"object\",\"tag\"}') \\?& ?", activity.data, ^tag_all) + ) + end + + defp restrict_tag_all(query, _), do: query + + defp restrict_tag(query, %{"tag" => tag}) when is_list(tag) do + from( + activity in query, + where: fragment("(? #> '{\"object\",\"tag\"}') \\?| ?", activity.data, ^tag) + ) + end + + defp restrict_tag(query, %{"tag" => tag}) when is_binary(tag) do from( activity in query, where: fragment("? <@ (? #> '{\"object\",\"tag\"}')", ^tag, activity.data) @@ -465,6 +515,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_local(query, _), do: query + defp restrict_max(query, %{"max_id" => ""}), do: query + defp restrict_max(query, %{"max_id" => max_id}) do from(activity in query, where: activity.id < ^max_id) end @@ -478,7 +530,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_actor(query, _), do: query defp restrict_type(query, %{"type" => type}) when is_binary(type) do - restrict_type(query, %{"type" => [type]}) + from(activity in query, where: fragment("?->>'type' = ?", activity.data, ^type)) end defp restrict_type(query, %{"type" => type}) do @@ -563,6 +615,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do base_query |> restrict_recipients(recipients, opts["user"]) |> restrict_tag(opts) + |> restrict_tag_reject(opts) + |> restrict_tag_all(opts) |> restrict_since(opts) |> restrict_local(opts) |> restrict_limit(opts) @@ -689,7 +743,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do end def publish(actor, activity) do - followers = + remote_followers = if actor.follower_address in activity.recipients do {:ok, followers} = User.get_followers(actor) followers |> Enum.filter(&(!&1.local)) @@ -699,37 +753,31 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do public = is_public?(activity) - remote_inboxes = - (Pleroma.Web.Salmon.remote_users(activity) ++ followers) + reachable_inboxes_metadata = + (Pleroma.Web.Salmon.remote_users(activity) ++ remote_followers) |> Enum.filter(fn user -> User.ap_enabled?(user) end) |> Enum.map(fn %{info: %{source_data: data}} -> (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"] end) |> Enum.uniq() |> Enum.filter(fn inbox -> should_federate?(inbox, public) end) + |> Instances.filter_reachable() {:ok, data} = Transmogrifier.prepare_outgoing(activity.data) json = Jason.encode!(data) - Enum.each(remote_inboxes, fn inbox -> + Enum.each(reachable_inboxes_metadata, fn {inbox, unreachable_since} -> Federator.enqueue(:publish_single_ap, %{ inbox: inbox, json: json, actor: actor, - id: activity.data["id"] + id: activity.data["id"], + unreachable_since: unreachable_since }) end) end - def publish_one(%{inbox: inbox} = activity) do - if Instances.reachable?(inbox) do - do_publish_one(activity) - else - {:error, :noop} - end - end - - defp do_publish_one(%{inbox: inbox, json: json, actor: actor, id: id}) do + def publish_one(%{inbox: inbox, json: json, actor: actor, id: id} = params) do Logger.info("Federating #{id} to #{inbox}") host = URI.parse(inbox).host @@ -750,16 +798,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do [ {"Content-Type", "application/activity+json"}, {"signature", signature}, - {"digest", digest}, - {"referer", Pleroma.Web.Endpoint.url()} + {"digest", digest} ] ) do - Instances.set_reachable(inbox) + if !Map.has_key?(params, :unreachable_since) || params[:unreachable_since], + do: Instances.set_reachable(inbox) + result else - e -> - Instances.set_unreachable(inbox) - e + {_post_result, response} -> + unless params[:unreachable_since], do: Instances.set_unreachable(inbox) + {:error, response} end end