Merge pull request 'docs: Remove quarantine section' (#324) from norm/akkoma:remove...
[akkoma] / docs / docs / configuration / mrf.md
1 # Message Rewrite Facility
2
3 The Message Rewrite Facility (MRF) is a subsystem that is implemented as a series of hooks that allows the administrator to rewrite or discard messages.
4
5 Possible uses include:
6
7 * marking incoming messages with media from a given account or instance as sensitive
8 * rejecting messages from a specific instance
9 * rejecting reports (flags) from a specific instance
10 * removing/unlisting messages from the public timelines
11 * removing media from messages
12 * sending only public messages to a specific instance
13
14 The MRF provides user-configurable policies. The default policy is `NoOpPolicy`, which disables the MRF functionality. Akkoma also includes an easy to use policy called `SimplePolicy` which maps messages matching certain pre-defined criterion to actions built into the policy module.
15
16 It is possible to use multiple, active MRF policies at the same time.
17
18 ## Using `SimplePolicy`
19
20 `SimplePolicy` is capable of handling most common admin tasks.
21
22 To use `SimplePolicy`, you must enable it. Do so by adding the following to your `:instance` config object, so that it looks like this:
23
24 ```elixir
25 config :pleroma, :mrf,
26 [...]
27 policies: Pleroma.Web.ActivityPub.MRF.SimplePolicy
28 ```
29
30 Once `SimplePolicy` is enabled, you can configure various groups in the `:mrf_simple` config object. These groups are:
31
32 * `reject`: Servers in this group will have their messages rejected. Also outbound messages will not be sent to these servers.
33 * `accept`: If not empty, only messages from these instances will be accepted (whitelist federation).
34 * `media_nsfw`: Servers in this group will have the #nsfw tag and sensitive setting injected into incoming messages which contain media.
35 * `media_removal`: Servers in this group will have media stripped from incoming messages.
36 * `avatar_removal`: Avatars from these servers will be stripped from incoming messages.
37 * `banner_removal`: Banner images from these servers will be stripped from incoming messages.
38 * `report_removal`: Servers in this group will have their reports (flags) rejected.
39 * `federated_timeline_removal`: Servers in this group will have their messages unlisted from the public timelines by flipping the `to` and `cc` fields.
40 * `reject_deletes`: Deletion requests will be rejected from these servers.
41
42 Servers should be configured as lists.
43
44 ### Example
45
46 This example will enable `SimplePolicy`, block media from `illegalporn.biz`, mark media as NSFW from `porn.biz` and `porn.business`, reject messages from `spam.com`, remove messages from `spam.university` from the federated timeline and block reports (flags) from `whiny.whiner`. We also give a reason why the moderation was done:
47
48 ```elixir
49 config :pleroma, :mrf,
50 policies: [Pleroma.Web.ActivityPub.MRF.SimplePolicy]
51
52 config :pleroma, :mrf_simple,
53 media_removal: [{"illegalporn.biz", "Media can contain illegal contant"}],
54 media_nsfw: [{"porn.biz", "unmarked nsfw media"}, {"porn.business", "A lot of unmarked nsfw media"}],
55 reject: [{"spam.com", "They keep spamming our users"}],
56 federated_timeline_removal: [{"spam.university", "Annoying low-quality posts who otherwise fill up TWKN"}],
57 report_removal: [{"whiny.whiner", "Keep spamming us with irrelevant reports"}]
58 ```
59
60 ### Use with Care
61
62 The effects of MRF policies can be very drastic. It is important to use this functionality carefully. Always try to talk to an admin before writing an MRF policy concerning their instance.
63
64 ## Writing your own MRF Policy
65
66 As discussed above, the MRF system is a modular system that supports pluggable policies. This means that an admin may write a custom MRF policy in Elixir or any other language that runs on the Erlang VM, by specifying the module name in the `policies` config setting.
67
68 For example, here is a sample policy module which rewrites all messages to "new message content":
69
70 ```elixir
71 defmodule Pleroma.Web.ActivityPub.MRF.RewritePolicy do
72 @moduledoc "MRF policy which rewrites all Notes to have 'new message content'."
73 @behaviour Pleroma.Web.ActivityPub.MRF.Policy
74
75 # Catch messages which contain Note objects with actual data to filter.
76 # Capture the object as `object`, the message content as `content` and the
77 # message itself as `message`.
78 @impl true
79 def filter(
80 %{"type" => "Create", "object" => %{"type" => "Note", "content" => content} = object} =
81 message
82 )
83 when is_binary(content) do
84 # Subject / CW is stored as summary instead of `name` like other AS2 objects
85 # because of Mastodon doing it that way.
86 summary = object["summary"]
87
88 # Message edits go here.
89 content = "new message content"
90
91 # Assemble the mutated object.
92 object =
93 object
94 |> Map.put("content", content)
95 |> Map.put("summary", summary)
96
97 # Assemble the mutated message.
98 message = Map.put(message, "object", object)
99 {:ok, message}
100 end
101
102 # Let all other messages through without modifying them.
103 @impl true
104 def filter(message), do: {:ok, message}
105
106 @impl true
107 def describe do
108 {:ok, %{mrf_sample: %{content: "new message content"}}}
109 end
110 end
111 ```
112
113 If you save this file as `lib/pleroma/web/activity_pub/mrf/rewrite_policy.ex`, it will be included when you next rebuild Akkoma. You can enable it in the configuration like so:
114
115 ```elixir
116 config :pleroma, :mrf,
117 policies: [
118 Pleroma.Web.ActivityPub.MRF.SimplePolicy,
119 Pleroma.Web.ActivityPub.MRF.RewritePolicy
120 ]
121 ```
122
123 Please note that the Akkoma developers consider custom MRF policy modules to fall under the purview of the AGPL. As such, you are obligated to release the sources to your custom MRF policy modules upon request.
124
125 ### MRF policies descriptions
126
127 If MRF policy depends on config, it can be added into MRF tab to adminFE by adding `config_description/0` method, which returns a map with a specific structure. See existing MRF's like `lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex` for examples. Note that more complex inputs, like tuples or maps, may need extra changes in the adminFE and just adding it to `config_description/0` may not be enough to get these inputs working from the adminFE.
128
129 Example:
130
131 ```elixir
132 %{
133 key: :mrf_activity_expiration,
134 related_policy: "Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy",
135 label: "MRF Activity Expiration Policy",
136 description: "Adds automatic expiration to all local activities",
137 children: [
138 %{
139 key: :days,
140 type: :integer,
141 description: "Default global expiration time for all local activities (in days)",
142 suggestions: [90, 365]
143 }
144 ]
145 }
146 ```