-# GrooveSong constants
-DOMAIN = "grooveshark.com"
-HOME_URL = "http://listen." + DOMAIN
-API_URL = "http://cowbell." + DOMAIN + "/more.php"
-SERVICE_URL = "http://cowbell." + DOMAIN + "/service.php"
-TOKEN_URL = "http://cowbell." + DOMAIN + "/more.php"
-
-CLIENT_NAME = "gslite"
-CLIENT_VERSION = "20101012.37"
-HEADERS = {"Content-Type": "application/json",
- "User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 (.NET CLR 3.5.30729)",
- "Referer": "http://listen.grooveshark.com/main.swf?cowbell=fe87233106a6cef919a1294fb2c3c05f"}
-
-RE_SESSION = re.compile('"sessionID":"\s*?([A-z0-9]+)"')
-RANDOM_CHARS = "1234567890abcdef"
-
-# Get a song
-class GrooveSong:
-
- def __init__(self):
-
- import simplejson
- self.simplejson = simplejson
-
- self.cacheDir = os.path.join(tempfile.gettempdir(), 'groovesong')
- self._lastSessionTime = 0
- self.uuid = self._getUUID()
-
- self._getSavedSession()
- # session ids last 1 week
- if self.sessionID == '' or time.time() - self._lastSessionTime >= SESSION_EXPIRY:
- self.sessionID = self._getSession(HOME_URL)
- if self.sessionID == '':
- raise StandardError('Failed to get session id')
- else:
- print "New GrooveSong session id: " + self.sessionID
- self._setSavedSession()
-
- # The actual call to the API
- def _callRemote(self, method, params, type="default"):
- postData = {
- "header": {
- "client": CLIENT_NAME,
- "clientRevision": CLIENT_VERSION,
- "uuid": self.uuid,
- "session": self.sessionID},
- "country": {"IPR":"1021", "ID":"223", "CC1":"0", "CC2":"0", "CC3":"0", "CC4":"2147483648"},
- "privacy": 1,
- "parameters": params,
- "method": method}
-
- token = self._getMethodToken(method)
- if token == None:
- raise StandardError("Cannot get token")
-
- postData["header"]["token"] = token
- if type == "service":
- url = SERVICE_URL + "?" + method
- else:
- url = API_URL + "?" + method
-
- postData = self.simplejson.dumps(postData)
- print "GrooveSong URL: " + url
- request = urllib2.Request(url, postData, HEADERS)
-
- response = urllib2.urlopen(request).read()
- try:
- response = self.simplejson.loads(response)
- print "GrooveSong Response..."
- pprint.pprint(response)
- except:
- raise StandardError("API error: " + response)
- try:
- response["fault"]
- except KeyError:
- return response
- else:
- raise StandardError("API error: " + response["fault"]["message"])
-
- # Generate a random uuid
- def _getUUID(self):
- return str(uuid.uuid4())
-
- # Make a token ready for a request header
- def _getMethodToken(self, method):
- self._token = self._getCommunicationToken()
- if self._token == None:
- return None
-
- randomChars = ""
- while 6 > len(randomChars):
- randomChars = randomChars + random.choice(RANDOM_CHARS)
-
- token = sha.new(method + ":" + self._token + ":quitStealinMahShit:" + randomChars).hexdigest()
-
- return randomChars + token
-
- # Generate a communication token
- def _getCommunicationToken(self):
- params = {"secretKey": self._getSecretKey(self.sessionID)}
- postData = {
- "header": {
- "client": CLIENT_NAME,
- "clientRevision": CLIENT_VERSION,
- "uuid": self.uuid,
- "session": self.sessionID},
- "country": {"IPR":"1021", "ID":"223", "CC1":"0", "CC2":"0", "CC3":"0", "CC4":"2147483648"},
- "privacy": 1,
- "parameters": params,
- "method": "getCommunicationToken"}
-
- postData = self.simplejson.dumps(postData)
- request = urllib2.Request(TOKEN_URL, postData, HEADERS)
- response = urllib2.urlopen(request).read()
- try:
- response = self.simplejson.loads(response)
- except:
- raise StandardError("API error: " + response)
- try:
- response["fault"]
- except KeyError:
- return response["result"]
- else:
- return None
-
- # Generate a secret key from a sessionID
- def _getSecretKey(self, sessionID):
- return md5.new(sessionID).hexdigest()
-
- # Get a session id from some HTML
- def _getSession(self, html):
- html = urllib2.urlopen(HOME_URL).read()
- session = RE_SESSION.search(html)
- if session:
- self._lastSessionTime = time.time()
- return session.group(1)
- else:
- return None
-
- def _getSavedSession(self):
- path = os.path.join(self.cacheDir, 'session.dmp')
- try:
- f = open(path, 'rb')
- session = pickle.load(f)
- self.sessionID = session['sessionID']
- self._lastSessionTime = session['lastSessionTime']
- f.close()
- except:
- self.sessionID = ''
- self._lastSessionTime = 0
- pass
-
- def _setSavedSession(self):
- try:
- # Create the 'data' directory if it doesn't exist.
- if not os.path.exists(self.cacheDir):
- os.makedirs(self.cacheDir)
- path = os.path.join(self.cacheDir, 'session.dmp')
- f = open(path, 'wb')
- session = {'sessionID' : self.sessionID, 'lastSessionTime' : self._lastSessionTime}
- pickle.dump(session, f, protocol=pickle.HIGHEST_PROTOCOL)
- f.close()
- except:
- print "An error occurred during save session"
- pass
-
- # Gets a stream key and host to get song content
- def _getStreamDetails(self, songID):
- params = {
- "songID": songID,
- "prefetch": False,
- "mobile": False,
- "country": {"IPR":"1021","ID":"223", "CC1":"0", "CC2":"0", "CC3":"0", "CC4":"2147483648"}
- }
- response = self._callRemote("getStreamKeyFromSongIDEx", params)
- try:
- self._lastStreamKey = response["result"]["streamKey"]
- self._lastStreamServer = response["result"]["ip"]
- self._lastStreamServerID = response["result"]["streamServerID"]
- return True
- except:
- return False
-
- # Tells Grooveshark you have downloaded a song
- def _markSongDownloaded(self, songID):
- params = {
- "streamKey": self._lastStreamKey,
- "streamServerID": self._lastStreamServerID,
- "songID": songID}
- self._callRemote("markSongDownloaded", params)
-
- # Get the song URL
- def getSongURL(self, songID):
- if self._getStreamDetails(songID) == True:
- postData = {"streamKey": self._lastStreamKey}
- postData = urllib.urlencode(postData)
- return "http://" + self._lastStreamServer + "/stream.php?" + str(postData)
- else:
- return ''
-