Add Extractor plugin

This commit is contained in:
Andrew Resch 2009-05-02 02:13:23 +00:00
parent 9a94b3719d
commit 9b25b63664
7 changed files with 452 additions and 0 deletions

View File

@ -0,0 +1,47 @@
#
# __init__.py
#
# 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>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
from deluge.plugins.init import PluginInitBase
class CorePlugin(PluginInitBase):
def __init__(self, plugin_name):
from core import Core as _plugin_cls
self._plugin_cls = _plugin_cls
super(CorePlugin, self).__init__(plugin_name)
class GtkUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from gtkui import GtkUI as _plugin_cls
self._plugin_cls = _plugin_cls
super(GtkUIPlugin, self).__init__(plugin_name)
class WebUIPlugin(PluginInitBase):
def __init__(self, plugin_name):
from webui import WebUI as _plugin_cls
self._plugin_cls = _plugin_cls
super(WebUIPlugin, self).__init__(plugin_name)

View File

@ -0,0 +1,27 @@
#
# common.py
#
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
def get_resource(filename):
import pkg_resources, os
return pkg_resources.resource_filename("extractor", os.path.join("data", filename))

View File

@ -0,0 +1,114 @@
#
# core.py
#
# 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>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
import os
from twisted.internet.utils import getProcessValue
from deluge.log import LOG as log
from deluge.plugins.pluginbase import CorePluginBase
import deluge.component as component
import deluge.configmanager
from deluge.core.rpcserver import export
DEFAULT_PREFS = {
"extract_path": ""
}
# The first format is the source file, the second is the dest path
EXTRACT_COMMANDS = {
".rar": ["unrar", "x -o+ -y"],
".zip": ["unzip", ""],
".tar.gz": ["tar", "xvzf"],
".tar.bz2": ["tar", "xvjf"],
".tar.lzma": ["tar", "--lzma xvf"]
}
class Core(CorePluginBase):
def enable(self):
self.config = deluge.configmanager.ConfigManager("extractor.conf", DEFAULT_PREFS)
component.get("EventManager").register_event_handler("TorrentFinishedEvent", self._on_torrent_finished)
def disable(self):
pass
def update(self):
pass
def _on_torrent_finished(self, torrent_id):
"""
This is called when a torrent finishes. We need to check to see if there
are any files to extract.
"""
# Get the save path
save_path = component.get("TorrentManager")[torrent_id].get_status(["save_path"])["save_path"]
files = component.get("TorrentManager")[torrent_id].get_files()
for f in files:
ext = os.path.splitext(f["path"])
if ext in (".gz", ".bz2", ".lzma"):
# We need to check if this is a tar
if os.path.splitext(ext[0]) == ".tar":
cmd = EXTRACT_COMMANDS[".tar" + ext[1]]
else:
if ext[1] in EXTRACT_COMMANDS:
cmd = EXTRACT_COMMANDS[ext[1]]
else:
log.debug("Can't extract unknown file type: %s", ext[1])
continue
# Now that we have the cmd, lets run it to extract the files
fp = os.path.join(save_path, f["path"])
if os.path.exists(self.config["extract_path"]):
dest = self.config["extract_path"]
else:
dest = None
def on_extract_success(result, torrent_id):
# XXX: Emit an event
log.debug("Extract was successful for %s", torrent_id)
def on_extract_failed(result, torrent_id):
# XXX: Emit an event
log.debug("Extract failed for %s", torrent_id)
# Run the command and add some callbacks
d = getProcessValue(cmd[0], cmd[1:] + [fp], {}, dest)
d.addCallback(on_extract_success, torrent_id)
d.addErrback(on_extract_failed, torrent_id)
@export()
def set_config(self, config):
"sets the config dictionary"
for key in config.keys():
self.config[key] = config[key]
self.config.save()
@export()
def get_config(self):
"returns the config dictionary"
return self.config.config

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.5 on Fri May 1 18:23:42 2009 -->
<glade-interface>
<widget class="GtkWindow" id="window1">
<child>
<widget class="GtkVBox" id="extractor_prefs_box">
<property name="visible">True</property>
<property name="spacing">5</property>
<child>
<widget class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="spacing">5</property>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="spacing">5</property>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">Extract to:</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkFileChooserButton" id="folderchooser_path">
<property name="visible">True</property>
<property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property>
<property name="title" translatable="yes">Select A Folder</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entry_path">
<property name="visible">True</property>
<property name="can_focus">True</property>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;General&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@ -0,0 +1,82 @@
#
# gtkui.py
#
# 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>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
import gtk
from deluge.log import LOG as log
from deluge.ui.client import client
from deluge.plugins.pluginbase import GtkPluginBase
import deluge.component as component
import deluge.common
from common import get_resource
class GtkUI(GtkPluginBase):
def enable(self):
self.glade = gtk.glade.XML(get_resource("extractor_prefs.glade"))
component.get("Preferences").add_page("Extractor", self.glade.get_widget("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)
def disable(self):
component.get("Preferences").remove_page("Extractor")
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.glade
def on_apply_prefs(self):
log.debug("applying prefs for Extractor")
if client.is_localhost():
path = self.glade.get_widget("folderchooser_path").get_current_folder()
else:
path = self.glade.get_widget("entry_path").get_text()
config = {
"extract_path": path
}
client.extractor.set_config(config)
def on_show_prefs(self):
if client.is_localhost():
self.glade.get_widget("folderchooser_path").show()
self.glade.get_widget("entry_path").hide()
else:
self.glade.get_widget("folderchooser_path").hide()
self.glade.get_widget("entry_path").show()
self.glade.get_widget("folderchooser_path").show()
def on_get_config(config):
if client.is_localhost():
self.glade.get_widget("folderchooser_path").set_current_folder(config["extract_path"])
else:
self.glade.get_widget("entry_path").set_text(config["extract_path"])
client.extractor.get_config().addCallback(on_get_config)

View File

@ -0,0 +1,39 @@
#
# webui.py
#
# 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>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
from deluge.log import LOG as log
from deluge.ui.client import client
from deluge import component
from deluge.plugins.pluginbase import WebPluginBase
class WebUI(WebPluginBase):
def enable(self):
pass
def disable(self):
pass

View File

@ -0,0 +1,62 @@
#
# setup.py
#
# 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>
#
# Deluge is free software.
#
# You may redistribute it and/or modify it under the terms of the
# GNU General Public License, as published by the Free Software
# Foundation; either version 3 of the License, or (at your option)
# any later version.
#
# deluge is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with deluge. If not, write to:
# The Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301, USA.
#
from setuptools import setup
__plugin_name__ = "Extractor"
__author__ = "Andrew Resch"
__author_email__ = "andrewresch@gmail.com"
__version__ = "0.1"
__url__ = "http://deluge-torrent.org"
__license__ = "GPLv3"
__description__ = "Extract files upon completion"
__long_description__ = """"""
__pkg_data__ = {__plugin_name__.lower(): ["template/*", "data/*"]}
setup(
name=__plugin_name__,
version=__version__,
description=__description__,
author=__author__,
author_email=__author_email__,
url=__url__,
license=__license__,
long_description=__long_description__ if __long_description__ else __description__,
packages=[__plugin_name__.lower()],
package_data = __pkg_data__,
entry_points="""
[deluge.plugin.core]
%s = %s:CorePlugin
[deluge.plugin.gtkui]
%s = %s:GtkUIPlugin
[deluge.plugin.webui]
%s = %s:WebUIPlugin
""" % ((__plugin_name__, __plugin_name__.lower())*3)
)