diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/activity.ex | 19 | ||||
| -rw-r--r-- | lib/pleroma/activity/queries.ex | 18 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 65 | ||||
| -rw-r--r-- | lib/pleroma/workers/remote_fetcher_worker.ex | 20 | 
4 files changed, 120 insertions, 2 deletions
| diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 72e2256ea..10b6d7ebd 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -330,4 +330,23 @@ defmodule Pleroma.Activity do        _ -> nil      end    end + +  def replies(activity, opts \\ []) do +    object = Object.normalize(activity) + +    query = +      Activity +      |> Queries.by_type("Create") +      |> Queries.by_object_in_reply_to_id(object.data["id"], skip_preloading: true) +      |> order_by([activity], asc: activity.id) + +    if opts[:self_only] do +      where(query, [a], a.actor == ^activity.actor) +    else +      query +    end +  end + +  def self_replies(activity, opts \\ []), +    do: replies(activity, Keyword.put(opts, :self_only, true))  end diff --git a/lib/pleroma/activity/queries.ex b/lib/pleroma/activity/queries.ex index 79f305201..c17affec9 100644 --- a/lib/pleroma/activity/queries.ex +++ b/lib/pleroma/activity/queries.ex @@ -7,7 +7,7 @@ defmodule Pleroma.Activity.Queries do    Contains queries for Activity.    """ -  import Ecto.Query, only: [from: 2] +  import Ecto.Query, only: [from: 2, where: 3]    @type query :: Ecto.Queryable.t() | Activity.t() @@ -63,6 +63,22 @@ defmodule Pleroma.Activity.Queries do      )    end +  @spec by_object_id(query, String.t()) :: query +  def by_object_in_reply_to_id(query, in_reply_to_id, opts \\ []) do +    query = +      if opts[:skip_preloading] do +        Activity.with_joined_object(query) +      else +        Activity.with_preloaded_object(query) +      end + +    where( +      query, +      [activity, object: o], +      fragment("(?)->>'inReplyTo' = ?", o.data, ^to_string(in_reply_to_id)) +    ) +  end +    @spec by_type(query, String.t()) :: query    def by_type(query \\ Activity, activity_type) do      from( diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index a72d8430f..8266545d1 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -424,7 +424,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do            ])        } -      ActivityPub.create(params) +      with {:ok, created_activity} <- ActivityPub.create(params) do +        for reply_id <- replies(object) do +          Pleroma.Workers.RemoteFetcherWorker.enqueue("fetch_remote", %{"id" => reply_id}) +        end + +        {:ok, created_activity} +      end      else        %Activity{} = activity -> {:ok, activity}        _e -> :error @@ -903,6 +909,62 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do    def set_reply_to_uri(obj), do: obj +  @doc """ +  Serialized Mastodon-compatible `replies` collection containing _self-replies_. +  Based on Mastodon's ActivityPub::NoteSerializer#replies. +  """ +  def set_replies(obj) do +    limit = Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0) + +    replies_uris = +      with true <- limit > 0 || nil, +           %Activity{} = activity <- Activity.get_create_by_object_ap_id(obj["id"]) do +        activity +        |> Activity.self_replies() +        |> select([a], fragment("?->>'id'", a.data)) +        |> limit(^limit) +        |> Repo.all() +      end + +    set_replies(obj, replies_uris || []) +  end + +  defp set_replies(obj, replies_uris) when replies_uris in [nil, []] do +    obj +  end + +  defp set_replies(obj, replies_uris) do +    # Note: stubs (Mastodon doesn't make separate requests via those URIs in FetchRepliesService) +    masto_replies_uri = nil +    masto_replies_next_page_uri = nil + +    replies_collection = %{ +      "type" => "Collection", +      "id" => masto_replies_uri, +      "first" => %{ +        "type" => "Collection", +        "part_of" => masto_replies_uri, +        "items" => replies_uris, +        "next" => masto_replies_next_page_uri +      } +    } + +    Map.merge(obj, %{"replies" => replies_collection}) +  end + +  def replies(%{"replies" => replies = %{}}) do +    replies = +      if is_map(replies["first"]) do +        replies["first"] +      else +        replies +      end + +    replies["items"] || [] +  end + +  def replies(_), do: [] +    # Prepares the object of an outgoing create activity.    def prepare_object(object) do      object @@ -914,6 +976,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do      |> prepare_attachments      |> set_conversation      |> set_reply_to_uri +    |> set_replies      |> strip_internal_fields      |> strip_internal_tags      |> set_type diff --git a/lib/pleroma/workers/remote_fetcher_worker.ex b/lib/pleroma/workers/remote_fetcher_worker.ex new file mode 100644 index 000000000..52db6059b --- /dev/null +++ b/lib/pleroma/workers/remote_fetcher_worker.ex @@ -0,0 +1,20 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.RemoteFetcherWorker do +  alias Pleroma.Object.Fetcher + +  use Pleroma.Workers.WorkerHelper, queue: "remote_fetcher" + +  @impl Oban.Worker +  def perform( +        %{ +          "op" => "fetch_remote", +          "id" => id +        }, +        _job +      ) do +    {:ok, _object} = Fetcher.fetch_object_from_id(id) +  end +end | 
