diff options
| -rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 33 | ||||
| -rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 1 | ||||
| -rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api_controller.ex | 4 | ||||
| -rw-r--r-- | test/web/activity_pub/activity_pub_test.exs | 48 | 
4 files changed, 85 insertions, 1 deletions
| diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index fc191addf..173ca688d 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -787,4 +787,37 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      y = activity.data["to"] ++ (activity.data["cc"] || [])      visible_for_user?(activity, nil) || Enum.any?(x, &(&1 in y))    end + +  # guard +  def entire_thread_visible_for_user?(nil, user), do: false + +  # child +  def entire_thread_visible_for_user?( +        %Activity{data: %{"object" => %{"inReplyTo" => _parent_id}}} = tail, +        user +      ) do +    parent = Activity.get_in_reply_to_activity(tail) +    visible_for_user?(tail, user) && entire_thread_visible_for_user?(parent, user) +  end + +  # root +  def entire_thread_visible_for_user?(tail, user), do: visible_for_user?(tail, user) + +  # filter out broken threads +  def contain_broken_threads(%Activity{} = activity, %User{} = user) do +    entire_thread_visible_for_user?(activity, user) +  end + +  # do post-processing on a specific activity +  def contain_activity(%Activity{} = activity, %User{} = user) do +    contain_broken_threads(activity, user) +  end + +  # do post-processing on a timeline +  def contain_timeline(timeline, user) do +    timeline +    |> Enum.filter(fn activity -> +      contain_activity(activity, user) +    end) +  end  end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 751698ca8..bc7558cb8 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -223,6 +223,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do      activities =        ActivityPub.fetch_activities([user.ap_id | user.following], params) +      |> ActivityPub.contain_timeline(user)        |> Enum.reverse()      conn diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index c6637e38d..4fc32b50c 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -79,7 +79,9 @@ defmodule Pleroma.Web.TwitterAPI.Controller do        |> Map.put("blocking_user", user)        |> Map.put("user", user) -    activities = ActivityPub.fetch_activities([user.ap_id | user.following], params) +    activities = +      ActivityPub.fetch_activities([user.ap_id | user.following], params) +      |> ActivityPub.contain_timeline(user)      conn      |> render(ActivityView, "index.json", %{activities: activities, for: user}) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 1cf7d6bbc..35c381ac3 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -476,6 +476,54 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do      end    end +  describe "timeline post-processing" do +    test "it filters broken threads" do +      user1 = insert(:user) +      user2 = insert(:user) +      user3 = insert(:user) + +      {:ok, user1} = User.follow(user1, user3) +      assert User.following?(user1, user3) + +      {:ok, user2} = User.follow(user2, user3) +      assert User.following?(user2, user3) + +      {:ok, user3} = User.follow(user3, user2) +      assert User.following?(user3, user2) + +      {:ok, public_activity} = CommonAPI.post(user3, %{"status" => "hi 1"}) + +      {:ok, private_activity_1} = +        CommonAPI.post(user3, %{"status" => "hi 2", "visibility" => "private"}) + +      {:ok, private_activity_2} = +        CommonAPI.post(user2, %{ +          "status" => "hi 3", +          "visibility" => "private", +          "in_reply_to_status_id" => private_activity_1.id +        }) + +      {:ok, private_activity_3} = +        CommonAPI.post(user3, %{ +          "status" => "hi 4", +          "visibility" => "private", +          "in_reply_to_status_id" => private_activity_2.id +        }) + +      assert user1.following == [user3.ap_id <> "/followers", user1.ap_id] + +      activities = ActivityPub.fetch_activities([user1.ap_id | user1.following]) + +      assert [public_activity, private_activity_1, private_activity_3] == activities +      assert length(activities) == 3 + +      activities = ActivityPub.contain_timeline(activities, user1) + +      assert [public_activity, private_activity_1] == activities +      assert length(activities) == 2 +    end +  end +    test "it can fetch plume articles" do      {:ok, object} =        ActivityPub.fetch_object_from_id( | 
