ocarina/trunk/src/scrobbler.py

241 lines
6.5 KiB
Python

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[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")
status = urllib2.urlopen(req)
self.fetchSimilar(info.artist)
#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")
status = urllib2.urlopen(req)
#for line in status:
# print line
#print status
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)
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
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
return urllib2.urlopen(req)
def parseRequest(self,url):
return minidom.parse(self.placeRequest(url)).documentElement