-
Notifications
You must be signed in to change notification settings - Fork 1
Getting Started
Welcome! This is a simple guide to get you started with handling spam with Ivory.
This guide makes a few assumptions about how you're installing:
- You're installing on Linux (BSD or OS X might also work, but this has not been tested).
- You can get into an
sh
-style terminal on the machine, and are moderately comfortable with it - Your machine has Python and Git installed (it probably does)
Installation is just a few terminal commands:
git clone https://github.com/bclindner/ivory
cd ivory
python -m venv .
./bin/python -m pip install -r requirements.txt
This is probably the hardest part about Ivory, and no one config will work for every instance. Ivory looks for the config file at config.json
in the directory you run it from. Go ahead and create a config.json
file there with this template:
{
"token": "...",
"instanceURL": "...",
"reports": {
"rules": [
]
}
}
You'll want to fill in that instance URL with your instance, and create a new application in the Development tab of the Mastodon preferences menu to get an access token. Make sure to give this token full admin access - and with that said, please, PLEASE be careful with this token - if it falls into the wrong hands, someone could literally ban everyone signed into your instance in minutes.
Now for the tough part - rules. Think of rules as tiny little automated tests for your moderation queues. You can handle individual spam patterns with these custom rules, and cut and paste them in and out as you see fit to make Ivory do exactly what you want it to. Rules in Ivory are set up in the JSON file as shown above, inside that empty "rules" section.
For your first rule, think of a common way spam shows up on your instance. A common spam pattern at the time of writing is breaking into accounts, changing their bio to add a spam link, and then following a ton of people in hopes that they'll look at the account and click the link out of curiosity. Users report these spammers and it's a pain to keep up with them all manually, so let's add a rule to make Ivory automatically suspend reported users that have one of those spam site links is in the bio.
{
"token": "...",
"instanceURL": "...",
"reports": {
"rules": [
{
"name": "No link-in-bio spammers",
"type": "bio_content",
"blocked": ["sexie\\.webzone", "evildatingsi\\.tes"],
"severity": 1,
"punishment": {
"type": "suspend",
"message": "Your account has been suspended for spamming."
}
}
]
}
}
That's quite a few lines, so let's break it down:
-
name
: This is the friendly, human-readable name that shows up in Ivory's logs when someone breaks a rule. Set this to whatever you like. -
type
: This is the most important field here -bio_content
tells Ivory it should filter all reports based on what's in a reported user's bio. For the full list of rules and some examples, check the Rules page. -
blocked
: This is essentially a list of stuff you don't want to see in the bio, in regular expression form. If you're not familiar with regular expressions, don't worry - for most use cases you can just put in the words or phrases you want to block in the quotes there and it will work okay. -
severity
: Severity is a sort of priority level for your rules. If a moderation item breaks multiple rules, it will use the punishment from the one with the highest number in the severity field. -
punishment
: This object is what tells Ivory how to swing the banhammer if a rule is violated.-
type
: This string here determines the exact action Ivory should take if a rule is violated. For this one, we're going for a full, no-mercy suspension. -
message
: If the punishment type supports it, you can send a message to the user being moderated.
-
Now that we've got this rule fully sorted out, we can test it. However, it would be foolish to just start it up and hope for the best. At the top of your config, add this dryRun
field as shown below, to signify to Ivory that you just want it to run the rules and see what it would do, without the fear of it accidentally suspending someone.
{
"dryRun": true,
"token": "..."
Once you've run it a few times on some reports (see Running below) and read the logs and are confident that Ivory is going to take the right actions with this config going forward, go ahead and remove that dryRun
field and start Ivory back up.
Ivory isn't only capable of handling reports - if your registrations are closed, it can also handle your pending account queue with almost all the same rules.
As an example, let's say you're getting automated signups with that same set of links from above in there. Using the previous config as a jumping off point, we can add a new pendingAccounts
field along with the reports
field we already have, set up almost exactly the same way. Instead of looking for the link in the bio, though, we're looking for the link in the signup message.
It'll look something like this:
{
"token": "...",
"instanceURL": "...",
"reports": {
"rules": [
{
"name": "No link-in-bio spammers",
"type": "bio_content",
"blocked": ["sexie\\.webzone", "evildatingsi\\.tes"],
"severity": 1,
"punishment": {
"type": "suspend",
"message": "Your account has been suspended for spamming."
}
}
]
},
"pendingAccounts": {
"rules": [
{
"name": "No bad links",
"type": "message_content",
"blocked": ["sexie\\.webzone", "evildatingsi\\.tes"],
"severity": 1,
"punishment": {
"type": "reject"
}
}
]
}
}
We have a very similar rule structure, but you'll notice the type has been changed to message_content
(for reasons discussed above), punishment's message
has been removed, and the type
has been changed to reject
- this is because this is the only action Ivory can take on pending accounts right now, and we can't send any message to the user when we reject them, so adding a message
is pointless.
You can run Ivory one of two ways: in "watch" mode, which just sort of keeps the script open and runs it every X seconds, or "oneshot" mode with a scheduler like cron or systemd timer units.
Watch is as simple as it gets - one command in terminal:
./bin/python .
This sets up Ivory to run immediately, and then try to run every 5 minutes thereafter. If you want to set a custom time, add a waitTime
field in the config with the number of seconds you want between checks - for instance, to make it run every 10 minutes you would set waitTime
to 600.
You can open up a terminal window on your computer and keep this running, but it's probably best to set the script up to run in the background with a systemd service or something like that.
Running in oneshot mode is also pretty simple:
./bin/python . oneshot
This just runs it once and exits. This is great for testing and debugging your rules, but it also lends itself extremely well to job schedulers. Here's an example of a cron job that will run Ivory every 10 minutes, and pipe the logs to a file:
*/10 * * * * cd /srv/ivory; ./bin/python . oneshot >> ivory.log