def h_method_call(self, _, mdic, cdic): """ Listens for "method_call" messages and adds the "user parameters" to a new message """ dic=self._getParams() Bus.publish(self, "umethod_call", (mdic, cdic, dic))
def h_auth_gettoken(self, status, response_headers, cdic, udic, response): """ Authentication flow Success: ["ok", url] Failure: ["error", error_code, error_msg] """ Bus.publish(self, "log", "h_auth_gettoken, status: %s" % status) if status!="200": cdic["e"](["error", "method_failed", "Cannot retrieve 'auth token' from Last.fm"]) return if not response: cdic["e"](["error", "invalid_response", "Invalid response received from Last.fm"]) return match=re.search("\<token\>(.*)\<\/token\>", response) if match is None: cdic["e"](["error", "token_missing", "Missing 'auth token' from Last.fm response"]) return auth_token=match.group(1) Bus.publish(self, "user_params", {"auth_token":auth_token, "token":""}) api_key=udic.get("api_key", "") ## Return URL that must be used by the user for authentication ## =========================================================== url=self.auth_url % (api_key, auth_token) cdic["c"](["ok", url])
def playing_song_changed (self, sp, entry): """ Just grab the current playing entry The rest of the work will be done through the event "playing_changed" """ if entry: self.current_entry = sp.get_playing_entry() ed = EntryHelper.track_details(self.shell, entry) Bus.publish(self, "entry-playing", entry, ed)
def _process(self): dic=self.mdic if self.method=="auth.getSession": dic["token"]=self.udic.get("auth_token", "MISSING_AUTH_TOKEN") else: if self.srequired: dic["sk"]=self.udic.get("token", "MISSING_SESSION_TOKEN") dic["api_key"]=self.udic.get("api_key","") ## Signing tsign="" if self.srequired or self.method=="auth.getSession": secret=self.udic.get("secret_key", "") keys=sorted(dic.keys()) for key in keys: value=self.mdic[key] if type(value)==dbus.Array: liste="" for item in value: liste=item+"," value=liste.strip(",") tsign += key+value tsign+=secret.strip() m=md5() m.update(tsign) api_sig=m.hexdigest() Bus.publish(self, "log", "tosign(%s)" % tsign) ## URL formatting / POST body formatting fragment="" for key in dic: value=dic[key] if type(value) == dbus.Array: liste="" for item in value: liste=str(item)+"," value=liste.strip(",") fragment+=key+"="+urllib.quote(value)+"&" if self.srequired or self.method=="auth.getSession": fragment+="api_sig="+str(api_sig) fragment=fragment.strip("&") ## We do not want to update 'dic' with 'api_sig' ## Do not add keys which would pollute unneccessarily ## -------------------------------------------------- if self.wmethod: self.url=self.API self.body=fragment else: self.url=self.API+"?"+fragment self.body=None
def entry_changed(self, db, entry, changes): """ Gets triggered on every entry change Unfortunately, this includes every entry during the "startup phase" which consists in scanning all the sources of the library Allow sending 'None' for entry """ ed = EntryHelper.track_details(self.shell, entry) Bus.publish(self, "entry-changed", entry, ed)
def activate (self, shell): self.shell = shell self.db=shell.props.db Bus.publish(self, "db", self.db) sp = shell.get_player () self.spcb = ( sp.connect ('playing-song-changed', self.playing_song_changed) , ) self.dbcb = ( self.db.connect('entry-changed', self.entry_changed) ,#self.db.connect('load-complete', self.load_complete) )
def _session_required_flow(self, mdic, cdic, udic): """ A session must be authenticated before calling the method We need to have a "token" as starting point """ #Bus.publish(self, "log", "_session_required_flow: mdic(%s)" % mdic) auth_token=udic.get("auth_token", "") if not auth_token: cdic["e"](["error", "session_required"]) return cdic.update({"original_mdic":mdic}) Bus.publish(self, "method_call", {"method":"auth.getSession"}, cdic)
def h_auth_getsession(self, status, response_headers, cdic, udic, response): """ Return from "getsession" - part of authentication flow """ Bus.publish(self, "log", "h_auth_getsession, status: %s" % status) if status!="200": cdic["e"](["error", "method_failed", "Cannot retrieve 'session token' from Last.fm"]) return if not response: cdic["e"](["error", "invalid_response", "Invalid response received from Last.fm"]) return match=re.search("\<key\>(.*)\<\/key\>", response) if match is None: cdic["e"](["error", "token_missing", "Missing 'session token' from Last.fm response"]) return ## We've got a "session token" ... ## Now we need to complete the original method call token=match.group(1) Bus.publish(self, "user_params", {"token":token}) orig_mdic=cdic["original_mdic"] # get rid of original_mdic in cdic del cdic["original_mdic"] Bus.publish(self, "method_call", orig_mdic, cdic)
def clientConnectionFailed(self, _, reason): self.eback(["error", "conn_error", "connection to Last.fm API failed"]) Bus.publish(self, "error", ["conn_error", {"reason":reason, "status":self.status}])
def page(self, response): if self.finished: return self.finished=True Bus.publish(self, "ws_response", (self.status, self.response_headers, self._ctx, response))
def q_user_params(self, _=None): """ Responder for the question "user_params?" """ dic=self._getParams() Bus.publish(self, "user_params", dic)
self.q_user_params() break ## ========================================================== Bus Interfacing user=User() Bus.subscribe("user_params?", user.q_user_params) Bus.subscribe("user_params", user.h_user_params) Bus.subscribe("method_call", user.h_method_call) ## ========================================================== TESTS if __name__ == '__main__': class Logger(object): def __call__(self, msgType, e): print "Logger: Error: msgType(%s) Exception(%s)" % (msgType, str(e)) class Test(object): def handler(self, msgType, params): print params Bus.logger=Logger() t=Test() Bus.subscribe("user_params", t.handler) t2=Test() Bus.publish(t2, "user_params?")
def sRateCurrentPlaying(self, rating): """ DBus signal handler - /Player/RateCurrentPlaying """ Bus.publish(self, "rate-current", rating)