Example #1
0
def enqueue_deluge():
    max_items = 200
    mongo = MongoClient(MONGO_HOST, MONGO_PORT)
    yts_db = mongo['yts']
    movies_collection = yts_db['movies']

    print colored("MESSG:Updating Deluge", "cyan")
    deluge = Deluge("127.0.0.1", 58846, 'admin', 'deluge')
    deluge.connect()
    torrents = deluge.call('core.get_torrents_status', {}, {})

    #remove completed torrents
    torrents_to_remove = []
    for torrent in torrents:
        if torrents[torrent]['is_finished']:
            deluge.call("core.remove_torrent", torrent, {})
            torrents_to_remove.append(torrent)
            print colored("DELTE:","red") + "{}".format(torrent)
    
    for id in torrents_to_remove:
        del torrents[id]

    #add a new one(s) to replace
    diff = max_items - len(torrents)
    if(diff > 0):
        for i in range(0,diff):
            movie = movies_collection.find({"downloaded": False, "year": {"$gt": 1970}, "language": "English"}).sort([("rating", -1),("year", -1)]).limit(1)[0]
            movie['downloaded'] = True
            movies_collection.save(movie);
            deluge.call('core.add_torrent_magnet', movie['magnet_url'], {})
            print colored("QUEUE:","yellow") + "({}) {} - {}".format(movie['rating'], movie['year'], movie['title'].encode("utf-8"))
Example #2
0
def deluge(torrent, CLIENT_URL, TOR_CLIENT_USER, TOR_CLIENT_PW, logger):
    TOR_CLIENT = "Deluge"
    print(f"Sending {torrent.description.decode('ascii')} to {TOR_CLIENT}")
    url = fetch_torrent_url(torrent)
    try:
        logger.debug("Connecting to torrent client...")
        # Connection
        logger.debug(
            f"{TOR_CLIENT} connection info: {CLIENT_URL.split(':')[0]}, {int(CLIENT_URL.split(':')[1])}, {TOR_CLIENT_USER}"
        )
        client = DelugeRPCClient(
            CLIENT_URL.split(':')[0], int(CLIENT_URL.split(':')[1]),
            TOR_CLIENT_USER, TOR_CLIENT_PW)
        client.connect()
        logger.debug(f"Connected to {TOR_CLIENT}")

        # Add torrent
        logger.debug(
            f"Adding {torrent.description.decode('ascii')} with url: {url}")
        client.call("download_torrent_from_url", url)
        print("Torrent sent!")
    except Exception as e:
        print(
            f"Unable to send to {TOR_CLIENT}. Check the logs for more information."
        )
        logger.error(f"Error sending to {TOR_CLIENT}. {str(e)}")
        exit()
Example #3
0
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
Example #4
0
    def add_rutracker_torrent(self, filename: str, torrent: bytes) -> None:
        logger.info("Add torrent")

        client = DelugeRPCClient(
            self.host,
            self.port,
            self.user,
            self.password,
        )
        client.call('core.add_torrent_file', filename, b64encode(torrent), {})
Example #5
0
class DelugeHost(object):
    def __init__(self, host, port, username, password):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.client = DelugeRPCClient(
            self.host, self.port, self.username, self.password
        )
        self.client.connect()
        if not self.client.connected:
            raise DelugeNotConnectedException()

    @property
    def display(self):
        return f"{self.username}@{self.host}:{self.port}"

    @property
    def torrent_hashes(self):
        if "_torrent_hashes" not in self.__dict__ or self._torrent_hashes is None:
            logger.debug("Getting hashes from {}", self.display)

            self._torrent_hashes = [
                key.decode("utf-8")
                for key in self.client.call("core.get_torrents_status", {}, []).keys()
            ]

        return self._torrent_hashes

    @property
    def torrent_count(self):
        return len(self.torrent_hashes)

    def add_torrent(self, torrent):
        with open(torrent, "rb") as file:
            data = bdecode(file.read())
        info = data[b"info"]
        hash = sha1(bencode(info)).hexdigest()
        if hash in self.torrent_hashes or []:
            raise TorrentAlreadyPresentException(hash)

        with open(torrent, "rb") as file:
            filedump = encodestring(file.read())
        filename = basename(torrent)
        result = self.client.call("core.add_torrent_file", filename, filedump, {})
        logger.debug("Returning {}", result.decode("utf-8"))
        if result.decode("utf-8") != hash:
            raise Exception(result.decode("utf-8"))
        self._torrent_hashes = None
        return True
Example #6
0
 def uploadTorrent(self, filename):
     """
     Upload a torrent to the deluge host based on the config file
     """
     print('Uploading torrent %s' % (filename))
     client = DelugeRPCClient(self.hostDeluge, self.portDeluge, self.usernameDeluge, self.passwordDeluge)
     client.connect()
     f = open(filename, 'rb')
     filedump = base64.encodestring(f.read())
     f.close()
     client.call('core.add_torrent_file', filename, filedump, {}, )
     bytes_available = client.call('core.get_free_space')
     gig_available = bytes_available/(1024.*1024*1024)
     print('There is %.1f GB available on the host \'%s\'.' % (gig_available, self.hostDeluge))
Example #7
0
def main():
    """
    Entry function
    """
    parser = argparse.ArgumentParser(description='Process some integers.')
    parser.add_argument(
        '-d', '--dir', type=lambda x: is_valid_directory(parser, x),
        help='the directory to hold the file structure', required=True
    )
    parser.add_argument(
        'hosts', metavar='H', type=lambda x: is_valid_host(parser, x),
        nargs='+', help='the Deluge hosts'
    )
    args = parser.parse_args()

    tracker_map = {}
    clients = []

    for host in args.hosts:
        client = DelugeRPCClient(*host)
        client.connect()

        clients.append(client)

    for entry in listdir_fullpath(args.dir):
        recursive_rm_dir(entry)

    for client in clients:
        torrents = client.call(
            'core.get_torrents_status',
            {},
            ['name', 'save_path', 'tracker_host']
        )

        for _, torrent in torrents.items():
            if torrent[b'tracker_host'] not in tracker_map:
                tracker_map[torrent[b'tracker_host'].decode('utf-8')] = []
            tracker_map[torrent[b'tracker_host'].decode('utf-8')].append(torrent)

        for tracker, torrents in tracker_map.items():
            loc = os.path.join(args.dir, tracker)
            if not os.path.exists(loc):
                os.makedirs(loc)
            for torrent in torrents:
                link_from = os.path.join(loc, torrent[b'name'].decode('utf-8'))
                link_to = os.path.join(
                    torrent[b'save_path'].decode('utf-8'),
                    torrent[b'name'].decode('utf-8')
                )
                if not os.path.exists(link_from):
                    try:
                        os.symlink(link_to, link_from)
                    except OSError as error:
                        if error.errno == errno.EEXIST:
                            os.remove(link_from)
                            os.symlink(link_to, link_from)
                        else:
                            raise error
Example #8
0
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 prepare_config(self, config):
        config.setdefault('host', 'localhost')
        config.setdefault('port', 58846)
        return config

    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
Example #9
0
def node_task_del(infohash):
    client = DelugeRPCClient('127.0.0.1', 58846, u, p)
    if client.connected is False:
        client.connect()
    ret = client.call('core.get_torrents_status', {'id': [infohash]},
                      [u'name'])
    if len(ret[infohash]) == 0:
        # clean cache
        try:
            download_location = app.config.get(
                'TASK_DOWNLOAD_PATH') + '/' + infohash
            os.removedirs(download_location)
        except:
            pass
        res = True
    else:
        res = client.call('core.remove_torrent', infohash, True)

    return jsonify({'data': res, 'errCode': 0})
Example #10
0
def torrents_status():
    STATUS_KEYS = [
    "state",
    "download_location",
    "tracker_host",
    "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"
    ]
    from deluge_client import DelugeRPCClient
    client = DelugeRPCClient('127.0.0.1', 2196, "seftembr", "TuGsFYqlNP")
    client.connect()
    print "--- ACTIVE ---"
    for (hashid, fields) in client.call('core.get_torrents_status', {"state":"Active"}, STATUS_KEYS).iteritems():
        print "%s: %s (%.2f out of %s - active for %s so far)" % (hashid, fields['name'], fields['progress'], sizeof_fmt(fields['total_size']), human_time(seconds=fields['active_time']))
    print "--- PAUSED ---"
    for (hashid, fields) in client.call('core.get_torrents_status', {"state":"Paused"}, STATUS_KEYS).iteritems():
        if fields['progress'] == 100:
            print "%s: %s (%s downloaded in %s)" % (hashid, fields['name'], sizeof_fmt(fields['total_size']), human_time(seconds=fields['active_time']))
        else:
            print "%s: %s (%.2f out of %s - was active for %s - and paused)" % (hashid, fields['name'], fields['progress'], sizeof_fmt(fields['total_size']), human_time(seconds=fields['active_time']))
Example #11
0
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)
Example #12
0
def main():
    parser = argparse.ArgumentParser(description="Change torrent trackers")
    parser.add_argument("-s", "--server", type=DelugeUri, required=True,
                        help="Deluge host or IP addresses to connect to in the form of user:pass@hostname:port")

    parser.add_argument("-c", "--src-substr", help="Tracker to replace", required=True)
    parser.add_argument("-t", "--tracker", help="URL of new tracker", required=True)
    parser.add_argument("-n", "--dry-run", action="store_true", help="Only print changed torrents")

    args = parser.parse_args()

    uri = urlparse('deluge://{}'.format(args.server))
    client = DelugeRPCClient(uri.hostname, uri.port if uri.port else 58846, uri.username, uri.password)
    client.connect()

    torrents = decodedict(client.call('core.get_torrents_status', {},
                                      ['name', 'trackers']))
    for torrent_id, torrent in torrents.items():
        tracker = torrent['trackers'][0]
        if args.src_substr in tracker["url"]:
            print("Updating '{}' on '{}' ({})".format(tracker["url"], torrent['name'], torrent_id))
            if not args.dry_run:
                client.call('core.set_torrent_trackers', torrent_id, [{"url": args.tracker, "tier": 0}])
Example #13
0
class DelugeClient():
    def __init__(self):
        import config
        self.client = DelugeRPCClient(
            host=config.DELUGE['host'],
            port=config.DELUGE['port'],
            username=config.DELUGE['uname'],
            password=config.DELUGE['pword']
        )
        self.client.connect()
        self.torrent_status_data = None

    def connected(self):
        return self.client.connected

    def all_torrent_id(self):
        return self.client.call('core.get_session_state')

    def torrent_status(self, torrent_id):
        return self.client.call('core.get_torrent_status', torrent_id, [])

    def all_torrent_status(self, refresh=False):
        if refresh or self.torrent_status_data is None:
            self.torrent_status_data = [self.torrent_status(t_id) for t_id in self.all_torrent_id()]
        return self.torrent_status_data

    def torrent_exists(self, torrent_name):
        res = self.all_torrent_status()
        for torrent in res:
            if torrent[b'name'].decode('ascii') == torrent_name:
                return torrent
        return None

    def recheck_torrent(self, torrent_id):
        return self.client.call('core.force_recheck', [torrent_id])

    def resume_torrent(self, torrent_id):
        return self.client.call('core.resume_torrent', [torrent_id])
    
    def remove_torrent(self, torrent_id, remove_data=False):
        return self.client.call('core.remove_torrent', torrent_id, remove_data)

    def set_do_not_download(self, torrent_id):
        res = self.torrent_status(torrent_id)
        if res:
            new_file_priorities = [0 for _ in res[b'file_priorities']]
            self.client.call('core.set_torrent_file_priorities', torrent_id, new_file_priorities)
        else:
            return None
Example #14
0
    async def send_request(self, request):
        conn = DelugeClient('master.seedhost.eu', 21110,
                            os.environ['DELUGE_USER'],
                            os.environ['DELUGE_PASS'])
        conn.connect()
        torrent_id = conn.call(
            'core.add_torrent_magnet', request.magnet, {
                'download_location':
                f'/home13/fufu/downloads/Watchtower/{request.channel}/{request.name}/'
            })

        with TinyDB('db') as db:
            db.insert({
                'requester_name': request.requester_name,
                'torrent_id': torrent_id.decode(),
                'torrent_name': request.name,
                'time': int(time.time())
            })
Example #15
0
class DelugeHelper:
    def __init__(self):
        self.login()

    def login(self):
        self.client = DelugeRPCClient(host, port, username, password)
        self.client.connect()

    def get_torrents(self):
        # list of keys? https://forum.deluge-torrent.org/viewtopic.php?t=54793
        res_torrents = self.client.call('core.get_torrents_status', {}, [
            'name', 'progress', 'ratio', 'tracker', 'seeding_time',
            'total_size'
        ])

        torrents = [
            TorrentStat(_id, torrent[b'name'], torrent[b'ratio'],
                        torrent[b'seeding_time'], torrent[b'tracker'])
            for _id, torrent in res_torrents.items()
        ]
        return torrents

    def delete_torrent(self, torrent_id):
        self.client.core.remove_torrent(torrent_id, remove_data=True)
Example #16
0
    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()
Example #17
0
class DelugeClient(BaseClient):
    identifier = 'deluge'
    
    def __init__(self, host, username, password):
        """
        Initializes a new Deluge client.
        
        url - The url where deluge json can be reached.
        password - The password used to login
        """
        host, port = host.split(':')
        self.host = host
        self.port = int(port)
        self.username = username
        self.password = password
        self.rpcclient = DelugeRPCClient(self.host, self.port, self.username, self.password)
    
    def _login(self):
        """
        Logs into deluge
        """
        if not self.rpcclient.connected:
            self.rpcclient.connect()
    
    def get_config(self):
        """
        Get the current configuration that can be used in the autotorrent config file
        """
        return {
            'host': '%s:%s' % (self.host, self.port),
            'username': self.username,
            'password': self.password,
        }
    
    @classmethod
    def auto_config(cls):
        """
        Tries to auto configure deluge using the .config/deluge files
        """
        config_path = os.path.expanduser('~/.config/deluge/core.conf')
        if not os.path.isfile(config_path):
            logger.debug('deluge config file was not found')
            return
        
        if not os.access(config_path, os.R_OK):
            logger.debug('Unable to access deluge config file at %s' % config_path)
            return
        
        auth_path = os.path.expanduser('~/.config/deluge/auth')
        if not os.path.isfile(auth_path):
            logger.debug('deluge auth file was not found')
            return
        
        if not os.access(auth_path, os.R_OK):
            logger.debug('Unable to access deluge confauthig file at %s' % auth_path)
            return
        
        with open(config_path, 'r') as f:
            config_data = f.read()
        
        daemon_port = re.findall('"daemon_port":\s*(\d+)', config_data)
        if not daemon_port:
            logger.debug('No deluge port, just trying to use default')
            daemon_port = 58846
        else:
            daemon_port = int(daemon_port[0])
        
        with open(auth_path, 'r') as f:
            auth_data = f.read()
        
        auth_data = auth_data.split('\n')[0].split(':')
        if len(auth_data[0]) < 2:
            logger.debug('Invalid entry found in auth file')
            return
        
        username = auth_data[0]
        password = auth_data[1]
        
        return cls('127.0.0.1:%s' % daemon_port, username, password)
    
    def test_connection(self):
        """
        Tests the Deluge RPC connection, returns message if found.
        """
        self._login()
        return 'Free space: %s' % humanize_bytes(self.rpcclient.call('core.get_free_space'))
    
    def get_torrents(self):
        """
        Returns a set of info hashes currently added to the client.
        """
        logger.info('Getting a list of torrent hashes')
        self._login()
        result = self.rpcclient.call('core.get_torrents_status', {}, ['name'])
        return set(x.lower().decode('ascii') for x in result.keys())
    
    def add_torrent(self, torrent, destination_path, files, fast_resume=True):
        """
        Add a new torrent to Deluge.
        
        torrent is the decoded file as a python object.
        destination_path is where the links are. The complete files must be linked already.
        files is a list of files found in the torrent.
        """
        name = torrent[b'info'][b'name']
        logger.info('Trying to add a new torrent to deluge: %r' % name)
        
        destination_path = os.path.abspath(destination_path)
        
        infohash = hashlib.sha1(bencode(torrent[b'info'])).hexdigest()
        encoded_torrent = base64.b64encode(bencode(torrent))
        
        basename = os.path.basename(destination_path)
        mapped_files = {}
        for i, f in enumerate(files):
            mapped_files[i] = os.path.join(basename, *f['path'])
        
        self._login()
        result = self.rpcclient.call('core.add_torrent_file', 'torrent.torrent', encoded_torrent, {
                                                                'download_location': os.path.dirname(destination_path),
                                                                'mapped_files': mapped_files,
                                                                'seed_mode': fast_resume})
        
        return result and result.decode('utf-8') == infohash
Example #18
0
class Deluge(IntervalModule):
    """
    Deluge torrent module
    Requires `deluge-client`

    .. rubric:: Formatters:

    * `{num_torrents}`       - number of torrents in deluge
    * `{free_space_bytes}`   - bytes free in path
    * `{used_space_bytes}`   - bytes used in path
    * `{upload_rate}` - bytes sent per second
    * `{download_rate}` - bytes received per second
    * `{total_uploaded}`     - bytes sent total
    * `{total_downloaded}`     - bytes received total

    """

    settings = (
        'format',
        ('rounding', 'number of decimal places to round numbers too'),
        ('host', 'address of deluge server (default: 127.0.0.1)'),
        ('port', 'port of deluge server (default: 58846)'),
        ('username', 'username to authenticate with deluge'),
        ('password', 'password to authenticate to deluge'),
        ('path',
         'override "download path" server-side when checking space used/free'),
    )
    required = ('username', 'password')

    host = '127.0.0.1'
    port = 58846
    path = None
    libtorrent_stats = False
    rounding = 2

    format = '⛆{num_torrents} ✇{free_space_bytes}'

    id = int(time.time())  # something random

    def init(self):
        self.client = DelugeRPCClient(self.host, self.port, self.username,
                                      self.password)
        self.data = {}

    def run(self):
        if not self.client.connected:
            self.client.connect()

        self.data = self.get_session_statistics()

        torrents = self.get_torrents_status()
        if torrents:
            self.data['num_torrents'] = len(torrents)

        if 'free_space_bytes' in self.format:
            self.data['free_space_bytes'] = self.get_free_space(self.path)
        if 'used_space_bytes' in self.format:
            self.data['used_space_bytes'] = self.get_path_size(self.path)

        self.parse_values(self.data)

        self.output = {'full_text': self.format.format(**self.data)}

    def parse_values(self, values):
        for k, v in values.items():
            if v:
                if k in [
                        'total_upload', 'total_download', 'download_rate',
                        'upload_rate'
                ] or k.endswith('_bytes'):
                    values[k] = '{value:.{round}f}{unit}'.format(
                        round=self.rounding, **bytes_info_dict(v))

    def get_path_size(self, path=None):
        """
        get used space of path in bytes (default: download location)
        """
        if path is None:
            path = []
        return self.client.call('core.get_path_size', path)

    def get_free_space(self, path=None):
        """
        get free space of path in bytes (default: download location)
        """
        if path is None:
            path = []
        return self.client.call('core.get_free_space', path)

    def get_torrents_status(self, torrent_id=None, keys=None):
        if torrent_id is None:
            torrent_id = []
        if keys is None:
            keys = []
        return self.client.call('core.get_torrents_status', torrent_id, keys)

    def get_session_statistics(self):
        keys = [
            'upload_rate', 'download_rate', 'total_upload', 'total_download'
        ]

        out = {
        }  # some of the values from deluge-client are bytes, the others are ints - we need to decode them
        for k, v in self.client.call('core.get_session_status', keys).items():
            k = k.decode('utf-8')  # keys aswell
            if type(v) == bytes:
                out[k] = v.decode('utf-8')
            else:
                out[k] = v

        return out
Example #19
0
File: deluge.py Project: 2mny/mylar
class TorrentClient(object):
    def __init__(self):
        self.conn = None
		
    def connect(self, host, username, password):
        if self.conn is not None:
            return self.connect
	
        if not host:
            return False

        # Get port from the config
        host,portnr = host.split(':')


        #if username and password:
        # logger.info('Connecting to ' + host + ':' + portnr + ' Username: '******' Password: '******'Could not create DelugeRPCClient Object' + e)
            return False
        else:
            try:
                self.client.connect()
            except Exception as e:
                logger.error('Could not connect to Deluge ' + host)
            else:
                return self.client
	
    def find_torrent(self, hash):
        logger.debug('Finding Torrent hash: ' + hash)
        torrent_info = self.get_torrent(hash)
        if torrent_info:
            return True
        else:
            return False

    def get_torrent(self, hash):
        logger.debug('Getting Torrent info from hash: ' + hash)
        try:
            torrent_info = self.client.call('core.get_torrent_status', hash, '')
        except Exception as e:
            logger.error('Could not get torrent info for ' + hash)
            return False
        else:
            if torrent_info is None:
                torrent_info = False
            return torrent_info


    def start_torrent(self, hash):
        try:
            self.find_torrent(hash)
        except Exception as e:
            return False
        else:
            try:
                self.client.call('core.resume_torrent', hash)
            except Exception as e:
                logger.error('Torrent failed to start ' + e)
            else:
                logger.info('Torrent ' + hash + ' was started')
                return True

    def stop_torrent(self, hash):
        try:
            self.client.find_torrent(hash)
        except Exception as e:
            logger.error('Torrent Not Found')
            return False
        else:
            try:
                self.client.call('core.pause_torrent', hash)
            except Exception as e:
                logger.error('Torrent failed to be stopped: ' + e)
                return False
            else:
                logger.info('Torrent ' + hash + ' was stopped')
                return True
        

    def load_torrent(self, filepath):
        
        logger.info('filepath to torrent file set to : ' + filepath)
        torrent_id = False
                
        if self.client.connected is True:
            logger.info('Checking if Torrent Exists!')
            
            if not filepath.startswith('magnet'):
                torrentcontent = open(filepath, 'rb').read()
                hash = str.lower(self.get_the_hash(filepath)) # Deluge expects a lower case hash

                logger.debug('Torrent Hash (load_torrent): "' + hash + '"')
                logger.debug('FileName (load_torrent): ' + str(os.path.basename(filepath)))


                #Check if torrent already added
                if self.find_torrent(str.lower(hash)):
                    logger.info('load_torrent: Torrent already exists!')
                    #should set something here to denote that it's already loaded, and then the failed download checker not run so it doesn't download
                    #multiple copies of the same issues that's already downloaded
                else:
                    logger.info('Torrent not added yet, trying to add it now!')
                    try:
                        torrent_id = self.client.call('core.add_torrent_file', str(os.path.basename(filepath)), base64.encodestring(torrentcontent), '')
                    except Exception as e:
                        logger.debug('Torrent not added')
                        return False
            else:
                try:
                    torrent_id = self.client.call('core.add_torrent_magnet', str(filepath), {})
                except Exception as e:
                    logger.debug('Torrent not added')
                    return False

            # If label enabled put label on torrent in Deluge
            if torrent_id and mylar.CONFIG.DELUGE_LABEL:
                logger.info ('Setting label to ' + mylar.CONFIG.DELUGE_LABEL)
                try:
                    self.client.call('label.set_torrent', torrent_id, mylar.CONFIG.DELUGE_LABEL)
                except:
                 #if label isn't set, let's try and create one.
                    try:
                        self.client.call('label.add', mylar.CONFIG.DELUGE_LABEL)
                        self.client.call('label.set_torrent', torrent_id, mylar.CONFIG.DELUGE_LABEL)
                    except:
                        logger.warn('Unable to set label - Either try to create it manually within Deluge, and/or ensure there are no spaces, capitalization or special characters in label')
                    else:
                        logger.info('Succesfully set label to ' + mylar.CONFIG.DELUGE_LABEL)

        try:
            torrent_info = self.get_torrent(torrent_id)
            logger.info('Double checking that the torrent was added.')
        except Exception as e:
            logger.warn('Torrent was not added! Please check logs')
            return False
        else:
            logger.info('Torrent successfully added!')
            return {'hash':             torrent_info['hash'],
                    'label':            mylar.CONFIG.DELUGE_LABEL,
                    'folder':           torrent_info['save_path'],
                    'total_filesize':   torrent_info['total_size'],
                    'name':             torrent_info['name'],
                    'files':            torrent_info['files'],
                    'time_started':     torrent_info['active_time'],
                    'completed':        torrent_info['is_finished']}


    def delete_torrent(self, hash, removeData=False):
        try:
            self.client.find_torrent(hash)
        except Exception as e:
            logger.error('Torrent ' + hash + ' does not exist')
            return False
        else:
            try:
                self.client.call('core.remote_torrent', hash, removeData)
            except Exception as e:
                logger.error('Unable to delete torrent ' + hash)
                return False
            else:
                logger.info('Torrent deleted ' + hash)
                return True


    def get_the_hash(self, filepath):
        import hashlib, StringIO
        import bencode

        # Open torrent file
        torrent_file = open(filepath, "rb")
        metainfo = bencode.decode(torrent_file.read())
        info = metainfo['info']
        thehash = hashlib.sha1(bencode.encode(info)).hexdigest().upper()
        logger.debug('Hash: ' + thehash)
        return thehash
Example #20
0
class TorrentClient(object):
    def __init__(self):
        self.conn = None

    def connect(self, host, username, password, test=False):
        if self.conn is not None:
            return self.connect

        if not host:
            return {'status': False, 'error': 'No host specified'}

        if not username:
            return {'status': False, 'error': 'No username specified'}

        if not password:
            return {'status': False, 'error': 'No password specified'}

        # Get port from the config
        host, portnr = host.split(':')

        # logger.info('Connecting to ' + host + ':' + portnr + ' Username: '******' Password: '******'Could not create DelugeRPCClient Object %s' % e)
            return {'status': False, 'error': e}
        else:
            try:
                self.client.connect()
            except Exception as e:
                logger.error('Could not connect to Deluge: %s' % host)
                return {'status': False, 'error': e}
            else:
                if test is True:
                    daemon_version = self.client.call('daemon.info')
                    libtorrent_version = self.client.call(
                        'core.get_libtorrent_version')
                    return {
                        'status': True,
                        'daemon_version': daemon_version,
                        'libtorrent_version': libtorrent_version
                    }
                else:
                    return self.client

    def find_torrent(self, hash):
        logger.debug('Finding Torrent hash: ' + hash)
        torrent_info = self.get_torrent(hash)
        if torrent_info:
            return True
        else:
            return False

    def get_torrent(self, hash):
        logger.debug('Getting Torrent info from hash: ' + hash)
        try:
            torrent_info = self.client.call('core.get_torrent_status', hash,
                                            '')
        except Exception as e:
            logger.error('Could not get torrent info for ' + hash)
            return False
        else:
            if torrent_info is None:
                torrent_info = False
            return torrent_info

    def start_torrent(self, hash):
        try:
            self.find_torrent(hash)
        except Exception as e:
            return False
        else:
            try:
                self.client.call('core.resume_torrent', hash)
            except Exception as e:
                logger.error('Torrent failed to start ' + e)
            else:
                logger.info('Torrent ' + hash + ' was started')
                return True

    def stop_torrent(self, hash):
        try:
            self.client.find_torrent(hash)
        except Exception as e:
            logger.error('Torrent Not Found')
            return False
        else:
            try:
                self.client.call('core.pause_torrent', hash)
            except Exception as e:
                logger.error('Torrent failed to be stopped: ' + e)
                return False
            else:
                logger.info('Torrent ' + hash + ' was stopped')
                return True

    def load_torrent(self, filepath):

        options = {}

        if mylar.CONFIG.DELUGE_DOWNLOAD_DIRECTORY:
            options[
                'download_location'] = mylar.CONFIG.DELUGE_DOWNLOAD_DIRECTORY

        if mylar.CONFIG.DELUGE_DONE_DIRECTORY:
            options['move_completed'] = 1
            options['move_completed_path'] = mylar.CONFIG.DELUGE_DONE_DIRECTORY

        if mylar.CONFIG.DELUGE_PAUSE:
            options['add_paused'] = int(mylar.CONFIG.DELUGE_PAUSE)

        logger.info('filepath to torrent file set to : ' + filepath)
        torrent_id = False

        if self.client.connected is True:
            logger.info('Checking if Torrent Exists!')

            if not filepath.startswith('magnet'):
                torrentcontent = open(filepath, 'rb').read()
                hash = str.lower(self.get_the_hash(
                    filepath))  # Deluge expects a lower case hash

                logger.debug('Torrent Hash (load_torrent): "' + hash + '"')
                logger.debug('FileName (load_torrent): ' +
                             str(os.path.basename(filepath)))

                #Check if torrent already added
                if self.find_torrent(str.lower(hash)):
                    logger.info('load_torrent: Torrent already exists!')
                    #should set something here to denote that it's already loaded, and then the failed download checker not run so it doesn't download
                    #multiple copies of the same issues that's already downloaded
                else:
                    logger.info('Torrent not added yet, trying to add it now!')
                    try:
                        torrent_id = self.client.call(
                            'core.add_torrent_file',
                            str(os.path.basename(filepath)),
                            base64.encodestring(torrentcontent), options)
                    except Exception as e:
                        logger.debug('Torrent not added')
                        return False
            else:
                try:
                    torrent_id = self.client.call('core.add_torrent_magnet',
                                                  str(filepath), options)
                except Exception as e:
                    logger.debug('Torrent not added')
                    return False

            # If label enabled put label on torrent in Deluge
            if torrent_id and mylar.CONFIG.DELUGE_LABEL:
                logger.info('Setting label to ' + mylar.CONFIG.DELUGE_LABEL)
                try:
                    self.client.call('label.set_torrent', torrent_id,
                                     mylar.CONFIG.DELUGE_LABEL)
                except:
                    #if label isn't set, let's try and create one.
                    try:
                        self.client.call('label.add',
                                         mylar.CONFIG.DELUGE_LABEL)
                        self.client.call('label.set_torrent', torrent_id,
                                         mylar.CONFIG.DELUGE_LABEL)
                    except:
                        logger.warn(
                            'Unable to set label - Either try to create it manually within Deluge, and/or ensure there are no spaces, capitalization or special characters in label'
                        )
                    else:
                        logger.info('Succesfully set label to ' +
                                    mylar.CONFIG.DELUGE_LABEL)

        try:
            torrent_info = self.get_torrent(torrent_id)
            logger.info('Double checking that the torrent was added.')
        except Exception as e:
            logger.warn('Torrent was not added! Please check logs')
            return False
        else:
            logger.info('Torrent successfully added!')
            return {
                'hash': torrent_info['hash'],
                'label': mylar.CONFIG.DELUGE_LABEL,
                'folder': torrent_info['save_path'],
                'move path': torrent_info['move_completed_path'],
                'total_filesize': torrent_info['total_size'],
                'name': torrent_info['name'],
                'files': torrent_info['files'],
                'time_started': torrent_info['active_time'],
                'pause': torrent_info['paused'],
                'completed': torrent_info['is_finished']
            }

    def delete_torrent(self, hash, removeData=False):
        try:
            self.client.find_torrent(hash)
        except Exception as e:
            logger.error('Torrent ' + hash + ' does not exist')
            return False
        else:
            try:
                self.client.call('core.remote_torrent', hash, removeData)
            except Exception as e:
                logger.error('Unable to delete torrent ' + hash)
                return False
            else:
                logger.info('Torrent deleted ' + hash)
                return True

    def get_the_hash(self, filepath):
        import hashlib, StringIO
        import bencode

        # Open torrent file
        torrent_file = open(filepath, "rb")
        metainfo = bencode.decode(torrent_file.read())
        info = metainfo['info']
        thehash = hashlib.sha1(bencode.encode(info)).hexdigest().upper()
        logger.debug('Hash: ' + thehash)
        return thehash
Example #21
0
class p2p_client():
    def __init__(self, com_id, host_id):
        self.com_id = int(com_id)
        self.host_id = int(host_id)
        self.port = 62000 + (self.com_id - 1) * 100 + (self.host_id - 1)
        self.home_dir = './experiment/'
        self.account = ''
        self.password = ''

    def config(self):
        dir_type = ['Config', 'Log', 'PID', 'Host_Local_Storage', 'NewTorrent']
        ids = 'Com' + str(self.com_id) + '_Host' + str(self.host_id)
        for k in dir_type:
            path = self.home_dir + k + '/' + ids
            if not os.path.isdir(path):
                try:
                    os.makedirs(path)
                except:
                    print 'Error: error when making directories!! dir:', path
                    sys.exit()

        log_file = self.home_dir + 'Log/' + ids + '/' + ids + '.txt'
        pid_file = self.home_dir + 'PID/' + ids + '/' + ids + '.txt'
        if not os.path.isfile(log_file):
            try:
                open(log_file, 'w').close()
            except:
                print 'Error when writing log file'
                sys.exit()
        if not os.path.isfile(pid_file):
            try:
                open(pid_file, 'w').close()
            except:
                print 'Error when writing pid file'
                sys.exit()

    def get_user_info(self):
        config = self.home_dir + 'Config/Com' + str(
            self.com_id) + '_Host' + str(self.host_id) + '/auth'
        try:
            f = open(config, 'r')
            data = f.read().split(':')
            self.account = data[0]
            self.password = data[1]
            f.close()
        except:
            print 'Error: error when getting Accoung/Password'
            sys.exit()

    def start_daemon(self):
        ids = 'Com' + str(self.com_id) + '_Host' + str(self.host_id)
        config_path = self.home_dir + 'Config/' + ids
        log_file = self.home_dir + 'Log/' + ids + '/' + ids + '.txt'
        pid_file = self.home_dir + 'PID/' + ids + '/' + ids + '.txt'
        command = 'deluged -c %s -l %s -P %s -p %s' % (
            config_path, log_file, pid_file, str(self.port))
        os.system(command)
        time.sleep(5)

    def shutdown(self):
        self.client.call('daemon.shutdown')

    def login(self):
        self.client = DelugeRPCClient('127.0.0.1', self.port, self.account,
                                      self.password)
        self.client.connect()

    def get_session_state(self):
        return self.client.call('core.get_session_state')

    def clean_session(self):
        item = self.get_session_state()
        for k in item:
            self.remove_torrent(k)

    def get_method_list(self):
        method = sorted(list(self.client.call('daemon.get_method_list')))
        for k in method:
            print k

    def get_torrent_status(self, hashid):
        return self.client.call('core.get_torrent_status', hashid, '')

    def get_torrents_status(self):
        return self.client.call('core.get_torrents_status', {}, [])

    def add_torrent(self, file_name):
        torrent_file = self.home_dir + 'torrent/' + file_name
        download_path = self.home_dir + 'Host_Local_Storage/' + 'Com' + str(
            self.com_id) + '_Host' + str(self.host_id)
        if not os.path.isdir(download_path):
            try:
                os.makedirs(download_path)
            except:
                print 'Error: error when making download directories'
                sys.exit()
        self.client.call('core.add_torrent_file', torrent_file,
                         base64.encodestring(open(torrent_file, 'rb').read()),
                         {
                             'add_paused': True,
                             'download_location': download_path
                         })

    def remove_torrent(self, hashid, remove_data=True):
        self.client.call('core.remove_torrent', hashid, remove_data)

    def create_torrent(self, file_dst, comment='', create_by=''):
        source = '/home/john/p2p/file/' + file_dst
        torrent_location = self.home_dir + 'NewTorrent/' + 'Com' + str(
            self.com_id) + '_Host' + str(
                self.host_id) + '/' + file_dst + '.torrent'
        tracker = 'http://192.168.144.126:9010/'
        piece_length = 30768
        webseeds = ''
        add_to_session = True
        private = False
        trackers = ''
        self.client.call('core.create_torrent', source, tracker, piece_length,
                         comment, torrent_location, webseeds, private,
                         create_by, trackers, add_to_session)

    def resume_torrent(self, torrents):
        self.client.call('core.resume_torrent', torrents)

    def pause_torrent(self, torrents):
        self.client.call('core.pause_torrent', torrents)

    def set_torrent_max_download_speed(self, torrent, value):
        self.client.call('core.set_torrent_max_download_speed', torrent, value)

    def set_torrent_max_upload_speed(self, torrent, value):
        self.client.call('core.set_torrent_max_upload_speed', torrent, value)

    def get_session_status(self, key=''):
        return self.client.call('core.get_session_status', key)
client = DelugeRPCClient(
    host=settings.deluge["host"],
    port=int(settings.deluge["port"]),
    username=settings.deluge["user"],
    password=settings.deluge["pass"],
)
client.connect()

if client.connected:
    log.info("Successfully connected to Deluge")
else:
    log.error("Failed to connect to Deluge")
    sys.exit()

torrent_data = client.call("core.get_torrent_status", torrent_id, ["files", "label"])
torrent_files = torrent_data["files"]
category = torrent_data["label"].lower()

files = []
log.debug("List of files in torrent:")
for contents in torrent_files:
    files.append(contents["path"])
    log.debug(contents["path"])

if category.lower() not in categories:
    log.error("No valid category detected.")
    sys.exit()

if len(categories) != len(set(categories)):
    log.error("Duplicate category detected. Category names must be unique.")
Example #23
0
client = DelugeRPCClient(
    host=settings.deluge["host"],
    port=int(settings.deluge["port"]),
    username=settings.deluge["user"],
    password=settings.deluge["pass"],
)
client.connect()

if client.connected:
    log.info("Successfully connected to Deluge")
else:
    log.error("Failed to connect to Deluge")
    sys.exit()

torrent_data = client.call("core.get_torrent_status", torrent_id,
                           ["files", "label"])
torrent_files = torrent_data["files"]
category = torrent_data["label"].lower()

files = []
log.debug("List of files in torrent:")
for contents in torrent_files:
    files.append(contents["path"])
    log.debug(contents["path"])

if category.lower() not in categories:
    log.error("No valid category detected.")
    sys.exit()

if len(categories) != len(set(categories)):
    log.error("Duplicate category detected. Category names must be unique.")
Example #24
0
class DelugeHelper:
    client = None

    def __init__(self, ip, port, user, password):
        self.client = DelugeRPCClient(ip, int(port), user, password)
        self.client.connect()

    def add_torrent(self, magnetlink, download_location):
        torrent_id = self.client.call(
            'core.add_torrent_magnet', magnetlink, {
                'download_location': download_location,
                'prioritize_first_last_pieces': True,
                'sequential_download': True
            })
        time.sleep(2)
        torrent_name = str(
            self.client.call('core.get_torrent_status', torrent_id,
                             ['name']).get(b'name'), 'utf-8')
        return 'Torrent %s started' % torrent_name

    def delete_torrent(self, torrent_id):
        torrent_name = str(
            self.client.call('core.get_torrent_status', torrent_id,
                             ['name']).get(b'name'), 'utf-8')
        if self.client.call('core.remove_torrent', torrent_id, True):
            return 'Torrent %s was successfully deleted' % torrent_name
        else:
            return 'An error occurred while deleting %s' % torrent_name

    def get_torrents_to_delete(self):
        status_keys = ['name', 'total_size']
        results = self.client.call('core.get_torrents_status', {}, status_keys)
        message = 'Name - Size\n'
        for torrent_id, status in results.items():
            message += '%s - %s /del_%s \n' % (str(
                status.get(b'name'),
                'utf-8'), format_size(
                    status.get(b'total_size')), str(torrent_id).split("'")[1])
        return message

    def get_active_torrents(self):
        status_keys = [
            'name', 'download_payload_rate', 'progress', 'eta', 'total_size'
        ]
        results = self.client.call('core.get_torrents_status',
                                   {'state': 'Allocating'}, status_keys)
        results.update(
            self.client.call('core.get_torrents_status', {'state': 'Checking'},
                             status_keys))
        results.update(
            self.client.call('core.get_torrents_status',
                             {'state': 'Downloading'}, status_keys))
        results.update(
            self.client.call('core.get_torrents_status', {'state': 'Error'},
                             status_keys))
        results.update(
            self.client.call('core.get_torrents_status', {'state': 'Queued'},
                             status_keys))
        results.update(
            self.client.call('core.get_torrents_status', {'state': 'Moving'},
                             status_keys))
        message = 'Name - Downloading speed - Progress - ETA - Size\n'
        for torrent_id, status in results.items():
            message += '%s - %s - %.1f%% - %s - %s \n' % (
                str(status.get(b'name'), 'utf-8'),
                format_speed(status.get(b'download_payload_rate')),
                status.get(b'progress'), format_time(status.get(b'eta')),
                format_size(status.get(b'total_size')))
        return message

    def get_finished_torrents(self):
        status_keys = ['name', 'upload_payload_rate', 'progress', 'total_size']
        results = self.client.call('core.get_torrents_status',
                                   {'state': 'Seeding'}, status_keys)
        results.update(
            self.client.call('core.get_torrents_status', {'state': 'Paused'},
                             status_keys))
        message = 'Name - Uploading speed - Progress - Size\n'
        for torrent_id, status in results.items():
            message += '%s - %s - %.1f%% - %s \n' % (
                str(status.get(b'name'),
                    'utf-8'), format_speed(status.get(b'upload_payload_rate')),
                status.get(b'progress'), format_size(
                    status.get(b'total_size')))
        return message
Example #25
0
        'message': msg,
        'random_id': random
    })


try:
    while True:
        response = vk.method('messages.getConversations', values)
        if response['items']:
            item = response['items'][0]
            last_mess = item['last_message']
            random = last_mess['random_id']
            my_id = last_mess['peer_id']
            text = last_mess['text']
            try:
                client.call('core.add_torrent_url', text,
                            {'download_location': '/home/pi/Torrents'})
            except Exception:
                write_msg(my_id, 'Link doesn\'t work', random)
            else:
                write_msg(my_id, 'Download started!', random)
        time.sleep(1)
except KeyboardInterrupt:
    print('Keyboard interrupt detected.')
finally:
    print('Program was stopped.')

#
#(4) Импортируем класс DelugeRPCClient из библиотеки deluge_client .
#(14-18) Создаём объект client для подключения к серверу deluge-web. Указываем локальный IP-адрес, порт, логин и пароль.
#(21) Подключаемся к серверу.
#(40) Функция API core.add_torrent_url принимает URL на торрент-файл и ставит его в очередь на скачивание. Дополнительно передаём параметр download_location, чтобы сохранить совместимость с deluge-web и web-пультом в хранении файлов.
client = DelugeRPCClient(
    host=settings.deluge["host"],
    port=int(settings.deluge["port"]),
    username=settings.deluge["user"],
    password=settings.deluge["pass"],
)
client.connect()

if client.connected:
    log.info("Successfully connected to Deluge")
else:
    log.error("Failed to connect to Deluge")
    sys.exit()

torrent_data = client.call("core.get_torrent_status", torrent_id, ["files", "label"])
torrent_files = torrent_data["files"]
category = torrent_data["label"].lower()

files = []
log.debug("List of files in torrent:")
for contents in torrent_files:
    files.append(contents["path"])
    log.debug(contents["path"])

if category.lower() not in categories:
    log.error("No valid category detected.")
    sys.exit()

if len(categories) != len(set(categories)):
    log.error("Duplicate category detected. Category names must be unique.")
Example #27
0
class Deluge(object):
    def __init__(self, host):
        # Host
        self._host = host
        # RPC Client
        self._client = None
        # Torrent Properties Cache
        self._torrent_cache = {}
        # Cache Valid Time
        self._refresh_expire_time = 30
        # Last Time of Refreshing Cache
        self._last_refresh = 0

    # Login to Deluge
    def login(self, username, password):
        # Split IP(or domain name) and port
        splits = self._host.split(':')
        host = splits[0] if len(splits) > 0 else ''
        port = int(splits[1]) if len(splits) > 1 else DEFAULT_PORT

        # Create RPC client and connect to Deluge
        self._client = DelugeRPCClient(host,
                                       port,
                                       username,
                                       password,
                                       decode_utf8=True)
        try:
            self._client.connect()
        except DelugeClientException as e:
            # Display class name of the exception if there is no error messages
            raise LoginFailure(e.args[0].split('\n')[0]
                               if len(e.args) > 0 else e.__class__.__name__)

    # A caller to call deluge api; includes exception processing
    def _call(self, method, *args, **kwargs):
        try:
            return self._client.call(method, *args, **kwargs)
        except DelugeClientException as e:
            # Raise our own exception
            raise RemoteFailure(e.args[0].split('\n')[0]
                                if len(e.args) > 0 else e.__class__.__name__)

    # Get client status
    def client_status(self):
        cs = ClientStatus()

        # Set remote free space checker
        cs.free_space = self.remote_free_space

        # Get DL/UL information
        session_stats = self._call('core.get_session_status', [
            'payload_download_rate',
            'payload_upload_rate',
            'total_download',
            'total_upload',
        ])
        cs.download_speed = session_stats['payload_download_rate']
        cs.total_downloaded = session_stats['total_download']
        cs.upload_speed = session_stats['payload_upload_rate']
        cs.total_uploaded = session_stats['total_upload']

        # Get port status
        port_is_open = self._call('core.test_listen_port')
        cs.port_status = PortStatus.Open if port_is_open else PortStatus.Closed

        return cs

    # Get Deluge version
    def version(self):
        funcs = {
            1: 'daemon.info',  # For Deluge 1.x, use daemon.info
            2: 'daemon.get_version',  # For Deluge 2.x, use daemon.get_version
        }
        ver = self._call(funcs[self._client.deluge_version])
        return ('Deluge %s' % ver)

    # Get API version
    def api_version(self):
        # Returns the protocol version
        return self._client.deluge_protocol_version if self._client.deluge_protocol_version is not None else 'not provided'

    # Get torrent list
    def torrents_list(self):
        # Save hashes
        torrents_hash = []
        # Get torrent list (and their properties)
        torrent_list = self._call(
            'core.get_torrents_status',
            {},
            [
                'active_time',
                'all_time_download',
                'download_payload_rate',
                'finished_time',
                'hash',
                'label',  # Available when the plugin 'label' is enabled
                'name',
                'num_peers',
                'num_seeds',
                'progress',
                'ratio',
                'seeding_time',
                'state',
                'time_added',
                'time_since_transfer',
                'total_peers',
                'total_seeds',
                'total_size',
                'total_uploaded',
                'trackers',
                'upload_payload_rate',
            ])
        # Save properties to cache
        self._torrent_cache = torrent_list
        self._last_refresh = time.time()
        # Return torrent hashes
        for h in torrent_list:
            torrents_hash.append(h)
        return torrents_hash

    # Get Torrent Properties
    def torrent_properties(self, torrent_hash):
        # Check cache expiration
        if time.time() - self._last_refresh > self._refresh_expire_time:
            self.torrents_list()
        # Extract properties
        torrent = self._torrent_cache[torrent_hash]
        # Create torrent object
        torrent_obj = Torrent()
        torrent_obj.hash = torrent['hash']
        torrent_obj.name = torrent['name']
        if 'label' in torrent:
            torrent_obj.category = [torrent['label']
                                    ] if len(torrent['label']) > 0 else []
        torrent_obj.tracker = [
            tracker['url'] for tracker in torrent['trackers']
        ]
        torrent_obj.status = Deluge._judge_status(torrent['state'])
        torrent_obj.size = torrent['total_size']
        torrent_obj.ratio = torrent['ratio']
        torrent_obj.uploaded = torrent['total_uploaded']
        torrent_obj.downloaded = torrent['all_time_download']
        torrent_obj.create_time = int(torrent['time_added'])
        torrent_obj.seeding_time = torrent['seeding_time']
        torrent_obj.upload_speed = torrent['upload_payload_rate']
        torrent_obj.download_speed = torrent['download_payload_rate']
        torrent_obj.seeder = torrent['total_seeds']
        torrent_obj.connected_seeder = torrent['num_seeds']
        torrent_obj.leecher = torrent['total_peers']
        torrent_obj.connected_leecher = torrent['num_peers']
        torrent_obj.average_upload_speed = torrent['total_uploaded'] / torrent[
            'active_time'] if torrent['active_time'] > 0 else 0
        if 'finished_time' in torrent:
            download_time = torrent['active_time'] - torrent['finished_time']
            torrent_obj.average_download_speed = torrent[
                'all_time_download'] / download_time if download_time > 0 else 0
        if 'time_since_transfer' in torrent:
            # Set the last active time of those never active torrents to timestamp 0
            torrent_obj.last_activity = torrent[
                'time_since_transfer'] if torrent[
                    'time_since_transfer'] > 0 else 0
        torrent_obj.progress = torrent['progress'] / 100  # Accept Range: 0-1

        return torrent_obj

    # Get free space
    def remote_free_space(self, path):
        return self._call('core.get_free_space', path)

    # Judge Torrent Status
    @staticmethod
    def _judge_status(state):
        return {
            'Allocating': TorrentStatus.Unknown,  # Ignore this state
            'Checking': TorrentStatus.Checking,
            'Downloading': TorrentStatus.Downloading,
            'Error': TorrentStatus.Error,
            'Moving': TorrentStatus.Unknown,  # Ignore this state
            'Paused': TorrentStatus.Paused,
            'Queued': TorrentStatus.Queued,
            'Seeding': TorrentStatus.Uploading,
        }[state]

    # Batch Remove Torrents
    def remove_torrents(self, torrent_hash_list, remove_data):
        if self._client.deluge_version >= 2:  # Method 'core.remove_torrents' is only available in Deluge 2.x
            failures = self._call('core.remove_torrents', torrent_hash_list,
                                  remove_data)
            failed_hash = [torrent[0] for torrent in failures]
            return (
                [
                    torrent for torrent in torrent_hash_list
                    if torrent not in failed_hash
                ],
                [{
                    'hash': torrent[0],
                    'reason': torrent[1],
                } for torrent in failures],
            )
        else:  # For Deluge 1.x, remove torrents one by one
            success_hash = []
            failures = []
            for torrent in torrent_hash_list:
                try:
                    self._call('core.remove_torrent', torrent, remove_data)
                    success_hash.append(torrent)
                except RemoteFailure as e:
                    failures.append({
                        'hash': torrent,
                        'reason': e.args[0],
                    })
            return (success_hash, failures)
delete_dir = None

log.debug("Path: %s." % path)
log.debug("Torrent: %s." % torrent_name)
log.debug("Hash: %s." % torrent_id)

client = DelugeRPCClient(host=settings.deluge['host'], port=int(settings.deluge['port']), username=settings.deluge['user'], password=settings.deluge['pass'])
client.connect()

if client.connected:
    log.info("Successfully connected to Deluge")
else:
    log.error("Failed to connect to Deluge")
    sys.exit()

torrent_data = client.call('core.get_torrent_status', torrent_id, ['files', 'label'])
torrent_files = torrent_data['files']
category = torrent_data['label'].lower()

files = []
log.debug("List of files in torrent:")
for contents in torrent_files:
    files.append(contents['path'])
    log.debug(contents['path'])

if category.lower() not in categories:
    log.error("No valid category detected.")
    sys.exit()

if len(categories) != len(set(categories)):
    log.error("Duplicate category detected. Category names must be unique.")
Example #29
0
class Deluge(IntervalModule):
    """
    Deluge torrent module
    Requires `deluge-client`

    .. rubric:: Formatters:

    * `{num_torrents}`       - number of torrents in deluge
    * `{free_space_bytes}`   - bytes free in path
    * `{used_space_bytes}`   - bytes used in path
    * `{upload_rate}` - bytes sent per second
    * `{download_rate}` - bytes received per second
    * `{total_uploaded}`     - bytes sent total
    * `{total_downloaded}`     - bytes received total

    """

    settings = (
        'format',
        ('rounding', 'number of decimal places to round numbers too'),
        ('host', 'address of deluge server (default: 127.0.0.1)'),
        ('port', 'port of deluge server (default: 58846)'),
        ('username', 'username to authenticate with deluge'),
        ('password', 'password to authenticate to deluge'),
        ('path', 'override "download path" server-side when checking space used/free'),
        ('offline_string', 'string to output while unable to connect to deluge daemon')
    )
    required = ('username', 'password')

    host = '127.0.0.1'
    port = 58846
    path = None
    libtorrent_stats = False
    rounding = 2
    offline_string = 'offline'

    format = '⛆{num_torrents} ✇{free_space_bytes}'

    id = int(time.time())  # something random

    def init(self):
        self.client = DelugeRPCClient(self.host, self.port, self.username, self.password)
        self.data = {}

    def run(self):
        if not self.client.connected:
            try:
                self.client.connect()
            except OSError:
                self.output = {
                    'full_text': self.offline_string
                }
                return

        try:
            self.data = self.get_session_statistics()

            torrents = self.get_torrents_status()
            if torrents:
                self.data['num_torrents'] = len(torrents)

            if 'free_space_bytes' in self.format:
                self.data['free_space_bytes'] = self.get_free_space(self.path)
            if 'used_space_bytes' in self.format:
                self.data['used_space_bytes'] = self.get_path_size(self.path)
        except FailedToReconnectException:
            return

        self.parse_values(self.data)

        self.output = {
            'full_text': self.format.format(**self.data)
        }

    def parse_values(self, values):
        for k, v in values.items():
            if v:
                if k in ['total_upload', 'total_download', 'download_rate', 'upload_rate'] or k.endswith('_bytes'):
                    values[k] = '{value:.{round}f}{unit}'.format(round=self.rounding, **bytes_info_dict(v))

    def get_path_size(self, path=None):
        """
        get used space of path in bytes (default: download location)
        """
        if path is None:
            path = []
        return self.client.call('core.get_path_size', path)

    def get_free_space(self, path=None):
        """
        get free space of path in bytes (default: download location)
        """
        if path is None:
            path = []
        return self.client.call('core.get_free_space', path)

    def get_torrents_status(self, torrent_id=None, keys=None):
        if torrent_id is None:
            torrent_id = []
        if keys is None:
            keys = []
        return self.client.call('core.get_torrents_status', torrent_id, keys)

    def get_session_statistics(self):
        keys = ['upload_rate', 'download_rate', 'total_upload', 'total_download']

        out = {}  # some of the values from deluge-client are bytes, the others are ints - we need to decode them
        for k, v in self.client.call('core.get_session_status', keys).items():
            k = k.decode('utf-8')  # keys aswell
            if type(v) == bytes:
                out[k] = v.decode('utf-8')
            else:
                out[k] = v

        return out
Example #30
0
class TorrentClient(object):
    def __init__(self):
        self.conn = None

    def connect(self, host, username, password):
        if self.conn is not None:
            return self.connect

        if not host:
            return False

        # Get port from the config
        host, portnr = host.split(':')

        #if username and password:
        # logger.info('Connecting to ' + host + ':' + portnr + ' Username: '******' Password: '******'Could not create DelugeRPCClient Object' + e)
            return False
        else:
            try:
                self.client.connect()
            except Exception as e:
                logger.error('Could not connect to Deluge ' + host)
            else:
                return self.client

    def find_torrent(self, hash):
        logger.debug('Finding Torrent hash: ' + hash)
        torrent_info = self.get_torrent(hash)
        if torrent_info:
            return True
        else:
            return False

    def get_torrent(self, hash):
        logger.debug('Getting Torrent info hash: ' + hash)
        try:
            torrent_info = self.client.call('core.get_torrent_status', hash,
                                            '')
        except Exception as e:
            logger.error('Could not get torrent info for ' + hash)
            return False
        else:
            logger.info('Getting Torrent Info!')
            return torrent_info

    def start_torrent(self, hash):
        try:
            self.find_torrent(hash)
        except Exception as e:
            return False
        else:
            try:
                self.client.call('core.resume_torrent', hash)
            except Exception as e:
                logger.error('Torrent failed to start ' + e)
            else:
                logger.info('Torrent ' + hash + ' was started')
                return True

    def stop_torrent(self, hash):
        try:
            self.client.find_torrent(hash)
        except Exception as e:
            logger.error('Torrent Not Found')
            return False
        else:
            try:
                self.client.call('core.pause_torrent', hash)
            except Exception as e:
                logger.error('Torrent failed to be stopped: ' + e)
                return false
            else:
                logger.info('Torrent ' + hash + ' was stopped')
                return True

    def load_torrent(self, filepath):

        logger.info('filepath to torrent file set to : ' + filepath)
        torrent_id = False

        if self.client.connected is True:
            logger.info('Checking if Torrent Exists!')

            torrentcontent = open(filepath, 'rb').read()
            hash = str.lower(self.get_the_hash(
                filepath))  # Deluge expects a lower case hash

            logger.debug('Torrent Hash (load_torrent): "' + hash + '"')
            logger.debug('FileName (load_torrent): ' +
                         str(os.path.basename(filepath)))

            #Check if torrent already added
            if self.find_torrent(str.lower(hash)):
                logger.info('load_torrent: Torrent already exists!')
                #should set something here to denote that it's already loaded, and then the failed download checker not run so it doesn't download
                #multiple copies of the same issues that's already downloaded
            else:
                logger.info('Torrent not added yet, trying to add it now!')
                try:
                    torrent_id = self.client.call(
                        'core.add_torrent_file',
                        str(os.path.basename(filepath)),
                        base64.encodestring(torrentcontent), '')
                except Exception as e:
                    logger.debug('Torrent not added')
                    return False
                else:
                    logger.debug('TorrentID: ' + torrent_id)

                # If label enabled put label on torrent in Deluge
                if torrent_id and mylar.DELUGE_LABEL:
                    logger.info('Setting label to ' + mylar.DELUGE_LABEL)
                    try:
                        self.client.call('label.set_torrent', torrent_id,
                                         mylar.DELUGE_LABEL)
                    except:
                        #if label isn't set, let's try and create one.
                        try:
                            self.client.call('label.add', mylar.DELUGE_LABEL)
                            self.client.call('label.set_torrent', torrent_id,
                                             mylar.DELUGE_LABEL)
                        except:
                            logger.warn(
                                'Unable to set label - Either try to create it manually within Deluge, and/or ensure there are no spaces, capitalization or special characters in label'
                            )
                            return torrent_id  #False
                    logger.info('Succesfully set label to ' +
                                mylar.DELUGE_LABEL)

        try:
            self.find_torrent(torrent_id)
            logger.info('Double checking torrent was added.')
        except Exception as e:
            logger.warn('Torrent was not added! Please check logs')
            return False
        else:
            logger.info('Torrent successfully added!')
            return torrent_id  #True

    def delete_torrent(self, hash, removeData=False):
        try:
            self.client.find_torrent(hash)
        except Exception as e:
            logger.error('Torrent ' + hash + ' does not exist')
            return False
        else:
            try:
                self.client.call('core.remote_torrent', hash, removeData)
            except Exception as e:
                logger.error('Unable to delete torrent ' + hash)
                return False
            else:
                logger.info('Torrent deleted ' + hash)
                return True

    def get_the_hash(self, filepath):
        import hashlib, StringIO
        from mylar import bencode

        # Open torrent file
        torrent_file = open(filepath, "rb")
        metainfo = bencode.bdecode(torrent_file.read())
        info = metainfo['info']
        thehash = hashlib.sha1(bencode.bencode(info)).hexdigest().upper()
        logger.debug('Hash: ' + thehash)
        return thehash
Example #31
0
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&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<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
Example #32
0
class Deluge:
    def _mkdtemp(self):
        cache_path = cherrypy.config['opmuse'].get('cache.path')
        dir = os.path.join(cache_path, 'deluge')

        if not os.path.exists(dir):
            os.mkdir(dir)

        return tempfile.mkdtemp(dir=dir)

    def connect(self, timeout=20):
        config = cherrypy.tree.apps[''].config['opmuse']

        if 'deluge.host' not in config:
            log('Deluge not configured, skipping')
            return False

        host = config['deluge.host']
        port = config['deluge.port']
        user = config['deluge.user']
        password = config['deluge.password']

        DelugeRPCClient.timeout = timeout
        self.client = DelugeRPCClient(host, port, user, password)

        try:
            self.client.connect()
        except OSError as e:
            if e.errno == 113: # "No route to host"
                log('No route to host: %s' % host)
                return False
            else:
                raise e

        return self.client.connected

    def update_torrents(self):
        torrents = self.client.call('core.get_torrents_status', {},
                                    ['name', 'files', 'save_path', 'time_added',
                                     'total_size', 'paused', 'is_finished', 'progress'])

        all_torrents = set()

        for torrent_id, in get_database().query(Torrent.torrent_id).all():
            all_torrents.add(torrent_id)

        for torrent_id, data in torrents.items():
            torrent_id = torrent_id.decode('utf-8')

            if torrent_id in all_torrents:
                all_torrents.remove(torrent_id)
                torrent = get_database().query(Torrent).filter(Torrent.torrent_id == torrent_id).one()
            else:
                torrent = Torrent()

            for file in data[b'files']:
                if Library.is_supported(file[b'path']):
                    has_supported_files = True
                    break
            else:
                has_supported_files = False

            torrent.torrent_id = torrent_id
            torrent.name = data[b'name'].decode('utf-8')
            torrent.has_supported_files = has_supported_files
            torrent.added = datetime.datetime.fromtimestamp(data[b'time_added'])
            torrent.size = data[b'total_size']
            torrent.paused = data[b'paused']
            torrent.finished = data[b'is_finished']
            torrent.progress = data[b'progress']

            get_database().add(torrent)
            get_database().commit()

        if len(all_torrents) > 0:
            (get_database().query(Torrent).filter(Torrent.torrent_id.in_(all_torrents))
                .delete(synchronize_session='fetch'))

        get_database().commit()

    def import_torrent(self, torrent_id):
        config = cherrypy.tree.apps[''].config['opmuse']
        ssh_host = config['deluge.ssh_host']

        if ssh_host is None:
            raise Exception('You need to set deluge.ssh_host')

        debug('fetching torrent %s info' % torrent_id)
        torrent = self.client.call('core.get_torrent_status', torrent_id, [])

        filelist_fd, filelist_path = tempfile.mkstemp()

        files = []

        tempdir = self._mkdtemp().encode()

        with os.fdopen(filelist_fd, 'bw') as f:
            for file in torrent[b'files']:
                path = os.path.join(torrent[b'save_path'], file[b'path'])
                f.write(path + b"\n")
                files.append(os.path.join(tempdir, path[1:]))

        try:
            debug('rsync torrent %s from %s' % (torrent_id, ssh_host))
            output = subprocess.check_output([
                'rsync',
                '-a',
                '-e', 'ssh -oBatchMode=yes -oVisualHostKey=no',
                '--files-from=%s' % filelist_path,
                '%s:/' % ssh_host,
                tempdir
            ], stderr=subprocess.STDOUT)
        except CalledProcessError as error:
            log('Failed to rsync', traceback=True)
            shutil.rmtree(tempdir)
            raise Exception(error.output.decode())
        except Exception:
            log('Failed to rsync', traceback=True)
            shutil.rmtree(tempdir)
            raise
        finally:
            os.remove(filelist_path)

        debug('done rsyncing torrent %s' % torrent_id)

        return files
delete_dir = None

log.debug("Path: %s." % path)
log.debug("Torrent: %s." % torrent_name)
log.debug("Hash: %s." % torrent_id)

client = DelugeRPCClient(host=settings.deluge['host'], port=int(settings.deluge['port']), username=settings.deluge['user'], password=settings.deluge['pass'])
client.connect()

if client.connected:
    log.info("Successfully connected to Deluge")
else:
    log.error("Failed to connect to Deluge")
    sys.exit()

torrent_data = client.call('core.get_torrent_status', torrent_id, ['files', 'label'])
torrent_files = torrent_data['files']
category = torrent_data['label'].lower()

files = []
log.debug("List of files in torrent:")
for contents in torrent_files:
    files.append(contents['path'])
    log.debug(contents['path'])

if category.lower() not in categories:
    log.error("No valid category detected.")
    sys.exit()

if len(categories) != len(set(categories)):
    log.error("Duplicate category detected. Category names must be unique.")
def main(torrent_id, torrent_name, save_path): 
    file_extensions = ['r\d+', 'rar', 'zip']
    client = DelugeRPCClient(cfg.deluge_address, cfg.deluge_port, cfg.deluge_user, cfg.deluge_pass)
    client.connect()

    print("Starting '%s' with id='%s' at %s" % (torrent_name, torrent_id, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
    
    if not client.connected:
        print("Error connecting to deluge")
        sys.exit()
    
    #pprint.pprint(client.call('core.get_torrents_status', {}, ['name']))
    #pprint.pprint(client.call('core.get_torrent_status', torrent_id, ['files']))
    #print("|".join(file_extensions))
    
    try:
        torrent_file = client.call('core.get_torrent_status', torrent_id, ['files'])['files']
    except:
        print("Error matching torrent_id in deluge")
        sys.exit()
    
    neither_radarr_sonarr = True
    search = False
    for file in torrent_file:
        search = re.search("(" + "|".join(file_extensions) + ")$", file['path'])
        search = search.group() if search else None
        if search:
            print("Torrent contained unwanted file type:")
            print("\t" + file['path'] + "\t" + str(search))
    
            sonarr_item = search_sonarr_for_torrent_name(torrent_name)

            if not sonarr_item:
                radarr_item = search_radarr_for_torrent_name(torrent_name)

                if not radarr_item:
                    print("Torrent not found in radarr or sonarr")
                    break
                else:
                    neither_radarr_sonarr = False

            # Blacklist in sonarr
            
            if radarr_item:
                id = radarr_item['id']
                sonarr_radarr_target = delete_from_radarr
                print("\tSending to radarr background thread.")

            if sonarr_item:
                id = sonarr_item['id']
                sonarr_radarr_target = delete_from_sonarr
                print("\tSending to sonarr background thread.")

            thread = Thread(target = sonarr_radarr_target, args = (id, ))
            thread.start()
            thread.join()
            break
    
    if (not search) and (neither_radarr_sonarr):
        # Torrent is okay, lets start the download.
         print("Torrent is okay, un-pausing download. Neither radar or sonarr == %s" % (neither_radarr_sonarr))
         client.call('core.resume_torrent', [torrent_id])
    else:
        if sonarr_item:
            print("Requesting sonarr searches for the eppisode again")
            url = "http://%s:%s/sonarr/api/command?apikey=%s" % (sonarr_host, sonarr_port, cfg.sonarr_apikey)
        elif radarr_item:
            print("Requesting radarr searches for the eppisode again")
            url = "http://%s:%s/radarr/api/command?apikey=%s" % (radarr_host, radarr_port, cfg.radarr_apikey)
        else:
            print("Neither sonar or radarr... exiting...")
            sys.exit(0)
    
        data={"name": "EpisodeSearch", "episodeIds": [sonarr_item['episode']['id']]}
        #pprint.pprint(data)
        time.sleep(90)
        d = requests.post(url, json=data)
        print("\t'" + url + "', response=" + str(d.status_code) + "\r\n")
    
    print("____________________________________________\r\n")
Example #35
0
class DelugeClient(object):
    def __init__(self, host, port, username, password):
        """
        Initializes a new Deluge client.
        
        url - The url where deluge json can be reached.
        password - The password used to login
        """
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.rpcclient = DelugeRPCClient(self.host, self.port, self.username, self.password)
    
    def _login(self):
        """
        Logs into deluge
        """
        if not self.rpcclient.connected:
            self.rpcclient.connect()
    
    def test_connection(self):
        """
        Tests the Deluge RPC connection, returns message if found.
        """
        self._login()
        return 'Free space: %s' % humanize_bytes(self.rpcclient.call('core.get_free_space'))
    
    def get_torrents(self):
        """
        Returns a set of info hashes currently added to the client.
        """
        logger.info('Getting a list of torrent hashes')
        self._login()
        result = self.rpcclient.call('core.get_torrents_status', {}, ['name'])
        return set(x.lower() for x in result.keys())
    
    def add_torrent(self, torrent, destination_path, files, fast_resume=True):
        """
        Add a new torrent to Deluge.
        
        torrent is the decoded file as a python object.
        destination_path is where the links are. The complete files must be linked already.
        files is a list of files found in the torrent.
        """
        name = torrent[b'info'][b'name']
        logger.info('Trying to add a new torrent to deluge: %r' % name)
        
        destination_path = os.path.abspath(destination_path)
        
        infohash = hashlib.sha1(bencode(torrent[b'info'])).hexdigest()
        encoded_torrent = base64.b64encode(bencode(torrent))
        
        basename = os.path.basename(destination_path)
        mapped_files = {}
        for i, f in enumerate(files):
            mapped_files[i] = os.path.join(basename, *f['path'])
        
        self._login()
        result = self.rpcclient.call('core.add_torrent_file', 'torrent.torrent', encoded_torrent, {
                                                                'download_location': os.path.dirname(destination_path),
                                                                'mapped_files': mapped_files})
        
        return result and result.decode('utf-8') == infohash
tID = sys.argv[1]
dHost = "127.0.0.1"
dPort = 58846
dUser = "******"
dPass = "******"

client = DelugeRPCClient(dHost,dPort,dUser,dPass)
client.connect()
while client.connected == False:
        time.sleep(3)
        client = DelugeRPCClient(dHost,dPort,dUser,dPass)
        client.connect()

time.sleep(3)
tData = client.call('core.get_torrent_status',tID,{})
print(tData)
while tData[b'state'] == b'Downloading' or tData[b'state'] == b'Paused':
#         if len(tData[b'peers']) < 1:
        if len(tData[b'peers']) < 1 or len(tData[b'num_seeds']) == 0:
                client.call('core.pause_torrent',tID)
                time.sleep(3)
                client.call('core.resume_torrent',tID)
                time.sleep(2)
                client.call('core.force_reannounce',[tID])
                time.sleep(3)
                tData = client.call('core.get_torrent_status',tID,{})
        else:
                exit()
exit()
Example #37
0
    async def on_message(self, message):

        if message.author == self.user:
            return

        text = message.content.strip()

        if message.channel.id == authentication_channel and message.author.id == authentication_user:
            if text == "!stop":
                await sys.exit(1)
            if text == "!clear":
                global queued_requests
                queued_requests = {}
            if text in queued_requests:
                request = queued_requests[text]
                await self.send_request(request)
                await message.channel.send(f"Request approved: {text}")
                await request.requester_channel.send(
                    f"The request for '{request.name}' has been approved!")
                del queued_requests[text]
            else:
                await message.channel.send("That uuid doesn't exist...")

        if not message.guild.name in active_servers:
            return

        if not message.channel.name in active_channels:
            return

        if text.lower().startswith("!add"):
            add_regex = "!add\nmagnet: *(magnet:\?[^ ]*)\nchannel: *([\w\d ]*)\nname: *([\w\d ]*)"
            regex = re.compile(add_regex, re.I | re.M)
            groups = regex.match(text)

            if groups is None:
                await message.channel.send(
                    "Not a valid '!add' command! Use '!help' if you are confused."
                )
                return
            magnet = groups.group(1).strip()
            channel = groups.group(2).strip()
            name = groups.group(3).strip()
            requester_name = message.author.name + message.author.discriminator

            if channel.lower() in plex_channels:
                channel = plex_channels[channel.lower()]
            else:
                await message.channel.send(
                    f"That's not a valid channel on plex! Please choose one of {plex_channels.values()}"
                )
                return

            request = Request(magnet, channel, name, requester_name,
                              message.channel)
            request_uuid = str(uuid.uuid4())
            queued_requests[request_uuid] = request

            auth_channel = self.get_channel(authentication_channel)
            await auth_channel.send(
                f"Request submitted:  {request}\n\n ID: {request_uuid}")
            await message.channel.send(
                f"Your request has been submitted, and is pending approval")

        elif text.lower().startswith("!status"):
            requester_name = message.author.name + message.author.discriminator
            now = time.time()
            then = now - 24 * 60 * 60

            with TinyDB('db') as db:
                request = Query()
                torrents = db.search((request.requester_name == requester_name)
                                     & (request.time > then))

            status_string = f"Here's the status for all the approved torrents requested by {requester_name} in the last 24 hours:\n"
            conn = DelugeClient('master.seedhost.eu', 21110,
                                os.environ['DELUGE_USER'],
                                os.environ['DELUGE_PASS'])
            conn.connect()

            for torrent in torrents:
                torrent_name = torrent['torrent_name']
                torrent_id = torrent['torrent_id']

                status = conn.call('core.get_torrent_status', torrent_id,
                                   ['state', 'total_done', 'total_wanted'])
                if not b'state' in status:
                    continue
                state = status[b'state'].decode()
                total_done = status[b'total_done']
                total_wanted = status[b'total_wanted']
                status_string += "{:<35} {:>15}% completed\n".format(
                    torrent_name, int(total_done / total_wanted * 100))

            await message.channel.send(status_string)

        elif text.lower().startswith("!"):
            help_text_1 = \
            "This is a simple bot that will let you download torrents onto the Plex server, without having harass me " \
            "a ton. Right now, there are only 3 commands:\n" \
            "!add : Allows you to add torrents to the server. Usage is detailed below.\n" \
            "!status : Shows you the download status of all of the approved torrents you requested in the  " \
            "last 24 hours\n" \
            "!help : Shows this message!\n" \
            "\n" \
            "To use !add, you need to provide a information in a specific format. The three pieces of information " \
            "that you will need to provide are: 1) the magnet link to the desired torrent, 2) the plex channel that " \
            "you want the torrent to show up on (so, one of: TV, Movies, Weeb TV), and 3) the name of the media you're " \
            "downloading. This must be provided in a message the follows the given format: \n" \
            "\n" \
            "!add\n" \
            "magnet: <magnet link>\n" \
            "channel: <plex channel>\n" \
            "name: <name of thing>\n" \
            "\n" \
            "So, an example of a valid request would be:\n" \
            "\n" \
            "!add\n" \
            "magnet: magnet:?xt=urn:btih:52FD58172C296021F2E351B8A12BBC8BE7C88F8D&dn=Batman+Begins+%282005%29+1080p+BluRay+x264+-+1.6GB+-+YIFY&tr=udp%3A%2F%2Ftracker.yify-torrents.com%2Fannounce&tr=http%3A%2F%2Finferno.demonoid.me%3A3414%2Fannounce&tr=http%3A%2F%2Ftracker.yify-torrents.com%2Fannounce&tr=udp%3A%2F%2Ftracker.1337x.org%3A80%2Fannounce&tr=http%3A%2F%2Fexodus.desync.com%2Fannounce&tr=http%3A%2F%2Ft1.pow7.com%2Fannounce&tr=http%3A%2F%2Fexodus.desync.com%2Fannounce&tr=http%3A%2F%2Feztv.tracker.prq.to%2Fannounce&tr=http%3A%2F%2Fpow7.com%2Fannounce&tr=http%3A%2F%2Ftracker.torrent.to%3A2710%2Fannounce&tr=udp%3A%2F%2Ftracker.zer0day.to%3A1337%2Fannounce&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969%2Fannounce&tr=udp%3A%2F%2Fcoppersurfer.tk%3A6969%2Fannounce\n" \
            "channel: Movies\n" \
            "name: Batman Begins\n"

            help_text_2 = \
            "\nNote that this command will not immediately download the torrent. Instead, it will send me a message, " \
            "asking me if I think it's a responsible request. If I approve it, this bot will update this channel to " \
            "let you know its been approved. Only approved torrents will show up in !status.\n" \
            "\n" \
            "Last thing-- I literally wrote this in a couple of hours, and its not meant tp be super robust (yet!). " \
            "I will be continually improving and updating this bot, and I know that there are a few potential bugs, " \
            "as well as a bunch of features I wanna add, so if you hit any issues, just lemme know."

            await message.channel.send(help_text_1)
            await message.channel.send(help_text_2)
Example #38
0
class DelugeClientKORPI():
    """
    Class for controlling deluge client.
    """

    def __init__(self, username, password, host="127.0.0.1", port=58846):
        self._username = username
        self._password = password
        self._host = host
        self._port = port

        self.__client = DelugeRPCClient(host, int(port), username, password)

    def connect(self):
        self.__client.connect()

    def list(self):
        """Returns tuple with torrent hashes"""
        return self.__client.call("core.get_session_state")

    def status(self, thash=None):
        if thash:
            return self.__client.call('core.get_torrents_status', {"hash": thash}, [])
        else:
            return self.__client.call('core.get_torrents_status', {}, [])

    def completed(self, thash):
        """Returns % of downloaded from torrent."""
        status = self.__client.call('core.get_torrents_status', {"hash": thash}, [])

        thash = thash.encode("utf-8")
        if status[thash][b"total_wanted"] == 0:
            return 0
        else:
            return status[thash][b"total_done"] / status[thash][b"total_wanted"] * 100

    def pause(self, thash=None):
        """
        If hash not provided, pause/resume all torrents.
        Returns False if torrent(s) was paused, True otherwise.
        """
        if thash:
            status = self.status(thash)[thash.encode("utf-8")][b"paused"]
            if status:
                self.__client.call('core.resume_torrent', [thash])
            else:
                self.__client.call('core.pause_torrent', [thash])

            return status
        else:
            if self.all_paused():
                self.__client.call("core.resume_torrent", self.list())
            else:
                self.__client.call("core.pause_torrent", self.list())

            return self.all_paused()

    def add(self, magnet, directory, max_speed):
        return self.__client.call('core.add_torrent_magnet', magnet, 
            {"download_location": directory, "max_download_speed": max_speed})

    def remove(self, thash, with_files):
        """Set with_files True to remove with files"""
        if with_files == "True": with_files = True
        elif with_files == "False": with_files = False

        return self.__client.call("core.remove_torrent", thash, with_files)

    def free_space(self, directory):
        """Get free space in megabytes."""
        return self.__client.call("core.get_free_space", directory) * TO_GB

    def download_speed(self, dmax=-1):
        for thash in self.list():
            self.__client.call("core.set_torrent_max_download_speed", 
                                thash, int(dmax))

    def all_paused(self):
        return all(paused[b"paused"]
                   for _, paused in self.status().items())
Example #39
0
def add_torrent(magnet_url):
    from deluge_client import DelugeRPCClient
    client = DelugeRPCClient('127.0.0.1', 2196, "seftembr", "TuGsFYqlNP")
    client.connect()
    result = client.call('core.add_torrent_magnet', magnet_url, {})
    print "Returned hash:", result
Example #40
0
log.debug("Torrent: %s." % torrent_name)
log.debug("Hash: %s." % torrent_id)

client = DelugeRPCClient(host=settings.deluge['host'],
                         port=int(settings.deluge['port']),
                         username=settings.deluge['user'],
                         password=settings.deluge['pass'])
client.connect()

if client.connected:
    log.info("Successfully connected to Deluge")
else:
    log.error("Failed to connect to Deluge")
    sys.exit()

torrent_data = client.call('core.get_torrent_status', torrent_id,
                           ['files', 'label'])
torrent_files = torrent_data['files']
category = torrent_data['label'].lower()

files = []
log.debug("List of files in torrent:")
for contents in torrent_files:
    files.append(contents['path'])
    log.debug(contents['path'])

if category.lower() not in categories:
    log.error("No valid category detected.")
    sys.exit()

if len(categories) != len(set(categories)):
    log.error("Duplicate category detected. Category names must be unique.")
Example #41
0

def get_movie(my_call, search_lst):
    for item, var in my_call.items():
        search_me = str(var[b'name'], 'utf-8')
        new_srch = PTN.parse(search_me.lower())
        if 'episode' in new_srch and 'season' in new_srch:
            continue
        choice = process.extractOne(new_srch['title'], search_lst)
        if choice[1] > 95:
            print(choice)
            print(item, var)


paramiko.util.log_to_file('/tmp/paramiko.log')

transport = paramiko.Transport(("dragoncave8.ddns.net", 1889))
transport.connect(None, "retsu", "dragon1991!")

sftp = paramiko.SFTPClient.from_transport(transport)
movies = sftp.listdir("/mnt/Media/Movies")
search_lst = [PTN.parse(item.lower())['title'] for item in movies]

client = DelugeRPCClient('perses.feralhosting.com', 53305, 'retsu8',
                         'yf-AXshN8_FjXTZA')
client.connect()
my_call = client.call('core.get_torrents_status', {}, ['name', 'ratio'])

if transport is not None:
    transport.close()
Example #42
0
log.debug("Torrent: %s." % torrent_name)
log.debug("Hash: %s." % torrent_id)

client = DelugeRPCClient(host=settings.deluge['host'],
                         port=int(settings.deluge['port']),
                         username=settings.deluge['user'],
                         password=settings.deluge['pass'])
client.connect()

if client.connected:
    log.info("Successfully connected to Deluge")
else:
    log.error("Failed to connect to Deluge")
    sys.exit()

torrent_data = client.call('core.get_torrent_status', torrent_id,
                           ['files', 'label'])
torrent_files = torrent_data['files']
category = torrent_data['label'].lower()

files = []
log.debug("List of files in torrent:")
for contents in torrent_files:
    files.append(contents['path'])
    log.debug(contents['path'])

if category.lower() not in categories:
    log.error("No valid category detected.")
    sys.exit()

if len(categories) != len(set(categories)):
    log.error("Duplicate category detected. Category names must be unique.")
Example #43
0
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
Example #44
0
username='******' # Se puede ver en home/.config/deluge/auth . Este es de level 10 = admin
password='******' # Se puede ver en home/.config/deluge/auth

client = DelugeRPCClient(servidor, puerto, username, password)
client.connect()

if client.connected: 
	print "Conectado a " +servidor+':'+str(puerto)

if len(sys.argv) > 1:

	if sys.argv[1] == '-add':

		if sys.argv[2] == '-magnet':
			uri = sys.argv[3]
			client.call('core.add_torrent_magnet', uri,{})
		elif sys.argv[2] == '-torrent':
			uri = sys.argv[3]
			# TODO
		else:
			print 'Error: Algo no va bien...'

	elif sys.argv[1] == '-s':
		status = client.call('core.get_torrents_status', {}, [])

		if sys.argv > 2:
			if sys.argv[2] == '-list':
				print 'Num. de Torrents: '+ str(len(status))
				c=0
				for i in status.values():
					c+=1			
Example #45
0
class TorrentUtils:
    client = None
    methods = []
    torrents = []

    def __init__(self, username='******', password='******', host='127.0.0.1', port=58846):
        self.checkDelugeExist()
        if username and password:
            self.client = DelugeRPCClient(host, port, username, password)
            try:
                self.client.connect()
            except ConnectionRefusedError:
                pass
            self.checkConnection()
            self.getMethods()
            self.getTorrents()

    def checkConnection(self):
        if not self.client or not self.client.connected:
            globalUtils.messageHandler('Torrent daemon not connected', tp='err')
            exit()

    @staticmethod
    def checkDelugeExist():
        if not which('deluge') or not which('deluged'):
            globalUtils.messageHandler('Deluge or Deluged daemon not installed', tp='err')
            exit()

    def getMethods(self) -> list:
        self.methods = self.client.call('daemon.get_method_list')
        return self.methods

    def getTorrents(self, fields: list = [], filters: dict = {}) -> list:
        self.torrents = self.client.call('core.get_torrents_status', filters, fields)
        return self.torrents

    def addTorrent(self, path: Union[str, Path]) -> Union[str, bool]:
        try:
            torrent = Torrent.from_file(path)
        except BencodeDecodingError:
            return False
        torrentId = torrent.info_hash
        if not self.checkTorrentExist(torrent.info_hash):
            fileEncoded = globalUtils.readFile(path)
            torrentId = self.client.call('core.add_torrent_file', '', fileEncoded, {
                'sequential_download': True,
                'prioritize_first_last': True})
            globalUtils.messageHandler(self.getTorrentName(path), '+ Download', tp='msg')
            return torrentId
        globalUtils.messageHandler(self.getTorrentName(path), 'Exist', tp='err')
        self.resumeTorrent(torrentId)
        return torrentId

    def stopTorrent(self, torrentHash: str):
        self.client.call('core.pause_torrent', [torrentHash])

    def resumeTorrent(self, torrentHash: str):
        self.client.call('core.resume_torrent', [torrentHash])

    def setTorrentOptions(self, torrentId: list, options: dict):
        self.client.call('core.set_torrent_options', [torrentId], options)

    def addPlugin(self, path: Union[str, Path]):
        fileEncoded = globalUtils.readFile(path)
        fileName = Path(path).name
        self.client.call('core.upload_plugin', fileName, fileEncoded)

    def checkTorrentExist(self, torrentHash):
        if type(torrentHash) != bytes:
            torrentHash = torrentHash.encode('UTF-8')
        return bool(torrentHash in self.torrents)

    @staticmethod
    def saveTorrentFile(torrentUrl, fileName):
        torrentData = requests.get(torrentUrl).content
        path = globalUtils.saveFile(torrentData, fileName, 'torrentFiles')
        return path

    @staticmethod
    def deleteTorrentFile(fileName):
        globalUtils.deleteFile(fileName, 'torrentFiles')

    @staticmethod
    def getTorrentName(torrent: Union[str, Path]):
        return Torrent.from_file(torrent).name

    @staticmethod
    def getSavedTorrentFiles():
        files = Path('torrentFiles').glob('*.torrent')
        filesList = []
        for f in files:
            filesList.append(str(f))
        return filesList