A silly conceit, but fun. The script is pretty simple (read: I’m an unsophisticated programmer), but it works. Because it hooks into last.fm, anything you scrobble (Roon, Spotify, iTunes, your player of choice) shows up.
I run it manually right now, but it could be cron’d.
#!/usr/bin/env /Library/Frameworks/Python.framework/Versions/3.7/bin/python3
# Installed Python 3.7 for Mac from python.org
import os
import json
import sys
import twitter # Installed python-twitter (https://python-twitter.readthedocs.io/en/latest/installation.html)
import requests
# Twitter API Setup -- the twitter API information has to come from your Twitter account
consumer_key = '[Twitter Consumer Key]'
consumer_secret = '[Twitter Consumer Secret]'
access_key = '[Twitter Access Key]'
access_secret = '[Twitter Access Secret]'
api = twitter.Api(consumer_key=consumer_key, consumer_secret=consumer_secret,
access_token_key=access_key, access_token_secret=access_secret)
# Files we use -- this is where my files live, but you will need to use your own filepath
scrobbleDir = os.path.join('/', 'Users', 'onlylooksharmless', 'Documents','Scripts', 'Scrobble to Twitter')
lastScrobbleFileLoc = os.path.join(scrobbleDir, 'lastscrobble.txt')
tweetErrFileLoc = os.path.join(scrobbleDir, 'tweeterr.txt')
# Get last date from stored file, increment by one, reset to string
# Consider using shelve module (https://automatetheboringstuff.com/chapter8/) in next version
# The very first time you run it, I'd recommend using a browser to pull the last NN scrobbles, and you can pick out a UTS to put in the file
lastScrobbleFile = open(lastScrobbleFileLoc)
startTime = lastScrobbleFile.read()
lastScrobbleFile.close
startTime = str(int(startTime) + 1)
# Get Scrobbles and set up iteration
# Block Comment is what I used to test against a downloaded JSON file
'''samplePath = os.path.join('/', 'Users', 'onlylooksharmless', 'Documents', 'Scripts', 'Scrobble to Twitter', 'Dev Process', 'Sample Scrobble.json')
sampleFile = open(samplePath)
scrobbleList=sampleFile.read()
scrobbleListAsPython = json.loads(scrobbleList)'''
# last.fm API call using startTime
# It works to increment last dateStamp by 1, append &from=[incremented] at end
# You have to get your own last.fm user name and api key
scrobbleURL ='http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&&user=[USERNAME]&api_key=[APIKEY]&format=json&from=%s' % (startTime)
try:
scrobbleList = requests.get(scrobbleURL)
except:
tweetErrFile = open(tweetErrFileLoc, 'a')
tweetErrFile.write('last.fm unavailable')
tweetErrFile.close()
sys.exit(2)
scrobbleList.raise_for_status()
scrobbleListAsPython = json.loads(scrobbleList.text) # I used JSON for no better reason that it's what "Automate the Boring Stuff worked with."
trackList = scrobbleListAsPython['recenttracks']['track']
trackListLen = len(trackList)
# Check to make sure Twitter is up; bail if not
try:
twitterTest = requests.get('http://twitter.com')
except:
tweetErrFile = open(tweetErrFileLoc, 'a')
tweetErrFile.write('twitter unavailable')
tweetErrFile.close()
sys.exit(2)
# Create the blank tweet list
# Goal of creating uniques is to reduce Twitter duplicate tweet errors
# Maybe use shelve module in future version to keep a history of NN tweets
# Setting up blanks here (a) prevents erroring out, and (b) allows for a test below
tweetList = []
dateStamp = ''
# Iterate in reverse chron order through scrobbles to create a list of (for this session) uniques
for i in reversed(range(trackListLen)):
currentTrack = trackList[i]
currentAlbum = currentTrack['album']['#text']
currentArtist = currentTrack['artist']['#text']
currentName = currentTrack['name']
currentURL = currentTrack['url']
dateStamp = currentTrack['date']['uts'] #this already shows as a string, so no need to convert
nowPlaying = ('#nowplaying ' + currentArtist + ' – \"' + currentName + '\" from \"' + currentAlbum + '\"' + ' ' + currentURL)
if nowPlaying not in tweetList:
tweetList.append(nowPlaying)
# Then run through the list in the new order -- it's now chronologically ordered
for i in range(len(tweetList)):
try:
status = api.PostUpdate(tweetList[i])
print("{0} just posted: {1}".format(status.user.name, status.text))
#print(tweetList[i])
except:
tweetErrFile = open(tweetErrFileLoc, 'a')
tweetErrFile.write(tweetList[i])
tweetErrFile.close()
time.sleep(120)
# I was running 1 minute intervals to get through the first block of scrobbles, and Twitter assumed it was spam after about 40
# Could have been extenuating circumstances, but two minutes seems to work.
# Stash the last scrobble datestamp (using the blank dateStamp to avoid blanking the file datestamp if there's no scrobbles)
if dateStamp:
lastScrobbleFile = open(lastScrobbleFileLoc, 'w')
lastScrobbleFile.write(dateStamp)
lastScrobbleFile.close()