Cleanup and Fixes and Inplace - Oh My
Add option to extract all archives to torrent root, destination folder, or true in-place. Add sonarr/radarr support (marks torrent "incomplete" until extraction is done). Bundle 7z.exe for windows users. Fix GTK UI not working...at all. Improve web and GTK UI so they're uniform, have radio buttons, etc.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -73,3 +73,4 @@ docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
/venv*
|
||||
|
||||
BIN
deluge_simpleextractor/7z.dll
Normal file
BIN
deluge_simpleextractor/7z.dll
Normal file
Binary file not shown.
BIN
deluge_simpleextractor/7z.exe
Normal file
BIN
deluge_simpleextractor/7z.exe
Normal file
Binary file not shown.
@@ -20,4 +20,4 @@ from pkg_resources import resource_filename
|
||||
|
||||
|
||||
def get_resource(filename):
|
||||
return resource_filename("simpleextractor", os.path.join('data', filename))
|
||||
return resource_filename(__package__, os.path.join('data', filename))
|
||||
@@ -29,7 +29,11 @@ from deluge.plugins.pluginbase import CorePluginBase
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_PREFS = {'extract_path': '', 'use_name_folder': False, 'in_place_extraction': True, 'extract_labels': ''}
|
||||
DEFAULT_PREFS = {'extract_path': '',
|
||||
'extract_in_place': False,
|
||||
'extract_selected_folder': False,
|
||||
'extract_torrent_root': True,
|
||||
'label_filter': ''}
|
||||
|
||||
if windows_check():
|
||||
win_7z_exes = [
|
||||
@@ -38,20 +42,6 @@ if windows_check():
|
||||
'C:\\Program Files (x86)\\7-Zip\\7z.exe',
|
||||
]
|
||||
|
||||
try:
|
||||
import winreg
|
||||
except ImportError:
|
||||
import _winreg as winreg # For Python 2.
|
||||
|
||||
try:
|
||||
hkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Software\\7-Zip')
|
||||
except WindowsError:
|
||||
pass
|
||||
else:
|
||||
win_7z_path = os.path.join(winreg.QueryValueEx(hkey, 'Path')[0], '7z.exe')
|
||||
winreg.CloseKey(hkey)
|
||||
win_7z_exes.insert(1, win_7z_path)
|
||||
|
||||
switch_7z = 'x -y'
|
||||
# Future suport:
|
||||
# 7-zip cannot extract tar.* with single command.
|
||||
@@ -128,12 +118,16 @@ class Core(CorePluginBase):
|
||||
tid_status = tid.get_status(['download_location', 'name'])
|
||||
tstatus = tid.get_status([], False, False, True)
|
||||
do_extract = False
|
||||
tid = component.get("TorrentManager").torrents[torrent_id]
|
||||
tid_status = tid.get_status(["save_path", "name"])
|
||||
|
||||
tid.is_finished = 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 "":
|
||||
if self.config['label_filter'] 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:
|
||||
@@ -165,6 +159,9 @@ class Core(CorePluginBase):
|
||||
do_extract = True
|
||||
|
||||
# Now, extract if filter match or no filter set
|
||||
extract_in_place = self.config["extract_in_place"]
|
||||
extract_torrent_root = self.config["extract_torrent_root"]
|
||||
|
||||
if do_extract:
|
||||
files = tid.get_files()
|
||||
for f in files:
|
||||
@@ -183,28 +180,29 @@ class Core(CorePluginBase):
|
||||
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'])
|
||||
|
||||
# Get the destination path
|
||||
dest = os.path.normpath(self.config["extract_path"])
|
||||
name_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)
|
||||
if extract_torrent_root:
|
||||
dest = tid_status["save_path"]
|
||||
name_dest = os.path.join(dest, tid_status["name"])
|
||||
|
||||
# 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
|
||||
if extract_in_place and ((not os.path.exists(name_dest)) or os.path.isdir(name_dest)):
|
||||
dest = name_dest
|
||||
|
||||
try:
|
||||
os.makedirs(dest)
|
||||
except OSError as ex:
|
||||
if not (ex.errno == errno.EEXIST and os.path.isdir(dest)):
|
||||
log.error("EXTRACTOR: Error creating destination folder: %s", ex)
|
||||
break
|
||||
|
||||
def on_extract(result, torrent_id, fpath):
|
||||
# Check command exit code.
|
||||
@@ -228,6 +226,7 @@ class Core(CorePluginBase):
|
||||
cmd[0], cmd[1].split() + [str(fpath)], os.environ, str(dest)
|
||||
)
|
||||
d.addCallback(on_extract, torrent_id, fpath)
|
||||
tid.is_finished = True
|
||||
|
||||
def get_labels(self, torrent_id):
|
||||
"""
|
||||
178
deluge_simpleextractor/data/simpleextractor.js
Normal file
178
deluge_simpleextractor/data/simpleextractor.js
Normal file
@@ -0,0 +1,178 @@
|
||||
/*!
|
||||
* simpleextractor.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2010 <damoxc@gmail.com>
|
||||
* Copyright (C) Digitalhigh 2019 <donate.to.digitalhigh@gmail.com>
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
Ext.ns('Deluge.ux.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.ux.preferences.SimpleExtractorPage
|
||||
* @extends Ext.Panel
|
||||
*/
|
||||
Deluge.ux.preferences.SimpleExtractorPage = Ext.extend(Ext.Panel, {
|
||||
|
||||
title: _('SimpleExtractor'),
|
||||
layout: 'fit',
|
||||
border: false,
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.ux.preferences.SimpleExtractorPage.superclass.initComponent.call(this);
|
||||
|
||||
this.form = this.add({
|
||||
xtype: 'form',
|
||||
layout: 'form',
|
||||
border: false,
|
||||
autoHeight: true
|
||||
});
|
||||
|
||||
|
||||
this.behaviorSet = this.form.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
title: '',
|
||||
autoHeight: true,
|
||||
labelAlign: 'top',
|
||||
labelWidth: 80,
|
||||
defaultType: 'textfield'
|
||||
});
|
||||
|
||||
this.behaviorSet.add({
|
||||
xtype: 'label',
|
||||
fieldLabel: _('<b>Extract Behavior:</b></br>'),
|
||||
labelSeparator : '',
|
||||
name: '',
|
||||
width: '97%'
|
||||
});
|
||||
|
||||
// Behavior Label
|
||||
|
||||
// Add radio group for extract behavior
|
||||
this.extractBehavior = this.behaviorSet.add({
|
||||
xtype: 'radiogroup',
|
||||
columns: 1,
|
||||
colspan: 2,
|
||||
style: 'margin-left: 10px',
|
||||
items: [
|
||||
{
|
||||
boxLabel: _('Selected Folder'),
|
||||
name: 'extract_behavior',
|
||||
inputValue: "extract_selected_folder"
|
||||
},
|
||||
{
|
||||
boxLabel: _('Torrent Root'),
|
||||
name: 'extract_behavior',
|
||||
inputValue: "extract_torrent_root"
|
||||
},
|
||||
{
|
||||
boxLabel: _('In-Place'),
|
||||
name: 'extract_behavior',
|
||||
inputValue: "extract_in_place"
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
this.destinationSet = this.form.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
title: '',
|
||||
autoHeight: true,
|
||||
labelAlign: 'top',
|
||||
labelWidth: 80,
|
||||
defaultType: 'textfield'
|
||||
});
|
||||
|
||||
// Destination label
|
||||
this.extractPath = this.destinationSet.add({
|
||||
fieldLabel: _('<b>Destination:</b></br>'),
|
||||
name: 'extract_path',
|
||||
labelSeparator : '',
|
||||
width: '97%'
|
||||
});
|
||||
|
||||
|
||||
this.labelSet = this.form.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
title: '',
|
||||
autoHeight: true,
|
||||
labelAlign: 'top',
|
||||
labelWidth: 80,
|
||||
defaultType: 'textfield'
|
||||
});
|
||||
|
||||
// Label Filter Label
|
||||
this.labelFilter = this.labelSet.add({
|
||||
fieldLabel: _('<b>Label Filtering:</b></br>'),
|
||||
name: 'label_filter',
|
||||
labelSeparator : '',
|
||||
width: '97%'
|
||||
});
|
||||
|
||||
this.labelSet.add({
|
||||
xtype: 'label',
|
||||
fieldLabel: _('</br>Comma-separated, leave blank for none.'),
|
||||
labelSeparator : '',
|
||||
name: '',
|
||||
width: '97%'
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
this.on('show', this.updateConfig, this);
|
||||
},
|
||||
|
||||
onApply: function() {
|
||||
// build settings object
|
||||
var config = {};
|
||||
config['extract_path'] = this.extractPath.getValue();
|
||||
var eBehavior = this.extractBehavior.getValue();
|
||||
config['extract_in_place'] = false;
|
||||
config['extract_torrent_root'] = false;
|
||||
config['extract_selected_folder'] = false;
|
||||
config[eBehavior] = true;
|
||||
config['label_filter'] = this.labelFilter.getValue();
|
||||
|
||||
deluge.client.simpleextractor.set_config(config);
|
||||
},
|
||||
|
||||
onOk: function() {
|
||||
this.onApply();
|
||||
},
|
||||
|
||||
updateConfig: function() {
|
||||
deluge.client.simpleextractor.get_config({
|
||||
success: function(config) {
|
||||
this.extractPath.setValue(config['extract_path']);
|
||||
var behavior = "extract_selected_folder";
|
||||
if (config['extract_in_place']) {
|
||||
behavior = 'extract_in_place';
|
||||
}
|
||||
if (config['extract_torrent_root']) {
|
||||
behavior = 'extract_torrent_root';
|
||||
}
|
||||
this.extractBehavior.setValue(behavior);
|
||||
this.labelFilter.setValue(config['label_filter']);
|
||||
},
|
||||
scope: this
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Deluge.plugins.SimpleExtractorPlugin = Ext.extend(Deluge.Plugin, {
|
||||
name: 'SimpleExtractor',
|
||||
onDisable: function() {
|
||||
deluge.preferences.removePage(this.prefsPage);
|
||||
},
|
||||
|
||||
onEnable: function() {
|
||||
this.prefsPage = deluge.preferences.addPage(new Deluge.ux.preferences.SimpleExtractorPage());
|
||||
}
|
||||
});
|
||||
Deluge.registerPlugin('SimpleExtractor', Deluge.plugins.SimpleExtractorPlugin);
|
||||
221
deluge_simpleextractor/data/simpleextractor_prefs.ui
Normal file
221
deluge_simpleextractor/data/simpleextractor_prefs.ui
Normal file
@@ -0,0 +1,221 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.10 -->
|
||||
<object class="GtkWindow" id="window1">
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="extractor_prefs_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="label_yalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="extract_behavior">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="extract_selected_folder">
|
||||
<property name="label" translatable="yes">Selected Folder</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">All torrents will be extracted to the selected folder below.</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">extract_torrent_root</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="extract_torrent_root">
|
||||
<property name="label" translatable="yes">Torrent Root</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Any found archives will be extracted to the root of the torrent directory.</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="extract_in_place">
|
||||
<property name="label" translatable="yes">In-Place</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Found archives will be extracted where they are found.</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">extract_torrent_root</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>Extract Behavior:</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="destination_path">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkFileChooserButton" id="folderchooser_path">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="action">select-folder</property>
|
||||
<property name="title" translatable="yes">Select A Folder</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="extract_path">
|
||||
<property name="can_focus">True</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>Destination:</b>
|
||||
</property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="label_filter">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Enter one or more labels to extract, separated by commas. Leave to extract any archive found.</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<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">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>Label Filtering:</b>
|
||||
</property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
97
deluge_simpleextractor/gtkui.py
Normal file
97
deluge_simpleextractor/gtkui.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# Basic plugin template created by:
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com>
|
||||
# Copyright (C) 2019-2020 Digitalhigh <donate.to.digitalhigh@gmail.com>
|
||||
#
|
||||
#
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
|
||||
import gi # isort:skip (Required before Gtk import).
|
||||
|
||||
gi.require_version('Gtk', '3.0') # NOQA: E402
|
||||
|
||||
# isort:imports-thirdparty
|
||||
from gi.repository import Gtk
|
||||
|
||||
# isort:imports-firstparty
|
||||
import deluge.component as component
|
||||
from deluge.plugins.pluginbase import Gtk3PluginBase
|
||||
from deluge.ui.client import client
|
||||
|
||||
# isort:imports-localfolder
|
||||
from .common import get_resource
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GtkUI(Gtk3PluginBase):
|
||||
def enable(self):
|
||||
self.plugin = component.get('PluginManager')
|
||||
self.builder = Gtk.Builder()
|
||||
self.builder.add_from_file(get_resource('simpleextractor_prefs.ui'))
|
||||
|
||||
component.get('Preferences').add_page(
|
||||
_('Simple Extractor'), self.builder.get_object('extractor_prefs_box')
|
||||
)
|
||||
|
||||
self.plugin.register_hook('on_apply_prefs', self.on_apply_prefs)
|
||||
self.plugin.register_hook('on_show_prefs', self.on_show_prefs)
|
||||
self.on_show_prefs()
|
||||
|
||||
def disable(self):
|
||||
component.get('Preferences').remove_page(_('Simple Extractor'))
|
||||
self.plugin.deregister_hook(
|
||||
'on_apply_prefs', self.on_apply_prefs
|
||||
)
|
||||
self.plugin.deregister_hook(
|
||||
'on_show_prefs', self.on_show_prefs
|
||||
)
|
||||
del self.builder
|
||||
|
||||
def on_apply_prefs(self):
|
||||
log.debug('applying prefs for Simple Extractor')
|
||||
if client.is_localhost():
|
||||
path = self.builder.get_object('folderchooser_path').get_filename()
|
||||
else:
|
||||
path = self.builder.get_object('extract_path').get_text()
|
||||
|
||||
config = {
|
||||
'extract_path': path,
|
||||
'extract_selected_folder': self.builder.get_object("extract_selected_folder").get_active(),
|
||||
'extract_in_place': self.builder.get_object("extract_in_place").get_active(),
|
||||
'extract_torrent_root': self.builder.get_object("extract_torrent_root").get_active(),
|
||||
'label_filter': self.builder.get_object("label_filter").get_text()
|
||||
}
|
||||
|
||||
client.simpleextractor.set_config(config)
|
||||
|
||||
def on_show_prefs(self):
|
||||
def on_get_config(config):
|
||||
if client.is_localhost():
|
||||
self.builder.get_object('folderchooser_path').set_current_folder(config['extract_path'])
|
||||
self.builder.get_object('folderchooser_path').show()
|
||||
self.builder.get_object('extract_path').hide()
|
||||
else:
|
||||
self.builder.get_object('extract_path').set_text(config['extract_path'])
|
||||
self.builder.get_object('folderchooser_path').hide()
|
||||
self.builder.get_object('extract_path').show()
|
||||
|
||||
self.builder.get_object('extract_selected_folder').set_active(
|
||||
config['extract_selected_folder']
|
||||
)
|
||||
self.builder.get_object('extract_torrent_root').set_active(
|
||||
config['extract_torrent_root']
|
||||
)
|
||||
self.builder.get_object('extract_in_place').set_active(
|
||||
config['extract_in_place']
|
||||
)
|
||||
self.builder.get_object('label_filter').set_text(config['label_filter'])
|
||||
|
||||
client.simpleextractor.get_config().addCallback(on_get_config)
|
||||
15
setup.py
15
setup.py
@@ -16,7 +16,7 @@ from setuptools import find_packages, setup
|
||||
__plugin_name__ = 'SimpleExtractor'
|
||||
__author__ = 'Digitalhigh'
|
||||
__author_email__ = 'donate.to.digitalhigh@gmail.com'
|
||||
__version__ = '1.0'
|
||||
__version__ = '1.1'
|
||||
__url__ = 'github.com/d8ahazard/deluge-extractor'
|
||||
__license__ = 'GPLv3'
|
||||
__description__ = 'Extract files upon torrent completion'
|
||||
@@ -30,7 +30,7 @@ Windows support: .rar, .zip, .tar, .7z, .xz, .lzma
|
||||
|
||||
Note: Will not extract with 'Move Completed' enabled
|
||||
"""
|
||||
__pkg_data__ = {__plugin_name__.lower(): ['template/*', 'data/*']}
|
||||
__pkg_data__ = {'deluge_' + __plugin_name__.lower(): ['data/*', '7z.dll', '7z.exe']}
|
||||
|
||||
setup(
|
||||
name=__plugin_name__,
|
||||
@@ -40,16 +40,17 @@ setup(
|
||||
author_email=__author_email__,
|
||||
url=__url__,
|
||||
license=__license__,
|
||||
long_description=__long_description__ if __long_description__ else __description__,
|
||||
packages=[__plugin_name__.lower()],
|
||||
zip_safe=False,
|
||||
long_description=__long_description__,
|
||||
packages=find_packages(),
|
||||
package_data=__pkg_data__,
|
||||
entry_points="""
|
||||
[deluge.plugin.core]
|
||||
%s = %s:CorePlugin
|
||||
%s = deluge_%s:CorePlugin
|
||||
[deluge.plugin.gtk3ui]
|
||||
%s = %s:GtkUIPlugin
|
||||
%s = deluge_%s:GtkUIPlugin
|
||||
[deluge.plugin.web]
|
||||
%s = %s:WebUIPlugin
|
||||
%s = deluge_%s:WebUIPlugin
|
||||
"""
|
||||
% ((__plugin_name__, __plugin_name__.lower()) * 3),
|
||||
)
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
/*!
|
||||
* simpleextractor.js
|
||||
*
|
||||
* Copyright (c) Damien Churchill 2010 <damoxc@gmail.com>
|
||||
* Copyright (C) Digitalhigh 2019 <donate.to.digitalhigh@gmail.com>
|
||||
*
|
||||
* This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
|
||||
* the additional special exception to link portions of this program with the OpenSSL library.
|
||||
* See LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
Ext.ns('Deluge.ux.preferences');
|
||||
|
||||
/**
|
||||
* @class Deluge.ux.preferences.SimpleExtractorPage
|
||||
* @extends Ext.Panel
|
||||
*/
|
||||
Deluge.ux.preferences.SimpleExtractorPage = Ext.extend(Ext.Panel, {
|
||||
|
||||
title: _('SimpleExtractor'),
|
||||
layout: 'fit',
|
||||
border: false,
|
||||
|
||||
initComponent: function() {
|
||||
Deluge.ux.preferences.SimpleExtractorPage.superclass.initComponent.call(this);
|
||||
|
||||
this.form = this.add({
|
||||
xtype: 'form',
|
||||
layout: 'form',
|
||||
border: false,
|
||||
autoHeight: true
|
||||
});
|
||||
|
||||
fieldset = this.form.add({
|
||||
xtype: 'fieldset',
|
||||
border: false,
|
||||
title: '',
|
||||
autoHeight: true,
|
||||
labelAlign: 'top',
|
||||
labelWidth: 80,
|
||||
defaultType: 'textfield'
|
||||
});
|
||||
|
||||
this.extract_path = fieldset.add({
|
||||
fieldLabel: _('Extract to:'),
|
||||
labelSeparator : '',
|
||||
name: 'extract_path',
|
||||
width: '97%'
|
||||
});
|
||||
|
||||
|
||||
this.use_name_folder = fieldset.add({
|
||||
xtype: 'checkbox',
|
||||
name: 'use_name_folder',
|
||||
height: 22,
|
||||
hideLabel: true,
|
||||
boxLabel: _('Create torrent name sub-folder')
|
||||
});
|
||||
|
||||
this.in_place_extraction = fieldset.add({
|
||||
xtype: 'checkbox',
|
||||
name: 'in_place_extraction',
|
||||
height: 22,
|
||||
hideLabel: true,
|
||||
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);
|
||||
},
|
||||
|
||||
onApply: function() {
|
||||
// build settings object
|
||||
var config = { }
|
||||
|
||||
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);
|
||||
},
|
||||
|
||||
onOk: function() {
|
||||
this.onApply();
|
||||
},
|
||||
|
||||
updateConfig: function() {
|
||||
deluge.client.simpleextractor.get_config({
|
||||
success: function(config) {
|
||||
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
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Deluge.plugins.SimpleExtractorPlugin = Ext.extend(Deluge.Plugin, {
|
||||
|
||||
name: 'SimpleExtractor',
|
||||
|
||||
onDisable: function() {
|
||||
deluge.preferences.removePage(this.prefsPage);
|
||||
},
|
||||
|
||||
onEnable: function() {
|
||||
this.prefsPage = deluge.preferences.addPage(new Deluge.ux.preferences.SimpleExtractorPage());
|
||||
}
|
||||
});
|
||||
Deluge.registerPlugin('SimpleExtractor', Deluge.plugins.SimpleExtractorPlugin);
|
||||
@@ -1,167 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.0"/>
|
||||
<object class="GtkWindow" id="window1">
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="extractor_prefs_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Extract to:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkFileChooserButton" id="folderchooser_path">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="action">select-folder</property>
|
||||
<property name="title" translatable="yes">Select A Folder</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_path">
|
||||
<property name="can_focus">True</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="chk_use_name">
|
||||
<property name="label" translatable="yes">Create torrent name sub-folder</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">This option will create a sub-folder using the torrent's name within the selected extract folder and put the extracted files there.</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>
|
||||
<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">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>General</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
@@ -1,100 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# Basic plugin template created by:
|
||||
# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
|
||||
# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
|
||||
# the additional special exception to link portions of this program with the OpenSSL library.
|
||||
# See LICENSE for more details.
|
||||
#
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
|
||||
import gi # isort:skip (Required before Gtk import).
|
||||
|
||||
gi.require_version('Gtk', '3.0') # NOQA: E402
|
||||
|
||||
# isort:imports-thirdparty
|
||||
from gi.repository import Gtk
|
||||
|
||||
# isort:imports-firstparty
|
||||
import deluge.component as component
|
||||
from deluge.plugins.pluginbase import Gtk3PluginBase
|
||||
from deluge.ui.client import client
|
||||
|
||||
# isort:imports-localfolder
|
||||
from .common import get_resource
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GtkUI(Gtk3PluginBase):
|
||||
def enable(self):
|
||||
self.builder = Gtk.Builder()
|
||||
self.builder.add_from_file(get_resource('extractor_prefs.ui'))
|
||||
|
||||
component.get('Preferences').add_page(
|
||||
_('SimpleExtractor'), self.builder.get_object('extractor_prefs_box')
|
||||
)
|
||||
component.get('PluginManager').register_hook(
|
||||
'on_apply_prefs', self.on_apply_prefs
|
||||
)
|
||||
component.get('PluginManager').register_hook(
|
||||
'on_show_prefs', self.on_show_prefs
|
||||
)
|
||||
self.on_show_prefs()
|
||||
|
||||
def disable(self):
|
||||
component.get('Preferences').remove_page(_('SimpleExtractor'))
|
||||
component.get('PluginManager').deregister_hook(
|
||||
'on_apply_prefs', self.on_apply_prefs
|
||||
)
|
||||
component.get('PluginManager').deregister_hook(
|
||||
'on_show_prefs', self.on_show_prefs
|
||||
)
|
||||
del self.builder
|
||||
|
||||
def on_apply_prefs(self):
|
||||
log.debug('applying prefs for Simple Extractor')
|
||||
if client.is_localhost():
|
||||
path = self.builder.get_object('folderchooser_path').get_filename()
|
||||
else:
|
||||
path = self.builder.get_object('entry_path').get_text()
|
||||
|
||||
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(),
|
||||
'extract_labels': self.builder.get_object("entry_labels").get_text()
|
||||
}
|
||||
|
||||
client.extractor.set_config(config)
|
||||
|
||||
def on_show_prefs(self):
|
||||
if client.is_localhost():
|
||||
self.builder.get_object('folderchooser_path').show()
|
||||
self.builder.get_object('entry_path').hide()
|
||||
else:
|
||||
self.builder.get_object('folderchooser_path').hide()
|
||||
self.builder.get_object('entry_path').show()
|
||||
|
||||
def on_get_config(config):
|
||||
if client.is_localhost():
|
||||
self.builder.get_object('folderchooser_path').set_current_folder(
|
||||
config['extract_path']
|
||||
)
|
||||
else:
|
||||
self.builder.get_object('entry_path').set_text(config['extract_path'])
|
||||
|
||||
self.builder.get_object('chk_use_name').set_active(
|
||||
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