Mastodon

Mastodon is a federated micro-blogging service. “Federated” means that there are many servers, each with their own rules, unlike Facebook, Google+ or Twitter. “Micro-blogging” means that you can post status updates up to 500 characters long.

I wrote mastodon-backup so that people can download their own toots, favorites and media attachments.

I also wrote bitlbee-mastodon. This plugin allows Bitblee to communicate with Mastodon instances. Bitlbee is an IRC server connecting to various other text messaging services. You run Bitlbee and connect to it using an IRC client, then configure Bitblee to connect to other services, such as a Mastodon instance where you already have an account. The benefit is that you can now use any IRC client you want to connect to Mastodon.

If you’re new, I recommend this post: How to Mastodon.

2018-09-12 OAuth and Mastodon

This page is mostly about trying to debug OAuth for Mastodon. Here’s the thing: I have a web application called Trunk. When you use it, you can mass-follow a number of accounts.

Sadly, I see OAuth issues piling up. I get the impression that my app mostly works, but every day I see reports by users getting “Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method”. The 3 instances I looked at reported their version to be 2.5.0 according to /api/v1/instances. What do you think I should do? How to debug this?

This is why I started writing this page. I’m hoping that some Mastodon client developer can look at the flow of things and tell me where I’m doing it wrong. Or perhaps they are running into similar issues and found a way around it? Perhaps register the app every single time? Who knows. All I know is that I’m seeing multiple reports.

If you want to look at the source code while you read this, you can find it in my repository.

The basic overview of the OAuth flow is this:

  1. Create your app in the instance and make sure you use the same scopes and redirect URL later. This gives you the client credentials client_id and client_secret.
  2. Redirect your user to the instance using the same scopes, redirect URL, and client credentials.
  3. If all went well, you’ll your redirection URL gets visited with a code parameter. Transform it into an access token ASAP (using the same parameters as before).
  4. Use the token as bearer token for each call to the mastodon API.

Here’s what this looks like in my app.

You start out with /follow_confirm. The web site says:

Please confirm
We’re going to use kensanata@octodon.social to follow all the accounts in Test.
Let’s do this
If you’d like to help us find the authorisation problems we’ve been having, please use the following link instead:
Let’s log this

When you click the link, you’re sent to the /auth route. There, we’re going to get ourselves a client. We check if the client is already registered. We do this by checking our file with all the client credentials and look for the octodon.social credentials. If we don’t find them, we’re going to register the client. in this case this is not necessary.

The /auth route now has a client. We’re going to authorise it. This means storing a bunch of cookies in the browser and then redirecting to the oauth URL of octodon.social. If the browser has the octodon.social cookie set, then no action is required. Otherwise, I need to click the big Authorize button. octodon.social then redirects back to our application, i.e. the / route, with an authorisation code.

I think this is where people are getting the error: “Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method”. They get the error from the instance, not from my web application, after all.

Screenshot of the error message

Anyway, assuming everything worked as intended... We’re back at / and we need to figure out what to do. If we are being called without a code, then we’re just going to show our main page. But in this case, we did get a code. So now we look at our cookies in order to discover what it was I was trying to accomplish. Ah! I was trying to follow the Test list, right. So we’re going to redirect to /do/follow.

The /do/follow route looks at the cookie and the parameters, again. Yep, got an account, got a list name, got a code... So now we’re going to get ourselves a client! You know how it is. The HTTP protocol is stateless. So we have to redo it all: get the client credentials from the file. This time we have a code, which is cool, so authorise the client again. Now we get the real deal: the authorisation token. Well, in my case the Mastodon::Client library handles all the painful details. But here we are, now. We have a client with the token. We’re good to go!

Now the application starts remote-following the accounts in the list. We end our journey on the /do/follow route. The URL actually contains the code but not the token. I still replaced the client_id and the authorisation code in the log with XXX.

Here’s what the log says:

[Wed Sep 12 22:58:24 2018] [debug] GET "/follow_confirm" (4fa2b1fd)
[Wed Sep 12 22:58:24 2018] [debug] Routing to a callback
[Wed Sep 12 22:58:24 2018] [debug] Rendering cached template "follow_confirm.html.ep" from DATA section
[Wed Sep 12 22:58:24 2018] [debug] Rendering cached template "layouts/default.html.ep" from DATA section
[Wed Sep 12 22:58:24 2018] [debug] 200 OK (0.003705s, 269.906/s)
[Wed Sep 12 22:58:32 2018] [debug] GET "/auth" (9f1d8f22)
[Wed Sep 12 22:58:32 2018] [debug] Routing to a callback
[Wed Sep 12 22:58:32 2018] [debug] kensanata@octodon.social wants to authorize the 'follow' action for the Test list
[Wed Sep 12 22:58:32 2018] [debug] kensanata@octodon.social found client credentials for octodon.social: id yes, secret yes
[Wed Sep 12 22:58:32 2018] [debug] kensanata@octodon.social has a client: yes
[Wed Sep 12 22:58:32 2018] [debug] kensanata@octodon.social is being redirected to https://octodon.social/oauth/authorize?redirect_uri=http%3A%2F%2Flocalhost%3A3000&response_type=code&client_id=XXX&scope=follow+read+write
[Wed Sep 12 22:58:32 2018] [debug] 302 Found (0.024886s, 40.183/s)
[Wed Sep 12 22:58:32 2018] [debug] GET "/" (8a14f8db)
[Wed Sep 12 22:58:32 2018] [debug] Routing to a callback
[Wed Sep 12 22:58:32 2018] [debug] kensanata@octodon.social is authorized for the 'follow' action using the Test list, redirecting to /do/follow?code=XXX&account=kensanata%40octodon.social&name=Test&logging=ok
[Wed Sep 12 22:58:32 2018] [debug] 302 Found (0.000799s, 1251.564/s)
[Wed Sep 12 22:58:32 2018] [debug] GET "/do/follow" (b79fbbdb)
[Wed Sep 12 22:58:32 2018] [debug] Routing to a callback
[Wed Sep 12 22:58:32 2018] [debug] kensanata@octodon.social found client credentials for octodon.social: id yes, secret yes
[Wed Sep 12 22:58:32 2018] [debug] kensanata@octodon.social has a client: yes
[Wed Sep 12 22:58:32 2018] [debug] kensanata@octodon.social authorizing using a code: yes
[Wed Sep 12 22:58:33 2018] [debug] kensanata@octodon.social begins to follow 2 accounts from list Test
[Wed Sep 12 22:58:33 2018] [debug] kensanata@octodon.social followed 2 accounts from list Test
[Wed Sep 12 22:58:33 2018] [debug] Rendering template "follow_done.html.ep" from DATA section
[Wed Sep 12 22:58:33 2018] [debug] Rendering cached template "layouts/default.html.ep" from DATA section
[Wed Sep 12 22:58:33 2018] [debug] 200 OK (0.762821s, 1.311/s)

Tags:

Comments on 2018-09-12 OAuth and Mastodon

Did you try with scope written with %20 instead of +?

"&scope=follow+read+write"

Other than that this call fail:

redirect_uri=https%3A%2F%2Fcommunitywiki.org%2Ftrunk&response_type=code&client_id=xxxxxxxxxxxxxxxxxxx&scope=follow+read+write

If it’s not the scope, your client_id is no longer known by the instance. Did you try to register the app each time to see if the problem comes from your way of storing app clients?

https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md#apps

– tom79 2018-09-13 05:41 UTC


It also fails with a fresh client id due to a server side error on this callback for code:

https://communitywiki.org/trunk?code=XXXXXXXXXXXXXXXXXXXXXXX

Header:

Location: /trunk/do/follow?code=XXXXXXXXXXXXXXXXXXXXXXX&account=tom79%40ins.mastalab.app&name=Biology&logging=

– tom79 2018-09-13 05:54 UTC


Hm, I need better logging at that point: I see in my logs that you got a 500 error:

[Thu Sep 13 07:51:40 2018] [info] 178.209.50.237 GET http://communitywiki.org:8080/trunk/do/follow?code=XXXXXXXXXXXXXXXXXXXXXXX&account=tom79%40ins.mastalab.app&name=Biology&logging= 500 0.1443s

But that’s it. As far as I can tell from here, the flow looks correct: you did get authorised or the instance would not have sent you back to the redirect URL with a code. But it did, so that worked. So now the code is about to do this:

  1. get the authorisation token using the code it just got
  2. use the token to create the list, follow people and add these people to the list

– Alex Schroeder 2018-09-13 07:03 UTC


OK, I found a problem! I currently have 159 client credentials but when I look for duplicates, there’s a problem:

qoto.org 4
mastodon.social 23
ins.mastalab.app 2
mastodon.art 3
mstdn.io 2

This is obviously a problem because only one of them is going to be the correct client_secret.

Well, at least here’s a clue!

– Alex Schroeder 2018-09-13 07:16 UTC


OK, here’s something else: I while ago I tried to follow the Test list using kensanata@octodon.social and got the error “Authorisation failed. Did you try to reload the page? This will not work since we’re not saving the access token.” And just now I tried again and it worked. Clearly not the same error (since the authorisation seems to work) but disconcerting none the less.

– Alex Schroeder 2018-09-13 07:50 UTC


Improved logging, tried following the Test list using my account on humanities.one.

“Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method”

The log:

[Thu Sep 13 10:12:49 2018] [info] 178.209.50.237 GET http://communitywiki.org:8080/trunk/follow_confirm?account=kensanata%40humanities.one&name=Test 200 0.0223s
...
[Thu Sep 13 10:12:54 2018] [debug] GET "/trunk/auth" (8d6b9c08)
[Thu Sep 13 10:12:54 2018] [debug] Routing to a callback
[Thu Sep 13 10:12:54 2018] [debug] kensanata@humanities.one wants to authorize the 'follow' action for the Test list
[Thu Sep 13 10:12:54 2018] [debug] kensanata@humanities.one found client credentials for humanities.one: id yes, secret yes
[Thu Sep 13 10:12:54 2018] [debug] kensanata@humanities.one has a client: yes
[Thu Sep 13 10:12:54 2018] [debug] kensanata@humanities.one is being redirected to https://humanities.one/oauth/authorize?redirect_uri=https%3A%2F%2Fcommunitywiki.org%2Ftrunk&response_type=code&client_id=XXX&scope=follow+read+write
...
[Thu Sep 13 10:12:54 2018] [info] 178.209.50.237 GET http://communitywiki.org:8080/trunk/auth?account=kensanata%40humanities.one&action=follow&logging=ok&name=Test 302 0.0516s
...

And that’s the end of it! OK, let’s compare this with the flow I described: We have a client and we want to authorize it. We’re going to redirect the user to their instance. If they have the instance’s cookie set, they’re authorized immediately and should get back to our redirect URL (the / route).

But this is not what happens. We’re not being sent back to the redirect URL and the error is shown instead.

– Alex Schroeder 2018-09-13 08:27 UTC


I’m looking at some info @NicolasConstant kindly sent me and the URLs he uses are:

create new app:
    FORM POST
    https://[instance]/api/v1/apps

    form data: 

    client_name
    redirect_uris
    scopes
    website


redirect sign-in url:        
     https://[instance]/oauth/authorize?scope=[scopes]&response_type=code&redirect_uri=[redirect_uri]&client_id=[client_id]


access_token retrieval 
    POST
    https://[instance]/oauth/token?client_id=[client_id]&client_secret=[client_secret]&grant_type=authorization_code&code=[code]&redirect_uri=[redirect_uri]

API access : 
    In the headers:
    'Authorization': 'Bearer [access_token]'

In this case, we’re not yet at the access_token retrieval stage. We’re at the “redirect sign-in URL” stage: https://humanities.one/oauth/authorize?redirect_uri=https%3A%2F%2Fcommunitywiki.org%2Ftrunk&response_type=code&client_id=XXX&scope=follow+read+write matches https://[instance]/oauth/authorize?scope=[scopes]&response_type=code&redirect_uri=[redirect_uri]&client_id=[client_id].

So why is the server rejecting it?

Let’s try the following:

Just do it again. A temporary fluke? → fail

[Thu Sep 13 11:06:46 2018] [debug] Routing to a callback
[Thu Sep 13 11:06:46 2018] [debug] kensanata@humanities.one wants to authorize the 'follow' action for the Test list
[Thu Sep 13 11:06:46 2018] [debug] kensanata@humanities.one found client credentials for humanities.one: id yes, secret yes
[Thu Sep 13 11:06:46 2018] [debug] kensanata@humanities.one has a client: yes
[Thu Sep 13 11:06:46 2018] [debug] kensanata@humanities.one is being redirected to https://humanities.one/oauth/authorize?redirect_uri=https%3A%2F%2Fcommunitywiki.org%2Ftrunk&response_type=co
de&client_id=XXX&scope=follow+read+write
[Thu Sep 13 11:06:46 2018] [debug] 302 Found (0.04456s, 22.442/s)
[Thu Sep 13 11:06:46 2018] [info] 178.209.50.237 GET http://communitywiki.org:8080/trunk/auth?account=kensanata%40humanities.one&action=follow&logging=ok&name=Test 302 0.0488s

Delete the client credentials and do it again. Perhaps the client_id is no longer valid? → fail

[Thu Sep 13 11:07:21 2018] [debug] kensanata@humanities.one wants to authorize the 'follow' action for the Test list
[Thu Sep 13 11:07:21 2018] [debug] kensanata@humanities.one found no client credentials for YYY
[Thu Sep 13 11:07:22 2018] [debug] kensanata@humanities.one registered client and got new credentials for YYY: id yes, secret yes
[Thu Sep 13 11:07:22 2018] [debug] kensanata@humanities.one has a client: yes
[Thu Sep 13 11:07:22 2018] [debug] kensanata@humanities.one is being redirected to https://humanities.one/oauth/authorize?redirect_uri=https%3A%2F%2Fcommunitywiki.org%2Ftrunk&response_type=code&client_id=XXX&scope=follow+read+write
[Thu Sep 13 11:07:22 2018] [debug] 302 Found (0.182976s, 5.465/s)

Oops! What’s YYY doing here? I wonder. My log writing got confused. Will rewrite this section and try again.

– Alex Schroeder 2018-09-13 09:13 UTC


Still borked:

[Thu Sep 13 11:28:07 2018] [debug] GET "/trunk/auth" (a8dae4dc)
[Thu Sep 13 11:28:07 2018] [debug] Routing to a callback
[Thu Sep 13 11:28:07 2018] [debug] kensanata@humanities.one wants to authorize the 'follow' action for the Test list
[Thu Sep 13 11:28:07 2018] [debug] kensanata@humanities.one found client credentials for humanities.one: id yes, secret yes
[Thu Sep 13 11:28:07 2018] [debug] kensanata@humanities.one has a client: yes
[Thu Sep 13 11:28:07 2018] [debug] kensanata@humanities.one is being redirected to https://humanities.one/oauth/authorize?redirect_uri=https%3A%2F%2Fcommunitywiki.org%2Ftrunk&response_type=code&client_id=XXX&scope=follow+read+write
[Thu Sep 13 11:28:07 2018] [debug] 302 Found (0.043568s, 22.953/s)
[Thu Sep 13 11:28:07 2018] [info] 178.209.50.237 GET http://communitywiki.org:8080/trunk/auth?account=kensanata%40humanities.one&action=follow&logging=ok&name=Test 302 0.0520s

And after removing the credentials – it worked‽

[Thu Sep 13 11:29:38 2018] [debug] GET "/trunk/auth" (353e6e43)
[Thu Sep 13 11:29:38 2018] [debug] Routing to a callback
[Thu Sep 13 11:29:38 2018] [debug] kensanata@humanities.one wants to authorize the 'follow' action for the Test list
[Thu Sep 13 11:29:38 2018] [debug] kensanata@humanities.one found no client credentials for humanities.one
[Thu Sep 13 11:29:38 2018] [debug] kensanata@humanities.one registered client and got new credentials for humanities.one: id yes, secret yes
[Thu Sep 13 11:29:38 2018] [debug] kensanata@humanities.one has a client: yes
[Thu Sep 13 11:29:38 2018] [debug] kensanata@humanities.one is being redirected to https://humanities.one/oauth/authorize?redirect_uri=https%3A%2F%2Fcommunitywiki.org%2Ftrunk&response_type=co
de&client_id=XXX&scope=follow+read+write
[Thu Sep 13 11:29:38 2018] [debug] 302 Found (0.591784s, 1.690/s)
[Thu Sep 13 11:29:38 2018] [info] 178.209.50.237 GET http://communitywiki.org:8080/trunk/auth?account=kensanata%40humanities.one&action=follow&logging=ok&name=Test 302 0.6006s
[Thu Sep 13 11:29:42 2018] [debug] GET "/trunk" (2ca628ab)
[Thu Sep 13 11:29:42 2018] [debug] Routing to a callback
[Thu Sep 13 11:29:42 2018] [debug] kensanata@humanities.one is authorized for the 'follow' action using the Test list, redirecting to /trunk/do/follow?code=XXX&account=kensanata%40humanities.
one&name=Test&logging=ok
[Thu Sep 13 11:29:42 2018] [debug] 302 Found (0.001252s, 798.722/s)
[Thu Sep 13 11:29:42 2018] [info] 178.209.50.237 GET http://communitywiki.org:8080/trunk?code=XXX 302 0.0078s
[Thu Sep 13 11:29:42 2018] [debug] GET "/trunk/do/follow" (1d4bad6a)
[Thu Sep 13 11:29:42 2018] [debug] Routing to a callback
[Thu Sep 13 11:29:42 2018] [debug] kensanata@humanities.one found client credentials for humanities.one: id yes, secret yes
[Thu Sep 13 11:29:42 2018] [debug] kensanata@humanities.one has a client: yes
[Thu Sep 13 11:29:42 2018] [debug] kensanata@humanities.one authorizing using a code: yes
[Thu Sep 13 11:29:42 2018] [debug] kensanata@humanities.one begins to follow 4 accounts from list Test
[Thu Sep 13 11:29:45 2018] [debug] kensanata@humanities.one followed 4 accounts from list Test
[Thu Sep 13 11:29:45 2018] [debug] Rendering template "follow_done.html.ep" from DATA section
[Thu Sep 13 11:29:45 2018] [debug] Rendering cached template "layouts/default.html.ep" from DATA section
[Thu Sep 13 11:29:45 2018] [debug] 200 OK (3.888279s, 0.257/s)
[Thu Sep 13 11:29:45 2018] [info] 178.209.50.237 GET http://communitywiki.org:8080/trunk/do/follow?code=XXX&account=kensanata%40humanities.one&name=Test&logging=ok 200 3.8928s

Hm. I am convinced that my rewriting just changed the way things are being logged. Just to be sure, though, I will delete all the client credentials (except for the one I just saved) and we’ll see whether the situation improves.

– Alex Schroeder 2018-09-13 09:38 UTC


I tested and it now works as expected.

– tom79 2018-09-13 11:15 UTC


Amazing. 🤷‍♂️

– Alex Schroeder 2018-09-13 13:51 UTC

Add Comment

2018-09-10 Trunk Explosion

Trunk A while ago, I wrote a little web app called Trunk. It was supposed to help beginners get started. Beginners see a bunch of people in lists and if they’re interested in the topic, they can follow all of these people. And if it failed, or if you wanted to pick and choose, no problem: you could always just click through and pick and choose yourself.

I’ve always asked for people to volunteer for being on the lists because I felt that adding people to lists without them knowing or agreeing to it is rude. It’s a surprise to be suddenly exposed like that! So people had to volunteer: message me and ask to be added to this list or that list. This was also to serve as some sort of minimum quality control: if your timeline is full of spam, I’d be able to deny that request.

Soon, a bunch of friendly people volunteered to help out. This is great. The task doesn’t require any programming, it’s all about getting messages, adding people to lists, and talking with the other admins about this list or that list. Recently one or two accounts with more reach mentioned Trunk and we were flooded with new requests.

If you’re interested in helping out, please contact me and volunteer for the admin team!

I just posted the following call for help:

We’re looking to add volunteers to help out with #Trunk administration. Mostly that means getting messages by people requesting to be added to a bunch of lists. There’s a simple admin interface where you then get to do that. There’s also a decent amount of discussion trying to figure out whether we need to add lists, what to call them, how to describe them, that sort of thing. It sometimes feel like a strange mix of philosophy and the Muppet show.

Some of the things we talk about:

  • What is the best name for a list? I had never heard of Wrenching before, for example.
  • How granular do we want this to be: do we need to have Knitting and Sewing and Crocheting or do we just need Fibre Arts? Do we list Dada or will we end up adding every art movement in history? Early on I was pointed at lumpers and splitters on Wikipedia. This discussion never ends and we might have to go back on them as the fediverse changes. We create lists for programming languages and sports now, but we don’t want to have lists for all the various diet trends: low carb, keto, paleo, etc. Perhaps that will have to change.
  • Do we add NGOs, and if we do, do we add them to a list of NGOs or do we add them to the topics they toot about? We decided to add them to a separate list of Organisations, NGOs & Associations because we want this Trunk instance to be about people connecting to other people.
  • What if the NGO wants to create a list for the NGO itself: FSF, FSFE, EFF, ACLU, Greenpeace, and what about other organisations: political parties, companies? We decided that in this case we’d like these organisations to run their own Trunk instances.
  • What about news bots? Given that we want this instance to be about newbies finding other people, we don’t want add bots.
  • What about people just boosting a lot of other people? Same argument: we’d prefer the people being boosted to volunteer for some of the lists. That would foster the people finding people aspect of it all.

That’s not to say that having lists of boosters and bots could not be useful, too. But it’s not what we want to do. The same is true for foreign languages.

I think that non-English speakers should start separate Trunk instances. Let me know if you’re interested and I’ll help you get it installed and everything. Right now I’m thinking that it doesn’t really make sense to add people that mostly toot in a foreign language. I just wonder about the numbers. It’s easy to say now that we don’t mind a French account tooting about Gamedev even if we don’t speak French, for example. But what will we do when 70% of the people in the Gamedev list are Japanese? So I suspect we’d need to have a “Gamedev 日本語” and “Gamedev Français” and so on. Maybe we’d need to translate “Gamedev” as well: “Spieleentwicklung auf Deutsch”. Soon we’re talking about lists we don’t understand to people we don’t understand... This will not scale.

I’ll try to make Trunk as easy to translate into other languages as I can. Please volunteer if you’re interested in this! 😅

Tags:

Comments on 2018-09-10 Trunk Explosion

The newer edition of Trunk now comes with a queue and a bot.

I installed the bot as @trunk and every ten minutes it connects to see if anybody mentioned it using the formula “Please add me to a comma separated list of names.” If so, it adds the request to a queue stored in the Trunk app. There, admins have an easy way to accept the request.

What this lacks is feedback! I’ll have to think of something. Right now, the bot will accept direct messages which the admins might not even see. Ideally, the admin’s action would then prompt the bot to reply, I guess.

– Alex Schroeder 2018-09-11 13:06 UTC

Add Comment

2018-09-04 Bitlbee Mastodon Plugin 1.4.0

I tagged a new release of the Bitlbee Mastodon plugin!

New features for 1.4.0:

  • new filter command
  • new list command
  • new settings to hide notifications by type

Incompatible change in 1.4.0:

If you have subscribed to a hashtag, you need to change your channel settings and prepend the hash. Without the hash, the plugin gets confused and things the channel is for a list of the same name. Do this from the control channel (&bitlbee). Let’s assume you have a channel called #hashtag. It’s room setting should be #hashtag. If it’s lacking the initial hash:

kensanata
channel #hashtag set room
root
room = ’hashtag’
kensanata
channel #hashtag set room #hashtag
root
room = ’#hashtag’

Tags:

Add Comment

2018-09-03 Unfollowing Lurkers

A direct message reminded me of another way you might want to trim the list of people you are following. Following too many people is a burden. When I see that it is taking too long for me to read all the new toots, it’s time to trim the list. I prefer to follow less people instead of not reading all the toots.

So I’ve added a following command to mastodon-archive. You can list the people you’re following who never mentioned you, and if you’re hardcore enough, you can unfollow them all.

This can probably use some fine-tuning:

  1. editing the list before submitting it?
  2. having exceptions for your favourite bots?

If you have strong opinions either way, let me know.

Tags:

Add Comment

2018-08-31 Mastodon Bitlbee

So... brainstorming about things I’d like to look at.

  1. Look at issues, of course
  2. Considering better filtering: I’m interested in expiration of filters; using phrases as regular expression; applying filters to usernames too (use them as temporary muting)
  3. I think I’d like to support a tiny bit of rich text: bold and italic, maybe underline. Don’t know about colors! But with Pleroma now doing rich text, we should at least support what IRC supports!

Tags:

Add Comment

2018-08-30 Dogpiling Wil

Wil Wheaton left Mastodon and he wrote a long blog post about it.

What happened? Here’s what I understand:

Wheaton is famous and gets to see a lot of comments directed at him that he doesn’t care for. When he was on Twitter, he started using block lists. I can’t find the post right now but at one point I thought he used Good Game Auto Blocker by Randi Lee Harper; on his blog post regarding blocklists, trolls, twitter’s systemic inaction against abuse, and the responsibility of wielding great power he mentions Block Together and Twitter Block Chain.

Here’s an extract from Good Game Auto Blocker:

history

A major problem with social media is the lack of flexible filtering controls. Twitter has a block mechanism, but a user has to initiate contact in order to be blocked. For most forms of harassment, this is an effective way of moderating conversations. Unfortunately, as more social campaigns use Twitter as their basis for communications, this approach becomes less effective. While it’s suitable for use against a single harasser, it’s useless against a large number of accounts targeting a single user. These tweets needed to be stopped before they land in the user’s notifications.

how it works

Good Game Auto Blocker compares the follower lists for a given set of Twitter accounts. If anyone is found to be following more than one of these accounts, they are added to a list and blocked.

That means the blocker will automatically block people that are following people on the block list. It’s contagious, trying to block people before they have actually done anything worth blocking them for. The other side argues, as shown in the quote above, that preventive blocking is necessary when you’re faced with a relentless onslaught.

Apparently, this list contained a lot of trans women. People concluded that Wheaton was therefore a transphobe. He denies it, of course. I haven’t seen any other evidence except for this: he used this blocker, promoted it, and people feel it contained false positives. Wheaton says he removed people who contacted him, except when he felt that they were overreacting, at which point he decided he might want to keep blocking them.

This gets us into the entire topic of tone policing. Marginalized people feel righteous anger, but at the same time Wheaton feels entitled to not having to face it.

And then there’s another element to it all: Wheaton is friends with Chris Hardwick who allegedly abused Chloe Dykstra. If you search the web for these names, you’ll find articles like ‘Speak up, Wesley’: Wheaton Wheaton under fire after he asks for time to process sexual abuse allegations against his best friend, Chris Hardwick. I’m not sure what to think of this. Chloe Dykstra’s story is terrible and heart breaking. Rose-Colored Glasses: A Confession. I couldn’t read it all. I skimmed large part of its. This is very painful. And there’s Chris Hardwick responds to Chloe Dykstra's allegations of sexual and emotional abuse, too. The entire disaster here is beyond words and there never was a trial and there’s no confession, so nobody knows whether it’s true or not. Dykstra’s story sounds compelling and Hardwick’s story is simply a denial. And now what?

Do we always believe the victims, no more fair trials? As a society we’ve struggled for hundreds of years to improve our judicial systems and I’m not yet ready to dump these principles. I want to believe and support victims all I can. But this is a story about Wheaton, and by extension about Hardwick. My heart goes out to Dykstra and everybody in a similar situation. You are not alone. I hope that it does get better. But the rest of this post is about the men in this story – and I cannot in good conscience punish the accused without a fair trial. So, with misgivings, and wishing it was different, the affair remains inconclusive.

In this situation, one might wish Wheaton to clear it all up, make a strong statement, help us decide whether Dykstra is right, whether his friend Hardwick is a terrible person. But it isn’t going to work that way. Wheaton was apparently faced with a constant stream of questions regarding Hardwick, some insulting and some not, but from his point of view, it was simply dogpiling, harassment (Wikipedia: “Harassment, under the laws of the United States, is defined as any repeated or continuing un-consented contact that serves no useful purpose beyond creating alarm, annoyance, or emotional distress.”)

Mastodon was supposed to be better than Twitter because each instance has their own maintainers, their own rules. But Wheaton was being reported 60 times per day and the administrator of his instance decided to kick him. Clearly, this system doesn’t scale, these tools don’t scale.

I am disappointed in how it all turned out. Dykstra’s story is sad. I wish I knew Hardwick was a good man. I wish Wheaton could clear it all up. But as a society, I think the most important thing is that we must be able to live and coexist in a world where these things happen, where these issues cannot be resolved. My wife used to work for the judiciary and now she works for the police and there are thousands of similar situations. Something terrible happened and there is not enough evidence to convict anybody. We try to help the victims, and I think the state could do much better in this respect, but when we cannot convict the accused, we must presume innocence. Sure, we don’t have to be friends with these people, but we shouldn’t punish them, and thus we should not harass them. No “repeated or continuing un-consented contact that serves no useful purpose beyond [...] emotional distress.” We can block and mute them all we want. But don’t send them a constant stream of tweets and toots.

At the same time, there are toots like the following:

POC, LGBT, women, literally EVERY community EXCEPT white guys have been continual targets of dog-piling and harassment from since day one, but when a famous white guy gets a small taste of the abuse... – @Are0h [1]
All the white men crying how disappointed they are in mastodon didnt lift a finger when women were being harassed shut up white men forever – @Laurelai [2]
Most hated star trek actor runs to mommy after girl says a swear – @eweish1 [3]

Ouch! Am I feeling white fragility? (see my post about white emoji.) I need to remind myself: one wrong does not justify another. Well, perhaps they also oppose the dog piling, they just mock the dismay people like me feel at witnessing it as we apparently didn’t lift a finger before. I don’t know. My first impulse is definitely to not engage. And perhaps I’m therefore similar to Wheaton in this respect: I feel like life is too short to deal with unfriendly people. And they of course feel they have a right to unfriendliness, having suffered under the oppression of people “with some or all of the P7 traits (Pale Patriarchal Protestant Plutocratic Penis-People of Power),” as Charles Stross called them in his blog post Dread of Heinleinism. I have no answer to this conundrum. This doesn’t lead to a constructive solution. We will be better off living in separate bubbles.

I feel like this is the long shadow of Gamergate, which I see as an extension of the culture war.

@zlg said: “No matter where you go on this planet, people are still the same.” Is this wisdom or cynicism? I don’t want to turn into a cynic old man who has no hope, but it is increasingly difficult. It’s like 1984: not only do you get punished but you must agree to it in your heart of hearts. And in the end we will see the planet burn and pat each other on the back and laugh because we will all agree: we deserve it.

The best takes on the situation ignore the details of who is right and who is wrong and focus on how we will enable healing to happen, what to watch out for, what to avoid. Things that concern the future. Watch out, both linked posts are about child abuse.

@fraying recommended this: “That vicious little voice inside you that cheers when you lash into someone — that voice is not your friend. It will never help you reach people. It will never change hearts or minds. It cannot build bridges, it can only destroy. It will never let you be happy, and it will never let you heal, because it will never, ever let your abuser die, because it lives inside you and comes out through your voice, your hands.” – It’s up to you, by yesivebeenthere2

@buzz recommended this: “Which is of course why it is so dangerous to join a mob… any mob, no matter how “noble” the stated purpose may be. The mob is almost surely led by a malignant narcissist. And that narcissist is using you.” – Narcissists: Sexists, Racists, Child Abusers, Saboteurs, Internet Trolls, also by yesivebeenthere2

Tags:

Comments on 2018-08-30 Dogpiling Wil

I enjoy Mastodon but, long term, it won't be better than Twitter, by @baldur.

Wil Wheaton Has a Listening Problem, by Amber Enderton.

Mastodon and the challenges of abuse in a federated system, by @nolan.

Social Media Mobs, by @brentsimmons. The article describes how it feels to be on the receiving end of a mob.

Proposals/Discussion on the 'wilw' Incident, by @SuperFloppies. This one comes with links to Mastodon issues related to defence.

– Alex Schroeder 2018-08-30 and beyond


I’ve been chatting with @mxfraud about @wilw. They had an interesting point: famous (or rich?) people shouldn’t rely on free services (like hosting and moderation). I hadn’t considered it before and I’m not sure I agree. I earn enough money, for example. Does that mean I should find a paid solution? Also, perhaps Wheaton would have donated to the instance’s admin. I wouldn’t know. But the idea itself is interesting. Who deserves free service? One thing I know about myself is that I often don’t feel like paying for Free Software or free hosting because I feel like I’m already giving back, writing Free Software and offering free hosting. I feel like I’m involved in a kind of “pay it forward” scheme already.

We also talked about the need to listen before joining a new platform. Get a feel for the culture, the vibe. At the same time, I know how hard it is. Just looking at the number of people complaining about other people butting into their conversations with unwanted advice. I’m assuming that’s how any sort of advice would have come across to Wheaton. That’s why I don’t fault him for not listening. I’ve also seen the kind of advice offered to him on a thread or two on mastodon.cloud and in sum it was bad. The good advice was hard to spot.

As for hurting trans women, I’m not sure what the accusation is, exactly. The one I do understand is that he used Randi Harper’s block list to block thousands, and later learned that Randi had blocked some trans people too, but the steps he took to counter this were weak, and by that time the block list had spread, cutting some of them off from their income. Is that it, or is there more to it? If that’s the only accusation, then I understand his position, though: compared to the thousands of trolls, and given the ludicrously bad defences we have on social media, a crude blocking mechanism is the only way to be online in any meaningful way. From his point of view, he used a crude hammer, and he’s sorry, but it isn’t obvious to me (and to him) how this makes him guilty regarding a specific subset of innocent people banned. How is he responsible for other people using the tool he is using if it does the job: making existing on social media bearable? How is he responsible for some people using Twitter as an essential tool for their livelihood? And taken together: if some innocent people are losing their income due to the crude defences deemed necessary on Twitter, isn’t that a problem of the platform? How does that make him guilty, in a moral sense? Surely a lot of other innocent people were banned, but one individual banning another is par for the course, that’s your right (except if you’re the president of the United States of America, apparently, according to Reuters).

Anyway, to focus on the more constructive aspects of it all. I interested in seeing how the moderation tools and defence mechanisms of the fediverse evolve to meet this challenge. And I keep thinking that we need to let go of a Manichaean world view where people have to be all good, all the time, in order to be accepted. That’s not how it works offline and I personally feel that’s also not how it should work online.

– Alex Schroeder 2018-09-03 06:14 UTC


I took the liberty of correcting the second yesivebeenthere2 link. You accidentally linked “It’s Up to You” twice.

zlg 2018-09-15 03:29 UTC


Thank you very much!

– Alex Schroeder 2018-09-17 06:25 UTC


On the topic of blocking, I’ve written a tool, Mastodon Blocker. And @codesections wrote Mastodon De-Mob.

– Alex Schroeder 2018-09-17 06:29 UTC

Add Comment

2018-08-27 Mastodon and rcirc

If you use rcirc (one of the two Emacs IRC clients) and the Bitlbee Mastodon plugin to communicate with a Mastodon instance via Bitlbee, and you want to “dim” the notifications of follows, boosts and favourites:

(eval-after-load 'rcirc
  '(add-to-list 'rcirc-markup-text-functions 'asc:rcirc-dim-keywords))

(defvar asc:rcirc-dim-keywords
  '("favourited your status: "
    "boosted your status: "
    " followed you")
  "Keywords which result in the entire message being dimmed.")

(defun asc:rcirc-dim-keywords (_senders _response)
  "Dim message if it contains particular phrases.
Phrases to take are from `asc:rcirc-dim-keywords'.
Each function takes two arguments, SENDER, and RESPONSE.  The
buffer is narrowed with the text to be printed and the point is
at the beginning of the ‘rcirc-text’ propertized text."
  (dolist (str asc:rcirc-dim-keywords)
    (goto-char (point-min))
    (when (search-forward str nil t)
      (rcirc-add-face (point-min) (point-max) 'rcirc-dim-nick))))

(Mastodon is a free, open-source, decentralized microblogging network. Bitlbee is an IRC server connecting to various other text messaging services. You run Bitlbee and connect to it using an IRC client, then configure Bitlbee to connect to other services, such as a Mastodon instance where you already have an account. The benefit is that you can now use any IRC client you want to connect to Mastodon.)

Tags:

Add Comment

2018-08-25 Identity, Keybase, Verification

Recently, @kaniini had a good thread about identity verification. Basically, they don’t like Keybase. I used to like Keybase and then I discovered that I wasn’t using them, ever. So now what?

What you want to prove is that the same person who controls these:

https://kaniini.dereferenced.org/ https://github.com/kaniini

Also controls:

https://pleroma.site/users/kaniini

I think that is correct.

Links in that thread:

And Kaniini is right: “Keybase represents more of the centralization of the web that we must resist.”

I guess the use case for Keybase still exists. It’s just that baking the graph of identities into our web would work just as well.

As I was looking into issue #121 I realized that Mastodon already does this: all links from your profile already have rel="me" added. So if my profile links to this blog and this blog links to the profile, I’ve established that we’re the same person! Yay!

Tags:

Comments on 2018-08-25 Identity, Keybase, Verification

I’m not entirely sure I see the harm in the amount of centralization keybase produces. Here’s my thought process:

If people have multiple identities (e.g., Mastodon, Reddit, HackerNews, Twitter, LinkedIn, etc…) then they have three options to verify those identities:

  • They can link every identity to every other identity. This gets very cumbersome as the number of identities grows and the number of required links grows exponentially.
  • They can link every identity to some other identity and let verification require following a chain (”I know that this Mastodon users owns that Reddit account, which is by the same person as this HackerNew account, which is linked to this other LinkedIn account. Thus, I know that the Mastodon and LinkedIn accounts are linked.”). This seems equally cumbersome, but shifts the burden onto the verifier—which seems even worse.
  • They can use a hub-and-spoke model. (e.g., all my accounts link to my blog, and my blog links to all my accounts; this lets you verify my account ownership by following just a couple of links).

Of these three, I’d say that the hub-and-spoke model is the best. But that prompts the question: where should the hub be? If we lived in a world where everyone had a home page (I wish!), then our personal home pages would be the natural hub. But, since we don’t, keybase seems to be stepping in to provide that hub function.

A couple of further points: Because all keybase does is provide a hub, it would be fairly easy to replace. In fact, I already use my website as a hub, in that it links to all my other profiles—keybase is a secondary hub that increases discoverability/credibility (to people who don’t understand the tech enough to trust the other hub). And if someone else wanted to create a keybase alternative—which they probably shouldn’t call freebase—then it seems like they’d be able to pretty easily: Keybase doesn’t create/own the links in the chain, just one central hub.

So, bottom line, I’m agree that keybase is centralizing things to an extent. I think it’s not that useful for people who already maintain personal websites. But, despite that, I think it’s not (that) dangerous because it’s natural to have some hub, but hubs are also—by their nature—pretty replicable.

But I’d love to hear where I’m wrong about any of that!

codesections 2018-09-03 13:34 UTC


I think it’s all about switching costs and capture: if we all use the same site, then suddenly the site is valuable: we’d never be able to switch everybody away, no matter how easy it is. If Microsoft buys the site, if finances fail, there are always risks and why but everybody on the same boat?

But Keybase also solves other problems, like maintaining a list of accounts you’re following. Also valuable information that is unrelated to the primary focus of this discussion: identity. So if we’re all in this one boat, the value of the boat is not only big because we’re all there, it’s even bigger because an entirely different class of attack can be fielded against us: a network analysis.

But all being on the same hub, we’re just making it easier for evil doers and we’re making ourselves more vulnerable for rare disasters (think The Black Swan: The Impact of the Highly Improbable).

That’s the only argument I have. The fact that there are other ways to establish identity, and silly ways of setting it up, doesn’t affect the main point: this is not resilient.

– Alex Schroeder 2018-09-03 13:46 UTC

Add Comment

2018-08-17 No Repost

There is no way to migrate an account and take your old toots with you. You download those via the export function in Mastodon, or using Mastodon Archive, but you cannot import then back. The API does not allow it.

It also makes no sense to repost toots on your new account: you would be annoying everybody under the sun as the local timeline gets flooded and all the mentioned accounts get notified again. Even if you decided to post them all unlisted, notification would still be a problem. And all the timestamps would be wrong.

What currently works: account migration: Settings > Edit profile > Move to a different account.

  1. Your toots stay.
  2. Your followers get notified and might or might not follow your new account.
  3. You keep the people you follow so you won’t miss a thing.
  4. Their toots start populating the federated timeline of your new instance; this will help small instances get better connected to the rest of the Fediverse.

Tags:

Add Comment

2018-08-12 Trunk for Mastodon

So the last two days I’ve been working on Trunk. Trunk allows you to mass-follow a bunch of people in order to get started with Mastodon. Mastodon is a free, open-source, decentralised micro-blogging network.

I’m imagining something like Google+ Circle sharing. Remember that? If you had a good bunch of people you wanted to share, you did, and others could subscribe to all of them in one go. At first I thought Mastodon Lists could serve the same purpose. But then people told me that public lists can be a means to harass people: put victims on the same list as know idiots, put victims on lists with an insulting name, point followers at a list and invite them to tell victims off, etc. But I still want a list of cool people to recommend for newbies to instantly follow. So now I’m trying to find a compromise. Trunk is a web app based on a public, curated list for all to see and maintain. Does better accountability solve the problem? I hope so!

  1. people need to volunteer for the list, I don’t want to put anybody on a list without their consent
  2. as a person, I’m going to try and make sure we don’t have any spammers, idiots, or sinister figures on the list
  3. I also want these to be quality lists, so I’ll check the timelines of suggested accounts to make sure that (at least at the time I added them) they actually posted on topic

I know this “tagging” of accounts is weird. I personally also don’t like too many accounts that just post about one topic. But when I was new, things were different. I had some topics I knew I was interested in: role-playing games, Emacs, pictures. I would have loved to find a way to quickly follow a few dozen accounts and fill my timeline with stuff I cared about.

Also, the list management interface for the Mastodon web client is atrocious. Perhaps I’ll turn Trunk into a kick-ass list-management tool for Mastodon. 🙂

I’ll be collection ideas on the Software Wiki.

Tags:

Comments on 2018-08-12 Trunk for Mastodon

Ugh, about two days if implementing this stuff – famously the first 80% are done in 20% of the time, of course – and then another two days of basically updating lists, manually. This is time not well spent. If only there was a way to automate this!

Perhaps a kind of bot with a conversational interface? “hey bot, please sign me up to Javascript and Lisp!” and it would do just that? But surely spammers would then abuse the system. So we’d need a review system? A rollback and ban mechanism? In the end it would mean using a wiki backend, perhaps? Or version control?

I like ephemeral data, of course, so a wiki that kept forgetting old revisions but kept some around, just in case, that might make sense.

– Alex Schroeder 2018-08-14 14:55 UTC


Well, I added the ability to add more lists and to add people to lists via an admin interface and two people volunteered to do this! Yay! Thanks! And now I’m off to a break.

– Alex Schroeder 2018-08-15 13:50 UTC

Add Comment

More...

Comments


Please make sure you contribute only your own work, or work licensed under the GNU Free Documentation License. Note: in order to facilitate peer review and fight vandalism, we will store your IP number for a number of days. See Privacy Policy for more information. See Info for text formatting rules. You can edit the comment page if you need to fix typos. You can subscribe to new comments by email without leaving a comment.

To save this page you must answer this question:

Please say HELLO.