0.2.14
This commit is contained in:
parent
8e390ea93e
commit
e916f791cf
|
@ -1,3 +1,11 @@
|
||||||
|
0.2.14:
|
||||||
|
* changed the version numbering system.
|
||||||
|
* fixed Authentication and MD5 with non-ASCII characters (issue #7)
|
||||||
|
* Created UserPlaylist class.
|
||||||
|
* User.getPlaylistIDs is now deprecated.
|
||||||
|
* track.addToPlaylist is now deprecated.
|
||||||
|
* User.fetchPlaylist is now deprecated.
|
||||||
|
|
||||||
0.2b13:
|
0.2b13:
|
||||||
* fixed: User.get_friends limit parameter (issue #5)
|
* fixed: User.get_friends limit parameter (issue #5)
|
||||||
* changed: using hashlib module instead of deprecated md5 module.
|
* changed: using hashlib module instead of deprecated md5 module.
|
||||||
|
|
186
pylast.py
186
pylast.py
|
@ -21,7 +21,7 @@
|
||||||
# http://code.google.com/p/pylast/
|
# http://code.google.com/p/pylast/
|
||||||
|
|
||||||
__name__ = 'pyLast'
|
__name__ = 'pyLast'
|
||||||
__version__ = '0.2b13'
|
__version__ = '0.2.14'
|
||||||
__doc__ = 'A Python interface to the Last.fm API.'
|
__doc__ = 'A Python interface to the Last.fm API.'
|
||||||
__author__ = 'Amr Hassan'
|
__author__ = 'Amr Hassan'
|
||||||
__email__ = 'amr.hassan@gmail.com'
|
__email__ = 'amr.hassan@gmail.com'
|
||||||
|
@ -82,6 +82,12 @@ DOMAIN_CHINESE = 'cn.last.fm'
|
||||||
USER_MALE = 'Male'
|
USER_MALE = 'Male'
|
||||||
USER_FEMALE = 'Female'
|
USER_FEMALE = 'Female'
|
||||||
|
|
||||||
|
def warn(message):
|
||||||
|
print "Warning:", message
|
||||||
|
|
||||||
|
def warn_deprecated(old, new):
|
||||||
|
warn('%s is now deprecated. Use %s instead.' %(old, new))
|
||||||
|
|
||||||
def _status2str(lastfm_status):
|
def _status2str(lastfm_status):
|
||||||
|
|
||||||
statuses = {
|
statuses = {
|
||||||
|
@ -272,7 +278,7 @@ class Request(Exceptionable):
|
||||||
string += self.secret
|
string += self.secret
|
||||||
|
|
||||||
hash = hashlib.md5()
|
hash = hashlib.md5()
|
||||||
hash.update(string)
|
hash.update(string.encode('utf-8'))
|
||||||
|
|
||||||
return hash.hexdigest()
|
return hash.hexdigest()
|
||||||
|
|
||||||
|
@ -847,8 +853,13 @@ class Track(BaseObject, Cacheable, Taggable):
|
||||||
def addToPlaylist(self, playlist_id):
|
def addToPlaylist(self, playlist_id):
|
||||||
"""Adds this track to a user playlist.
|
"""Adds this track to a user playlist.
|
||||||
* playlist_id: The unique playlist ID.
|
* playlist_id: The unique playlist ID.
|
||||||
|
|
||||||
|
[DEPRECATED]
|
||||||
|
Use UserPlaylist.addTrack instead.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
warn_deprecated('Track.addToPlaylist', 'UserPlaylist.addTrack')
|
||||||
|
|
||||||
params = self._getParams()
|
params = self._getParams()
|
||||||
params['playlistID'] = unicode(playlist_id)
|
params['playlistID'] = unicode(playlist_id)
|
||||||
|
|
||||||
|
@ -2346,6 +2357,25 @@ class User(BaseObject, Cacheable):
|
||||||
|
|
||||||
return list
|
return list
|
||||||
|
|
||||||
|
def getPlaylists(self):
|
||||||
|
"""Returns a list of UserPlaylists that this user owns."""
|
||||||
|
|
||||||
|
data = self.getPlaylistsData()
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
return data
|
||||||
|
|
||||||
|
ids = []
|
||||||
|
for p in data:
|
||||||
|
ids.append(p['id'])
|
||||||
|
|
||||||
|
playlists = []
|
||||||
|
|
||||||
|
for id in ids:
|
||||||
|
playlists.append(UserPlaylist(self.getName(), id, *self.auth_data))
|
||||||
|
|
||||||
|
return playlists
|
||||||
|
|
||||||
def getPlaylistsData(self):
|
def getPlaylistsData(self):
|
||||||
"""Returns a list of dictionaries for each playlist. """
|
"""Returns a list of dictionaries for each playlist. """
|
||||||
|
|
||||||
|
@ -2362,13 +2392,24 @@ class User(BaseObject, Cacheable):
|
||||||
p['title'] = self._extract(playlist, 'title')
|
p['title'] = self._extract(playlist, 'title')
|
||||||
p['date'] = self._extract(playlist, 'date')
|
p['date'] = self._extract(playlist, 'date')
|
||||||
p['size'] = int(self._extract(playlist, 'size'))
|
p['size'] = int(self._extract(playlist, 'size'))
|
||||||
|
p['description'] = self._extract(playlist, 'description')
|
||||||
|
p['duration'] = self._extract(playlist, 'duration')
|
||||||
|
p['streamable'] = self._extract(playlist, 'streamable')
|
||||||
|
p['images'] = self._extract_all(playlist, 'image')
|
||||||
|
p['url_appendix'] = self._extract(playlist, 'url')[19:]
|
||||||
|
|
||||||
list.append(p)
|
list.append(p)
|
||||||
|
|
||||||
return list
|
return list
|
||||||
|
|
||||||
def getPlaylistIDs(self):
|
def getPlaylistIDs(self):
|
||||||
"""Returns a list the playlists IDs this user has created. """
|
"""Returns a list the playlists IDs this user has created.
|
||||||
|
|
||||||
|
[DEPRECATED]
|
||||||
|
Use User.getPlaylists() instead.
|
||||||
|
"""
|
||||||
|
|
||||||
|
warn_deprecated('User.getPlaylistIDs', 'User.getPlaylists')
|
||||||
|
|
||||||
ids = []
|
ids = []
|
||||||
for i in self.getPlaylistsData():
|
for i in self.getPlaylistsData():
|
||||||
|
@ -2379,8 +2420,13 @@ class User(BaseObject, Cacheable):
|
||||||
def fetchPlaylist(self, playlist_id):
|
def fetchPlaylist(self, playlist_id):
|
||||||
"""Returns a list of the tracks on a playlist.
|
"""Returns a list of the tracks on a playlist.
|
||||||
* playlist_id: A unique last.fm playlist ID, can be retrieved from getPlaylistIDs().
|
* playlist_id: A unique last.fm playlist ID, can be retrieved from getPlaylistIDs().
|
||||||
|
|
||||||
|
[DEPRECATED]
|
||||||
|
Use UserPlaylist.getTracks() instead.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
warn_deprecated('User.fetchPlaylist', 'UserPlaylist.getTracks')
|
||||||
|
|
||||||
uri = u'lastfm://playlist/%s' %unicode(playlist_id)
|
uri = u'lastfm://playlist/%s' %unicode(playlist_id)
|
||||||
|
|
||||||
return Playlist(uri, *self.auth_data).fetch()
|
return Playlist(uri, *self.auth_data).fetch()
|
||||||
|
@ -2742,6 +2788,140 @@ class ArtistSearch(Search):
|
||||||
|
|
||||||
return list
|
return list
|
||||||
|
|
||||||
|
class UserPlaylist(BaseObject, Cacheable):
|
||||||
|
def __init__(self, username, playlist_id, api_key, api_secret, session_key):
|
||||||
|
BaseObject.__init__(self, api_key, api_secret, session_key)
|
||||||
|
Cacheable.__init__(self)
|
||||||
|
|
||||||
|
self._username = username
|
||||||
|
self._playlist_id = unicode(playlist_id)
|
||||||
|
|
||||||
|
self._cached_info = None
|
||||||
|
|
||||||
|
def _getInfo(self):
|
||||||
|
|
||||||
|
playlists = self.getUser().getPlaylistsData()
|
||||||
|
data = None
|
||||||
|
|
||||||
|
for p in playlists:
|
||||||
|
if p['id'] == self.getPlaylistID():
|
||||||
|
data = p
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def _getParams(self):
|
||||||
|
return {'sk': self.session_key, 'user': self._username, 'playlistID': self._playlist_id}
|
||||||
|
|
||||||
|
def getPlaylistID(self):
|
||||||
|
"""Returns the playlist id."""
|
||||||
|
|
||||||
|
return self._playlist_id
|
||||||
|
|
||||||
|
def getUser(self):
|
||||||
|
"""Returns the owner user of this playlist."""
|
||||||
|
|
||||||
|
return User(self._username, *self.auth_data)
|
||||||
|
|
||||||
|
def getTracks(self):
|
||||||
|
"""Returns a list of the tracks on this user playlist."""
|
||||||
|
|
||||||
|
uri = u'lastfm://playlist/%s' %unicode(self.getPlaylistID())
|
||||||
|
|
||||||
|
return Playlist(uri, *self.auth_data).fetch()
|
||||||
|
|
||||||
|
def addTrack(self, track):
|
||||||
|
"""Adds a Track to this UserPlaylist.
|
||||||
|
* track: Any Track object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
params = self._getParams()
|
||||||
|
params['artist'] = track.getArtist().getName()
|
||||||
|
params['track'] = track.getTitle()
|
||||||
|
|
||||||
|
Request(self, 'playlist.addTrack', self.api_key, params, True, self.secret).execute()
|
||||||
|
|
||||||
|
def getTitle(self):
|
||||||
|
"""Returns the title of this playlist."""
|
||||||
|
|
||||||
|
return self._getCachedInfo('title')
|
||||||
|
|
||||||
|
def getCreationDate(self):
|
||||||
|
"""Returns the creation date of this playlist."""
|
||||||
|
|
||||||
|
return self._getCachedInfo('date')
|
||||||
|
|
||||||
|
def getSize(self):
|
||||||
|
"""Returns the size of this playlist."""
|
||||||
|
|
||||||
|
return self._getCachedInfo('size')
|
||||||
|
|
||||||
|
def getDescription(self):
|
||||||
|
"""Returns the description of this playlist."""
|
||||||
|
|
||||||
|
return self._getCachedInfo('description')
|
||||||
|
|
||||||
|
def getDuration(self):
|
||||||
|
"""Returns the duration of this playlist."""
|
||||||
|
|
||||||
|
return self._getCachedInfo('duration')
|
||||||
|
|
||||||
|
def isStreamable(self):
|
||||||
|
"""Returns True if the playlist is streamable.
|
||||||
|
For a playlist to be streamable, it needs at least 45 tracks by 15 different artists."""
|
||||||
|
|
||||||
|
if self._getCachedInfo('streamable') == '1':
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def hasTrack(self, track):
|
||||||
|
"""Checks to see if track is already in the playlist.
|
||||||
|
* track: Any Track object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
tracks = self.getTracks()
|
||||||
|
|
||||||
|
if not tracks:
|
||||||
|
return False
|
||||||
|
|
||||||
|
has_it = False
|
||||||
|
for t in tracks:
|
||||||
|
if track._hash() == t._hash():
|
||||||
|
has_it = True
|
||||||
|
break
|
||||||
|
|
||||||
|
return has_it
|
||||||
|
|
||||||
|
def getImage(self, size = IMAGE_LARGE):
|
||||||
|
"""Returns the associated image URL.
|
||||||
|
* size: The image size. Possible values:
|
||||||
|
o IMAGE_LARGE
|
||||||
|
o IMAGE_MEDIUM
|
||||||
|
o IMAGE_SMALL
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._getCachedInfo('images', size)
|
||||||
|
|
||||||
|
def getURL(self, domain_name = DOMAIN_ENGLISH):
|
||||||
|
"""Returns the url of the playlist on Last.fm.
|
||||||
|
* domain_name: Last.fm's language domain. Possible values:
|
||||||
|
o DOMAIN_ENGLISH
|
||||||
|
o DOMAIN_GERMAN
|
||||||
|
o DOMAIN_SPANISH
|
||||||
|
o DOMAIN_FRENCH
|
||||||
|
o DOMAIN_ITALIAN
|
||||||
|
o DOMAIN_POLISH
|
||||||
|
o DOMAIN_PORTUGUESE
|
||||||
|
o DOMAIN_SWEDISH
|
||||||
|
o DOMAIN_TURKISH
|
||||||
|
o DOMAIN_RUSSIAN
|
||||||
|
o DOMAIN_JAPANESE
|
||||||
|
o DOMAIN_CHINESE
|
||||||
|
"""
|
||||||
|
url = 'http://%(domain)s/%(appendix)s'
|
||||||
|
|
||||||
|
return url %{'domain': domain_name, 'appendix': self._getCachedInfo('url_appendix')}
|
||||||
|
|
||||||
class TagSearch(Search):
|
class TagSearch(Search):
|
||||||
"""Search for a tag by tag name."""
|
"""Search for a tag by tag name."""
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue