Manage your Mastodon blocked domains using cURL

       702 words, 4 minutes

I am no Dev and have nearly no clue on how to deal with APIs. But I am a SysAdmin. And where there’s a shell, there’s a way. So those are my notes on how to deal with Mastodon API using shell tools.

During the Fedi Spam Attacks, I started by silencing the few spams I received at the user level. After a few days, I got bored and decided to simply block those faulty instances. Then a Mastodon-DE blocklist pops out and I decided to apply it.

At some point, I had to apply mass-modifications to my blocked list and discovered that the Mastodon Web GUI lacks a whole lot of options. So I decided to go the API way.

Get an Access Token

Using the admin/domain_blocks Mastodon API requires an authenticated token with the proper permissions to do stuff. Depending on the API you plan to use, have a look at the OAuth value to identify the proper required authorizations. As I wanted to manage the whole blocking stuff, I chose:

From the Mastodon Web GUI, browse to Preferences > Development and click the New application button. Fill-in the “Application name” and select the appropriate “Scopes”.

When everything is setup properly, click the Submit button.

Back to the applications list, select the newly created one to display the access token. It will be listed as… you guessed it: Your access token. This is what will be used in the Authorization header with curl.

Note that if you modify the scope, the token will be regenerated.

You may want to delete the token once the work is done.

Get your tools ready

I’ll be using curl(1) and jq(1) on OpenBSD.

# pkg_add curl jq

Control the Mastodon

For easy command line management and notes taking, I’ve configured the Mastodon API URL and the token as shell variables.

# _url='https://<your mastodon host>/api/v1/admin/domain_blocks'
# _token='Authorization: Bearer <insert Your access token here>'

List all blocked domains

A simple API call will reply with a JSON list.

# curl "$_url" -H "$_token"
[{"id":"226","domain":"9kb.me","created_at":"2024-02-22T14:19:41.937Z","severity":"suspend","reject_media":true,"reject_reports":false,"private_comment":"Imported from 20240222-domain_blocks.csv on Feb 22, 2024, 14:19","public_comment":"SPAM 2024-114","obfuscate":false},{"id":"225","domain":"zettel.haus","created_at":"2024-02-22T14:19:41.917Z","severity":"suspend","reject_media":true,"reject_rep(...),{"id":"127","domain":"i.transmit.love","created_at":"2024-02-22T14:19:39.784Z","severity":"suspend","reject_media":true,"reject_reports":false,"private_comment":"Imported from 20240222-domain_blocks.csv on Feb 22, 2024, 14:19","public_comment":"SPAM 2024-15","obfuscate":false}]

If that’s horrible for you too, you can parse and display only parts.

# curl -s "$_url" -H "$_token" | jq '.'
[
  {
    "id": "226",
    "domain": "9kb.me",
    "created_at": "2024-02-22T14:19:41.937Z",
    "severity": "suspend",
    "reject_media": true,
    "reject_reports": false,
    "private_comment": "Imported from 20240222-domain_blocks.csv on Feb 22, 2024, 14:19",
    "public_comment": "SPAM 2024-114",
    "obfuscate": false
  },
  {
    "id": "225",
    "domain": "zettel.haus",
    "created_at": "2024-02-22T14:19:41.917Z",
    "severity": "suspend",
    "reject_media": true,
    "reject_reports": false,
    "private_comment": "Imported from 20240222-domain_blocks.csv on Feb 22, 2024, 14:19",
    "public_comment": "SPAM 2024-113",
    "obfuscate": false
  },
(...)

# curl -s "$_url" -H "$_token" | jq -r '.[] | [.id, .domain, .severity] | @csv'
"226","9kb.me","suspend"
"225","zettel.haus","suspend"
"224","wpmastodon.es","suspend"
(...)

Get a single blocked domain

To get all information from a specific domain, simply add the id to the curl(1) request.

# curl -s "$_url/225" -H "$_token" | jq
{
  "id": "225",
  "domain": "zettel.haus",
  "created_at": "2024-02-22T14:19:41.917Z",
  "severity": "suspend",
  "reject_media": true,
  "reject_reports": false,
  "private_comment": "Imported from 20240222-domain_blocks.csv on Feb 22, 2024, 14:19",
  "public_comment": "SPAM 2024-113",
  "obfuscate": false
}

Block a domain from federating

If a domain does not behave, it can be blocked easily.

# curl -s "$_url/" -H "$_token"               \
  -X POST -H 'Content-Type: application/json' \
  -d '{"domain": "zettel.haus", "severity": "suspend"}'
{"id":"227","domain":"zettel.haus","created_at":"2024-02-22T16:13:10.669Z","severity":"suspend","reject_media":false,"reject_reports":false,"private_comment":null,"public_comment":null,"obfuscate":false}

Update a domain block

If you change you mind, the domain block can be modified.

# curl -s "$_url/225" -H "$_token" -X PUT -H 'Content-Type: application/json' -d '{"severity": "noop"}'    
{"id":"225","domain":"zettel.haus","created_at":"2024-02-22T14:19:41.917Z","severity":"noop","reject_media":true,"reject_reports":false,"private_comment":"Imported from 20240222-domain_blocks.csv on Feb 22, 2024, 14:19","public_comment":"SPAM 2024-113","obfuscate":false}

Remove a domain block

If the domain starts behaving properly, it can be unblocked.

# curl -s "$_url/225" -H "$_token" -X DELETE                                                                    
{}

Remove all domain blocks

If you made a mistake and don’t want any blocks at all, they can be removed at once.

# for i in $(curl -s "$_url" -H "$_token" | jq -r '.[] | .id' | xargs); do
    curl -s "$_url/$i" -H "$_token" -X DELETE
done
{}{}{}{}{}{}{}{}{}{}{}{}{}(...)

Bibliography