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.
This commit is contained in:
@@ -22,13 +22,14 @@ from twisted.python.procutils import which
|
||||
|
||||
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 @@ if not EXTRACT_COMMANDS:
|
||||
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 @@ class Core(CorePluginBase):
|
||||
"""
|
||||
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'])
|
||||
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)
|
||||
# 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
|
||||
# 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]
|
||||
)
|
||||
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
|
||||
|
||||
# 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):
|
||||
|
||||
@@ -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
|
||||
});
|
||||
|
||||
@@ -100,7 +100,51 @@
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_labels">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Enter labels to extract (comma-separated, leave blank for all)</property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry_labels">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Enter one or more labels to extract, separated by commas. Leave to extract any archive found.</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label1">
|
||||
|
||||
@@ -69,7 +69,8 @@ class GtkUI(Gtk3PluginBase):
|
||||
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 @@ class GtkUI(Gtk3PluginBase):
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user