def __init__(self): """A deluge client session.""" self.transfer = DelugeTransfer() self.modules = [] self._request_counter = 0
class DelugeClient(object): def __init__(self): """A deluge client session.""" self.transfer = DelugeTransfer() self.modules = [] self._request_counter = 0 def _get_local_auth(self): auth_file = "" username = password = "" if platform.system() in ('Windows', 'Microsoft'): appDataPath = os.environ.get("APPDATA") if not appDataPath: try: import winreg except ImportError: import _winreg as winreg hkey = winreg.OpenKey( winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" ) appDataReg = winreg.QueryValueEx(hkey, "AppData") appDataPath = appDataReg[0] winreg.CloseKey(hkey) auth_file = os.path.join(appDataPath, "deluge", "auth") else: from xdg.BaseDirectory import save_config_path try: auth_file = os.path.join(save_config_path("deluge"), "auth") except OSError: return username, password if os.path.exists(auth_file): for line in open(auth_file): if line.startswith("#"): # This is a comment line continue line = line.strip() try: lsplit = line.split(":") except Exception: continue if len(lsplit) == 2: username, password = lsplit elif len(lsplit) == 3: username, password, level = lsplit else: continue if username == "localclient": return (username, password) return ("", "") def _create_module_method(self, module, method): fullname = "{0}.{1}".format(module, method) def func(obj, *args, **kwargs): return self.remote_call(fullname, *args, **kwargs) func.__name__ = str(method) return func def _introspect(self): self.modules = [] methods = self.remote_call("daemon.get_method_list").get() methodmap = defaultdict(dict) text_splitter = lambda v: v.decode().split(".") for module, method in map(text_splitter, methods): methodmap[module][method] = self._create_module_method( module, method) for module, methods in methodmap.items(): clsname = "DelugeModule{0}".format(module.capitalize()) cls = type(clsname, (), methods) setattr(self, module, cls()) self.modules.append(module) def remote_call(self, method, *args, **kwargs): req = DelugeRPCRequest(self._request_counter, method, *args, **kwargs) message = next(self.transfer.send_request(req)) response = DelugeRPCResponse() if not isinstance(message, tuple): return if len(message) < 3: return message_type = message[0] # if message_type == RPC_EVENT: # event = message[1] # values = message[2] # # if event in self._event_handlers: # for handler in self._event_handlers[event]: # gevent.spawn(handler, *values) # # elif message_type in (RPC_RESPONSE, RPC_ERROR): if message_type in (RPC_RESPONSE, RPC_ERROR): request_id = message[1] value = message[2] if request_id == self._request_counter: if message_type == RPC_RESPONSE: response.set(value) elif message_type == RPC_ERROR: err = DelugeRPCError(*value) response.set_exception(err) self._request_counter += 1 return response def connect(self, host="127.0.0.1", port=58846, username="", password=""): """Connects to a daemon process. :param host: str, the hostname of the daemon :param port: int, the port of the daemon :param username: str, the username to login with :param password: str, the password to login with """ # Connect transport self.transfer.connect((host, port)) # Attempt to fetch local auth info if needed if not username and host in ("127.0.0.1", "localhost"): username, password = self._get_local_auth() # Authenticate self.remote_call("daemon.login", username, password).get() # Introspect available methods self._introspect() @property def connected(self): return self.transfer.connected def disconnect(self): """Disconnects from the daemon.""" self.transfer.disconnect()
class DelugeClient(object): def __init__(self): """A deluge client session.""" self.transfer = DelugeTransfer() self.modules = [] self._request_counter = 0 def _get_local_auth(self): xdg_config = os.path.expanduser( os.environ.get("XDG_CONFIG_HOME", "~/.config")) config_home = os.path.join(xdg_config, "deluge") auth_file = os.path.join(config_home, "auth") username = password = "" with open(auth_file) as fd: for line in fd: if line.startswith("#"): continue auth = line.split(":") if len(auth) >= 2 and auth[0] == "localclient": username, password = auth[0], auth[1] break return username, password def _create_module_method(self, module, method): fullname = "{0}.{1}".format(module, method) def func(obj, *args, **kwargs): return self.remote_call(fullname, *args, **kwargs) func.__name__ = method return func def _introspect(self): self.modules = [] methods = self.remote_call("daemon.get_method_list").get() methodmap = defaultdict(dict) splitter = lambda v: v.split(".") for module, method in imap(splitter, methods): methodmap[module][method] = self._create_module_method( module, method) for module, methods in methodmap.items(): clsname = "DelugeModule{0}".format(module.capitalize()) cls = type(clsname, (), methods) setattr(self, module, cls()) self.modules.append(module) def remote_call(self, method, *args, **kwargs): req = DelugeRPCRequest(self._request_counter, method, *args, **kwargs) message = next(self.transfer.send_request(req)) response = DelugeRPCResponse() if not isinstance(message, tuple): return if len(message) < 3: return message_type = message[0] # if message_type == RPC_EVENT: # event = message[1] # values = message[2] # # if event in self._event_handlers: # for handler in self._event_handlers[event]: # gevent.spawn(handler, *values) # # elif message_type in (RPC_RESPONSE, RPC_ERROR): if message_type in (RPC_RESPONSE, RPC_ERROR): request_id = message[1] value = message[2] if request_id == self._request_counter: if message_type == RPC_RESPONSE: response.set(value) elif message_type == RPC_ERROR: err = DelugeRPCError(*value) response.set_exception(err) self._request_counter += 1 return response def connect(self, host="127.0.0.1", port=58846, username="", password=""): """Connects to a daemon process. :param host: str, the hostname of the daemon :param port: int, the port of the daemon :param username: str, the username to login with :param password: str, the password to login with """ # Connect transport self.transfer.connect((host, port)) # Attempt to fetch local auth info if needed if not username and host in ("127.0.0.1", "localhost"): username, password = self._get_local_auth() # Authenticate self.remote_call("daemon.login", username, password).get() # Introspect available methods self._introspect() @property def connected(self): return self.transfer.connected def disconnect(self): """Disconnects from the daemon.""" self.transfer.disconnect()
class DelugeClient(object): def __init__(self): """A deluge client session.""" self.transfer = DelugeTransfer() self.modules = [] self._request_counter = 0 def _get_local_auth(self): xdg_config = os.path.expanduser(os.environ.get("XDG_CONFIG_HOME", "~/.config")) config_home = os.path.join(xdg_config, "deluge") auth_file = os.path.join(config_home, "auth") username = password = "" with open(auth_file) as fd: for line in fd: if line.startswith("#"): continue auth = line.split(":") if len(auth) >= 2 and auth[0] == "localclient": username, password = auth[0], auth[1] break return username, password def _create_module_method(self, module, method): fullname = "{0}.{1}".format(module, method) def func(obj, *args, **kwargs): return self.remote_call(fullname, *args, **kwargs) func.__name__ = method return func def _introspect(self): self.modules = [] methods = self.remote_call("daemon.get_method_list").get() methodmap = defaultdict(dict) splitter = lambda v: v.split(".") for module, method in imap(splitter, methods): methodmap[module][method] = self._create_module_method(module, method) for module, methods in methodmap.items(): clsname = "DelugeModule{0}".format(module.capitalize()) cls = type(clsname, (), methods) setattr(self, module, cls()) self.modules.append(module) def remote_call(self, method, *args, **kwargs): req = DelugeRPCRequest(self._request_counter, method, *args, **kwargs) message = next(self.transfer.send_request(req)) response = DelugeRPCResponse() if not isinstance(message, tuple): return if len(message) < 3: return message_type = message[0] # if message_type == RPC_EVENT: # event = message[1] # values = message[2] # # if event in self._event_handlers: # for handler in self._event_handlers[event]: # gevent.spawn(handler, *values) # # elif message_type in (RPC_RESPONSE, RPC_ERROR): if message_type in (RPC_RESPONSE, RPC_ERROR): request_id = message[1] value = message[2] if request_id == self._request_counter : if message_type == RPC_RESPONSE: response.set(value) elif message_type == RPC_ERROR: err = DelugeRPCError(*value) response.set_exception(err) self._request_counter += 1 return response def connect(self, host="127.0.0.1", port=58846, username="", password=""): """Connects to a daemon process. :param host: str, the hostname of the daemon :param port: int, the port of the daemon :param username: str, the username to login with :param password: str, the password to login with """ # Connect transport self.transfer.connect((host, port)) # Attempt to fetch local auth info if needed if not username and host in ("127.0.0.1", "localhost"): username, password = self._get_local_auth() # Authenticate self.remote_call("daemon.login", username, password).get() # Introspect available methods self._introspect() @property def connected(self): return self.transfer.connected def disconnect(self): """Disconnects from the daemon.""" self.transfer.disconnect()