First attempt at new API.
[clinton/xbmc-groove.git] / resources / lib / GrooveAPIWP.py
1 import socket, hmac, urllib, urllib2, pprint, md5, os, pickle
2 from operator import itemgetter
3
4 THUMB_URL = 'http://beta.grooveshark.com/static/amazonart/'
5 THUMB_URL_DEFAULT = 'http://grooveshark.com/webincludes/logo/Grooveshark_Logo_No-Text.png'
6 SONG_LIMIT = 25
7 ALBUM_LIMIT = 15
8 ARTIST_LIMIT = 15
9
10
11 class GrooveAPI:
12
13 sessionID = ''
14 userID = 0
15 host = 'api.grooveshark.com'
16
17 # Constructor
18 def __init__(self, sessionID = ''):
19 import simplejson
20 self.simplejson = simplejson
21 socket.setdefaulttimeout(40)
22 if sessionID == '':
23 self.sessionID = self._getSessionID()
24 else:
25 self.sessionID = sessionID
26
27 def _keySort(self, d):
28 return [(k,d[k]) for k in sorted(d.keys())]
29
30 # Make a message sig
31 def _createMessageSig(self, method, params, secret):
32 args = self._keySort(params);
33 data = '';
34 for arg in args:
35 data += str(arg[0])
36 data += str(arg[1])
37 data = method + data
38
39 h = hmac.new(secret, data)
40 return h.hexdigest()
41
42 # The actual call to the API
43 def _callRemote(self, method, params = {}):
44 url = 'http://%s/ws/2.1/?method=%s&%s&wsKey=wordpress&sig=%s&format=json' % (self.host, method, urllib.urlencode(params), self._createMessageSig(method, params, 'd6c59291620c6eaa5bf94da08fae0ecc'))
45 print url
46 req = urllib2.Request(url)
47 response = urllib2.urlopen(req)
48 result = response.read()
49 pprint.pprint(result)
50 response.close()
51 try:
52 result = self.simplejson.loads(result)
53 return result
54 except:
55 return []
56
57 def getUserID(self):
58 return self.userID
59
60 def getSessionID(self):
61 return self.sessionID
62
63 def _getSessionID(self):
64 params = {}
65 result = self._callRemote('startSession', params)
66 return result['result']['sessionID']
67
68 # Make user authentication token
69 def _getUserToken(self, username, password):
70 return md5.new(username.lower() + md5.new(password).hexdigest()).hexdigest()
71
72 # Authenticates the user for current API session
73 def _authenticateUser(self, username, token):
74 params = {'sessionID': self.sessionID, 'username': username, 'token': token}
75 result = self._callRemote('authenticateUser', params)
76 return result['result']['UserID']
77
78 # Login
79 def login(self, username, password):
80 token = self._getUserToken(username, password)
81 self.userID = self._authenticateUser(username, token)
82 return self.userID
83
84 # Logs the user out
85 def logout(self):
86 self._callRemote('logout', {'sessionID' : self.sessionID})
87
88 # Search for albums
89 def getArtistSearchResults(self, query, limit=ARTIST_LIMIT):
90 result = self._callRemote('getArtistSearchResults', {'query' : query,'limit' : limit})
91 if 'result' in result:
92 return self._parseArtists(result)
93 else:
94 return ''
95
96 # Search for albums
97 def getAlbumSearchResults(self, query, limit=ALBUM_LIMIT):
98 result = self._callRemote('getAlbumSearchResults', {'query' : query,'limit' : limit})
99 if 'result' in result:
100 return self._parseAlbums(result)
101 else:
102 return ''
103
104 # Search for songs
105 def getSongSearchResults(self, query, limit=SONG_LIMIT):
106 result = self._callRemote('getSongSearchResultsEx', {'query' : query, 'limit' : limit})
107 if 'result' in result:
108 return self._parseSongs(result)
109 else:
110 return ''
111
112 # Gets the popular songs
113 def getPopularSongsToday(self, limit=SONG_LIMIT):
114 result = self._callRemote('getPopularSongsToday', {'limit' : limit})
115 if 'result' in result:
116 return self._parseSongs(result)
117 else:
118 return ''
119
120 # Gets the favorite songs of the logged-in user
121 def getUserFavoriteSongs(self):
122 if (self.userID == 0):
123 return [];
124 result = self._callRemote('getUserFavoriteSongs', {'sessionID' : self.sessionID})
125 if 'result' in result:
126 return self._parseSongs(result)
127 else:
128 return ''
129
130 # Get the url to link to a song on Grooveshark
131 def getSongURLFromSongID(self, songID):
132 result = self._callRemote('getSongURLFromSongID', {'songID' : songID})
133 if 'result' in result:
134 url = result['result']['url']
135 return url.encode('ascii', 'ignore')
136 else:
137 return ''
138
139 # Gets the playlists of the logged-in user
140 def getUserPlaylists(self):
141 if (self.userID == 0):
142 return [];
143 result = self._callRemote('getUserPlaylists', {'sessionID' : self.sessionID})
144 if 'result' in result:
145 playlists = result['result']['playlists']
146 else:
147 return []
148 i = 0
149 list = []
150 while(i < len(playlists)):
151 p = playlists[i]
152 list.append([p['playlistName'].encode('ascii', 'ignore'), p['playlistID']])
153 i = i + 1
154 return sorted(list, key=itemgetter(0))
155
156 # Gets playlist information
157 def getPlaylistInfo(self, playlistID):
158 result = self._callRemote('getPlaylistInfo', {'playlistID' : playlistID})
159 if 'result' in result:
160 return result['result']
161 else:
162 return []
163
164 # Creates a playlist with songs
165 def createPlaylist(self, name, songIDs):
166 result = self._callRemote('createPlaylist', {'name' : name, 'songIDs' : songIDs, 'sessionID' : self.sessionID})
167 if 'result' in result and result['result']['success'] == 1:
168 return result['result']['playlistID']
169 elif 'errors' in result:
170 duplicate = False;
171 for error in result['errors']:
172 if (error['code'] == 800):
173 duplicate = True;
174 if (duplicate):
175 return -1
176 else:
177 return 0
178 else:
179 return 0
180
181 # Sets the songs for a playlist
182 def setPlaylistSongs(self, playlistID, songIDs):
183 result = self._callRemote('setPlaylistSongs', {'playlistID' : playlistID, 'songIDs' : songIDs, 'sessionID' : self.sessionID})
184 if 'result' in result and result['result']['success'] == 1:
185 return True;
186 else:
187 return False;
188
189 # Gets the songs of a playlist
190 def getPlaylistSongs(self, playlistID):
191 result = self._callRemote('getPlaylistSongs', {'playlistID' : playlistID});
192 if 'result' in result:
193 return result['result'];
194 elif result['errors'] in result :
195 return result['errors'][0]['code']
196 else:
197 return {'error':-512};
198
199 # Extract song data
200 def _parseSongs(self, items):
201 if 'result' in items:
202 i = 0
203 list = []
204 if 'songs' in items['result']:
205 l = len(items['result']['songs'])
206 index = 'songs'
207 elif 'song' in items['result']:
208 l = 1
209 index = 'song'
210 else:
211 l = 0
212 index = ''
213 while(i < l):
214 if index == 'songs':
215 s = items['result'][index][i]
216 else:
217 s = items['result'][index]
218 if s['CoverArtFilename'] != None:
219 coverart = THUMB_URL+s['CoverArtFilename'].encode('ascii', 'ignore')
220 else:
221 coverart = THUMB_URL_DEFAULT
222 list.append([s['SongName'].encode('ascii', 'ignore'),\
223 s['SongID'],\
224 s['AlbumName'].encode('ascii', 'ignore'),\
225 s['AlbumID'],\
226 s['ArtistName'].encode('ascii', 'ignore'),\
227 s['ArtistID'],\
228 coverart])
229 i = i + 1
230 return list
231 else:
232 return []
233
234 # Extract artist data
235 def _parseArtists(self, items):
236 if 'result' in items:
237 i = 0
238 list = []
239 artists = items['result']['artists']
240 while(i < len(artists)):
241 s = artists[i]
242 list.append([s['ArtistName'].encode('ascii', 'ignore'),\
243 s['ArtistID']])
244 i = i + 1
245 return list
246 else:
247 return []
248
249 # Extract album data
250 def _parseAlbums(self, items):
251 if 'result' in items:
252 i = 0
253 list = []
254 albums = items['result']['albums']
255 while(i < len(albums)):
256 s = albums[i]
257 if s['CoverArtFilename'] != None:
258 coverart = THUMB_URL+s['CoverArtFilename'].encode('ascii', 'ignore')
259 else:
260 coverart = THUMB_URL_DEFAULT
261 list.append([s['ArtistName'].encode('ascii', 'ignore'),\
262 s['ArtistID'],\
263 s['AlbumName'].encode('ascii', 'ignore'),\
264 s['AlbumID'],\
265 coverart])
266 i = i + 1
267 return list
268 else:
269 return []
270
271 def _parsePlaylists(self, items):
272 if 'result' in items:
273 i = 0
274 list = []
275 playlists = items['result']['playlists']
276 while(i < len(playlists)):
277 s = playlists[i]
278 list.append([s['PlaylistID'],\
279 s['PlaylistName'].encode('ascii', 'ignore'),\
280 s['Username'].encode('ascii', 'ignore')])
281 i = i + 1
282 return list
283 else:
284 return []
285
286
287 groovesharkApi = GrooveAPI('c4285d93d556349d284704100eb557d7')
288 print "SessionID: " + groovesharkApi.getSessionID()
289 print "UserID: " + str(groovesharkApi.login('stephendenham', 'lond0n'))
290
291 #res = groovesharkApi.getSongSearchResults('jimmy jazz', 3)
292 #res = groovesharkApi.getPopularSongsToday()
293 #res = groovesharkApi.getSongURLFromSongID('27425375')
294 #res = groovesharkApi.getAlbumSearchResults('london calling', 3)
295 #res = groovesharkApi.getArtistSearchResults('the clash', 3)
296 res = groovesharkApi.getUserFavoriteSongs()
297
298
299 pprint.pprint(res)
300
301
302