Build your own Mastodon client
Tutorial – Mastodon
Creating your own clients to interact with your friends in the Fediverse is easy. A bit of Python and an off-the-shelf module will do the trick.
Although there are plenty of Mastodon [1] clients out there (as we saw in the prior installment [2]), sometimes you just want that something special to satisfy your needs. Fortunately, Mastodon's API is open and well-organized and there is a Python wrapper [3] that makes it even easier.
Registration
First, you need to install the Mastodon.py
wrapper. The easiest way to do this is by using pip
:
pip install Mastodon.py
or, if pip
complains about permissions:
sudo pip install Mastodon.py
Next you want to register your application with the Mastodon network. You can do this from the Mastodon website where you have opened your account. We talked about how to do this in Linux Magazine, issue 227 [4].
Or you could do it all from the comfort of your command line with something like what you see in Listing 1.
Listing 1
readtoots_register.py
01 #!/usr/bin/env python 02 03 from mastodon import Mastodon 04 05 Mastodon.create_app( 06 'readtoots', 07 scopes=['read'], 08 api_base_url = 'https://your.mastodon.server', 09 to_file = '.secrets' 10 )
Line 1 of Listing 1 just sets the interpreter you want to use to run this script (your default Python interpreter).
Line 3 pulls in the bits of the mastodon
module you need. Lines 5 through 10 registers the app, giving it a name the server can identify it by (readtoots
on line 6). On line 7, you tell the server what sort of actions it will be able to carry out (in this case only 'read'
– other actions are 'write'
, 'follow'
, and 'push'
). The api_base_url
on line 8 tells the application what instance of Mastodon you want to go through. This is the address of a Mastodon server – you would usually use the instance where you have your account for this. Finally, the to_file
argument tells readtoots_register.py
where to store the credentials information the server will send back down the line for the application.
Save the file as readtoots_register.py
, make it executable with
chmod a+x readtoots_register.py
and run it with:
./readtoots_register.py
After running it for the first time, nothing apparently happens, but you will find a new .secrets
file in your app's directory. If you look inside, you will see something similar to Listing 2.
Listing 2
.secrets
01 53eM1n9lyHR4nd0mUnUMB3r5vAN6G133TeR5X4g 02 KM0r340FdTh3p54M3A60nTnUkKN0WC0hweMigLcng6U 03 https://your.mastodon.server
The Mastodon.create_app()
function shown in Listing 1 not only registers the application, it also returns a client_id
(line 1 in Listing 2) and a client_secret
(line 2 in Listing 2) that you will be able to use to identify your application each time it has to interact with the Mastodon instance. It also kindly adds the address of the instance the app is registered with, making it super convenient as you will see later on.
You will only need to run readtoots_register.py
once, and, when you're done, you can crack on with readtoots.py
proper.
Reading Toots
Let's build a command-line Mastodon client that reads, by default, the toots of the account you log into, but that will also let you read toots from any federated account you pass as a parameter to the script.
As you will also need login credentials to access an account, you are going to need at least three options on the command line. As command line arguments tend to pile up as you add features, let's keep things organized and use the optparse
Python module to keep things tidy.
Take a look at Listing 3 to see how it all works.
Listing 3
readtoots.py
01 #!/usr/bin/env python 02 03 from mastodon import Mastodon 04 from optparse import OptionParser 05 06 if __name__ == '__main__': 07 08 parser = OptionParser () 09 parser.add_option ('-u', '--username', help = 'your email', dest = 'maUser') 10 parser.add_option ('-p', '--password', help = 'your password', dest = 'maPassword') 11 parser.add_option ('-a', '--account', help = 'account you want to read', dest = 'sosAccount', default = 'me') 12 13 (options, args) = parser.parse_args() 14 15 app=Mastodon ( 16 client_id = '.secrets' 17 ) 18 19 app.log_in ( 20 username = options.maUser, 21 password = options.maPassword, 22 to_file = '.token', 23 scopes = ['read'] 24 ) 25 26 if (options.sosAccount == 'me'): 27 maId = app.me ()['id'] 28 29 else: 30 maId = app.account_search (options.sosAccount)[0]['id'] 31 32 maToots = app.account_statuses (maId) 33 34 for status in maToots: 35 print ('==================== Status ' + str (status['id']) + ' ====================') 36 print (status['content'])
Once you have imported the modules you need (lines 3 and 4) and set up the OptionParser()
to manage your command line arguments (lines 8 through 13), it is time to activate your application (lines 15 through 17).
See how convenient this is: If you hadn't registered and stored the credentials and the address of the Mastodon instance in .secrets
, you would have had to hard code them in with the client_secret
, client_id
, and api_base_url
option when you instantiate the Mastodon
class.
Next, you log into your account (lines 19 through 24). This is not always necessary. In theory, you can have an application read public toots from public accounts without having to log in, but this only works on some Mastodon servers. Turns out mine is not one of them.
Whether logging in is necessary or not will depend on the version of the Mastodon software the server is running and how the administrator has configured it. To be on the safe side, always log in, and your application will not fail.
The logging in itself is straightforward: pass the username and password collected from the command line to Mastodon.py's log_in()
function and you will get an access token in return (which you can store in a file for when you need it – line 22).
For some reason not explained in Mastodon's API documentation, my server also required the application's scope as defined when registering it (see Listing 1, line 7). Oh well! I added it on line 23 of Listing 3, and everything worked.
Next you get the id
of the account you want to read. The id
is not the same as the name of the account (@someusername@some.mastodon.instance), but a unique numerical value assigned to each account. There is no easy way to discover an account's id on a Mastodon website, but you can discover what yours is with Mastodon.py
's me()
function (line 27).
The me()
function returns a Mastodon user
dictionary. A user
dictionary contains information about the account. It includes, among other things, the display_name
, the username
, when it was created, how many followers it has, and, yes, the account's id
.
In case the user has decided to peruse the statuses of another account, you can use the app.account_search()
to find the account passed on by the -a
option on the command line. As app.account_search()
returns a list of user
dictionaries, you have to pick the first one (line 30).
The account_statuses()
function returns a list of toot
dictionaries containing all the toots of an account identified by maId
(line 32). You then loop through them (lines 34 through 36), extract the content
field (line 36), and print it to the command line.
Save the file as readtoots.py
and make it executable with:
chmod a+x readtoots.py
You can then run it like this:
./readtoots.py -u your@email.com -p "Your secret password"
where your@email.com
is the email you used when you registered for your Mastodon account and "Your secret password"
is the password you use to log into your account.
This will output your account's 20 latest toots to the command line (Figure 1). It doesn't look pretty, but it works.
In the first run, you don't specify any account, so the application goes with the default ("me"
) and prints out the statuses of the account it is logged in to.
If you run readtools.py
like this:
./readtoots.py -u your@email.com -p"Your secret password" -a @kde@mastodon.technology
you will see the latest 20 toots from the KDE community account.
I have mentioned several times that, by default, all you get is the 20 latest statuses. You can push up that limit to a maximum of 40 by adding limit = 40
as an argument in account_statuses()
on line 32, but that is still a paltry feed if ever there was one. Who posts only 40 statuses and stops there? Incidentally, this is a limitation of the Mastodon API, not of Mastodon.py
. You can get past this limitation, however. Take a look at Listing 4.
Listing 4
readtoots.py (better version)
01 #!/usr/bin/env python 02 03 from mastodon import Mastodon 04 from optparse import OptionParser 05 06 if __name__ == '__main__': 07 08 parser = OptionParser () 09 parser.add_option ('-u', '--username', help = 'your email', dest = 'maUser') 10 parser.add_option ('-p', '--password', help = 'your password', dest = 'maPassword') 11 parser.add_option ('-a', '--account', help = 'account you want to read', dest = 'sosAccount', default = 'me') 12 13 (options, args) = parser.parse_args() 14 15 app=Mastodon ( 16 client_id = '.secrets' 17 ) 18 19 app.log_in ( 20 username = options.maUser, 21 password = options.maPassword, 22 to_file = '.token', 23 scopes = ['read'] 24 ) 25 26 if (options.sosAccount == 'me'): 27 maId = app.me ()['id'] 28 29 else: 30 maId = app.account_search (options.sosAccount)[0]['id'] 31 32 maMaxId = None 33 wannaRepeat = "Y" 34 35 while (wannaRepeat in "YyYesyesYeahyeah"): 36 37 maToots = app.account_statuses (maId, max_id = maMaxId) 38 39 for status in maToots: 40 print ('==================== Status ' + str (status['id']) + ' ====================') 41 print (status['content']) 42 43 maMaxId = status['id'] 44 print ('========================================') 45 print ("More?") 46 wannaRepeat = input()
The trick is using account_statuses()
's max_id
argument (line 37). All you have to do is put the for
loop inside a while
loop (lines 35 through 46) and collect the last status id after the for
loop exits (line 43). Then you ask the user if they want to continue (lines 45 and 46) and, if they say Yes (line 35), use the status id in account_statuses()
and start over.
When you run readtoots.py
now, it prints out the 20 latest toots and then prints More?; if the user enters Y, Yes, or Yeah, it prints out the next 20 toots and asks again. If the user types in No, the application exits (Figure 2).
Improvements
You will immediately notice that statuses come laced with HTML tags. To make them more readable, you could strip them out. Or, even better, use the HTML to format the text as the author intended. Modern terminal emulators accept colored, bold, and highlighted text, even emojis. Most also allow for "live" links the user can click.
Another thing is that images, videos, and other media files included in toots are lost. To be able to see them, you would have to design a client with a graphical interface, with boxes that display pictures and clips. Implementing a client with these features goes well beyond the scope of this article.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Halcyon Creates Anti-Ransomware Protection for Linux
As more Linux systems are targeted by ransomware, Halcyon is stepping up its protection.
-
Valve and Arch Linux Announce Collaboration
Valve and Arch have come together for two projects that will have a serious impact on the Linux distribution.
-
Hacker Successfully Runs Linux on a CPU from the Early ‘70s
From the office of "Look what I can do," Dmitry Grinberg was able to get Linux running on a processor that was created in 1971.
-
OSI and LPI Form Strategic Alliance
With a goal of strengthening Linux and open source communities, this new alliance aims to nurture the growth of more highly skilled professionals.
-
Fedora 41 Beta Available with Some Interesting Additions
If you're a Fedora fan, you'll be excited to hear the beta version of the latest release is now available for testing and includes plenty of updates.
-
AlmaLinux Unveils New Hardware Certification Process
The AlmaLinux Hardware Certification Program run by the Certification Special Interest Group (SIG) aims to ensure seamless compatibility between AlmaLinux and a wide range of hardware configurations.
-
Wind River Introduces eLxr Pro Linux Solution
eLxr Pro offers an end-to-end Linux solution backed by expert commercial support.
-
Juno Tab 3 Launches with Ubuntu 24.04
Anyone looking for a full-blown Linux tablet need look no further. Juno has released the Tab 3.
-
New KDE Slimbook Plasma Available for Preorder
Powered by an AMD Ryzen CPU, the latest KDE Slimbook laptop is powerful enough for local AI tasks.
-
Rhino Linux Announces Latest "Quick Update"
If you prefer your Linux distribution to be of the rolling type, Rhino Linux delivers a beautiful and reliable experience.