Mastodon.py in the browser!
Today, I learned that PyScript exists. PyScript is, at its core, some rigging to make Pyodide, a WebAssembly port of the CPython Python interpreter, real easy to use as a proper client-side web scripting tool. Just include one <script>
tag and now <script type="py">
is a valid thing you can have in your website. Put Python code inside of it, interact with the DOM, the works. I think that rules and/or is kind of horrifying, depending. Obviously, for me, the immediate question was: Can this run Mastodon.py? And the answer is: Yes, very competently.
Some initial snags:
- I didn’t understand at first how to get a Python module loaded, and messed around a bunch until I finally understood that PyScript comes with pip included (well, okay, not literally pip - it uses something called micropip and will grab the package and depends from PyPi, and works as long as they’re pure python packages, more complex things will not work). Yes, it will just install the module plus dependencies from PyPi on page load. This is, again, equal parts awesome and horrible.
- To do HTTP requests, you need to import another module that will patch Pythons requests library to use XMLHttpRequest. Once you know, that works perfectly, though, and is just one import and one line to patch.
- At first, all my requests were failing with an
422 Unprocessable Entity
response from Mastodon. I spent some time trying to figure out whether my parameters were set wrongly, or maybe being passed in some incompatible or badly escaped way (which is what that would usually indicate), until I finally figured out that this response was due to the “Origin” header. I was testing with a local file, which makes theOrigin
benull
. That causes Mastodon (or nginx - in any case, something in the stack) to refuse the request and return status422
. Once I put the website on an actual server, things worked perfectly right away.
With that sorted out, the first step was to just auth. I started with a hardcoded access token, but wait, this is just a website on a server, and the browser knows the query parameters right, so can we do OAuth entirely inside a website without any help from server side? Sure:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
|
And there we go: That’s Mastodon.py, fully inside a web page, letting you log into your account and post something (if you are on mastodon.social - sorry, for the basic sample, it’s hardcoded)! You can’t get much more SPA than that! And you can log in with confidence: The server hosting the web page never even sees your credentials1, so even if I was intent on acting maliciously (I am not), I couldn’t do anything, and if someone else got in, there is no database for them to leak!
So how far can we go with this? Well, here is a reasonably complete, mostly working single page web client for Mastodon. You can enter your instance URL, log in, send posts, look at posts and notifications, favourite, boost, reply, new posts and notifications load automatically. It’s certainly not the nicest, god knows I am Not A Frontend Guy, even when asking sparkly autocomplete to fill in the blanks for me, but it’s perfectly functional. You could use social media like this, if you wanted to. The streaming API, unfortunately, would need some work to get running - the threading
module, which it uses internally (at least in the useful mode where it doesn’t block) isn’t supported by Pyodide (yet?), so you’d have to work around that, which is maybe possible using WebWorkers, but that’s certainly not a quick “haha wait this actually works?” type task. Getting attachments to post would also require some more hooking things up. But everything else should basically Just Work.
One open question here is: Why? Mastodon already comes with two perfectly fine web interfaces, and there’s more to choose from if you want them. Python doesn’t seem like the obvious choice for writing one, and the one I wrote as a test is obviously more of a high effort shitpost than anything intended for serious, continous use. But I think that there is quite a bit of space for simple tools that maybe currently only exist as a Python script you’d have to figure out how to run, because a lot of people would rather write Python than JavaScript. Stuff like that could very easily just also be a webpage using this. And that’s potentially pretty neat!
As for myself, I threw something a bit more meta together that I’ve wanted to have for a while: A Mastodon.py API explorer! Which is much nicer now, thanks to the extensive documentation and types for all fields! And with Mastodon.py running in the browser, is actually reasonably safe to do, because I am not executing any Python code on my server! Maybe it’ll be useful for people wanting to play around with Mastodon.py or with the Mastodon API in general!
P.S.: If you want the source code for any of these… you can just view-source the HTML page! That is quite literally all there is (links may not be clickable, browsers don’t like you linking to this):
-
It does see the OAuth auth code, but that code is useless without the client id and secret, which are only ever sent to the instance you’re logging into. ↩
tagged: | criminal activity python wasm |
filed under: | lets be honest, it's probably not much worse than the average JS web framework |