diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 62f4a33c8..d94ad9748 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -426,15 +426,26 @@ defp restrict_since(query, %{"since_id" => since_id}) do defp restrict_since(query, _), do: query - defp restrict_tag(query, %{"tag" => tag, "tag_reject" => tag_reject}) - when is_list(tag) and tag_reject != [] 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("(? #> '{\"object\",\"tag\"}') \\?| ?", activity.data, ^tag), 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, @@ -591,6 +602,8 @@ def fetch_activities_query(recipients, opts \\ %{}) 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) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 6811f827e..4c5f1e7a9 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -541,11 +541,16 @@ def hashtag_timeline(%{assigns: %{user: user}} = conn, params) do local_only = params["local"] in [true, "True", "true", "1"] tags = - ([params["tag"]] ++ (params["all"] || []) ++ (params["any"] || [])) + ([params["tag"]] ++ (params["any"] || [])) |> Enum.uniq() |> Enum.filter(& &1) |> Enum.map(&String.downcase(&1)) + tag_all = + params["all"] || + [] + |> Enum.map(&String.downcase(&1)) + tag_reject = params["none"] || [] @@ -557,6 +562,7 @@ def hashtag_timeline(%{assigns: %{user: user}} = conn, params) do |> Map.put("local_only", local_only) |> Map.put("blocking_user", user) |> Map.put("tag", tags) + |> Map.put("tag_all", tag_all) |> Map.put("tag_reject", tag_reject) activities = diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index acece36f0..48eed3f13 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -81,9 +81,16 @@ test "it fetches the appropriate tag-restricted posts" do "tag_reject" => ["reject"] }) + fetch_four = + ActivityPub.fetch_activities([], %{ + "tag" => ["test"], + "tag_all" => ["test", "reject"] + }) + assert fetch_one == [status_one, status_three] assert fetch_two == [status_one, status_two, status_three] assert fetch_three == [status_one, status_two] + assert fetch_four == [status_three] end end diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index be868c081..b4870e0b2 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -1051,11 +1051,11 @@ test "multi-hashtag timeline", %{conn: conn} do {:ok, activity_test1} = CommonAPI.post(user, %{"status" => "#test1"}) {:ok, activity_none} = CommonAPI.post(user, %{"status" => "#test #none"}) - all_test = + any_test = conn - |> get("/api/v1/timelines/tag/test", %{"all" => ["test1"]}) + |> get("/api/v1/timelines/tag/test", %{"any" => ["none"]}) - assert [status_none, status_test1, status_test] = json_response(all_test, 200) + [status_none, status_test1, status_test] = json_response(any_test, 200) assert to_string(activity_test.id) == status_test["id"] assert to_string(activity_test1.id) == status_test1["id"] @@ -1066,6 +1066,10 @@ test "multi-hashtag timeline", %{conn: conn} do |> get("/api/v1/timelines/tag/test", %{"all" => ["test1"], "none" => ["none"]}) assert [status_test1, status_test] == json_response(restricted_test, 200) + + all_test = conn |> get("/api/v1/timelines/tag/test", %{"all" => ["none"]}) + + assert [status_none] == json_response(all_test, 200) end test "getting followers", %{conn: conn} do