def dwnTorrent(magnet, hash, dir): client = DelugeRPCClient(dHost, dPort, dUser, dPass) try: client.connect() except: return path = '' torrent = client.call('core.get_torrent_status', hash, []) if torrent: percent = float(torrent[b'file_progress'][0] * 100) #msg = 'already in deluge ({0})'.format(percent) else: client.call('core.add_torrent_magnet', magnet, {'download_location': dir}) #msg = 'not found, adding to deluge' #waiting for the files to appear while not (client.call('core.get_torrent_status', hash, [])[b'files']): time.sleep(2) else: files = client.call('core.get_torrent_status', hash, [])[b'files'] for format in video_formats: for file in files: if format in file[b'path'].decode('utf-8'): path = file[b'path'].replace(b'/', b'\\').decode('utf-8') client.disconnect() return path
def downloadTorrent(url): url = url + "&authkey=" + AuthKey + "&torrent_pass="******"Downloading: " + url) client = DelugeRPCClient(DelugeIp, DelugePort, DelugeUser, DelugePass) client.connect() hash = client.core.add_torrent_url(url, [], []) print("Hash: " + str(hash)) client.disconnect()
def get_progress(hash): client = DelugeRPCClient(dHost, dPort, dUser, dPass) try: client.connect() except ValueError as err: if ('already-connected SSLSocket' in str(err)): pass torrent = client.call('core.get_torrent_status', hash, []) percent = float(torrent[b'progress']) client.disconnect() return ('%.2f' % percent)
class DelugeConnect: def __init__(self, host, port, username, password): self.host = host self.port = port self.username = username self.password = password def connect(self): #connect based on the host:port and username and password self.client = DelugeRPCClient(self.host, self.port, self.username, self.password, automatic_reconnect=True) #please recommend everyone else to make a proper client username and password try: self.client.connect() return "Client connected." except Exception as e: print(e) return "Cannot connect, something is wrong." def add_torrent(self, filename): torrent = open(filename, 'r').read() print(torrent) metadata = base64.b64encode(torrent) #this function is to add torrent based on the existing torrent file in the name of add_torrent return self.client.core.add_torrent_file(filename, metadata, {}) def get_torrent_status(self): raw_progress = self.client.core.get_torrents_status( {}, ['name', 'progress']) list_of_progress = [] for a in raw_progress.items(): list_of_progress.append(a[1]) return list_of_progress #this function is to get the torrent status from a specified ip address def disconnect(self): try: self.client.disconnect() return "Disconnected" except Exception as e: print(e) return "Cannot be disconnected, maybe it's already disconnected?"
class DefineDelugeInterface: def __init__(self, address, port, username, password): # The actual interface with the deluge daemon, via the RPCClient package # This object captures the interface (including address & credentials) to be # opened, closed, and used to pass messages to the daemon self.delugeinterface = DelugeDaemonInterface(address, port, username, password) # The deluge keys used for gaining overall session data via the 'core.get_session_status' call self.delugekeysforsessioninfo = [ "payload_download_rate", "payload_upload_rate", "total_payload_upload" ] # The deluge keys used for gaining detailed data about a single torrent via the 'core.get_torrent_status' call self.delugekeysfortorrentinfo = [ "state", "save_path", "name", "total_size", "progress", "eta", "files", "tracker_status", "is_finished", "time_added", "num_seeds", "num_peers" ] # The full list deluge keys available for gaining detailed data about a single torrent via the # 'core.get_torrent_status' call self.alldelugekeysavailablefortorrentinfo = [ "state", "save_path", "tracker", "tracker_status", "next_announce", "name", "total_size", "progress", "num_seeds", "total_seeds", "num_peers", "total_peers", "eta", "download_payload_rate", "upload_payload_rate", "ratio", "distributed_copies", "num_pieces", "piece_length", "total_done", "files", "file_priorities", "file_progress", "peers", "is_seed", "is_finished", "active_time", "seeding_time" ] # ========================================================================================= # Opens a connection with the deluge daemon, for messages to be passed to/from it # ========================================================================================= def openconnection(self): # Logging.printout("- Connecting to Deluge Daemon <small>(" + reasontext + ")</small>") try: while self.delugeinterface.connected == False: self.delugeinterface.connect() # print "=========================================================" # print self.delugeinterface.call('client.api_methods') # print "=========================================================" # WORKS! print self.delugeinterface.call('core.get_free_space') # print "=========================================================" # WORKS! print self.delugeinterface.call('core.get_config') # print "=========================================================" outcome = self.delugeinterface.connected except Exception as errortype: outcome = None print( "DELUGE INTERFACE ERROR: Trying to connect to deluge client (", errortype, ")") return outcome # ========================================================================================= # Closes the open connection with the deluge daemon # ========================================================================================= def closeconnection(self): try: while self.delugeinterface.connected == True: self.delugeinterface.disconnect() outcome = self.delugeinterface.connected except Exception as errortype: outcome = None print( "DELUGE INTERFACE ERROR: Trying to disconnect from deluge client (", errortype, ")") return outcome # ========================================================================================= # Returns a list of strings, one per torrent, providing the GUID of each torrent # ========================================================================================= def retrievetorrentlist(self): try: outcome = [] rawtorrentlist = self.delugeinterface.call( 'core.get_session_state') for rawtorrentid in rawtorrentlist: outcome.append(rawtorrentid.decode("ascii", "ignore")) except Exception as errortype: print("DELUGE INTERFACE ERROR: Trying to retrieve torrent list (", errortype, ")") outcome = None return outcome # ========================================================================================= # Returns a structured/layered dictionary of information about a specified (by GUID) torrent # ========================================================================================= def retrievetorrentdata(self, torrentid): try: outcome = {} rawtorrentdata = self.delugeinterface.call( 'core.get_torrent_status', torrentid, self.delugekeysfortorrentinfo) for itemkey in rawtorrentdata: itemdata = rawtorrentdata[itemkey] newkeyname = itemkey.decode("utf-8", "ignore") if isinstance(itemdata, bytes) == True: outcome[newkeyname] = itemdata.decode("utf-8", "ignore") elif isinstance(itemdata, tuple) == True: newlist = [] for subitem in itemdata: newsubdictionary = {} for subitemkey in subitem: newsubitemkey = subitemkey.decode( "utf-8", "ignore") if isinstance(subitem[subitemkey], bytes) == True: newsubitemdata = subitem[subitemkey].decode( "utf-8", "ignore") else: newsubitemdata = subitem[subitemkey] newsubdictionary[newsubitemkey] = newsubitemdata newlist.append(newsubdictionary) outcome[newkeyname] = newlist else: outcome[newkeyname] = itemdata except Exception as errortype: print( "DELUGE INTERFACE ERROR: Trying to retrieve torrent data for " + torrentid + " (", errortype, ")") outcome = None return outcome # ========================================================================================= # Adds a new torrent to the daemon, using the specified link URL # Returns the GUID of the added torrent # ========================================================================================= def addtorrentlink(self, linkstring): try: if linkstring[:7] == "magnet:": newtorrentid = self.delugeinterface.call( 'core.add_torrent_magnet', linkstring, {}) else: newtorrentid = self.delugeinterface.call( 'core.add_torrent_url', linkstring, {}) outcome = newtorrentid.decode("ascii", "ignore") except Exception as errortype: print("DELUGE INTERFACE ERROR: Trying to add new torrent (", errortype, ")") outcome = None return outcome # ========================================================================================= # Instigates a recheck of the specified (by GUID) torrent # (Returns the RPCClient response, an unknown object) # ========================================================================================= def rechecktorrent(self, torrentids): try: outcome = self.delugeinterface.call('core.force_recheck', torrentids) except Exception as errortype: print( "DELUGE INTERFACE ERROR: Trying to force recheck of torrent " + torrentids + " (", errortype, ")") outcome = None return outcome # ========================================================================================= # Pauses the specified (by GUID) torrent # If "ALL" is specified, all torrents in the daemon are paused # (Returns the RPCClient response, an unknown object) # ========================================================================================= def pausetorrent(self, torrentid): try: if torrentid == "ALL": outcome = self.delugeinterface.call('core.pause_all_torrents') else: outcome = self.delugeinterface.call('core.pause_torrent', [torrentid]) except Exception as errortype: print( "DELUGE INTERFACE ERROR: Trying to pause torrent " + torrentid + " (", errortype, ")") outcome = None return outcome # ========================================================================================= # Unpauses the specified (by GUID) torrent # If "ALL" is specified, all torrents in the daemon are unpaused # (Returns the RPCClient response, an unknown object) # ========================================================================================= def resumetorrent(self, torrentid): try: if torrentid == "ALL": outcome = self.delugeinterface.call('core.resume_all_torrents') else: outcome = self.delugeinterface.call('core.resume_torrent', [torrentid]) except Exception as errortype: print( "DELUGE INTERFACE ERROR: Trying to resume torrent " + torrentid + " (", errortype, ")") outcome = None return outcome # ========================================================================================= # Deletes the specified (by GUID) torrent # (Returns the RPCClient response, an unknown object) # ========================================================================================= def deletetorrent(self, torrentid): try: outcome = self.delugeinterface.call('core.remove_torrent', torrentid, True) except Exception as errortype: print( "DELUGE INTERFACE ERROR: Trying to delete torrent " + torrentid + " (", errortype, ")") outcome = None return outcome # ========================================================================================= # Returns a dictionary of information about the daemon session # ========================================================================================= def retrievesessiondata(self): try: rawstats1 = self.delugeinterface.call( 'core.get_session_status', self.delugekeysforsessioninfo) rawstats2 = self.delugeinterface.call('core.get_free_space') outcome = {} outcome['uploadspeed'] = rawstats1[b'payload_upload_rate'] outcome['downloadspeed'] = rawstats1[b'payload_download_rate'] outcome['uploadedtotal'] = rawstats1[b'total_payload_upload'] outcome['freespace'] = rawstats2 / 1000000000 except Exception as errortype: print("DELUGE INTERFACE ERROR: Trying to retrieve session data (", errortype, ")") outcome = None return outcome
class DelugeRPC(object): """Deluge RPC client class.""" def __init__(self, host='localhost', port=58846, username=None, password=None): """Constructor. :param host: :type host: str :param port: :type port: int :param username: :type username: str :param password: :type password: str """ super(DelugeRPC, self).__init__() self.host = host self.port = int(port) self.username = username self.password = password def connect(self): """Connect to the host using synchronousdeluge API.""" self.client = DelugeRPCClient(self.host, self.port, self.username, self.password, decode_utf8=True) self.client.connect() def test(self): """Test connection. :return: :rtype: bool """ try: self.connect() except Exception: return False else: return True def remove_torrent_data(self, torrent_id): """Remove torrent from client using given info_hash. :param torrent_id: :type torrent_id: str :return: :rtype: str or bool """ try: self.connect() self.client.core.remove_torrent(torrent_id, True) except Exception: return False else: return True finally: if self.client: self.disconnect() def move_storage(self, torrent_id, location): """Move torrent to new location and return torrent id/hash. :param torrent_id: :type torrent_id: str :param location: :type location: str :return: :rtype: str or bool """ try: self.connect() self.client.core.move_storage([torrent_id], location) except Exception: return False else: return True finally: if self.client: self.disconnect() def add_torrent_magnet(self, torrent, options, info_hash): """Add Torrent magnet and return torrent id/hash. :param torrent: :type torrent: str :param options: :type options: dict :param info_hash: :type info_hash: str :return: :rtype: str or bool """ try: self.connect() torrent_id = self.client.core.add_torrent_magnet(torrent, options) if not torrent_id: torrent_id = self._check_torrent(info_hash) except Exception: raise return False else: return torrent_id finally: if self.client: self.disconnect() def add_torrent_file(self, filename, torrent, options, info_hash): """Add Torrent file and return torrent id/hash. :param filename: :type filename: str :param torrent: :type torrent: str :param options: :type options: dict :param info_hash: :type info_hash: str :return: :rtype: str or bool """ try: self.connect() torrent_id = self.client.core.add_torrent_file(filename, b64encode(torrent), options) if not torrent_id: torrent_id = self._check_torrent(info_hash) except Exception: return False else: return torrent_id finally: if self.client: self.disconnect() def set_torrent_label(self, torrent_id, label): """Set Torrent label. :param torrent_id: :type torrent_id: str :param label: :type label: str :return: :rtype: bool """ try: self.connect() self.client.label.set_torrent(torrent_id, label) except Exception: return False else: return True finally: if self.client: self.disconnect() def set_torrent_path(self, torrent_id, path): """Set Torrent path. :param torrent_id: :type torrent_id: str :param path: :type path: str :return: :rtype: bool """ try: self.connect() self.client.core.set_torrent_move_completed_path(torrent_id, path) self.client.core.set_torrent_move_completed(torrent_id, 1) except Exception: return False else: return True finally: if self.client: self.disconnect() def set_torrent_priority(self, torrent_id, priority): """Set Torrent priority. :param torrent_id: :type torrent_id: str :param priority: :type priority: bool :return: :rtype: bool """ try: self.connect() if priority: self.client.core.queue_top([torrent_id]) except Exception: return False else: return True finally: if self.client: self.disconnect() def set_torrent_ratio(self, torrent_id, ratio): """Set Torrent ratio. :param torrent_id: :type torrent_id: str :param ratio: :type ratio: float :return: :rtype: bool """ try: self.connect() self.client.core.set_torrent_stop_at_ratio(torrent_id, True) self.client.core.set_torrent_stop_ratio(torrent_id, ratio) except Exception: return False else: return True finally: if self.client: self.disconnect() def pause_torrent(self, torrent_ids): """Pause torrent. :param torrent_ids: :type torrent_ids: list of str :return: :rtype: bool """ try: self.connect() self.client.core.pause_torrent(torrent_ids) except Exception: return False else: return True finally: if self.client: self.disconnect() def disconnect(self): """Disconnect RPC client.""" self.client.disconnect() def _check_torrent(self, info_hash): torrent_id = self.client.core.get_torrent_status(info_hash, {}) if torrent_id.get('hash'): log.debug('DelugeD: Torrent already exists in Deluge') return info_hash return False def get_all_torrents(self): """Get all torrents in client. :return: :rtype: bool """ try: self.connect() torrents_data = self.client.core.get_torrents_status({}, ('name', 'hash', 'progress', 'state', 'ratio', 'stop_ratio', 'is_seed', 'is_finished', 'paused', 'files')) except Exception: return False else: return torrents_data finally: if self.client: self.disconnect()
class DelugePlugin(object): """Base class for deluge plugins, contains settings and methods for connecting to a deluge daemon.""" def on_task_start(self, task, config): """Raise a DependencyError if our dependencies aren't available""" try: from deluge_client import DelugeRPCClient except ImportError as e: log.debug('Error importing deluge-client: %s' % e) raise plugin.DependencyError( 'deluge', 'deluge-client', 'deluge-client >=1.5 is required. `pip install deluge-client` to install.', log) config = self.prepare_config(config) if config['host'] in ['localhost', '127.0.0.1' ] and not config.get('username'): # If an username is not specified, we have to do a lookup for the localclient username/password auth = self.get_localhost_auth() if auth and auth[0]: config['username'], config['password'] = auth else: raise plugin.PluginError( 'Unable to get local authentication info for Deluge. You may need to ' 'specify an username and password from your Deluge auth file.' ) self.client = DelugeRPCClient(config['host'], config['port'], config['username'], config['password'], decode_utf8=True) def on_task_abort(self, task, config): pass def prepare_config(self, config): config.setdefault('host', 'localhost') config.setdefault('port', 58846) return config def connect(self): """Connects to the deluge daemon and runs on_connect_success """ self.client.connect() if not self.client.connected: raise plugin.PluginError('Deluge failed to connect.') def disconnect(self): self.client.disconnect() def get_torrents_status(self, fields, filters=None): """Fetches all torrents and their requested fields optionally filtered""" if filters is None: filters = {} return self.client.call('core.get_torrents_status', filters, fields) @staticmethod def get_localhost_auth(): if sys.platform.startswith('win'): auth_file = os.path.join(os.getenv('APPDATA'), 'deluge', 'auth') else: auth_file = os.path.expanduser('~/.config/deluge/auth') with open(auth_file) as auth: for line in auth: line = line.strip() if line.startswith('#') or not line: # This is a comment or blank line continue lsplit = line.split(':') if lsplit[0] == 'localclient': username, password = lsplit[:2] return username, password
class DelugePlugin(object): """Base class for deluge plugins, contains settings and methods for connecting to a deluge daemon.""" def on_task_start(self, task, config): """Raise a DependencyError if our dependencies aren't available""" try: from deluge_client import DelugeRPCClient except ImportError as e: log.debug('Error importing deluge-client: %s' % e) raise plugin.DependencyError('deluge', 'deluge-client', 'deluge-client >=1.5 is required. `pip install deluge-client` to install.', log) config = self.prepare_config(config) if config['host'] in ['localhost', '127.0.0.1'] and not config.get('username'): # If an username is not specified, we have to do a lookup for the localclient username/password auth = self.get_localhost_auth() if auth and auth[0]: config['username'], config['password'] = auth else: raise plugin.PluginError('Unable to get local authentication info for Deluge. You may need to ' 'specify an username and password from your Deluge auth file.') self.client = DelugeRPCClient(config['host'], config['port'], config['username'], config['password'], decode_utf8=True) def on_task_abort(self, task, config): pass def prepare_config(self, config): config.setdefault('host', 'localhost') config.setdefault('port', 58846) return config def connect(self): """Connects to the deluge daemon and runs on_connect_success """ self.client.connect() if not self.client.connected: raise plugin.PluginError('Deluge failed to connect.') def disconnect(self): self.client.disconnect() def get_torrents_status(self, fields, filters=None): """Fetches all torrents and their requested fields optionally filtered""" if filters is None: filters = {} return self.client.call('core.get_torrents_status', filters, fields) @staticmethod def get_localhost_auth(): if sys.platform.startswith('win'): auth_file = os.path.join(os.getenv('APPDATA'), 'deluge', 'auth') else: auth_file = os.path.expanduser('~/.config/deluge/auth') if not os.path.isfile(auth_file): return None with open(auth_file) as auth: for line in auth: line = line.strip() if line.startswith('#') or not line: # This is a comment or blank line continue lsplit = line.split(':') if lsplit[0] == 'localclient': username, password = lsplit[:2] return username, password
class DelugeService: # list of deluge filed - https://libtorrent.org/single-page-ref.html def __init__(self, config): self._deluge_client = DelugeRPCClient(config.get('deluge', 'host'), int(config.get('deluge', 'port')), config.get('deluge', 'username'), config.get('deluge', 'password'), decode_utf8=True) self._deluge_client.connect() self._label_enable = False try: self._label_enable = bool( strtobool(config.get('deluge', 'LabelEnable', fallback='false'))) except ValueError: pass self._label_id = config.get('deluge', 'LabelId', fallback=None) if self._is_label_enabled(): self.create_label(self._label_id) def add_torrent_magnet(self, magnet_url: str) -> str: # https://github.com/deluge-torrent/deluge/blob/deluge-2.0.3/deluge/core/core.py#L556 torrent_id = self._deluge_client.core.add_torrent_magnet( magnet_url, {}) if self._is_label_enabled(): self.set_torrent_label(torrent_id, self._label_id) return torrent_id def add_torrent_file(self, file_name: str, file_base64_str: str) -> str: # https://github.com/deluge-torrent/deluge/blob/deluge-2.0.3/deluge/core/core.py#L407 torrent_id = self._deluge_client.core.add_torrent_file( file_name, file_base64_str, {}) if self._is_label_enabled(): self.set_torrent_label(torrent_id, self._label_id) return torrent_id def create_label(self, label_id: str): # https://github.com/deluge-torrent/deluge/blob/deluge-2.0.3/deluge/plugins/Label/deluge_label/core.py#L178 try: self._deluge_client.label.add(label_id) except Exception as e: if 'Exception: Label already exists' not in str(e): raise e def delete_label(self, label_id: str): # https://github.com/deluge-torrent/deluge/blob/deluge-2.0.3/deluge/plugins/Label/deluge_label/core.py#L193 try: self._deluge_client.label.remove(label_id) except Exception as e: if 'Exception: Unknown Label' not in str(e): raise e def get_labels(self) -> List[str]: # https://github.com/deluge-torrent/deluge/blob/deluge-2.0.3/deluge/plugins/Label/deluge_label/core.py#L173 return self._deluge_client.label.get_labels() def set_torrent_label(self, torrent_id: str, label_id: str): # https://github.com/deluge-torrent/deluge/blob/deluge-2.0.3/deluge/plugins/Label/deluge_label/core.py#L312 self._deluge_client.label.set_torrent(torrent_id, label_id) def delete_torrent(self, torrent_id: str): # https://github.com/deluge-torrent/deluge/blob/deluge-2.0.3/deluge/core/core.py#L574 self._deluge_client.core.remove_torrent(torrent_id, False) def torrent_name_by_id(self, torrent_id: str) -> str: # https://github.com/deluge-torrent/deluge/blob/deluge-2.0.3/deluge/core/core.py#L758 return self._deluge_client.core.get_torrent_status( torrent_id, ['name'])['name'] def torrent_status(self, torrent_id: str) -> Dict[str, str]: # https://github.com/deluge-torrent/deluge/blob/deluge-2.0.3/deluge/core/core.py#L758 return self._deluge_client.core.get_torrent_status( torrent_id, ['name', 'state']) def torrents_status(self, torrent_ids: List[str]) -> List[Dict[str, str]]: fields = ['name', 'state', 'progress', 'completed_time', 'time_added'] torrents_dict = self._deluge_client.core.get_torrents_status( {"id": [i for i in torrent_ids]}, fields) return DelugeService._dict_key_to_obj(torrents_dict) def labeled_torrents(self) -> List[Dict[str, str]]: if self._is_label_enabled(): fields = [ 'name', 'state', 'progress', 'completed_time', 'time_added' ] labeled_torrents = self._deluge_client.core.get_torrents_status( {'label': self._label_id}, fields) return DelugeService._dict_key_to_obj(labeled_torrents) else: return [] def stop_download_torrents(self): self._deluge_client.core.set_config({'max_download_speed': "0"}) def resume_download_torrents(self): self._deluge_client.core.set_config({'max_download_speed': "-1"}) def _is_label_enabled(self) -> bool: if self._label_enable and self._label_id: return True else: return False @staticmethod def _dict_key_to_obj(d) -> List[Dict[str, str]]: if not d or not len(d): return [] torrents = [] for key, value in d.items(): value['_id'] = key torrents.append(value) return torrents def disconnect(self): self._deluge_client.disconnect()
DelugeIp = "<Deluge IP>" DelugePort = <Deluge Port> DelugeUser = "******" DelugePass = "******" client = DelugeRPCClient(DelugeIp, DelugePort, DelugeUser, DelugePass) client.connect() mtvTorrents = client.core.get_torrents_status({"tracker_host": "morethantv.net"}, ["total_wanted"]) mtvTotalSize = 0 for i in mtvTorrents: mtvTotalSize += int(mtvTorrents[i]["total_wanted"]) mtvTotalSize = mtvTotalSize / 1024 / 1024 / 1024 print("MTV: " + str(mtvTotalSize)) ptpTorrents = client.core.get_torrents_status({"tracker_host": "passthepopcorn.me"}, ["total_wanted"]) ptpTotalSize = 0 for i in ptpTorrents: ptpTotalSize += int(ptpTorrents[i]["total_wanted"]) ptpTotalSize = ptpTotalSize / 1024 / 1024 / 1024 print("PTP: " + str(ptpTotalSize)) torrents = client.core.get_torrents_status({}, ["total_wanted"]) totalSize = 0 for i in torrents: totalSize += int(torrents[i]["total_wanted"]) totalSize = totalSize / 1024 / 1024 / 1024 print("Total: " + str(totalSize)) client.disconnect()
class DelugeClient(BTClientBase): def __init__(self, rpc_address, rpc_port, username, password, config=None): if config is None: self.use_config = False self.rpc_address = rpc_address self.rpc_port = int(rpc_port) self.username = username self.password = password self.client = DelugeRPCClient(self.rpc_address, self.rpc_port, self.username, self.password, automatic_reconnect=True) self.connected = False else: self.use_config = True self.config = config def connect(self): self.client.connect() self.connected = self.client.connected if self.connected: ret = ClientRet(ret_type=2) else: ret = ClientRet(ret_type=-2) return ret def add_torrent(self, torrent_path, download_path=None): if not self.connected: ret = ClientRet(ret_type=-2) return ret options = { } # Ref: https://github.com/deluge-torrent/deluge/blob/1.3-stable/deluge/core/torrent.py options['add_paused'] = False if download_path is not None: options['download_location'] = str(Path(download_path).resolve()) abs_torrent_path = str(Path(torrent_path).resolve()) torrent_content = open(abs_torrent_path, 'rb').read() torrent_base64 = base64.b64encode(torrent_content) torrent_idx = self.client.core.add_torrent_file( filename=abs_torrent_path, filedump=torrent_base64, options=options) if torrent_idx is not None: ret = ClientRet(ret_type=3, ret_value=torrent_idx.decode()) else: ret = ClientRet(ret_type=-3) return ret def list_torrents(self): if not self.connected: ret = ClientRet(ret_type=-2) return ret torrent_id_list = self.client.core.get_session_state() session_status = {} for idx in torrent_id_list: torrent_status_raw = self.client.core.get_torrent_status( torrent_id=idx, keys=bt_client.client_base.torrent_status_key) torrent_status = TorrentStatus( torrent_id=idx.decode(), is_finished=torrent_status_raw['is_finished'.encode()], name=torrent_status_raw['name'.encode()].decode()) session_status[torrent_status.torrent_id] = torrent_status ret = ClientRet(ret_type=4, ret_value=session_status) return ret def get_torrent_status( self, idx ): # All the value inputted and returned back should be string, not bytearray if not self.connected: ret = ClientRet(ret_type=-2) return ret idx = idx.encode() # Convert to byte array for Deluge torrent_status_raw = self.client.core.get_torrent_status( torrent_id=idx, keys=bt_client.client_base.torrent_status_key) torrent_status = TorrentStatus( torrent_id=idx.decode(), is_finished=torrent_status_raw[ 'is_finished'.encode()], # Decode bytearray to string name=torrent_status_raw[ 'name'.encode()].decode()) # Decode bytearray to string ret = ClientRet(ret_type=6, ret_value=torrent_status) return ret def del_torrent(self, idx, remove_data=True): if not self.connected: ret = ClientRet(ret_type=-2) return ret idx_byte = str(idx).encode() torrent_id_list = self.client.core.get_session_state() if idx_byte in torrent_id_list: self.client.core.remove_torrent(torrent_id=idx_byte, remove_data=remove_data) tlist = self.client.core.get_session_state() if idx not in tlist: ret = ClientRet(ret_type=5) return ret else: ret = ClientRet(ret_type=-5) return ret else: ret = ClientRet(ret_type=-5) return ret def disconnect(self): if self.connected: self.client.disconnect() self.connected = False ret = ClientRet(ret_type=0) return ret
import shutil import xmlrpclib from deluge_client import DelugeRPCClient DelugeIp = "<Deluge IP>" DelugePort = <Deluge Port> DelugeUser = "******" DelugePass = "******" DelugeStatePath = "/home/user1/.config/deluge/state/" rTorrentUrl = "https://<Username>:<Password>@<XmlRpc Url> TorrentLabel = "Archive/MoreThanTV" TorrentPath = "/home/user1/torrents/rtorrent/archive/morethantv/" TempPath = "/home/user1/scripts/ruTorrentXmlRpc/temp/" if not os.path.exists(TempPath): os.makedirs(TempPath) dClient = DelugeRPCClient(DelugeIp, DelugePort, DelugeUser, DelugePass) dClient.connect() rClient = xmlrpclib.ServerProxy(rTorrentUrl); torrents = dClient.core.get_torrents_status({"tracker_host": "morethantv.net"}, []) for t in torrents: print([t]) dClient.core.move_storage([t], TorrentPath) shutil.copyfile(DelugeStatePath + str(t) + ".torrent", TempPath + str(t) + ".torrent") dClient.core.remove_torrent(t, False) rClient.load_start_verbose(TempPath + str(t) + ".torrent", "d.custom1.set=" + TorrentLabel, "d.directory.set=" + TorrentPath, "d.delete_tied=") dClient.disconnect()
class DelugeRPC(object): """Deluge RPC client class.""" def __init__(self, host='localhost', port=58846, username=None, password=None): """Constructor. :param host: :type host: str :param port: :type port: int :param username: :type username: str :param password: :type password: str """ super(DelugeRPC, self).__init__() self.host = host self.port = int(port) self.username = username self.password = password def connect(self): """Connect to the host using synchronousdeluge API.""" self.client = DelugeRPCClient(self.host, self.port, self.username, self.password, decode_utf8=True) self.client.connect() def test(self): """Test connection. :return: :rtype: bool """ try: self.connect() except Exception: return False else: return True def remove_torrent_data(self, torrent_id): """Remove torrent from client using given info_hash. :param torrent_id: :type torrent_id: str :return: :rtype: str or bool """ try: self.connect() self.client.core.remove_torrent(torrent_id, True) except Exception: return False else: return True finally: if self.client: self.disconnect() def move_storage(self, torrent_id, location): """Move torrent to new location and return torrent id/hash. :param torrent_id: :type torrent_id: str :param location: :type location: str :return: :rtype: str or bool """ try: self.connect() self.client.core.move_storage(torrent_id, location) except Exception: return False else: return True finally: if self.client: self.disconnect() def add_torrent_magnet(self, torrent, options, info_hash): """Add Torrent magnet and return torrent id/hash. :param torrent: :type torrent: str :param options: :type options: dict :param info_hash: :type info_hash: str :return: :rtype: str or bool """ try: self.connect() torrent_id = self.client.core.add_torrent_magnet(torrent, options) if not torrent_id: torrent_id = self._check_torrent(info_hash) except Exception: raise return False else: return torrent_id finally: if self.client: self.disconnect() def add_torrent_file(self, filename, torrent, options, info_hash): """Add Torrent file and return torrent id/hash. :param filename: :type filename: str :param torrent: :type torrent: str :param options: :type options: dict :param info_hash: :type info_hash: str :return: :rtype: str or bool """ try: self.connect() torrent_id = self.client.core.add_torrent_file(filename, b64encode(torrent), options) if not torrent_id: torrent_id = self._check_torrent(info_hash) except Exception: return False else: return torrent_id finally: if self.client: self.disconnect() def set_torrent_label(self, torrent_id, label): """Set Torrent label. :param torrent_id: :type torrent_id: str :param label: :type label: str :return: :rtype: bool """ try: self.connect() self.client.label.set_torrent(torrent_id, label) except Exception: return False else: return True finally: if self.client: self.disconnect() def set_torrent_path(self, torrent_id, path): """Set Torrent path. :param torrent_id: :type torrent_id: str :param path: :type path: str :return: :rtype: bool """ try: self.connect() self.client.core.set_torrent_move_completed_path(torrent_id, path) self.client.core.set_torrent_move_completed(torrent_id, 1) except Exception: return False else: return True finally: if self.client: self.disconnect() def set_torrent_priority(self, torrent_id, priority): """Set Torrent priority. :param torrent_id: :type torrent_id: str :param priority: :type priority: bool :return: :rtype: bool """ try: self.connect() if priority: self.client.core.queue_top([torrent_id]) except Exception: return False else: return True finally: if self.client: self.disconnect() def set_torrent_ratio(self, torrent_id, ratio): """Set Torrent ratio. :param torrent_id: :type torrent_id: str :param ratio: :type ratio: float :return: :rtype: bool """ try: self.connect() self.client.core.set_torrent_stop_at_ratio(torrent_id, True) self.client.core.set_torrent_stop_ratio(torrent_id, ratio) except Exception: return False else: return True finally: if self.client: self.disconnect() def pause_torrent(self, torrent_ids): """Pause torrent. :param torrent_ids: :type torrent_ids: list of str :return: :rtype: bool """ try: self.connect() self.client.core.pause_torrent(torrent_ids) except Exception: return False else: return True finally: if self.client: self.disconnect() def disconnect(self): """Disconnect RPC client.""" self.client.disconnect() def _check_torrent(self, info_hash): torrent_id = self.client.core.get_torrent_status(info_hash, {}) if torrent_id.get('hash'): log.debug('DelugeD: Torrent already exists in Deluge') return info_hash return False def get_all_torrents(self): """Get all torrents in client. :return: :rtype: bool """ try: self.connect() torrents_data = self.client.core.get_torrents_status({}, ('name', 'hash', 'progress', 'state', 'ratio', 'stop_ratio', 'is_seed', 'is_finished', 'paused', 'files')) except Exception: return False else: return torrents_data finally: if self.client: self.disconnect()
class DelugeRPC(object): """Deluge RPC client class.""" def __init__(self, host='localhost', port=58846, username=None, password=None): """Deluge RPC Constructor. :param host: :type host: str :param port: :type port: int :param username: :type username: str :param password: :type password: str """ super(DelugeRPC, self).__init__() self.host = host self.port = int(port) self.username = username self.password = password def connect(self): """Connect to the host using synchronousdeluge API.""" try: self.client = DelugeRPCClient(self.host, self.port, self.username, self.password, decode_utf8=True) self.client.connect() except Exception as error: log.warning('Error while trying to connect to deluge daemon. Error: {error}', {'error': error}) raise def disconnect(self): """Disconnect RPC client.""" self.client.disconnect() def test(self): """Test connection. :return: :rtype: bool """ try: self.connect() except Exception: return False else: return True def move_storage(self, torrent_id, location): """Move torrent to new location and return torrent id/hash. :param torrent_id: :type torrent_id: str :param location: :type location: str :return: :rtype: str or bool """ try: self.connect() self.client.core.move_storage([torrent_id], location) except Exception: return False else: return True finally: if self.client: self.disconnect() def add_torrent_magnet(self, torrent, options, info_hash): """Add Torrent magnet and return torrent id/hash. :param torrent: :type torrent: str :param options: :type options: dict :param info_hash: :type info_hash: str :return: :rtype: str or bool """ try: self.connect() torrent_id = self.client.core.add_torrent_magnet(torrent, options) except Exception: return False else: return torrent_id finally: if self.client: self.disconnect() def add_torrent_file(self, filename, torrent, options, info_hash): """Add Torrent file and return torrent id/hash. :param filename: :type filename: str :param torrent: :type torrent: str :param options: :type options: dict :param info_hash: :type info_hash: str :return: :rtype: str or bool """ try: self.connect() torrent_id = self.client.core.add_torrent_file(filename, b64encode(torrent), options) except Exception: return False else: return torrent_id finally: if self.client: self.disconnect() def set_torrent_label(self, torrent_id, label): """Set Torrent label. :param torrent_id: :type torrent_id: str :param label: :type label: str :return: :rtype: bool """ try: self.connect() self.client.label.set_torrent(torrent_id, label) except Exception: return False else: return True finally: if self.client: self.disconnect() def set_torrent_path(self, torrent_id, path): """Set Torrent path. :param torrent_id: :type torrent_id: str :param path: :type path: str :return: :rtype: bool """ try: self.connect() self.client.core.set_torrent_move_completed_path(torrent_id, path) self.client.core.set_torrent_move_completed(torrent_id, 1) except Exception: return False else: return True finally: if self.client: self.disconnect() def set_torrent_priority(self, torrent_id, priority): """Set Torrent priority. :param torrent_id: :type torrent_id: str :param priority: :type priority: bool :return: :rtype: bool """ try: self.connect() if priority: self.client.core.queue_top([torrent_id]) except Exception: return False else: return True finally: if self.client: self.disconnect() def set_torrent_ratio(self, torrent_id, ratio): """Set Torrent ratio. :param torrent_id: :type torrent_id: str :param ratio: :type ratio: float :return: :rtype: bool """ try: self.connect() self.client.core.set_torrent_stop_at_ratio(torrent_id, True) self.client.core.set_torrent_stop_ratio(torrent_id, ratio) except Exception: return False else: return True finally: if self.client: self.disconnect() def remove_torrent_data(self, torrent_id): """Remove torrent from client and disk using given info_hash. :param torrent_id: :type torrent_id: str :return: :rtype: str or bool """ try: self.connect() self.client.core.remove_torrent(torrent_id, True) except Exception: return False else: return True finally: if self.client: self.disconnect() def remove_torrent(self, torrent_id): """Remove torrent from client using given info_hash. :param torrent_id: :type torrent_id: str :return: :rtype: str or bool """ try: self.connect() self.client.core.remove_torrent(torrent_id, False) except Exception: return False else: return True finally: if self.client: self.disconnect() def pause_torrent(self, torrent_ids): """Pause torrent. :param torrent_ids: :type torrent_ids: list of str :return: :rtype: bool """ try: self.connect() self.client.core.pause_torrent(torrent_ids) except Exception: return False else: return True finally: if self.client: self.disconnect() def _torrent_properties(self, info_hash): """Get torrent properties.""" try: self.connect() log.debug('Checking DelugeD torrent {hash} status.', {'hash': info_hash}) torrent_data = self.client.core.get_torrent_status( info_hash, ('name', 'hash', 'progress', 'state', 'ratio', 'stop_ratio', 'is_seed', 'is_finished', 'paused', 'files', 'download_location')) except RequestException as error: raise DownloadClientConnectionException(f'Error while fetching torrent info_hash {info_hash}. Error: {error}') except Exception: log.warning('Error while fetching torrent {hash} status.', {'hash': info_hash}) return else: return torrent_data finally: if self.client: self.disconnect()
class DelugeRPC(object): host = 'localhost' port = 58846 username = None password = None client = None def __init__(self, host='localhost', port=58846, username=None, password=None): super(DelugeRPC, self).__init__() self.host = host self.port = port self.username = username self.password = password def connect(self): self.client = DelugeRPCClient(self.host, int(self.port), self.username, self.password) self.client.connect() return self.client.connected def disconnect(self): self.client.disconnect() def test(self): try: return self.connect() except Exception: return False def add_torrent_magnet(self, torrent, options, torrent_hash): try: if not self.connect(): return False torrent_id = self.client.core.add_torrent_magnet(torrent, options).get() if not torrent_id: torrent_id = self._check_torrent(torrent_hash) except Exception: return False finally: if self.client: self.disconnect() return torrent_id def add_torrent_file(self, filename, torrent, options, torrent_hash): try: if not self.connect(): return False torrent_id = self.client.core.add_torrent_file( filename, b64encode(torrent), options).get() if not torrent_id: torrent_id = self._check_torrent(torrent_hash) except Exception: return False finally: if self.client: self.disconnect() return torrent_id def set_torrent_label(self, torrent_id, label): try: if not self.connect(): return False self.client.label.set_torrent(torrent_id, label).get() except Exception: return False finally: if self.client: self.disconnect() return True def set_torrent_path(self, torrent_id, path): try: if not self.connect(): return False self.client.core.set_torrent_move_completed_path(torrent_id, path).get() self.client.core.set_torrent_move_completed(torrent_id, 1).get() except Exception: return False finally: if self.client: self.disconnect() return True def set_torrent_priority(self, torrent_ids, priority): try: if not self.connect(): return False if priority: self.client.core.queue_top([torrent_ids]).get() except Exception as err: return False finally: if self.client: self.disconnect() return True def set_torrent_ratio(self, torrent_ids, ratio): try: if not self.connect(): return False self.client.core.set_torrent_stop_at_ratio(torrent_ids, True).get() self.client.core.set_torrent_stop_ratio(torrent_ids, ratio).get() except Exception as err: return False finally: if self.client: self.disconnect() return True def pause_torrent(self, torrent_ids): try: if not self.connect(): return False self.client.core.pause_torrent(torrent_ids).get() except Exception: return False finally: if self.client: self.disconnect() return True def _check_torrent(self, torrent_hash): torrent_id = self.client.core.get_torrent_status(torrent_hash, {}).get() if torrent_id['hash']: sickrage.app.log.debug('DelugeD: Torrent already exists in Deluge') return torrent_hash return False
def collect(self): deluge_host = os.environ.get('DELUGE_HOST', '127.0.0.1') client = DelugeRPCClient(deluge_host, self.rpc_port, self.rpc_user, self.rpc_password) client.connect() libtorrent_metrics = get_libtorrent_metrics_meta() libtorrent_metric_values = client.call('core.get_session_status', []) for metric, metric_type in libtorrent_metrics.items(): encoded_name = metric.encode('ascii') if encoded_name in libtorrent_metric_values: yield metric_type('deluge_libtorrent_{}'.format( metric.replace('.', '_')), 'libtorrent metric {}'.format(metric), value=libtorrent_metric_values[encoded_name]) yield new_metric_with_labels_and_value( GaugeMetricFamily, 'deluge_info', 'Deluge information', labels={ 'version': client.call('daemon.info').decode('utf-8'), 'libtorrent_version': client.call('core.get_libtorrent_version').decode('utf-8'), }, value=1) for key, value in client.call('core.get_config').items(): if isinstance(value, (int, float, bool)): yield GaugeMetricFamily( 'deluge_config_{}'.format(key.decode('utf-8')), 'Value of the deluge config setting {}'.format( key.decode('utf-8')), value=value) torrents_by_state = { 'downloading': 0, 'seeding': 0, 'paused': 0, 'checking': 0, 'queued': 0, 'error': 0, 'active': 0, # not the prometheus way, but the states above (as defined by deluge) are already overlapping, so sum() over them is already meaningless 'total': 0, } torrents_by_label = defaultdict(int) for torrent in client.core.get_torrents_status({}, [ b'label', b'state', b'download_payload_rate', b'upload_payload_rate' ]).values(): if b'label' in torrent: torrents_by_label[torrent[b'label'].decode('utf-8')] += 1 torrents_by_state[torrent[b'state'].decode('utf-8').lower()] += 1 torrents_by_state['total'] += 1 if torrent[b'download_payload_rate'] > 0 or torrent[ b'upload_payload_rate'] > 0: torrents_by_state['active'] += 1 if len(torrents_by_label) > 0: torrents_by_label_metric = GaugeMetricFamily( 'deluge_torrents_by_label', 'The number of torrents for each label assigned to a torrent using the deluge label plugin', labels=['label']) for label, count in torrents_by_label.items(): torrents_by_label_metric.add_metric([label], count) yield torrents_by_label_metric torrents_metric = GaugeMetricFamily( 'deluge_torrents', 'The number of torrents in a specific state (note: some states overlap)', labels=['state']) for state, torrent_count in torrents_by_state.items(): torrents_metric.add_metric([state], torrent_count) yield torrents_metric client.disconnect()
def collect(self): deluge_host = os.environ.get('DELUGE_HOST', '127.0.0.1') client = DelugeRPCClient(deluge_host, self.rpc_port, self.rpc_user, self.rpc_password) client.connect() libtorrent_status_metrics = get_libtorrent_status_metrics_meta() libtorrent_status_metric_source_names = [ x['source'] for x in libtorrent_status_metrics.values() ] libtorrent_status_metric_values = client.call( 'core.get_session_status', libtorrent_status_metric_source_names) for metric, props in libtorrent_status_metrics.items(): if props['type'] is None: continue value = libtorrent_status_metric_values[props['source']] if 'conv' in props: value = props['conv'](value) yield props['type']('deluge_libtorrent_{}'.format(metric), props['help'], value=value) for direction in ['upload', 'download']: transfer_metric = CounterMetricFamily( 'deluge_libtorrent_{}_bytes_total'.format(direction), 'Total bytes {}ed for all torrents.'.format(direction), labels=['type']) for traffic_type in ['payload', 'ip_overhead', 'dht', 'tracker']: transfer_metric.add_metric( [traffic_type], libtorrent_status_metric_values['total_{}_{}'.format( traffic_type, direction).encode('ascii')]) yield transfer_metric yield new_metric_with_labels_and_value( GaugeMetricFamily, 'deluge_info', 'Deluge information', labels={ 'version': client.call('daemon.info').decode('utf-8'), 'libtorrent_version': client.call('core.get_libtorrent_version').decode('utf-8'), }, value=1) for key, value in client.call('core.get_config').items(): if isinstance(value, (int, float, bool)): yield GaugeMetricFamily( 'deluge_config_{}'.format(key.decode('utf-8')), 'Value of the deluge config setting {}'.format( key.decode('utf-8')), value=value) torrents_by_state = { 'downloading': 0, 'seeding': 0, 'paused': 0, 'checking': 0, 'queued': 0, 'error': 0, 'active': 0, # not the prometheus way, but the states above (as defined by deluge) are already overlapping, so sum() over them is already meaningless 'total': 0, } torrents_by_label = defaultdict(int) for torrent in client.core.get_torrents_status({}, [ b'label', b'state', b'download_payload_rate', b'upload_payload_rate' ]).values(): if b'label' in torrent: torrents_by_label[torrent[b'label'].decode('utf-8')] += 1 torrents_by_state[torrent[b'state'].decode('utf-8').lower()] += 1 torrents_by_state['total'] += 1 if torrent[b'download_payload_rate'] > 0 or torrent[ b'upload_payload_rate'] > 0: torrents_by_state['active'] += 1 if len(torrents_by_label) > 0: torrents_by_label_metric = GaugeMetricFamily( 'deluge_torrents_by_label', 'The number of torrents for each label assigned to a torrent using the deluge label plugin', labels=['label']) for label, count in torrents_by_label.items(): torrents_by_label_metric.add_metric([label], count) yield torrents_by_label_metric torrents_metric = GaugeMetricFamily( 'deluge_torrents', 'The number of torrents in a specific state (note: some states overlap)', labels=['state']) for state, torrent_count in torrents_by_state.items(): torrents_metric.add_metric([state], torrent_count) yield torrents_metric client.disconnect()