Once upon a time I made a Python script that posts the music playing in Banshee (Ubuntu) on Twitter. Times have changed and now I use Clementine to listen to music, furthermore I jumped the Mastodon bandwagon too, so I wanted my script to toot too, not just tweet.

I’ve handled the Clementine part a while back already. Its interface is basically the same as Banshee, just different DBus objects. I also tweaked the message body so that extremely long artist names or titles don’t mess up the Twitter character limit.

Yes, I know that Mastodon’s character limit is much higher than Twitter’s, but having to adjust that part too would be too much effort for what it’s worth. Posting on Mastodon is a much gentler task than using Twitter’s app registration system. Luckily enough, there is already a Python module just for this task. I saved my creditentials in files just as the docs told me.

#!/usr/bin/env python
#coding=utf-8

import sys, tweepy, urllib
from dbus import Bus, DBusException
from gi.repository import Notify
from mastodon import Mastodon

bus = Bus(Bus.TYPE_SESSION)

def get_clem():
  try:
    return bus.get_object('org.mpris.clementine', '/Player')
  except DBusException:
    sys.exit(1)

clem = get_clem()

data = clem.GetMetadata()

if not "artist" in data.keys() or not "title" in data.keys() or not "album" in data.keys():
	sys.exit(1)

str = u'#nowplaying '+unicode(data["artist"])[:45]+
	u' - '+unicode(data["title"])[:40]+
	('...' if len(unicode(data['title'])) > 40 else '')+
	' ('+unicode(data["album"])[:40]+
	('...' if len(unicode(data['album'])) > 40 else '')+')'

str = str.encode('utf8')

try:
	auth = tweepy.OAuthHandler('consumer key', 'consumer secret')
	auth.set_access_token('access token','access token secret')

	api = tweepy.API(auth)
	api.update_status(status=str)
except TweepError as e:
	print "Twitter error: ", e.strerror

try:
	mastodon = Mastodon(client_id="mastodon_app.txt",
		access_token="mastodon_user.txt",
		api_base_url="https://pawoo.net/")
	mastodon.toot(str)
except:
	print "Mastodon error: ", sys.exec_info()[0]

Notify.init('#nowplaying')
Notify.Notification.new('#nowplaying','#nowplaying sent').show()

sys.exit(0)

The logical next step would be to merge scripts, allowing it to support both Banshee and Clementine, and also enable logging in dynamically instead of having to hard-code the creds. It’s definitely doable, but it’s more hassle than I’m up for at the moment.

The biggest issue is that apparently the app would need to register with every Mastodon instance individually, and preferably only once with each. To this my solution would be running a server-side code that stores the app’s tokens for each service (Twitter, Mastodon instances) and just forwards messages to those services from the desktop script (which would still need to be desktop, since it’d need to access DBus). Logging in would then be the bottleneck, since the server would need to return the user’s creds to the userside script (while storing its own creds for every new Mastodon instance).

Either way, it’d be way more than what I could (or would be willing to) achieve with a single-file little script.