From ad8049b89a53802e27e0d697dacf0085f662e1aa Mon Sep 17 00:00:00 2001 From: d8ahazard Date: Fri, 25 Oct 2019 11:52:23 -0500 Subject: [PATCH] Add option to only extract specific labels Add UI element for a comma-separated list of labels to extract by. Should work with both Label and LabelPlus plugins. If no filter is specified, it will extract anything. --- setup.py | 2 +- simpleextractor/core.py | 188 ++++++++++++------ simpleextractor/data/simpleextractor.js | 19 ++ simpleextractor/data/simpleextractor_prefs.ui | 44 ++++ simpleextractor/gtkui.py | 4 +- 5 files changed, 193 insertions(+), 64 deletions(-) diff --git a/setup.py b/setup.py index 1509d99..cc1e292 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ __plugin_name__ = 'SimpleExtractor' __author__ = 'Digitalhigh' __author_email__ = 'donate.to.digitalhigh@gmail.com' -__version__ = '0.8' +__version__ = '0.9' __url__ = 'github.com/d8ahazard/deluge-extractor' __license__ = 'GPLv3' __description__ = 'Extract files upon torrent completion' diff --git a/simpleextractor/core.py b/simpleextractor/core.py index 66a9a66..3a377d0 100644 --- a/simpleextractor/core.py +++ b/simpleextractor/core.py @@ -22,13 +22,14 @@ import deluge.component as component import deluge.configmanager +from deluge.configmanager import ConfigManager from deluge.common import windows_check from deluge.core.rpcserver import export from deluge.plugins.pluginbase import CorePluginBase log = logging.getLogger(__name__) -DEFAULT_PREFS = {'extract_path': '', 'use_name_folder': False, 'in_place_extraction': True} +DEFAULT_PREFS = {'extract_path': '', 'use_name_folder': False, 'in_place_extraction': True, 'extract_labels': ''} if windows_check(): win_7z_exes = [ @@ -101,7 +102,7 @@ class Core(CorePluginBase): def enable(self): self.config = deluge.configmanager.ConfigManager( - 'extractor.conf', DEFAULT_PREFS + 'simpleextractor.conf', DEFAULT_PREFS ) if not self.config['extract_path']: self.config['extract_path'] = deluge.configmanager.ConfigManager( @@ -125,69 +126,132 @@ def _on_torrent_finished(self, torrent_id): """ tid = component.get('TorrentManager').torrents[torrent_id] tid_status = tid.get_status(['download_location', 'name']) + tstatus = tid.get_status([], False, False, True) + do_extract = False + log.info("Processing completed torrent %s", tstatus) + # Fetch our torrent's label + labels = self.get_labels(torrent_id) + log.info("Schmancy label collector: %s", labels) + # If we've set a label filter, process it + if self.config['extract_labels'] is not "": + log.info("We should filter by label(s): %s", self.config['extract_labels']) + # Make sure there's actually a label + if len(labels) > 0: + for label in labels: + log.info("Label for torrent is %s", label) + # Check if it's more than one, split + if "," in self.config['extract_labels']: + log.info("And we have a list") + label_list = self.config['extract_labels'].split(",") + # And loop + for label in label_list: + if label.strip() == label: + log.info("This matches") + do_extract = True + break + # Otherwise, just check the whole string + else: + log.info("Single label string detected.") + if self.config['extract_labels'].strip() == label: + log.info("This matches") + do_extract = True + # We don't need to do this, but it adds sanity + else: + log.info("We have a label filter and no label, doing nothing") + do_extract = False + # Otherwise, we just extract everything + else: + log.info("No label, extracting.") + do_extract = True - files = tid.get_files() - for f in files: - log.debug("Handling file %s", f['path']) - file_root, file_ext = os.path.splitext(f['path']) - file_ext_sec = os.path.splitext(file_root)[1] - if file_ext_sec and file_ext_sec + file_ext in EXTRACT_COMMANDS: - file_ext = file_ext_sec + file_ext - elif file_ext not in EXTRACT_COMMANDS or file_ext_sec == '.tar': - log.debug('Cannot extract file with unknown file type: %s', f['path']) - continue - elif file_ext == '.rar' and 'part' in file_ext_sec: - part_num = file_ext_sec.split('part')[1] - if part_num.isdigit() and int(part_num) != 1: - log.debug('Skipping remaining multi-part rar files: %s', f['path']) + # Now, extract if filter match or no filter set + if do_extract: + files = tid.get_files() + for f in files: + log.info("Handling file %s", f['path']) + file_root, file_ext = os.path.splitext(f['path']) + file_ext_sec = os.path.splitext(file_root)[1] + if file_ext_sec and file_ext_sec + file_ext in EXTRACT_COMMANDS: + file_ext = file_ext_sec + file_ext + elif file_ext not in EXTRACT_COMMANDS or file_ext_sec == '.tar': + log.info('Cannot extract file with unknown file type: %s', f['path']) continue + elif file_ext == '.rar' and 'part' in file_ext_sec: + part_num = file_ext_sec.split('part')[1] + if part_num.isdigit() and int(part_num) != 1: + log.info('Skipping remaining multi-part rar files: %s', f['path']) + continue + + cmd = EXTRACT_COMMANDS[file_ext] + fpath = os.path.join( + tid_status['download_location'], os.path.normpath(f['path']) + ) + dest = os.path.normpath(self.config['extract_path']) + if self.config['use_name_folder']: + dest = os.path.join(dest, tid_status['name']) + + # Override destination if in_place_extraction is set + if self.config["in_place_extraction"]: + name = tid_status["name"] + save_path = tid_status["download_location"] + dest = os.path.join(save_path, name) + log.info("Save path is %s, dest is %s, fpath is %s", save_path, dest, fpath) + + # Create the destination folder if it doesn't exist + if not os.path.exists(dest): + try: + os.makedirs(dest) + except OSError as ex: + if not (ex.errno == errno.EEXIST and os.path.isdir(dest)): + log.error('Error creating destination folder: %s', ex) + break + + def on_extract(result, torrent_id, fpath): + # Check command exit code. + if not result[2]: + log.info('Extract successful: %s (%s)', fpath, torrent_id) + else: + log.error( + 'Extract failed: %s (%s) %s', fpath, torrent_id, result[1] + ) + + # Run the command and add callback. + log.info( + 'Extracting %s from %s with %s %s to %s', + fpath, + torrent_id, + cmd[0], + cmd[1], + dest, + ) + d = getProcessOutputAndValue( + cmd[0], cmd[1].split() + [str(fpath)], os.environ, str(dest) + ) + d.addCallback(on_extract, torrent_id, fpath) + + def get_labels(self, torrent_id): + """ + Asking the system about the labels isn't very cool, so try this instead + """ + labels = [] + label_config = ConfigManager('label.conf', defaults=False) + if label_config is not False: + log.info("We have a Label config") + if 'torrent_labels' in label_config: + if torrent_id in label_config['torrent_labels']: + log.info("Data from Label plugin: %s", label_config['torrent_labels'][torrent_id]) + labels.append(label_config['torrent_labels'][torrent_id]) + + label_plus_config = ConfigManager('labelplus.conf', defaults=False) + if label_plus_config is not False: + log.info("We have a label plus config") + if 'mappings' in label_plus_config: + if torrent_id in label_plus_config['mappings']: + mapping = label_plus_config['mappings'][torrent_id] + log.info("We have a label plus mapping: %s", mapping) + labels.append(label_plus_config['labels'][mapping]['name']) + return labels - cmd = EXTRACT_COMMANDS[file_ext] - fpath = os.path.join( - tid_status['download_location'], os.path.normpath(f['path']) - ) - dest = os.path.normpath(self.config['extract_path']) - if self.config['use_name_folder']: - dest = os.path.join(dest, tid_status['name']) - - # Override destination if in_place_extraction is set - if self.config["in_place_extraction"]: - name = tid_status["name"] - save_path = tid_status["download_location"] - dest = os.path.join(save_path, name) - log.debug("Save path is %s, dest is %s, fpath is %s", save_path, dest, fpath) - - # Create the destination folder if it doesn't exist - if not os.path.exists(dest): - try: - os.makedirs(dest) - except OSError as ex: - if not (ex.errno == errno.EEXIST and os.path.isdir(dest)): - log.error('Error creating destination folder: %s', ex) - break - - def on_extract(result, torrent_id, fpath): - # Check command exit code. - if not result[2]: - log.info('Extract successful: %s (%s)', fpath, torrent_id) - else: - log.error( - 'Extract failed: %s (%s) %s', fpath, torrent_id, result[1] - ) - - # Run the command and add callback. - log.debug( - 'Extracting %s from %s with %s %s to %s', - fpath, - torrent_id, - cmd[0], - cmd[1], - dest, - ) - d = getProcessOutputAndValue( - cmd[0], cmd[1].split() + [str(fpath)], os.environ, str(dest) - ) - d.addCallback(on_extract, torrent_id, fpath) @export def set_config(self, config): diff --git a/simpleextractor/data/simpleextractor.js b/simpleextractor/data/simpleextractor.js index a105ba2..471b65a 100644 --- a/simpleextractor/data/simpleextractor.js +++ b/simpleextractor/data/simpleextractor.js @@ -66,6 +66,23 @@ Deluge.ux.preferences.SimpleExtractorPage = Ext.extend(Ext.Panel, { boxLabel: _('Extract torrent in-place') }); + fieldset2 = this.form.add({ + xtype: 'fieldset', + border: false, + title: '', + autoHeight: true, + labelAlign: 'top', + labelWidth: 80, + defaultType: 'textfield' + }); + + this.extract_labels = fieldset.add({ + fieldLabel: _('Label Filter:'), + labelSeparator : '', + name: 'extract_labels', + width: '97%' + }); + this.on('show', this.updateConfig, this); }, @@ -76,6 +93,7 @@ Deluge.ux.preferences.SimpleExtractorPage = Ext.extend(Ext.Panel, { config['extract_path'] = this.extract_path.getValue(); config['use_name_folder'] = this.use_name_folder.getValue(); config['in_place_extraction'] = this.in_place_extraction.getValue(); + config['extract_labels'] = this.extract_labels.getValue(); deluge.client.simpleextractor.set_config(config); }, @@ -90,6 +108,7 @@ Deluge.ux.preferences.SimpleExtractorPage = Ext.extend(Ext.Panel, { this.extract_path.setValue(config['extract_path']); this.use_name_folder.setValue(config['use_name_folder']); this.in_place_extraction.setValue(config['in_place_extraction']); + this.extract_labels.setValue(config['extract_labels']); }, scope: this }); diff --git a/simpleextractor/data/simpleextractor_prefs.ui b/simpleextractor/data/simpleextractor_prefs.ui index 6f34b44..4cf1bf7 100644 --- a/simpleextractor/data/simpleextractor_prefs.ui +++ b/simpleextractor/data/simpleextractor_prefs.ui @@ -100,7 +100,51 @@ 1 + + + True + False + 5 + + + True + False + Enter labels to extract (comma-separated, leave blank for all) + True + + + True + True + 0 + + + + + True + True + False + Enter one or more labels to extract, separated by commas. Leave to extract any archive found. + True + + + False + False + 1 + + + + + True + True + 0 + + + + True + True + 2 + diff --git a/simpleextractor/gtkui.py b/simpleextractor/gtkui.py index 691f233..a47f0c6 100644 --- a/simpleextractor/gtkui.py +++ b/simpleextractor/gtkui.py @@ -69,7 +69,8 @@ def on_apply_prefs(self): config = { 'extract_path': path, 'use_name_folder': self.builder.get_object('chk_use_name').get_active(), - 'in_place_extraction': self.builder.get_object("chk_in_place_extraction").get_active() + 'in_place_extraction': self.builder.get_object("chk_in_place_extraction").get_active(), + 'extract_labels': self.builder.get_object("entry_labels").get_text() } client.extractor.set_config(config) @@ -94,5 +95,6 @@ def on_get_config(config): config['use_name_folder'] ) self.builder.get_object('chk_in_place_extraction').set_active(config['in_place_extraction']) + self.builder.get_object('entry_labels').set_text(config['extract_labels']) client.extractor.get_config().addCallback(on_get_config)