291 lines
10 KiB
Python
291 lines
10 KiB
Python
#!/usr/bin/env python
|
|
|
|
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
|
|
__version__ = "0.2"
|
|
__license__ = "GNU Lesser General Public License"
|
|
|
|
from base import LastfmBase
|
|
from lazylist import lazylist
|
|
|
|
class Track(LastfmBase):
|
|
"""A class representing a track."""
|
|
def init(self,
|
|
api,
|
|
name = None,
|
|
mbid = None,
|
|
url = None,
|
|
streamable = None,
|
|
artist = None,
|
|
album = None,
|
|
image = None,
|
|
stats = None,
|
|
fullTrack = None,
|
|
playedOn = None,
|
|
lovedOn = None):
|
|
if not isinstance(api, Api):
|
|
raise LastfmInvalidParametersError("api reference must be supplied as an argument")
|
|
self.__api = api
|
|
self.__name = name
|
|
self.__mbid = mbid
|
|
self.__url = url
|
|
self.__streamable = streamable
|
|
self.__artist = artist
|
|
self.__album = album
|
|
self.__image = image
|
|
self.__stats = stats and Stats(
|
|
subject = self,
|
|
match = stats.match,
|
|
playcount = stats.playcount,
|
|
rank = stats.rank,
|
|
listeners = stats.listeners,
|
|
)
|
|
self.__fullTrack = fullTrack
|
|
self.__playedOn = playedOn
|
|
self.__lovedOn = lovedOn
|
|
|
|
@property
|
|
def name(self):
|
|
"""name of the track"""
|
|
return self.__name
|
|
|
|
@property
|
|
def mbid(self):
|
|
"""mbid of the track"""
|
|
return self.__mbid
|
|
|
|
@property
|
|
def url(self):
|
|
"""url of the tracks's page"""
|
|
return self.__url
|
|
|
|
@property
|
|
def streamable(self):
|
|
"""is the track streamable"""
|
|
return self.__streamable
|
|
|
|
@property
|
|
def artist(self):
|
|
"""artist of the track"""
|
|
return self.__artist
|
|
|
|
@property
|
|
def album(self):
|
|
"""artist of the track"""
|
|
return self.__album
|
|
|
|
@property
|
|
def image(self):
|
|
"""image of the track's album cover"""
|
|
return self.__image
|
|
|
|
@property
|
|
def stats(self):
|
|
"""stats of the track"""
|
|
return self.__stats
|
|
|
|
@property
|
|
def fullTrack(self):
|
|
"""is the full track streamable"""
|
|
return self.__fullTrack
|
|
|
|
@property
|
|
def playedOn(self):
|
|
"""datetime the track was last played"""
|
|
return self.__playedOn
|
|
|
|
@property
|
|
def lovedOn(self):
|
|
"""datetime the track was marked 'loved'"""
|
|
return self.__lovedOn
|
|
|
|
def __checkParams(self,
|
|
params,
|
|
artist = None,
|
|
track = None,
|
|
mbid = None):
|
|
if not ((artist and track) or mbid):
|
|
raise LastfmInvalidParametersError("either (artist and track) or mbid has to be given as argument.")
|
|
|
|
if artist and track:
|
|
params.update({'artist': artist, 'track': track})
|
|
elif mbid:
|
|
params.update({'mbid': mbid})
|
|
return params
|
|
|
|
@LastfmBase.cachedProperty
|
|
def similar(self):
|
|
"""tracks similar to this track"""
|
|
params = self.__checkParams(
|
|
{'method': 'track.getsimilar'},
|
|
self.artist.name,
|
|
self.name,
|
|
self.mbid
|
|
)
|
|
data = self.__api._fetchData(params).find('similartracks')
|
|
return [
|
|
Track(
|
|
self.__api,
|
|
subject = self,
|
|
name = t.findtext('name'),
|
|
artist = Artist(
|
|
self.__api,
|
|
subject = self,
|
|
name = t.findtext('artist/name'),
|
|
mbid = t.findtext('artist/mbid'),
|
|
url = t.findtext('artist/url')
|
|
),
|
|
mbid = t.findtext('mbid'),
|
|
stats = Stats(
|
|
subject = t.findtext('name'),
|
|
match = float(t.findtext('match'))
|
|
),
|
|
streamable = (t.findtext('streamable') == '1'),
|
|
fullTrack = (t.find('streamable').attrib['fulltrack'] == '1'),
|
|
image = dict([(i.get('size'), i.text) for i in t.findall('image')]),
|
|
)
|
|
for t in data.findall('track')
|
|
]
|
|
|
|
@LastfmBase.topProperty("similar")
|
|
def mostSimilar(self):
|
|
"""track most similar to this track"""
|
|
pass
|
|
|
|
@LastfmBase.cachedProperty
|
|
def topFans(self):
|
|
"""top fans of the track"""
|
|
params = self.__checkParams(
|
|
{'method': 'track.gettopfans'},
|
|
self.artist.name,
|
|
self.name,
|
|
self.mbid
|
|
)
|
|
data = self.__api._fetchData(params).find('topfans')
|
|
return [
|
|
User(
|
|
self.__api,
|
|
subject = self,
|
|
name = u.findtext('name'),
|
|
url = u.findtext('url'),
|
|
image = dict([(i.get('size'), i.text) for i in u.findall('image')]),
|
|
stats = Stats(
|
|
subject = u.findtext('name'),
|
|
weight = int(u.findtext('weight'))
|
|
)
|
|
)
|
|
for u in data.findall('user')
|
|
]
|
|
|
|
@LastfmBase.topProperty("topFans")
|
|
def topFan(self):
|
|
"""topmost fan of the track"""
|
|
pass
|
|
|
|
@LastfmBase.cachedProperty
|
|
def topTags(self):
|
|
"""top tags for the track"""
|
|
params = self.__checkParams(
|
|
{'method': 'track.gettoptags'},
|
|
self.artist.name,
|
|
self.name,
|
|
self.mbid
|
|
)
|
|
data = self.__api._fetchData(params).find('toptags')
|
|
return [
|
|
Tag(
|
|
self.__api,
|
|
subject = self,
|
|
name = t.findtext('name'),
|
|
url = t.findtext('url'),
|
|
stats = Stats(
|
|
subject = t.findtext('name'),
|
|
count = int(t.findtext('count')),
|
|
)
|
|
)
|
|
for t in data.findall('tag')
|
|
]
|
|
|
|
@LastfmBase.topProperty("topTags")
|
|
def topTag(self):
|
|
"""topmost tag for the track"""
|
|
pass
|
|
|
|
@staticmethod
|
|
def search(api,
|
|
track,
|
|
artist = None,
|
|
limit = None):
|
|
params = {'method': 'track.search', 'track': track}
|
|
if artist is not None:
|
|
params.update({'artist': artist})
|
|
if limit is not None:
|
|
params.update({'limit': limit})
|
|
|
|
@lazylist
|
|
def gen(lst):
|
|
data = api._fetchData(params).find('results')
|
|
totalPages = int(data.findtext("{%s}totalResults" % Api.SEARCH_XMLNS))/ \
|
|
int(data.findtext("{%s}itemsPerPage" % Api.SEARCH_XMLNS)) + 1
|
|
|
|
@lazylist
|
|
def gen2(lst, data):
|
|
for t in data.findall('trackmatches/track'):
|
|
yield Track(
|
|
api,
|
|
name = t.findtext('name'),
|
|
artist = Artist(
|
|
api,
|
|
name = t.findtext('artist')
|
|
),
|
|
url = t.findtext('url'),
|
|
stats = Stats(
|
|
subject = t.findtext('name'),
|
|
listeners = int(t.findtext('listeners'))
|
|
),
|
|
streamable = (t.findtext('streamable') == '1'),
|
|
fullTrack = (t.find('streamable').attrib['fulltrack'] == '1'),
|
|
image = dict([(i.get('size'), i.text) for i in t.findall('image')]),
|
|
)
|
|
|
|
for t in gen2(data):
|
|
yield t
|
|
|
|
for page in xrange(2, totalPages+1):
|
|
params.update({'page': page})
|
|
data = api._fetchData(params).find('results')
|
|
for t in gen2(data):
|
|
yield t
|
|
return gen()
|
|
|
|
@staticmethod
|
|
def hashFunc(*args, **kwds):
|
|
try:
|
|
return hash("%s%s" % (kwds['name'], hash(kwds['artist'])))
|
|
except KeyError:
|
|
raise LastfmInvalidParametersError("name and artist have to be provided for hashing")
|
|
|
|
def __hash__(self):
|
|
return self.__class__.hashFunc(name = self.name, artist = self.artist)
|
|
|
|
def __eq__(self, other):
|
|
if self.mbid and other.mbid:
|
|
return self.mbid == other.mbid
|
|
if self.url and other.url:
|
|
return self.url == other.url
|
|
if (self.name and self.artist) and (other.name and other.artist):
|
|
return (self.name == other.name) and (self.artist == other.artist)
|
|
return super(Track, self).__eq__(other)
|
|
|
|
def __lt__(self, other):
|
|
return self.name < other.name
|
|
|
|
def __repr__(self):
|
|
return "<lastfm.Track: '%s' by %s>" % (self.name, self.artist.name)
|
|
|
|
from api import Api
|
|
from artist import Artist
|
|
from error import LastfmInvalidParametersError
|
|
from stats import Stats
|
|
from tag import Tag
|
|
from user import User
|