summaryrefslogtreecommitdiffstats
path: root/deluge/plugins/WebUi
diff options
context:
space:
mode:
Diffstat (limited to 'deluge/plugins/WebUi')
-rwxr-xr-xdeluge/plugins/WebUi/create_dev_link.sh11
-rw-r--r--deluge/plugins/WebUi/deluge_webui/__init__.py37
-rw-r--r--deluge/plugins/WebUi/deluge_webui/common.py20
-rw-r--r--deluge/plugins/WebUi/deluge_webui/core.py117
-rw-r--r--deluge/plugins/WebUi/deluge_webui/data/config.ui127
-rw-r--r--deluge/plugins/WebUi/deluge_webui/gtkui.py97
-rw-r--r--deluge/plugins/WebUi/deluge_webui/tests/__init__.py0
-rw-r--r--deluge/plugins/WebUi/deluge_webui/tests/test_plugin_webui.py44
-rw-r--r--deluge/plugins/WebUi/setup.py43
9 files changed, 496 insertions, 0 deletions
diff --git a/deluge/plugins/WebUi/create_dev_link.sh b/deluge/plugins/WebUi/create_dev_link.sh
new file mode 100755
index 0000000..f4d60d2
--- /dev/null
+++ b/deluge/plugins/WebUi/create_dev_link.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+BASEDIR=$(cd `dirname $0` && pwd)
+CONFIG_DIR=$( test -z $1 && echo "/home/damien/.config/deluge/" || echo "$1")
+[ -d "$CONFIG_DIR/plugins" ] || echo "Config dir "$CONFIG_DIR" is either not a directory or is not a proper deluge config directory. Exiting"
+[ -d "$CONFIG_DIR/plugins" ] || exit 1
+cd $BASEDIR
+test -d $BASEDIR/temp || mkdir $BASEDIR/temp
+export PYTHONPATH=$BASEDIR/temp
+python setup.py build develop --install-dir $BASEDIR/temp
+cp $BASEDIR/temp/*.egg-link $CONFIG_DIR/plugins
+rm -fr $BASEDIR/temp
diff --git a/deluge/plugins/WebUi/deluge_webui/__init__.py b/deluge/plugins/WebUi/deluge_webui/__init__.py
new file mode 100644
index 0000000..ba978b2
--- /dev/null
+++ b/deluge/plugins/WebUi/deluge_webui/__init__.py
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2009 Damien Churchill <damoxc@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 deluge.plugins.init import PluginInitBase
+
+
+class CorePlugin(PluginInitBase):
+ def __init__(self, plugin_name):
+ from .core import Core as _pluginCls
+
+ self._plugin_cls = _pluginCls
+ super().__init__(plugin_name)
+
+
+class GtkUIPlugin(PluginInitBase):
+ def __init__(self, plugin_name):
+ from .gtkui import GtkUI as _pluginCls
+
+ self._plugin_cls = _pluginCls
+ super().__init__(plugin_name)
+
+
+class WebUIPlugin(PluginInitBase):
+ def __init__(self, plugin_name):
+ from webui import WebUI as _pluginCls
+
+ self._plugin_cls = _pluginCls
+ super().__init__(plugin_name)
diff --git a/deluge/plugins/WebUi/deluge_webui/common.py b/deluge/plugins/WebUi/deluge_webui/common.py
new file mode 100644
index 0000000..eb47f13
--- /dev/null
+++ b/deluge/plugins/WebUi/deluge_webui/common.py
@@ -0,0 +1,20 @@
+#
+# Basic plugin template created by:
+# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com>
+# 2007-2009 Andrew Resch <andrewresch@gmail.com>
+# 2009 Damien Churchill <damoxc@gmail.com>
+# 2010 Pedro Algarvio <pedro@algarvio.me>
+# 2017 Calum Lind <calumlind+deluge@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.
+#
+
+import os.path
+
+from pkg_resources import resource_filename
+
+
+def get_resource(filename):
+ return resource_filename(__package__, os.path.join('data', filename))
diff --git a/deluge/plugins/WebUi/deluge_webui/core.py b/deluge/plugins/WebUi/deluge_webui/core.py
new file mode 100644
index 0000000..f18203e
--- /dev/null
+++ b/deluge/plugins/WebUi/deluge_webui/core.py
@@ -0,0 +1,117 @@
+#
+# Copyright (C) 2009 Damien Churchill <damoxc@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.
+#
+
+import logging
+
+from twisted.internet import defer
+from twisted.internet.error import CannotListenError
+
+import deluge.component as component
+from deluge import configmanager
+from deluge.core.rpcserver import export
+from deluge.plugins.pluginbase import CorePluginBase
+
+try:
+ from deluge.ui.web import server
+except ImportError:
+ server = False
+
+log = logging.getLogger(__name__)
+
+DEFAULT_PREFS = {'enabled': False, 'ssl': False, 'port': 8112}
+
+
+class Core(CorePluginBase):
+ server = None
+
+ def enable(self):
+ self.config = configmanager.ConfigManager('web_plugin.conf', DEFAULT_PREFS)
+ if self.config['enabled']:
+ self.start_server()
+
+ def disable(self):
+ self.stop_server()
+
+ def update(self):
+ pass
+
+ def _on_stop(self, *args):
+ return self.start_server()
+
+ @export
+ def got_deluge_web(self):
+ """Status of deluge-web module installation.
+
+ Check if deluge.ui.web.server modulge is installed and has been successfully imported.
+
+ Returns:
+ bool: True is deluge-web is installed and available, otherwise False.
+
+ """
+
+ return bool(server)
+
+ def start_server(self):
+ if not self.server:
+ if not self.got_deluge_web():
+ return False
+
+ try:
+ self.server = component.get('DelugeWeb')
+ except KeyError:
+ self.server = server.DelugeWeb(daemon=False)
+
+ self.server.port = self.config['port']
+ self.server.https = self.config['ssl']
+ try:
+ self.server.start()
+ except CannotListenError as ex:
+ log.warning('Failed to start WebUI server: %s', ex)
+ raise
+ return True
+
+ def stop_server(self):
+ if self.server:
+ return self.server.stop()
+ return defer.succeed(True)
+
+ def restart_server(self):
+ return self.stop_server().addCallback(self._on_stop)
+
+ @export
+ def set_config(self, config):
+ """Sets the config dictionary."""
+
+ action = None
+ if 'enabled' in config:
+ if config['enabled'] != self.config['enabled']:
+ action = config['enabled'] and 'start' or 'stop'
+
+ if 'ssl' in config:
+ if not action:
+ action = 'restart'
+
+ for key in config:
+ self.config[key] = config[key]
+ self.config.save()
+
+ if action == 'start':
+ return self.start_server()
+ elif action == 'stop':
+ return self.stop_server()
+ elif action == 'restart':
+ return self.restart_server()
+
+ @export
+ def get_config(self):
+ """Returns the config dictionary."""
+ return self.config.config
diff --git a/deluge/plugins/WebUi/deluge_webui/data/config.ui b/deluge/plugins/WebUi/deluge_webui/data/config.ui
new file mode 100644
index 0000000..c58edd0
--- /dev/null
+++ b/deluge/plugins/WebUi/deluge_webui/data/config.ui
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">99999</property>
+ <property name="value">8112</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkWindow" id="window1">
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkBox" id="prefs_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkFrame" id="settings_frame">
+ <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="GtkAlignment" id="settings_alignment">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="top_padding">10</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkBox" id="settings_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">5</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="enabled_checkbutton">
+ <property name="label" translatable="yes">Enable web interface</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="ssl_checkbutton">
+ <property name="label" translatable="yes">Enable SSL</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</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="port_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="port_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Listening port:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="port_spinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="numeric">True</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">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="settings_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">&lt;b&gt;Settings&lt;/b&gt;</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>
diff --git a/deluge/plugins/WebUi/deluge_webui/gtkui.py b/deluge/plugins/WebUi/deluge_webui/gtkui.py
new file mode 100644
index 0000000..3d19417
--- /dev/null
+++ b/deluge/plugins/WebUi/deluge_webui/gtkui.py
@@ -0,0 +1,97 @@
+#
+# Copyright (C) 2009 Damien Churchill <damoxc@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.
+#
+
+import logging
+
+from gi.repository import Gtk
+
+import deluge.component as component
+from deluge.plugins.pluginbase import Gtk3PluginBase
+from deluge.ui.client import client
+
+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('config.ui'))
+
+ component.get('Preferences').add_page(
+ _('WebUi'), self.builder.get_object('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
+ )
+ client.webui.get_config().addCallback(self.cb_get_config)
+ client.webui.got_deluge_web().addCallback(self.cb_chk_deluge_web)
+
+ def disable(self):
+ component.get('Preferences').remove_page(_('WebUi'))
+ component.get('PluginManager').deregister_hook(
+ 'on_apply_prefs', self.on_apply_prefs
+ )
+ component.get('PluginManager').deregister_hook(
+ 'on_show_prefs', self.on_show_prefs
+ )
+
+ def on_apply_prefs(self):
+ if not self.have_web:
+ return
+ log.debug('applying prefs for WebUi')
+ config = {
+ 'enabled': self.builder.get_object('enabled_checkbutton').get_active(),
+ 'ssl': self.builder.get_object('ssl_checkbutton').get_active(),
+ 'port': self.builder.get_object('port_spinbutton').get_value_as_int(),
+ }
+ client.webui.set_config(config)
+
+ def on_show_prefs(self):
+ client.webui.get_config().addCallback(self.cb_get_config)
+
+ def cb_get_config(self, config):
+ """Callback for on show_prefs."""
+ self.builder.get_object('enabled_checkbutton').set_active(config['enabled'])
+ self.builder.get_object('ssl_checkbutton').set_active(config['ssl'])
+ self.builder.get_object('port_spinbutton').set_value(config['port'])
+
+ def cb_chk_deluge_web(self, have_web):
+ self.have_web = have_web
+ if have_web:
+ return
+ self.builder.get_object('settings_vbox').set_sensitive(False)
+
+ vbox = self.builder.get_object('prefs_box')
+
+ hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, spacing=0)
+ icon = Gtk.Image.new_from_icon_name('dialog-error', Gtk.IconSize.BUTTON)
+ icon.set_padding(5, 5)
+ hbox.pack_start(icon, False, False, 0)
+
+ label = Gtk.Label(
+ _(
+ 'The Deluge web interface is not installed, '
+ 'please install the\ninterface and try again'
+ )
+ )
+ label.set_alignment(0, 0.5)
+ label.set_padding(5, 5)
+ hbox.pack_start(label, False, False, 0)
+
+ vbox.pack_start(hbox, False, False, 10)
+ vbox.reorder_child(hbox, 0)
+ vbox.show_all()
diff --git a/deluge/plugins/WebUi/deluge_webui/tests/__init__.py b/deluge/plugins/WebUi/deluge_webui/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/deluge/plugins/WebUi/deluge_webui/tests/__init__.py
diff --git a/deluge/plugins/WebUi/deluge_webui/tests/test_plugin_webui.py b/deluge/plugins/WebUi/deluge_webui/tests/test_plugin_webui.py
new file mode 100644
index 0000000..413d259
--- /dev/null
+++ b/deluge/plugins/WebUi/deluge_webui/tests/test_plugin_webui.py
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2016 bendikro <bro.devel+deluge@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.
+#
+import pytest
+import pytest_twisted
+
+from deluge.core.core import Core
+from deluge.core.rpcserver import RPCServer
+from deluge.tests import common
+
+common.disable_new_release_check()
+
+
+class TestWebUIPlugin:
+ @pytest_twisted.async_yield_fixture(autouse=True)
+ async def set_up(self, request, component):
+ self = request.instance
+ self.rpcserver = RPCServer(listen=False)
+ self.core = Core()
+ await component.start()
+
+ yield
+
+ await component.shutdown()
+ del self.rpcserver
+ del self.core
+
+ def test_enable_webui(self):
+ if 'WebUi' not in self.core.get_available_plugins():
+ pytest.skip('WebUi plugin not available for testing')
+
+ d = self.core.enable_plugin('WebUi')
+
+ def result_cb(result):
+ if 'WebUi' not in self.core.get_enabled_plugins():
+ self.fail('Failed to enable WebUi plugin')
+ assert result
+
+ d.addBoth(result_cb)
+ return d
diff --git a/deluge/plugins/WebUi/setup.py b/deluge/plugins/WebUi/setup.py
new file mode 100644
index 0000000..5f2184c
--- /dev/null
+++ b/deluge/plugins/WebUi/setup.py
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2009 Damien Churchill <damoxc@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 setuptools import find_packages, setup
+
+__plugin_name__ = 'WebUi'
+__author__ = 'Damien Churchill'
+__author_email__ = 'damoxc@gmail.com'
+__version__ = '0.2'
+__url__ = 'http://deluge-torrent.org'
+__license__ = 'GPLv3'
+__description__ = 'Allows starting the web interface within the daemon.'
+__long_description__ = """"""
+__pkg_data__ = {'deluge_' + __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__ if __long_description__ else __description__,
+ packages=find_packages(),
+ package_data=__pkg_data__,
+ entry_points="""
+ [deluge.plugin.core]
+ %s = deluge_%s:CorePlugin
+ [deluge.plugin.gtk3ui]
+ %s = deluge_%s:GtkUIPlugin
+ """
+ % ((__plugin_name__, __plugin_name__.lower()) * 2),
+)