From a0e9fafb8f222b4124bc8090de5be2cd341f641c Mon Sep 17 00:00:00 2001 From: Damien Churchill Date: Sun, 22 Mar 2009 23:37:21 +0000 Subject: [PATCH] begin an execute command upon event plugin --- deluge/plugins/execute/execute/__init__.py | 34 ++++ deluge/plugins/execute/execute/common.py | 29 ++++ deluge/plugins/execute/execute/core.py | 103 ++++++++++++ .../execute/execute/data/execute_prefs.glade | 157 ++++++++++++++++++ deluge/plugins/execute/execute/gtkui.py | 109 ++++++++++++ deluge/plugins/execute/execute/webui.py | 36 ++++ deluge/plugins/execute/setup.py | 56 +++++++ 7 files changed, 524 insertions(+) create mode 100644 deluge/plugins/execute/execute/__init__.py create mode 100644 deluge/plugins/execute/execute/common.py create mode 100644 deluge/plugins/execute/execute/core.py create mode 100644 deluge/plugins/execute/execute/data/execute_prefs.glade create mode 100644 deluge/plugins/execute/execute/gtkui.py create mode 100644 deluge/plugins/execute/execute/webui.py create mode 100644 deluge/plugins/execute/setup.py diff --git a/deluge/plugins/execute/execute/__init__.py b/deluge/plugins/execute/execute/__init__.py new file mode 100644 index 000000000..267a95668 --- /dev/null +++ b/deluge/plugins/execute/execute/__init__.py @@ -0,0 +1,34 @@ +# +# __init__.py +# +# Copyright (C) 2009 Damien Churchill +# +# 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): + from core import Core as _plugin_cls + +class GtkUIPlugin(PluginInitBase): + from gtkui import GtkUI as _plugin_cls + +class WebUIPlugin(PluginInitBase): + from webui import WebUI as _plugin_cls diff --git a/deluge/plugins/execute/execute/common.py b/deluge/plugins/execute/execute/common.py new file mode 100644 index 000000000..d39163afe --- /dev/null +++ b/deluge/plugins/execute/execute/common.py @@ -0,0 +1,29 @@ +# +# common.py +# +# Copyright (C) 2009 Andrew Resch +# +# 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 pkg_resources +import os.path + +def get_resource(filename): + return pkg_resources.resource_filename("example", os.path.join("data", filename)) diff --git a/deluge/plugins/execute/execute/core.py b/deluge/plugins/execute/execute/core.py new file mode 100644 index 000000000..54950c6c5 --- /dev/null +++ b/deluge/plugins/execute/execute/core.py @@ -0,0 +1,103 @@ +# +# core.py +# +# Copyright (C) 2009 Andrew Resch +# +# 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 +import time +import hashlib +from subprocess import Popen, PIPE + +from deluge.log import LOG as log +from deluge.plugins.pluginbase import CorePluginBase +import deluge.component as component +from deluge.configmanager import ConfigManager +from deluge.core.rpcserver import export + +DEFAULT_CONFIG = { + "commands": [] +} + +EXECUTE_ID = 0 +EXECUTE_EVENT = 1 +EXECUTE_COMMAND = 2 + +class Core(CorePluginBase): + def enable(self): + self.config = ConfigManager("execute.conf", DEFAULT_CONFIG) + event_manager = component.get("EventManager") + event_manager.register_event_handler("TorrentFinishedEvent", + self.on_torrent_finished) + log.debug("Example core plugin enabled!") + + def execute_commands(self, torrent_id, event): + torrent = component.get("TorrentManager").torrents[torrent_id] + info = torrent.get_status(["name", "save_path"]) + torrent_name = info["name"] + path = info["save_path"] + for command in self.config["commands"]: + if command[EXECUTE_EVENT] == event: + command = os.path.expandvars(command[EXECUTE_COMMAND]) + command = os.path.expanduser(command) + p = Popen([command, torrent_id, torrent_name, path], + stdin=PIPE, stdout=PIPE, stderr=PIPE) + if p.wait() != 0: + log.warn("Execute command failed with exit code %d", + p.returncode) + + def disable(self): + self.config.save() + event_manager = component.get("EventManager") + event_manager.deregister_event_handler("TorrentFinishedEvent", + self.on_torrent_finished) + log.debug("Example core plugin disabled!") + + def on_torrent_finished(self, torrent_id): + self.execute_commands(torrent_id, "complete") + + ### Exported RPC methods ### + @export + def add_command(self, event, command): + command_id = hashlib.sha1(str(time.time())).hexdigest() + self.config["commands"].append((command_id, event, command)) + self.config.save() + + @export + def get_commands(self): + return self.config["commands"] + + @export + def remove_command(self, command_id): + for command in self.config["commands"]: + if command[EXECUTE_ID] == command_id: + self.config["commands"].remove(command) + break + self.config.save() + + @export + def save_command(self, command_id, event, command): + for command in self.config["commands"]: + if command[EXECUTE_ID] == command_id: + command[EXECUTE_EVENT] = event + command[EXECUTE_COMMAND] = event + break + self.config.save() \ No newline at end of file diff --git a/deluge/plugins/execute/execute/data/execute_prefs.glade b/deluge/plugins/execute/execute/data/execute_prefs.glade new file mode 100644 index 000000000..d6864a0a0 --- /dev/null +++ b/deluge/plugins/execute/execute/data/execute_prefs.glade @@ -0,0 +1,157 @@ + + + + + + + + True + + + True + 0 + none + + + True + 12 + + + True + + + + + + + + + + True + <b>Commands</b> + True + + + label_item + + + + + 0 + + + + + True + 0 + none + + + True + 12 + + + True + 3 + 2 + + + True + 0 + Event + + + GTK_FILL + 5 + + + + + True + 0 + Command + + + 1 + 2 + GTK_FILL + 5 + + + + + True + True + + + 1 + 2 + 1 + 2 + + + + + True + + + + 1 + 2 + + + + + True + + + Add + True + True + True + + + + False + 5 + 0 + + + + + + + + 1 + 2 + 2 + 3 + + + + + + + + + + + + True + <b>Add Command</b> + True + + + label_item + + + + + False + 1 + + + + + + diff --git a/deluge/plugins/execute/execute/gtkui.py b/deluge/plugins/execute/execute/gtkui.py new file mode 100644 index 000000000..e6d035764 --- /dev/null +++ b/deluge/plugins/execute/execute/gtkui.py @@ -0,0 +1,109 @@ +# +# gtkui.py +# +# Copyright (C) 2009 Damien Churchill +# +# 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 +import gtk +import pkg_resources + +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 + +EXECUTE_ID = 0 +EXECUTE_EVENT = 1 +EXECUTE_COMMAND = 2 + +EVENT_MAP = { + "complete": _("Torrent Complete") +} + +class ExecutePreferences(object): + def __init__(self, plugin): + self.plugin = plugin + + def load(self): + log.debug("Adding Execute Preferences page") + self.glade = gtk.glade.XML(self.get_resource("execute_prefs.glade")) + self.glade.signal_autoconnect({ + "on_add_button_clicked": self.on_add_button_clicked + }) + + events = self.glade.get_widget("event_combobox") + + store = gtk.ListStore(str, str) + store.append((_("Torrent Complete"), "complete")) + events.set_model(store) + + self.plugin.add_preferences_page(_("Execute"), + self.glade.get_widget("execute_box")) + self.plugin.register_hook("on_show_prefs", self.load_commands) + self.plugin.register_hook("on_apply_prefs", self.on_apply_prefs) + + def unload(self): + self.plugin.remove_preferences_page(_("Execute")) + self.plugin.deregister_hook("on_apply_prefs", self.on_apply_prefs) + self.plugin.deregister_hook("on_show_prefs", self.load_commands) + + def get_resource(self, filename): + return pkg_resources.resource_filename("execute", os.path.join("data", + filename)) + + def load_commands(self): + def on_get_commands(commands): + vbox = self.glade.get_widget("commands_vbox") + for command in commands: + command_id, event, command = command + log.debug("Adding command `%s`", command_id) + hbox = gtk.HBox(False, 0) + label = gtk.Label(EVENT_MAP[event]) + entry = gtk.Entry() + entry.set_text(command) + hbox.pack_start(label, padding = 5) + hbox.pack_start(entry) + vbox.pack_start(hbox) + hbox.show_all() + client.execute.get_commands().addCallback(on_get_commands) + + def on_add_button_clicked(self, *args): + command = self.glade.get_widget("command_entry").get_text() + events = self.glade.get_widget("event_combobox") + event = events.get_model()[events.get_active()][1] + client.execute.add_command(event, command) + + def on_apply_prefs(self): + options = {} + #update options dict here. + client.label.set_config(options) + +class GtkUI(GtkPluginBase): + + def enable(self): + self.plugin = component.get("PluginManager") + self.prefences = ExecutePreferences(self.plugin) + self.prefences.load() + + def disable(self): + pass diff --git a/deluge/plugins/execute/execute/webui.py b/deluge/plugins/execute/execute/webui.py new file mode 100644 index 000000000..465293937 --- /dev/null +++ b/deluge/plugins/execute/execute/webui.py @@ -0,0 +1,36 @@ +# +# webui.py +# +# Copyright (C) 2009 Damien Churchill +# +# 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): + log.debug("Example Web plugin enabled!") + + def disable(self): + log.debug("Example Web plugin disabled!") diff --git a/deluge/plugins/execute/setup.py b/deluge/plugins/execute/setup.py new file mode 100644 index 000000000..5f46dba87 --- /dev/null +++ b/deluge/plugins/execute/setup.py @@ -0,0 +1,56 @@ +# +# setup.py +# +# Copyright (C) 2009 Damien Churchill +# +# This program is free software; you can 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, or (at your option) +# any later version. +# +# This program 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 this program. 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__ = "Execute" +__author__ = "Damien Churchill" +__author_email__ = "damoxc@gmail.com" +__version__ = "1.2" +__url__ = "http://deluge-torrent.org" +__license__ = "GPLv3" +__description__ = "Plugin to execute a command upon an event" +__long_description__ = __description__ +__pkg_data__ = {__plugin_name__.lower(): ["data/*"]} + +setup( + name=__plugin_name__, + version=__version__, + description=__description__, + author=__author__, + author_email=__author_email__, + url=__url__, + license=__license__, + long_description=__long_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) +)