Skip to content

Commit

Permalink
Add option to only extract specific labels
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
d8ahazard committed Oct 25, 2019
1 parent 739a933 commit ad8049b
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 64 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
__plugin_name__ = 'SimpleExtractor'
__author__ = 'Digitalhigh'
__author_email__ = '[email protected]'
__version__ = '0.8'
__version__ = '0.9'
__url__ = 'github.com/d8ahazard/deluge-extractor'
__license__ = 'GPLv3'
__description__ = 'Extract files upon torrent completion'
Expand Down
188 changes: 126 additions & 62 deletions simpleextractor/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down Expand Up @@ -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(
Expand All @@ -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):
Expand Down
19 changes: 19 additions & 0 deletions simpleextractor/data/simpleextractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
},

Expand All @@ -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);
},
Expand All @@ -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
});
Expand Down
44 changes: 44 additions & 0 deletions simpleextractor/data/simpleextractor_prefs.ui
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down
4 changes: 3 additions & 1 deletion simpleextractor/gtkui.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)

0 comments on commit ad8049b

Please sign in to comment.