diff options
author | Mark Felder <feld@FreeBSD.org> | 2020-11-10 13:32:15 -0600 |
---|---|---|
committer | Mark Felder <feld@feld.me> | 2021-05-11 16:50:09 -0500 |
commit | 2880d223181a33efb143012e61603995ef87e6c3 (patch) | |
tree | f0535c96765f37cf0de8f4a010df6fab075af729 | |
parent | 745375bdcf2679ff803dd4ebc4a8313a7b5fb157 (diff) | |
download | pleroma-2880d223181a33efb143012e61603995ef87e6c3.tar.gz |
Add MRF to automatically append keywords to subject when matches found in post content
-rw-r--r-- | lib/pleroma/web/activity_pub/mrf/auto_subject_policy.ex | 135 |
1 files changed, 135 insertions, 0 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 new file mode 100644 index 000000000..d94e243f6 --- /dev/null +++ b/lib/pleroma/web/activity_pub/mrf/auto_subject_policy.ex @@ -0,0 +1,135 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# 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?(string, _) when not is_binary(string) do + false + end + + defp string_matches?(string, pattern) when is_binary(pattern) do + String.contains?(string, pattern) + end + + defp string_matches?(string, pattern) do + String.match?(string, pattern) + 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.reduce( + Pleroma.Config.get([:mrf_auto_subject, :match]), + [], + fn {pat, key}, acc -> + if string_matches?(object["content"], pat) do + [key | acc] + else + acc + end + end + ) + |> Enum.join(", ") + + object = Map.put(object, "summary", auto_summary) + + message = Map.put(message, "object", object) + + {:ok, message} + end + + @impl true + def filter(%{"type" => "Create", "actor" => actor, "object" => _object} = message) do + with {:ok, %User{local: true}} <- User.get_or_fetch_by_ap_id(actor), + {:ok, message} <- check_subject(message), + {:ok, message} <- check_match(message) do + {:ok, message} + else + {:ok, %User{local: false}} -> + {:ok, message} + + {:error, :has_subject} -> + {:ok, message} + + {:error, _} -> + {:reject, "[AutoSubjectPolicy] Failed to get or fetch user by ap_id"} + + e -> + {:reject, "[AutoSubjectPolicy] Unhandled error #{inspect(e)}"} + end + end + + @impl true + def filter(message), do: {:ok, message} + + @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) + |> Enum.into(%{}) + + {:ok, %{mrf_autosubject: mrf_autosubject}} + end + + @impl true + def config_description do + %{ + key: :mrf_autosubject, + related_policy: "Pleroma.Web.ActivityPub.MRF.AutoSubjectPolicy", + label: "MRF AutoSubject", + description: + "Adds subject to messages matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).", + children: [ + %{ + key: :match, + type: {:list, :tuple}, + description: """ + **Pattern**: a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`. + + **Keyword**: a keyword to apply to the subject field. + """ + } + ] + } + end +end |