Advertisement
Guest User

Pandora Temporary Fix

a guest
Apr 28th, 2012
690
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.36 KB | None | 0 0
  1. import xmlrpclib
  2. import urllib2
  3. import time
  4.  
  5. import crypt
  6. import keys
  7.  
  8. PROTOCOL_VERSION=34
  9. BASE_URL = "https://www.pandora.com/radio/xmlrpc/v%d?" %PROTOCOL_VERSION
  10. BASE_URL_RID = BASE_URL + "rid=%sP&method=%s"
  11. BASE_URL_LID = BASE_URL + "rid=%sP&lid=%s&method=%s"
  12.  
  13. def _inttime():
  14.     return int( time.time() )
  15.  
  16. class PandoraError(Exception):
  17.     def __init__( self, value ):
  18.         self.value = value
  19.     def __str__( self ):
  20.         return repr( self.value )
  21.  
  22. class Pandora:
  23.     rid = ""
  24.     lid = ""
  25.     authToken = ""
  26.     curStation = ""
  27.     curFormat = ""
  28.     offset = 0
  29.  
  30.     def __init__( self, dataDir, fmt = "mp3" ):
  31.         self.dataDir = dataDir
  32.         self.rid = "%07i" %( time.time() % 10000000 )
  33.         self.keys = keys.Keys( self.dataDir, PROTOCOL_VERSION )
  34.         if not self.keys.loadKeys():
  35.             raise PandoraError("Unable to load keys")
  36.         self.curFormat = fmt
  37.  
  38.     def _timestamp( self ):
  39.         return _inttime() - self.offset
  40.  
  41.     def setProxy( self, proxy_info ):
  42.         if proxy_info["user"] == "" and proxy_info["pass"] == "":
  43.             proxy_h = urllib2.ProxyHandler( { "http" : \
  44.                 "http://%(host)s:%(port)s" %proxy_info } )
  45.         else:
  46.             proxy_h = urllib2.ProxyHandler( { "http" : \
  47.                 "http://%(user)s:%(pass)s@%(host)s:%(port)s" %proxy_info } )
  48.  
  49.         proxy_o = urllib2.build_opener( proxy_h, urllib2.HTTPHandler )
  50.  
  51.         urllib2.install_opener( proxy_o )
  52.  
  53.     def sync( self ):
  54.         #reqUrl = BASE_URL_RID %( self.rid, "sync" )
  55.         reqUrl = 'http://ridetheclown.com/s2/synctime.php'
  56.  
  57.         #req = xmlrpclib.dumps( (), "misc.sync" ).replace( "\n", "" )
  58.         #enc = crypt.encryptString( req, self.keys['out'] )
  59.  
  60.         #u = urllib2.urlopen( reqUrl, enc )
  61.         u = urllib2.urlopen(reqUrl)
  62.         resp = u.read()
  63.         u.close()
  64.  
  65.         #parsed = xmlrpclib.loads( resp )[0][0]
  66.         #t = crypt.decryptString( parsed, self.keys['in'] )
  67.         #print 'Debugging pandora: ' + str(_inttime())
  68.         #print 'From Hack: ' + resp
  69.         #self.offset = _inttime() - int(t[4:-2])
  70.         self.offset = _inttime() - int(resp)
  71.  
  72.     def authListener( self, user, pwd ):
  73.         reqUrl = BASE_URL_RID %( self.rid, "authenticateListener" )
  74.  
  75.         req = xmlrpclib.dumps( ( self._timestamp(), "00000000000000000000000000000000", user, pwd, "html5tuner", "", "", "HTML5", True ), \
  76.                                 "listener.authenticateListener" )
  77.         #req = '<?xml version=\"1.0\"?><methodCall><methodName>listener.authenticateListener</methodName><params><param><value><int>%lu</int></value></param><param><value><string>%s</string></value></param><param><value><string>%s</string></value></param><param><value><string>html5tuner</string></value></param><param><value><string/></value></param><param><value><string/></value></param><param><value><string>HTML5</string></value></param><param><value><boolean>1</boolean></value></param></params></methodCall>' % (self._timestamp(), user, pwd)
  78.        
  79.         req = req.replace( "\n", "" )
  80.         enc = crypt.encryptString( req, self.keys['out'] )
  81.  
  82.         u = urllib2.urlopen( reqUrl, enc )
  83.         resp = u.read()
  84.         u.close()
  85.  
  86.         try:
  87.             parsed = xmlrpclib.loads( resp )[0][0]
  88.         except xmlrpclib.Fault, fault:
  89.             print "Error:", fault.faultString
  90.             print "Code:", fault.faultCode
  91.             return False
  92.  
  93.         self.authToken = parsed["authToken"]
  94.         self.lid = parsed["listenerId"]
  95.        
  96.         return True
  97.  
  98.     def getStations( self ):
  99.         reqUrl = BASE_URL_LID %( self.rid, self.lid, "getStations" )
  100.  
  101.         req = xmlrpclib.dumps( ( self._timestamp(), self.authToken ), \
  102.                                 "station.getStations" )
  103.         req = req.replace( "\n", "" )
  104.         enc = crypt.encryptString( req, self.keys['out'] )
  105.  
  106.         u = urllib2.urlopen( reqUrl, enc )
  107.         resp = u.read()
  108.         u.close()
  109.  
  110.         parsed = xmlrpclib.loads( resp )[0][0]
  111.  
  112.         return parsed
  113.  
  114.     def getFragment( self, stationId=None, format=None ):
  115.         if stationId == None:
  116.             stationId = self.curStation
  117.         if format == None:
  118.             format = self.curFormat
  119.         reqUrl = BASE_URL_LID.replace('https', 'http') %(
  120. self.rid, self.lid, "getFragment" )
  121.  
  122.         args = ( self._timestamp(), self.authToken, stationId, "0", "", "", \
  123.                     format, "0", "0" )
  124.         req = xmlrpclib.dumps( args, "playlist.getFragment" )
  125.         req = req.replace( "\n", "" )
  126.         enc = crypt.encryptString( req, self.keys['out'] )
  127.  
  128.         u = urllib2.urlopen( reqUrl, enc )
  129.         resp = u.read()
  130.         u.close()
  131.  
  132.         parsed = xmlrpclib.loads( resp )[0][0]
  133.  
  134.         #last 48 chars of URL encrypted, padded w/ 8 * '\x08'
  135.         for i in range( len( parsed ) ):
  136.             url = parsed[i]["audioURL"]
  137.             url = url[:-48] + crypt.decryptString( url[-48:],\
  138.                                              self.keys['in'] )[:-8]
  139.             parsed[i]["audioURL"] = url
  140.  
  141.         self.curStation = stationId
  142.         self.curFormat = format
  143.  
  144.         return parsed
  145.  
  146.     def addFeedback( self, stationId, musicId, likeFlag ):
  147.  
  148.         reqUrl = BASE_URL_LID %( self.rid, self.lid, "addFeedback" )
  149.  
  150.         matchingSeed = ""
  151.         userSeed = ""
  152.         focusTraitId = ""
  153.  
  154.         args = ( self._timestamp(), self.authToken, stationId, musicId, matchingSeed, userSeed, focusTraitId, "", likeFlag, False )
  155.  
  156.         req = xmlrpclib.dumps( args, "station.addFeedback" )
  157.         req = req.replace( "\n", "" )
  158.         enc = crypt.encryptString( req, self.keys['out'] )
  159.  
  160.         u = urllib2.urlopen( reqUrl, enc )
  161.         resp = u.read()
  162.         u.close()
  163.  
  164.     def addTiredSong( self, musicId ):
  165.         reqUrl = BASE_URL_LID %( self.rid, self.lid, "addTiredSong" )
  166.  
  167.         req = xmlrpclib.dumps( ( self._timestamp(), self.authToken, musicId ), \
  168.                                 "listener.addTiredSong" )
  169.         req = req.replace( "\n", "" )
  170.         enc = crypt.encryptString( req, self.keys['out'] )
  171.  
  172.         u = urllib2.urlopen( reqUrl, enc )
  173.         resp = u.read()
  174.         u.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement