Skip to content
This repository was archived by the owner on Nov 13, 2017. It is now read-only.

Album art / artist art via Last.fm API #7

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions theory/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def config(self, use_htmlfill=True):
'password':g.tc.password,'webpassword':g.tc.webpassword,
'awskey':g.tc.awskey,'timeout':g.tc.timeout,
'aws_secret':g.tc.aws_secret,
'lastfmkey':g.tc.lastfmkey,
'default_search':g.tc.default_search,
'outputs': configured_outputs})

Expand Down
77 changes: 70 additions & 7 deletions theory/model/albumart.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class NoArtOnDisk(Exception):
pass

class AlbumArt:
amazonurl = None
weburl = None
imgurl = None
logger = None

Expand All @@ -46,7 +46,7 @@ def album_fetch(self,artist,album):
"""
attempt to load an album's cover art from disk.
if it doesn't exist, make a request using Amazon's
Web Services
Web Services and/or the Last.fm API.
"""

self.artist = artist
Expand All @@ -63,7 +63,10 @@ def album_fetch(self,artist,album):
try:
self.check_disk()
except NoArtOnDisk:
self.amazon_fetch()
try:
self.amazon_fetch()
except NoArtError:
self.lastfm_fetch()

def artist_art(self,artist):
""" return all of the album covers for a particular artist """
Expand Down Expand Up @@ -154,11 +157,71 @@ def amazon_fetch(self):
imgnodes = doc.getElementsByTagName('LargeImage')
if len(imgnodes) > 0:
node = imgnodes[0]
self.amazonurl = node.firstChild.firstChild.nodeValue
self.log('Found album art: %s' % self.amazonurl)
self.weburl = node.firstChild.firstChild.nodeValue
self.log('Found album art: %s' % self.weburl)
break

if not self.amazonurl:
if not self.weburl:
raise NoArtError

self.save_to_disk()

def lastfm_fetch(self):
"""
attempts to fetch album cover art from last.fm and
calls save_to_disk() to save the largest image permanently
to avoid subsequent lookups.
no album? get a picture of the artist.
get a key for the last.fm API here: http://www.last.fm/api/account
example URL: http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=b25b959554ed76058ac220b7b2e0a026&artist=Cher&album=Believe
"""

album = self.album if self.album != 'undefined' else ''
artist = self.artist if self.artist != 'undefined' else ''

if g.tc.lastfmkey == '' or not artist:
raise NoArtError

type = 'album' if (album and artist) else 'artist'

artist_safe = urllib2.quote(artist)
album_safe = urllib2.quote(album)

query_string = {'api_key': g.tc.lastfmkey, 'artist': artist_safe}

if type == 'album':
query_string.update({'method': 'album.getinfo','album': album_safe})

elif type == 'artist':
query_string.update({'method': 'artist.getinfo'})

query_string_sorted = '&'.join(['='.join(kv) for kv in sorted(query_string.items())])

url = {'verb': 'GET',
'protocol': 'http://',
'host': 'ws.audioscrobbler.com',
'request_uri': '/2.0',
'query_string': query_string_sorted.replace(':','%3A')}

real_url = url['protocol'] + url['host'] + url['request_uri'] + '?' + url['query_string']

try:
self.log('Fetching last.fm %s image: %s' % (type, real_url))
urlfile = urllib2.urlopen(real_url)
except urllib2.URLError:
# there are probably other exceptions that need to be caught here..
self.log('Error fetching last.fm XML')
raise NoArtError

doc = xml.dom.minidom.parse(urlfile)
urlfile.close()
images = doc.getElementsByTagName('image')
node = filter(lambda x: x.getAttribute('size') == 'extralarge' and x.parentNode.parentNode.nodeName == 'lfm', images)[0]
if node.hasChildNodes():
self.weburl = node.firstChild.nodeValue
self.log('Found %s art: %s' % (type, self.weburl))

if not self.weburl:
raise NoArtError

self.save_to_disk()
Expand All @@ -183,7 +246,7 @@ def check_disk(self):
def save_to_disk(self):
""" save the fetched cover image to disk permanently """
try:
urlfile = urllib2.urlopen(self.amazonurl)
urlfile = urllib2.urlopen(self.weburl)
except urllib2.URLError:
raise NoArtError

Expand Down
1 change: 1 addition & 0 deletions theory/model/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class ConfigForm(formencode.Schema):
default_search = formencode.validators.String(not_empty=True)
awskey = formencode.validators.String(strip=True,not_empty=False,if_missing=None)
aws_secret = formencode.validators.String(strip=True,not_empty=False,if_missing=None)
lastfmkey = formencode.validators.String(strip=True,not_empty=False,if_missing=None)
outputs = formencode.ForEach(OutputSchema(), if_missing=[])

class StreamNameInUse(formencode.validators.FancyValidator):
Expand Down
3 changes: 3 additions & 0 deletions theory/model/tconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def __init__(self):
self.webpassword = ''
self.timeout = False
self.awskey = None
self.lastfmkey = None
self.aws_secret = None
self.streams = []
self.default_search = 'Any'
Expand All @@ -49,6 +50,7 @@ def __init__(self):
self.password = conf.get('mpd','password')
self.awskey = conf.get('services','awskey')
self.aws_secret = conf.get('services','aws_secret')
self.lastfmkey = conf.get('services','lastfmkey')
self.webpassword = conf.get('main','webpassword')
self.timeout = conf.getboolean('main','timeout')
self.default_search = conf.get('main','default_search')
Expand All @@ -75,6 +77,7 @@ def commit_config(self):
conf.add_section("services")
conf.set('services','awskey',self.awskey)
conf.set('services','aws_secret',self.aws_secret)
conf.set('services','lastfmkey',self.lastfmkey)
conf.add_section('main')
conf.set('main','webpassword',self.webpassword)
conf.set('main','timeout',self.timeout)
Expand Down
12 changes: 11 additions & 1 deletion theory/templates/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@
${h.html.tags.text('aws_secret', None, size=45)}<br />
</td>
</tr>
<tr>
<td align=right>
Last.fm API Key:</td>
<td>
${h.html.tags.text('lastfmkey', None, size=32)}<br />
(for automatic downloading of album / artist art)
</td>
</tr>
<tr>
<td align=right>
Default search type:</td>
Expand Down Expand Up @@ -122,4 +130,6 @@

</form>

<div style="color:white;margin-top:25px">sign up for an Amazon Developer Key at <a href="https://aws-portal.amazon.com/gp/aws/developer/registration/index.html" target="_blank">https://aws-portal.amazon.com/gp/aws/developer/registration/index.html</a></div>
<div style="color:white;margin-top:25px">sign up for an Amazon Developer Key at <a href="https://aws-portal.amazon.com/gp/aws/developer/registration/index.html" target="_blank">https://aws-portal.amazon.com/gp/aws/developer/registration/index.html</a><br/>
sign up for a Last.fm Developer Key at <a href="http://www.last.fm/api/account" target="_blank">http://www.last.fm/api/account</a>
</div>