begin an execute command upon event plugin
This commit is contained in:
parent
3f0a1eb896
commit
a0e9fafb8f
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# __init__.py
|
||||
#
|
||||
# Copyright (C) 2009 Damien Churchill <damoxc@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):
|
||||
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
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
import pkg_resources
|
||||
import os.path
|
||||
|
||||
def get_resource(filename):
|
||||
return pkg_resources.resource_filename("example", os.path.join("data", filename))
|
|
@ -0,0 +1,103 @@
|
|||
#
|
||||
# core.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.
|
||||
#
|
||||
|
||||
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()
|
|
@ -0,0 +1,157 @@
|
|||
<?xml version="1.0"?>
|
||||
<glade-interface>
|
||||
<!-- interface-requires gtk+ 2.16 -->
|
||||
<!-- interface-naming-policy project-wide -->
|
||||
<widget class="GtkWindow" id="execute_window">
|
||||
<child>
|
||||
<widget class="GtkVBox" id="execute_box">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="commands_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="commands_alignment">
|
||||
<property name="visible">True</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="commands_vbox">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="commands_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Commands</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkFrame" id="add_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="add_alignment">
|
||||
<property name="visible">True</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<widget class="GtkTable" id="add_table">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="n_columns">2</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="event_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Event</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="x_padding">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="command_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Command</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="x_padding">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="command_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkComboBox" id="event_combobox">
|
||||
<property name="visible">True</property>
|
||||
<property name="items" translatable="yes"></property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="add_button">
|
||||
<property name="label" translatable="yes">Add</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="on_add_button_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="add_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Add Command</b></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="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
|
@ -0,0 +1,109 @@
|
|||
#
|
||||
# gtkui.py
|
||||
#
|
||||
# Copyright (C) 2009 Damien Churchill <damoxc@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
|
||||
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
|
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# webui.py
|
||||
#
|
||||
# Copyright (C) 2009 Damien Churchill <damoxc@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):
|
||||
log.debug("Example Web plugin enabled!")
|
||||
|
||||
def disable(self):
|
||||
log.debug("Example Web plugin disabled!")
|
|
@ -0,0 +1,56 @@
|
|||
#
|
||||
# setup.py
|
||||
#
|
||||
# Copyright (C) 2009 Damien Churchill <damoxc@gmail.com>
|
||||
#
|
||||
# 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)
|
||||
)
|
Loading…
Reference in New Issue