aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/pleroma/web/activity_pub/mrf/auto_subject_policy.ex113
-rw-r--r--test/pleroma/web/activity_pub/mrf/auto_subject_policy_test.exs98
2 files changed, 139 insertions, 72 deletions
diff --git a/lib/pleroma/web/activity_pub/mrf/auto_subject_policy.ex b/lib/pleroma/web/activity_pub/mrf/auto_subject_policy.ex
index 0f9ed4ed1..a882ec8d6 100644
--- a/lib/pleroma/web/activity_pub/mrf/auto_subject_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/auto_subject_policy.ex
@@ -3,57 +3,14 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.AutoSubjectPolicy do
- alias Pleroma.User
-
- require Pleroma.Constants
-
- require Logger
-
@moduledoc "Apply Subject to local posts matching certain keywords."
@behaviour Pleroma.Web.ActivityPub.MRF
- defp string_matches?(content, _) when not is_binary(content) do
- false
- end
-
- defp string_matches?(content, keywords) when is_list(keywords) do
- wordlist = content |> String.downcase() |> String.split(" ", trim: true) |> Enum.uniq()
- Enum.any?(keywords, fn match -> String.downcase(match) in wordlist end)
- end
-
- defp string_matches?(content, keyword) when is_binary(keyword) do
- wordlist = content |> String.downcase() |> String.split(" ", trim: true) |> Enum.uniq()
- String.downcase(keyword) in wordlist
- end
-
- defp check_subject(%{"object" => %{} = object} = message) do
- if String.length(object["summary"] |> String.trim()) == 0 do
- {:ok, message}
- else
- {:error, :has_subject}
- end
- end
-
- defp check_match(%{"object" => %{} = object} = message) do
- auto_summary =
- Enum.map(
- Pleroma.Config.get([:mrf_auto_subject, :match]),
- fn {keyword, subject} ->
- if string_matches?(object["content"], keyword) do
- subject
- end
- end
- )
- |> Enum.filter(& &1)
- |> Enum.join(", ")
-
- object = Map.put(object, "summary", auto_summary)
-
- message = Map.put(message, "object", object)
+ alias Pleroma.User
- {:ok, message}
- end
+ require Pleroma.Constants
+ require Logger
@impl true
def filter(%{"type" => "Create", "actor" => actor, "object" => _object} = message) do
@@ -79,42 +36,54 @@ defmodule Pleroma.Web.ActivityPub.MRF.AutoSubjectPolicy do
@impl true
def filter(message), do: {:ok, message}
+ defp check_subject(%{"object" => %{"summary" => subject}} = message) do
+ subject = String.trim(subject)
+
+ if String.length(subject) == 0 do
+ {:ok, message}
+ else
+ {:error, :has_subject}
+ end
+ end
+
+ defp check_subject(message), do: {:ok, message}
+
+ defp string_matches?(content, pattern) when is_binary(content) do
+ String.contains?(content, pattern)
+ end
+
+ defp check_match(%{"object" => %{} = object} = message) do
+ match_settings = Pleroma.Config.get([:mrf_auto_subject, :match])
+
+ auto_summary =
+ Enum.reduce(match_settings, [], fn {keywords, subject}, acc ->
+ if string_matches?(object["content"], keywords) do
+ [subject | acc]
+ else
+ acc
+ end
+ end)
+ |> Enum.join(", ")
+
+ message = put_in(message["object"]["summary"], auto_summary)
+
+ {:ok, message}
+ end
+
@impl true
def describe do
- # This horror is needed to convert regex sigils to strings
mrf_autosubject =
- Pleroma.Config.get(:mrf_autosubject, [])
- |> Enum.map(fn {key, value} ->
- {key,
- Enum.map(value, fn
- {pattern, keyword} ->
- %{
- "pattern" =>
- if not is_binary(pattern) do
- inspect(pattern)
- else
- pattern
- end,
- "keyword" => keyword
- }
-
- pattern ->
- if not is_binary(pattern) do
- inspect(pattern)
- else
- pattern
- end
- end)}
- end)
+ :mrf_auto_subject
+ |> Pleroma.Config.get()
|> Enum.into(%{})
- {:ok, %{mrf_autosubject: mrf_autosubject}}
+ {:ok, %{mrf_auto_subject: mrf_autosubject}}
end
@impl true
def config_description do
%{
- key: :mrf_autosubject,
+ key: :mrf_auto_subject,
related_policy: "Pleroma.Web.ActivityPub.MRF.AutoSubjectPolicy",
label: "MRF AutoSubject",
description:
diff --git a/test/pleroma/web/activity_pub/mrf/auto_subject_policy_test.exs b/test/pleroma/web/activity_pub/mrf/auto_subject_policy_test.exs
new file mode 100644
index 000000000..ed7fa9385
--- /dev/null
+++ b/test/pleroma/web/activity_pub/mrf/auto_subject_policy_test.exs
@@ -0,0 +1,98 @@
+defmodule Pleroma.Web.ActivityPub.MRF.AutoSubjectPolicyTest do
+ use Pleroma.DataCase
+
+ import Pleroma.Factory
+
+ alias Pleroma.Web.ActivityPub.MRF.AutoSubjectPolicy
+
+ describe "filter/1" do
+ setup do
+ user = insert(:user)
+ [user: user]
+ end
+
+ test "pattern as string", %{user: user} do
+ clear_config([:mrf_auto_subject, :match], [{"yes", "no"}])
+
+ assert {:ok, %{"object" => %{"content" => "yes & no", "summary" => "no"}}} =
+ AutoSubjectPolicy.filter(%{
+ "type" => "Create",
+ "actor" => user.ap_id,
+ "object" => %{"content" => "yes & no", "summary" => ""}
+ })
+ end
+
+ test "pattern as list", %{user: user} do
+ clear_config([:mrf_auto_subject, :match], [{["yes", "yep"], "no"}])
+
+ assert {:ok, %{"object" => %{"content" => "yes & no & yep", "summary" => "no"}}} =
+ AutoSubjectPolicy.filter(%{
+ "type" => "Create",
+ "actor" => user.ap_id,
+ "object" => %{"content" => "yes & no & yep"}
+ })
+ end
+
+ test "multiple matches", %{user: user} do
+ clear_config([:mrf_auto_subject, :match], [{["yes", "yep"], "no"}, {"cat", "dog"}])
+
+ assert {:ok, %{"object" => %{"content" => "yes & no & cat", "summary" => "dog, no"}}} =
+ AutoSubjectPolicy.filter(%{
+ "type" => "Create",
+ "actor" => user.ap_id,
+ "object" => %{"content" => "yes & no & cat"}
+ })
+ end
+
+ test "with no match", %{user: user} do
+ clear_config([:mrf_auto_subject, :match], [{"yes", "no"}])
+
+ assert {:ok, %{"object" => %{"content" => "only no", "summary" => ""}}} =
+ AutoSubjectPolicy.filter(%{
+ "type" => "Create",
+ "actor" => user.ap_id,
+ "object" => %{"content" => "only no", "summary" => ""}
+ })
+ end
+
+ test "user is not local" do
+ user = insert(:user, local: false)
+ clear_config([:mrf_auto_subject, :match], [{"yes", "no"}])
+
+ assert {:ok, %{"object" => %{"content" => "yes & no", "summary" => ""}}} =
+ AutoSubjectPolicy.filter(%{
+ "type" => "Create",
+ "actor" => user.ap_id,
+ "object" => %{"content" => "yes & no", "summary" => ""}
+ })
+ end
+
+ test "object contains summary", %{user: user} do
+ clear_config([:mrf_auto_subject, :match], [{"yes", "no"}])
+
+ assert {:ok, %{"object" => %{"content" => "yes & no", "summary" => "subject"}}} =
+ AutoSubjectPolicy.filter(%{
+ "type" => "Create",
+ "actor" => user.ap_id,
+ "object" => %{"content" => "yes & no", "summary" => "subject"}
+ })
+ end
+ end
+
+ test "describe/0" do
+ clear_config([:mrf_auto_subject, :match], [{"yes", "no"}])
+
+ assert AutoSubjectPolicy.describe() ==
+ {:ok,
+ %{
+ mrf_auto_subject: %{
+ match: [{"yes", "no"}]
+ }
+ }}
+ end
+
+ test "config_description/0" do
+ assert %{key: _, related_policy: _, label: _, description: _} =
+ AutoSubjectPolicy.config_description()
+ end
+end