import urllib import urllib2 #import pygtk #pygtk.require('2.0') import gtk import webbrowser import hashlib import datetime import time import thread from button import Button #import xml.dom from xml.dom import minidom class Scrobbler(gtk.VBox): def __init__(self,data): gtk.VBox.__init__(self,False,0) self.data = data self.url = "http://ws.audioscrobbler.com/2.0/" self.key = "2c76f85a6704efd74b5a358821284ef9" self.secret = "3a6012bfb627b60a884cf33fc044885c" self.token = "" # Session ID self.session = "" # Now playing URL self.npurl = "" # Submission URL self.suburl = "" # Run these in new thread so we can keep loading other things while waiting self.makegui() #thread.start_new_thread(self.setup,("setup",None)) self.show() def makegui(self): if self.data.lfm == "": uname = gtk.Label("Username:") username = gtk.Entry() passwd = gtk.Label("Password:") password = gtk.Entry() password.set_visibility(False) username.connect("activate",self.fetchSession,username,uname,password,passwd) password.connect("activate",self.fetchSession,username,uname,password,passwd) uname.show() username.show() passwd.show() password.show() self.pack_start(uname,False,False,0) self.pack_start(username,False,False,0) self.pack_start(passwd,False,False,0) self.pack_start(password,False,False,0) else: thread.start_new_thread(self.handshake,("","")) #self.labels = [gtk.Label("")]*10 self.similar = [] for i in range(10): label = gtk.Label(" ") self.pack_start(label,False,False,0) self.similar+=[label] label.show() def fetchSession(self,widgit,username,uname,password,passwd): self.data.lfmuser = username.get_text().lower() self.data.lfmpass = self.md5(password.get_text()) if self.data.lfmuser=="" or self.data.lfmpass=="": return else: self.token = self.md5(self.data.lfmuser+self.data.lfmpass) (url,list) = self.addMethod(self.url,"auth.getMobileSession") (url,list) = self.addParam(url,list,"username",self.data.lfmuser) (url,list) = self.addParam(url,list,"authToken",self.token) (url,list) = self.addParam(url,list,"api_key",self.key) (url,list) = self.addParam(url,list,"api_sig",self.getSig(list)) status = self.parseRequest(url) attr = status.getAttributeNode("status") if attr.value != "ok": return self.data.lfm = status.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.firstChild.data username.hide() uname.hide() password.hide() passwd.hide() self.makegui() def handshake(self,widgit,data): #print "shaking hands" url = "http://post.audioscrobbler.com/?hs=true" list = [("hs","true")] (url,list) = self.addParam(url,list,"p","1.2.1") (url,list) = self.addParam(url,list,"c","tst") (url,list) = self.addParam(url,list,"v","1.0") (url,list) = self.addParam(url,list,"u",self.data.lfmuser) tstp = self.timestamp() (url,list) = self.addParam(url,list,"t",tstp) (url,list) = self.addParam(url,list,"a",self.authToken(tstp)) (url,list) = self.addParam(url,list,"api_key",self.key) status = self.placeRequest(url).readlines() if status == None: return if status[0].strip() != "OK": return self.session = status[1].strip() self.npurl = status[2].strip()#+"/?" self.suburl = status[3].strip()#+"/?" #for line in status: # print line.strip() def nowPlaying(self,info): if self.data.lfm == "": return elif self.session == None: self.handshake() vals = {"s":self.session, "a":info.artist.title(), "t":info.title.title(), "b":info.album.title(), "l":str(info.duration), "n":info.tnum, "m":""} data = urllib.urlencode(vals) #status = self.placeRequest(url).readlines() req = urllib2.Request(self.npurl,data) req.add_header("User-Agent","Ocarina") try: status = urllib2.urlopen(req) self.fetchSimilar(info.artist) except: return #if status[0].strip() == "OK": # print "Submission successful" # Submit song and increment play count # Playcount incremented if length < 30 seconds OR # song played for > 240 seconds OR song played for > 1/2 total time def submit(self,timestp): if self.data.lfm == "": return elif self.session == None: self.handshake() info = self.data.song.info if info.duration < 30: info.count+=1 return exit = True if (self.data.song.position > 240): exit = False if self.data.song.position > (self.data.song.info.duration/2): exit = False if exit == True: return info.count+=1 vals = {"s":self.session, "a[0]":info.artist.title(), "t[0]":info.title.title(), "i[0]":timestp, "o[0]":"P", "r[0]":"", "l[0]":str(info.duration), "b[0]":info.album.title(), "n[0]":info.tnum, "m[0]":""} data = urllib.urlencode(vals) req = urllib2.Request(self.suburl,data) req.add_header("User-Agent","Ocarina") try: status = urllib2.urlopen(req) except: return #for line in status: # print line #print status # Fetch similar artists def fetchSimilar(self,artist): (url,list) = self.addMethod(self.url,"artist.getsimilar") (url,list) = self.addParam(url,list,"artist",artist) (url,list) = self.addParam(url,list,"limit","10") (url,list) = self.addParam(url,list,"api_key",self.key) status = self.parseRequest(url) if status == None: return list = status.firstChild.nextSibling.childNodes for i in range(list.length): node = list.item(i) if node.hasChildNodes()==True: nameNode = node.firstChild.nextSibling.firstChild self.similar[i/2].set_text(nameNode.data) #for node in status.firstChild.childNodes: # print node # Retreive album art from last.fm def fetchAlbumArt(self,artist,album,path): if self.data.lfm == None: return if self.session == None: self.handshake() (url,list) = self.addMethod(self.url,"album.getInfo") (url,list) = self.addParam(url,list,"artist",artist) (url,list) = self.addParam(url,list,"album",album) (url,list) = self.addParam(url,list,"api_key",self.key) status = self.parseRequest(url) if status == None: return list = status.childNodes imgUrl = "" for i in range(list.length): items = list.item(i).childNodes for node in items: if node.hasChildNodes() == True: if node.tagName == "image": imgUrl = node.firstChild.data if imgUrl: try: imgIn = urllib2.urlopen(imgUrl) out = open(path,'w') out.write(imgIn.read()) imgIn.close() out.close() except: print "Error opening:",imgUrl def authToken(self,t): return self.md5(self.data.lfmpass+t) def md5(self,string): return hashlib.md5(string).hexdigest() def timestamp(self): now = datetime.datetime.now() return str(int(time.mktime(now.timetuple()))) def addMethod(self,url,method): return (self.url+"?method="+method,[("method",method)]) def addParam(self,url,list,param,val): val = val.replace(" ","%20") url+="&"+param+"="+val if list: list += [(param,val)] return url,list #return (url+"&"+param+"="+val,list+[(param,val)]) def getSig(self,list): list.sort() string = "" for entry in list: string+=entry[0]+entry[1] #string = string + self.secret return self.md5(string+self.secret) #m = hashlib.md5(string) #return m.hexdigest() def placeRequest(self,url): #print url req = urllib2.Request(url) req.add_header('User-Agent','Ocarina') #return minidom.parse(urllib2.urlopen(req)).documentElement try: return urllib2.urlopen(req) except: return None def parseRequest(self,url): request = self.placeRequest(url) if not (request == None): return minidom.parse(request).documentElement else: return None #return minidom.parse(self.placeRequest(url)).documentElement