-import urllib2, md5, unicodedata, re, os, traceback, sys, pickle, socket
-from operator import itemgetter, attrgetter
+import urllib2, md5, os, traceback, sys, pickle, socket, xbmc
+from operator import itemgetter
class LoginTokensExceededError(Exception):
def __init__(self):
class GrooveAPI:
def __init__(self, enableDebug = False, isXbox = False):
- if isXbox == True:
- import simplejson_xbox
- self.simplejson = simplejson_xbox
- print 'GrooveShark: Initialized as XBOX script'
- else:
- import simplejson
- self.simplejson = simplejson
+ import simplejson
+ self.simplejson = simplejson
timeout = 40
socket.setdefaulttimeout(timeout)
self.enableDebug = enableDebug
self.loggedIn = 0
- self.radioEnabled = 0
self.userId = 0
- self.seedArtists = []
- self.frowns = []
- self.songIDsAlreadySeen = []
- self.recentArtists = []
- self.rootDir = os.getcwd()
+ self.removeDuplicates = False
+
+ self.radioRecentSongs = []
+ self.radioRecentArtists = []
+ self.radioEnabled = False
+
+ self.dataDir = 'addon_data'
+ self.confDir = xbmc.translatePath(os.path.join('special://masterprofile/' + self.dataDir, os.path.basename(os.getcwd())))
self.sessionID = self.getSavedSession()
self.debug('Saved sessionID: ' + self.sessionID)
- self.sessionID = self.getSessionFromAPI()
- self.debug('API sessionID: ' + self.sessionID)
+ #self.sessionID = self.getSessionFromAPI()
+ #self.debug('API sessionID: ' + self.sessionID)
if self.sessionID == '':
self.sessionID = self.startSession()
self.debug('Start() sessionID: ' + self.sessionID)
def debug(self, msg):
if self.enableDebug == True:
print msg
+
+ def setRemoveDuplicates(self, enable):
+ if enable == True or enable == 'true' or enable == 'True':
+ self.removeDuplicates = True
+ else:
+ self.removeDuplicates = False
def getSavedSession(self):
sessionID = ''
- path = os.path.join(self.rootDir, 'data', 'session.txt')
+ path = os.path.join(self.confDir, 'session', 'session.txt')
try:
f = open(path, 'rb')
def saveSession(self):
try:
- dir = os.path.join(self.rootDir, 'data')
+ dir = os.path.join(self.confDir, 'session')
# Create the 'data' directory if it doesn't exist.
if not os.path.exists(dir):
- os.mkdir(dir)
+ os.makedirs(dir)
path = os.path.join(dir, 'session.txt')
f = open(path, 'wb')
pickle.dump(self.sessionID, f, protocol=pickle.HIGHEST_PROTOCOL)
def saveSettings(self):
try:
- dir = os.path.join(self.rootDir, 'data')
+ dir = os.path.join(self.confDir, 'data')
# Create the 'data' directory if it doesn't exist.
if not os.path.exists(dir):
- os.mkdir(dir)
+ os.makedirs(dir)
path = os.path.join(dir, 'settings1.txt')
f = open(path, 'wb')
pickle.dump(self.settings, f, protocol=pickle.HIGHEST_PROTOCOL)
def callRemote(self, method, params={}):
data = {'header': {'sessionID': self.sessionID}, 'method': method, 'parameters': params}
- #data = {'header': {'sessionID': None}, 'method': method, 'parameters': params}
data = self.simplejson.dumps(data)
- #proxy_support = urllib2.ProxyHandler({"http" : "http://wwwproxy.kom.aau.dk:3128"})
- ## build a new opener with proxy details
- #opener = urllib2.build_opener(proxy_support, urllib2.HTTPHandler)
- ## install it
- #urllib2.install_opener(opener)
- #print data
req = urllib2.Request("http://api.grooveshark.com/ws/1.0/?json")
req.add_header('Host', 'api.grooveshark.com')
req.add_header('Content-type', 'text/json')
result = self.simplejson.loads(result)
if 'fault' in result:
self.debug(result)
+ if result['fault']['code'] == 8: #Session ID has expired. Get a new and try again if possible.
+ self.debug(result['fault']['message'])
+ self.sessionID = self.startSession()
+ if self.sessionID != '':
+ self.saveSession()
+ return self.callRemote(method, params)
+ else:
+ self.debug('GrooveShark: SessionID expired, but unable to get new')
+ return []
return result
except:
return []
def startSession(self):
- response = urllib2.urlopen("http://www.moovida.com/services/grooveshark/session_start")
- result = response.read()
- result = self.simplejson.loads(result)
- response.close()
+ try:
+ response = urllib2.urlopen("http://www.moovida.com/services/grooveshark/session_start")
+ result = response.read()
+ result = self.simplejson.loads(result)
+ response.close()
+ except:
+ return ''
+
if 'fault' in result:
return ''
else:
- return result['header']['sessionID']
+ return result['result']['sessionID']
def sessionDestroy(self):
return self.callRemote("session.destroy")
else:
self.loggedIn = 1
return self.userId
+
def loginExt(self, username, password):
if self.loggedIn == 1:
return 0
else:
return 0
+
+ def playlistCreateUnique(self, name, songIds):
+ if self.loggedIn == 1:
+ result = self.callRemote("playlist.createunique", {"name": name, "songIDs": songIds})
+ if 'result' in result:
+ return result['result']['playlistID']
+ else:
+ return 0
+ else:
+ return 0
def playlistGetSongs(self, playlistId, limit=25):
result = self.callRemote("playlist.getSongs", {"playlistID": playlistId})
def playlistDelete(self, playlistId):
if self.loggedIn == 1:
- return self.callRemote("playlist.delete", {"playlistID": playlistId})
+ result = self.callRemote("playlist.delete", {"playlistID": playlistId})
+ if 'fault' in result:
+ return 0
+ else:
+ return 1
+ else:
+ return 0
def playlistRename(self, playlistId, name):
if self.loggedIn == 1:
return 1
else:
return 0
+
+ def playlistDeleteSong(self, playlistId, position):
+ if self.loggedIn == 1:
+ result = self.callRemote("playlist.removeSong", {"playlistID": playlistId, "position": position})
+ if 'fault' in result:
+ return 0
+ else:
+ return 1
+ else:
+ return 0
def playlistReplace(self, playlistId, songIds):
if self.loggedIn == 1:
else:
return 0
- def autoplayStartWithArtistIDs(self, artistIds):
- result = self.callRemote("autoplay.startWithArtistIDs", {"artistIDs": artistIds})
- if 'fault' in result:
- self.radioEnabled = 0
- return 0
- else:
- self.radioEnabled = 1
- return 1
-
- def autoplayStart(self, songIds):
- result = self.callRemote("autoplay.start", {"songIDs": songIds})
- if 'fault' in result:
- self.radioEnabled = 0
- return 0
- else:
- self.radioEnabled = 1
- return 1
-
- def autoplayStop(self):
- result = self.callRemote("autoplay.stop", {})
+ def radioStartArtists(self):
+ radio = self.getSavedRadio()
+ if radio == None:
+ return False
+ result = self.callRemote("autoplay.startWithArtistIDs", {"artistIDs": radio['seedArtists']})
if 'fault' in result:
- self.radioEnabled = 1
- return 0
+ print "Cannot autoplay artists"
+ self.radioEnabled = False
else:
- self.radioEnabled = 0
- return 1
+ self.radioEnabled = True
+ return self.radioEnabled
- def autoplayGetNextSongEx(self, seedArtists = [], frowns = [], songIDsAlreadySeen = [], recentArtists = []):
- result = self.callRemote("autoplay.getNextSongEx", {"seedArtists": seedArtists, "frowns": frowns, "songIDsAlreadySeen": songIDsAlreadySeen, "recentArtists": recentArtists})
+ def radioStartSongs(self):
+ radio = self.getSavedRadio()
+ if radio == None:
+ return False
+ result = self.callRemote("autoplay.start", {"songIDs": radio['seedSongs']})
if 'fault' in result:
- return []
+ print "Cannot autoplay songs"
+ self.radioEnabled = False
else:
- return result
+ self.radioEnabled = True
+ return self.radioEnabled
- def radioGetNextSong(self):
- if self.seedArtists == []:
- return []
+ def radioNextSong(self):
+ radio = self.getSavedRadio()
+ if radio == None:
+ return None
else:
- result = self.autoplayGetNextSongEx(self.seedArtists, self.frowns, self.songIDsAlreadySeen, self.recentArtists)
-# print result
+ result = self.callRemote("autoplay.getNextSongEx", {"seedArtists": radio['seedArtists'], "frowns": radio['frowns'], "songIDsAlreadySeen": self.radioRecentSongs, "recentArtists": self.radioRecentArtists})
if 'fault' in result:
return []
else:
song = self.parseSongs(result)
- self.radioAlreadySeen(song[0][1])
+ self.radioRecentSongs.append(song[0][1])
+ self.radioRecentArtists.append(song[0][7])
return song
- def radioFrown(self, songId):
- self.frown.append(songId)
-
- def radioAlreadySeen(self, songId):
- self.songIDsAlreadySeen.append(songId)
-
- def radioAddArtist(self, artistId):
- self.seedArtists.append(artistId)
-
- def radioStart(self, artists = [], frowns = []):
- for artist in artists:
- self.seedArtists.append(artist)
- for artist in frowns:
- self.frowns.append(artist)
- if self.autoplayStartWithArtistIDs(self.seedArtists) == 1:
- self.radioEnabled = 1
- return 1
+ def radioFrown(self, songId = None):
+ radio = self.getSavedRadio()
+ if radio != None and songId != None:
+ try:
+ radio['frowns'].remove(songId)
+ except: pass
+ radio['frowns'].append(songId)
+ return self.saveRadio(radio = radio)
else:
- self.radioEnabled = 0
- return 0
-
- def radioStop(self):
- self.seedArtists = []
- self.frowns = []
- self.songIDsAlreadySeen = []
- self.recentArtists = []
- self.radioEnabled = 0
+ return False
+
+ def radioArtist(self, artistId = None):
+ radio = self.getSavedRadio()
+ if radio != None and artistId != None:
+ try:
+ radio['seedArtists'].remove(artistId)
+ except: pass
+ radio['seedArtists'].append(artistId)
+ print "Saved radio"
+ return self.saveRadio(radio = radio)
+ else:
+ print "Failed to get radio"
+ return False
+
+ def radioSong(self, songId = None):
+ radio = self.getSavedRadio()
+ if radio != None and songId != None:
+ try:
+ radio['seedSongs'].remove(songId)
+ except: pass
+ radio['seedSongs'].append(songId)
+ print "Saved radio"
+ return self.saveRadio(radio = radio)
+ else:
+ print "Failed to get radio"
+ return False
def radioTurnedOn(self):
return self.radioEnabled
+ def getSavedRadio(self):
+ path = os.path.join(self.confDir, 'radio', 'radio.dmp')
+ try:
+ f = open(path, 'rb')
+ radio = pickle.load(f)
+ f.close()
+ except:
+ print "Failed to open " + path
+ radio = {}
+ radio['seedSongs'] = []
+ radio['seedArtists'] = []
+ radio['frowns'] = []
+ if self.saveRadio(radio) == False:
+ return None
+ return radio
+
+ def saveRadio(self, radio): #blaher
+ if radio == {}:
+ print 'Invalid radio'
+ return False
+ try:
+ dir = os.path.join(self.confDir, 'radio')
+ # Create the 'data' directory if it doesn't exist.
+ if not os.path.exists(dir):
+ os.mkdir(dir)
+ path = os.path.join(dir, 'radio.dmp')
+ f = open(path, 'wb')
+ pickle.dump(radio, f, protocol=pickle.HIGHEST_PROTOCOL)
+ f.close()
+ return True
+ except IOError, e:
+ print 'There was an error while saving the radio pickle (%s)' % e
+ return False
+ except:
+ print "An unknown error occurred during save radio: " + str(sys.exc_info()[0])
+ return False
+
def favoriteSong(self, songID):
return self.callRemote("song.favorite", {"songID": songID})
list = self.parseAlbums(result)
return list
+ def artistAbout(self, artistId):
+ result = self.callRemote("artist.about", {"artistID": artistId})
+ return result
+
def artistGetAlbums(self, artistId, limit, sortKey=2):
result = self.callRemote("artist.getAlbums", {"artistID": artistId, "limit": limit})
list = self.parseAlbums(result)
list = self.parseSongs(result)
return list
+ def artistGetSimilar(self, artistId, limit):
+ result = self.callRemote("artist.getSimilar", {"artistID": artistId, "limit": limit})
+ list = self.parseArtists(result)
+ return list
+
+ def songAbout(self, songId):
+ result = self.callRemote("song.about", {"songID": songId})
+ return result['result']['song']
+
+ def getVersion(self):
+ result = self.callRemote("service.getVersion", {})
+ return result
+
def parseSongs(self, items):
try:
if 'result' in items:
songName = s['songName'].encode('ascii', 'ignore')
albumName = s['albumName'].encode('ascii', 'ignore')
artistName = s['artistName'].encode('ascii', 'ignore')
- if (entry[0].lower() == songName.lower()) and (entry[3].lower() == albumName.lower()) and (entry[6].lower() == artistName.lower()):
- notIn = False
+ if self.removeDuplicates == True:
+ if (entry[0].lower() == songName.lower()) and (entry[3].lower() == albumName.lower()) and (entry[6].lower() == artistName.lower()):
+ notIn = False
if notIn == True:
list.append([s['songName'].encode('ascii', 'ignore'),\
s['songID'],\
return []
def parseArtists(self, items):
- if 'result' in items:
- i = 0
- list = []
- artists = items['result']['artists']
- while(i < len(artists)):
- s = artists[i]
- list.append([s['artistName'].encode('ascii', 'ignore'),\
- s['artistID']])
- i = i + 1
- return list
- else:
+ try:
+ if 'result' in items:
+ i = 0
+ list = []
+ artists = items['result']['artists']
+ while(i < len(artists)):
+ s = artists[i]
+ try:
+ list.append([s['artistName'].encode('ascii', 'ignore'),\
+ s['artistID']])
+ except:
+ print 'GrooveShark: Could not parse album number: ' + str(i)
+ traceback.print_exc()
+ i = i + 1
+ return list
+ else:
+ return []
+ except:
+ print 'GrooveShark: Could not parse artists. Got this:'
+ traceback.print_exc()
return []
def parseAlbums(self, items):
- if 'result' in items:
- i = 0
- list = []
- albums = items['result']['albums']
- while(i < len(albums)):
- s = albums[i]
- list.append([s['artistName'].encode('ascii', 'ignore'),\
- s['artistID'],\
- s['albumName'].encode('ascii', 'ignore'),\
- s['albumID'],\
- s['image']['tiny'].encode('ascii', 'ignore')])
- i = i + 1
- return list
- else:
+ try:
+ if 'result' in items:
+ i = 0
+ list = []
+ albums = items['result']['albums']
+ while(i < len(albums)):
+ s = albums[i]
+ try: # Avoid ascii ancoding errors
+ list.append([s['artistName'].encode('ascii', 'ignore'),\
+ s['artistID'],\
+ s['albumName'].encode('ascii', 'ignore'),\
+ s['albumID'],\
+ s['image']['medium'].encode('ascii', 'ignore')])
+ except:
+ print 'GrooveShark: Could not parse album number: ' + str(i)
+ traceback.print_exc()
+ i = i + 1
+ return list
+ else:
+ return []
+ except:
+ print 'GrooveShark: Could not parse albums. Got this'
+ traceback.print_exc()
return []
def parsePlaylists(self, items):
- if 'result' in items:
- i = 0
- list = []
- playlists = items['result']['playlists']
- while(i < len(playlists)):
- s = playlists[i]
- list.append([s['playlistID'],\
- s['playlistName'].encode('ascii', 'ignore'),\
- s['username'].encode('ascii', 'ignore')])
- i = i + 1
- return list
- else:
+ try:
+ if 'result' in items:
+ i = 0
+ list = []
+ playlists = items['result']['playlists']
+ while(i < len(playlists)):
+ s = playlists[i]
+ try: # Avoid ascii ancoding errors
+ list.append([s['playlistID'],\
+ s['playlistName'].encode('ascii', 'ignore'),\
+ s['username'].encode('ascii', 'ignore')])
+ except:
+ print 'GrooveShark: Could not parse playlist number: ' + str(i)
+ traceback.print_exc()
+ i = i + 1
+ return list
+ else:
+ return []
+ except:
+ print 'GrooveShark: Could not parse playlists. Got this:'
+ print items
return []