deluge-webapi 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- deluge_webapi-0.5.0/AUTHORS +14 -0
- deluge_webapi-0.5.0/CHANGELOG +40 -0
- deluge_webapi-0.5.0/LICENSE +27 -0
- deluge_webapi-0.5.0/MANIFEST.in +12 -0
- deluge_webapi-0.5.0/PKG-INFO +71 -0
- deluge_webapi-0.5.0/README.rst +51 -0
- deluge_webapi-0.5.0/deluge_webapi/__init__.py +28 -0
- deluge_webapi-0.5.0/deluge_webapi/common.py +17 -0
- deluge_webapi-0.5.0/deluge_webapi/core.py +35 -0
- deluge_webapi-0.5.0/deluge_webapi/data/config.ui +146 -0
- deluge_webapi-0.5.0/deluge_webapi/data/webapi.js +198 -0
- deluge_webapi-0.5.0/deluge_webapi/gtk3ui.py +99 -0
- deluge_webapi-0.5.0/deluge_webapi/test.py +48 -0
- deluge_webapi-0.5.0/deluge_webapi/webui.py +176 -0
- deluge_webapi-0.5.0/deluge_webapi.egg-info/PKG-INFO +71 -0
- deluge_webapi-0.5.0/deluge_webapi.egg-info/SOURCES.txt +24 -0
- deluge_webapi-0.5.0/deluge_webapi.egg-info/dependency_links.txt +1 -0
- deluge_webapi-0.5.0/deluge_webapi.egg-info/entry_points.txt +8 -0
- deluge_webapi-0.5.0/deluge_webapi.egg-info/top_level.txt +1 -0
- deluge_webapi-0.5.0/docs/Makefile +130 -0
- deluge_webapi-0.5.0/docs/source/conf.py +216 -0
- deluge_webapi-0.5.0/docs/source/index.rst +63 -0
- deluge_webapi-0.5.0/docs/source/quickstart.rst +129 -0
- deluge_webapi-0.5.0/docs/source/rst_guide.rst +92 -0
- deluge_webapi-0.5.0/pyproject.toml +41 -0
- deluge_webapi-0.5.0/setup.cfg +4 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
deluge-webapi authors
|
|
2
|
+
=====================
|
|
3
|
+
|
|
4
|
+
Created by Igor `idle sign` Starikov.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Contributors
|
|
8
|
+
------------
|
|
9
|
+
|
|
10
|
+
theonedemon <https://github.com/theonedemon>
|
|
11
|
+
Daniel Marcos <https://github.com/dmarcosl>
|
|
12
|
+
Brandon Gillis <https://github.com/BrandonGillis>
|
|
13
|
+
Ivan Filippov <https://github.com/ivanfilippov>
|
|
14
|
+
griest024 <https://github.com/griest024>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
deluge-webapi changelog
|
|
2
|
+
=======================
|
|
3
|
+
|
|
4
|
+
v0.5.0
|
|
5
|
+
------
|
|
6
|
+
* CORS patching is moved into the WebUI part of the plugin, where the JSON component lives, fixing KeyError: 'JSON' when the WebUI and the daemon run in separate processes; changing CORS settings now requires a WebUI restart (close #36)
|
|
7
|
+
* The plugin package is renamed into `deluge_webapi` to comply with the Deluge 2 plugin naming requirements (close #25)
|
|
8
|
+
|
|
9
|
+
v0.4.0
|
|
10
|
+
------
|
|
11
|
+
* Added support for Deluge 2
|
|
12
|
+
* get_torrents will now accept a comma separated string in addition to accepting a list for field filters
|
|
13
|
+
* Future support for Deluge 1.x is no longer possible, please use the older eggs
|
|
14
|
+
|
|
15
|
+
v0.3.1
|
|
16
|
+
------
|
|
17
|
+
* Added CORS settings for WebUI.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
v0.3.0
|
|
21
|
+
------
|
|
22
|
+
* Add CORS support.
|
|
23
|
+
* Added CORS settings for GTK.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
v0.2.1
|
|
27
|
+
------
|
|
28
|
+
* Fixed add_rorrent download_location not honored (see #8).
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
v0.2.0
|
|
32
|
+
------
|
|
33
|
+
+ Plugin updated to work with Deluge 1.3.15
|
|
34
|
+
+ `add_torrent` now returns torrent id (hash) (see #5).
|
|
35
|
+
+ `remove_torrent` now returns the result of core function instad of `True`.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
v0.1.0
|
|
39
|
+
------
|
|
40
|
+
+ Basic functionality.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Copyright (c) 2014-2019 Igor `idle sign` Starikov
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
|
8
|
+
list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
and/or other materials provided with the distribution.
|
|
13
|
+
|
|
14
|
+
* Neither the name of the deluge-webapi nor the names of its
|
|
15
|
+
contributors may be used to endorse or promote products derived from
|
|
16
|
+
this software without specific prior written permission.
|
|
17
|
+
|
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
19
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
20
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
22
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
23
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
24
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
25
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
26
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
27
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
include AUTHORS
|
|
2
|
+
include CHANGELOG
|
|
3
|
+
include LICENSE
|
|
4
|
+
include README.rst
|
|
5
|
+
|
|
6
|
+
include docs/Makefile
|
|
7
|
+
recursive-include docs *.rst
|
|
8
|
+
recursive-include docs *.py
|
|
9
|
+
|
|
10
|
+
recursive-exclude * __pycache__
|
|
11
|
+
recursive-exclude * *.py[co]
|
|
12
|
+
recursive-exclude * empty
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deluge-webapi
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Plugin for Deluge WebUI providing sane JSON API.
|
|
5
|
+
Author-email: Igor `idle sign` Starikov <idlesign@yandex.ru>
|
|
6
|
+
License: BSD 3-Clause License
|
|
7
|
+
Project-URL: Homepage, https://github.com/idlesign/deluge-webapi
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
+
Classifier: Environment :: Plugins
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/x-rst
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
License-File: AUTHORS
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
deluge-webapi
|
|
22
|
+
=============
|
|
23
|
+
https://github.com/idlesign/deluge-webapi
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
.. image:: https://img.shields.io/pypi/v/deluge-webapi.svg
|
|
27
|
+
:target: https://pypi.python.org/pypi/deluge-webapi
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
Description
|
|
31
|
+
-----------
|
|
32
|
+
|
|
33
|
+
*Plugin for Deluge WebUI providing sane JSON API.*
|
|
34
|
+
|
|
35
|
+
Exposes some sane JSON API through Deluge WebUI (missing out of the box or restyled) so that you can manipulate
|
|
36
|
+
Deluge from your programs using HTTP requests.
|
|
37
|
+
|
|
38
|
+
Supported methods:
|
|
39
|
+
|
|
40
|
+
* ``get_torrents``
|
|
41
|
+
* ``add_torrent`` (magnet or file)
|
|
42
|
+
* ``remove_torrent``
|
|
43
|
+
* ``get_api_version``
|
|
44
|
+
|
|
45
|
+
Deluge is a lightweight, Free Software, cross-platform BitTorrent client. Download it at http://deluge-torrent.org/
|
|
46
|
+
|
|
47
|
+
.. note:: Use egg version 0.4.0 or higher for Deluge 2
|
|
48
|
+
.. note:: Use egg version 0.3.2 or lower for Deluge 1.x
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
Installation
|
|
52
|
+
------------
|
|
53
|
+
|
|
54
|
+
1. Get plugin egg file, from ``dist/`` (https://github.com/idlesign/deluge-webapi/tree/master/dist) directory.
|
|
55
|
+
|
|
56
|
+
2. Open Deluge Web UI, go to "Preferences -> Plugins -> Install plugin" and choose egg file.
|
|
57
|
+
|
|
58
|
+
3. Activate ``WebAPI`` plugin.
|
|
59
|
+
|
|
60
|
+
4. In case you use Client-Server setup, you'll need to install the plugin both on client and server, see - https://dev.deluge-torrent.org/wiki/Plugins#Client-ServerSetups
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
.. note::
|
|
64
|
+
|
|
65
|
+
To build .egg file from source code yourself use ``python setup.py bdist_egg`` command in source code directory.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
Documentation
|
|
69
|
+
-------------
|
|
70
|
+
|
|
71
|
+
http://deluge-webapi.readthedocs.org/
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
deluge-webapi
|
|
2
|
+
=============
|
|
3
|
+
https://github.com/idlesign/deluge-webapi
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
.. image:: https://img.shields.io/pypi/v/deluge-webapi.svg
|
|
7
|
+
:target: https://pypi.python.org/pypi/deluge-webapi
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
Description
|
|
11
|
+
-----------
|
|
12
|
+
|
|
13
|
+
*Plugin for Deluge WebUI providing sane JSON API.*
|
|
14
|
+
|
|
15
|
+
Exposes some sane JSON API through Deluge WebUI (missing out of the box or restyled) so that you can manipulate
|
|
16
|
+
Deluge from your programs using HTTP requests.
|
|
17
|
+
|
|
18
|
+
Supported methods:
|
|
19
|
+
|
|
20
|
+
* ``get_torrents``
|
|
21
|
+
* ``add_torrent`` (magnet or file)
|
|
22
|
+
* ``remove_torrent``
|
|
23
|
+
* ``get_api_version``
|
|
24
|
+
|
|
25
|
+
Deluge is a lightweight, Free Software, cross-platform BitTorrent client. Download it at http://deluge-torrent.org/
|
|
26
|
+
|
|
27
|
+
.. note:: Use egg version 0.4.0 or higher for Deluge 2
|
|
28
|
+
.. note:: Use egg version 0.3.2 or lower for Deluge 1.x
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
Installation
|
|
32
|
+
------------
|
|
33
|
+
|
|
34
|
+
1. Get plugin egg file, from ``dist/`` (https://github.com/idlesign/deluge-webapi/tree/master/dist) directory.
|
|
35
|
+
|
|
36
|
+
2. Open Deluge Web UI, go to "Preferences -> Plugins -> Install plugin" and choose egg file.
|
|
37
|
+
|
|
38
|
+
3. Activate ``WebAPI`` plugin.
|
|
39
|
+
|
|
40
|
+
4. In case you use Client-Server setup, you'll need to install the plugin both on client and server, see - https://dev.deluge-torrent.org/wiki/Plugins#Client-ServerSetups
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
.. note::
|
|
44
|
+
|
|
45
|
+
To build .egg file from source code yourself use ``python setup.py bdist_egg`` command in source code directory.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
Documentation
|
|
49
|
+
-------------
|
|
50
|
+
|
|
51
|
+
http://deluge-webapi.readthedocs.org/
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
VERSION = (0, 5, 0)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from deluge.plugins.init import PluginInitBase
|
|
6
|
+
|
|
7
|
+
class CorePlugin(PluginInitBase):
|
|
8
|
+
def __init__(self, plugin_name):
|
|
9
|
+
from .core import Core as _plugin_cls
|
|
10
|
+
self._plugin_cls = _plugin_cls
|
|
11
|
+
super(CorePlugin, self).__init__(plugin_name)
|
|
12
|
+
|
|
13
|
+
class Gtk3UIPlugin(PluginInitBase):
|
|
14
|
+
def __init__(self, plugin_name):
|
|
15
|
+
from .gtk3ui import Gtk3UI as _plugin_cls
|
|
16
|
+
self._plugin_cls = _plugin_cls
|
|
17
|
+
super(Gtk3UIPlugin, self).__init__(plugin_name)
|
|
18
|
+
|
|
19
|
+
class WebUIPlugin(PluginInitBase):
|
|
20
|
+
def __init__(self, plugin_name):
|
|
21
|
+
from .webui import WebUI as _plugin_cls
|
|
22
|
+
self._plugin_cls = _plugin_cls
|
|
23
|
+
super(WebUIPlugin, self).__init__(plugin_name)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
except ImportError:
|
|
27
|
+
# That's what we do when this import prevents docs from being built.
|
|
28
|
+
pass
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from importlib.resources import files
|
|
2
|
+
|
|
3
|
+
from packaging import version
|
|
4
|
+
|
|
5
|
+
from deluge.common import get_version
|
|
6
|
+
|
|
7
|
+
DEFAULT_PREFS = {
|
|
8
|
+
"enable_cors": False,
|
|
9
|
+
"allowed_origin": [],
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
# twisted uses byte strings in deluge version 2.1.0 onward
|
|
13
|
+
use_bytes = version.parse(get_version()) >= version.parse("2.1.0")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_resource(filename):
|
|
17
|
+
return str(files("deluge_webapi").joinpath("data", filename))
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import deluge.configmanager
|
|
4
|
+
from deluge.core.rpcserver import export
|
|
5
|
+
from deluge.plugins.pluginbase import CorePluginBase
|
|
6
|
+
|
|
7
|
+
from .common import DEFAULT_PREFS
|
|
8
|
+
|
|
9
|
+
LOGGER = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Core(CorePluginBase):
|
|
13
|
+
|
|
14
|
+
def enable(self):
|
|
15
|
+
LOGGER.info('Enabling WebAPI plugin CORE ...')
|
|
16
|
+
|
|
17
|
+
self.config = deluge.configmanager.ConfigManager('webapi.conf', DEFAULT_PREFS)
|
|
18
|
+
|
|
19
|
+
def disable(self):
|
|
20
|
+
LOGGER.info('Disabling WebAPI plugin CORE ...')
|
|
21
|
+
|
|
22
|
+
self.config.save()
|
|
23
|
+
|
|
24
|
+
@export
|
|
25
|
+
def set_config(self, config):
|
|
26
|
+
"""sets the config dictionary"""
|
|
27
|
+
|
|
28
|
+
for key in config.keys():
|
|
29
|
+
self.config[key] = config[key]
|
|
30
|
+
|
|
31
|
+
self.config.save()
|
|
32
|
+
|
|
33
|
+
@export
|
|
34
|
+
def get_config(self):
|
|
35
|
+
return self.config.config
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<interface>
|
|
3
|
+
<!-- interface-requires gtk+ 2.24 -->
|
|
4
|
+
<!-- interface-naming-policy toplevel-contextual -->
|
|
5
|
+
<object class="GtkWindow" id="window1">
|
|
6
|
+
<property name="can_focus">False</property>
|
|
7
|
+
<child>
|
|
8
|
+
<object class="GtkHBox" id="prefs_box">
|
|
9
|
+
<property name="visible">True</property>
|
|
10
|
+
<property name="can_focus">False</property>
|
|
11
|
+
<child>
|
|
12
|
+
<object class="GtkLayout" id="layout1">
|
|
13
|
+
<property name="visible">True</property>
|
|
14
|
+
<property name="can_focus">False</property>
|
|
15
|
+
<child>
|
|
16
|
+
<object class="GtkCheckButton" id="enable_cors">
|
|
17
|
+
<property name="label" translatable="yes">enable CORS (cross-origin request)</property>
|
|
18
|
+
<property name="width_request">247</property>
|
|
19
|
+
<property name="height_request">80</property>
|
|
20
|
+
<property name="visible">True</property>
|
|
21
|
+
<property name="can_focus">True</property>
|
|
22
|
+
<property name="receives_default">False</property>
|
|
23
|
+
<property name="use_action_appearance">False</property>
|
|
24
|
+
<property name="draw_indicator">True</property>
|
|
25
|
+
</object>
|
|
26
|
+
<packing>
|
|
27
|
+
<property name="x">18</property>
|
|
28
|
+
</packing>
|
|
29
|
+
</child>
|
|
30
|
+
<child>
|
|
31
|
+
<object class="GtkLabel" id="label1">
|
|
32
|
+
<property name="width_request">152</property>
|
|
33
|
+
<property name="height_request">21</property>
|
|
34
|
+
<property name="visible">True</property>
|
|
35
|
+
<property name="can_focus">False</property>
|
|
36
|
+
<property name="xalign">0</property>
|
|
37
|
+
<property name="yalign">0</property>
|
|
38
|
+
<property name="label" translatable="yes">Allowed domain name :</property>
|
|
39
|
+
</object>
|
|
40
|
+
<packing>
|
|
41
|
+
<property name="x">19</property>
|
|
42
|
+
<property name="y">60</property>
|
|
43
|
+
</packing>
|
|
44
|
+
</child>
|
|
45
|
+
<child>
|
|
46
|
+
<object class="GtkEntry" id="new_domain">
|
|
47
|
+
<property name="width_request">153</property>
|
|
48
|
+
<property name="height_request">27</property>
|
|
49
|
+
<property name="visible">True</property>
|
|
50
|
+
<property name="can_focus">True</property>
|
|
51
|
+
<property name="invisible_char">●</property>
|
|
52
|
+
<property name="primary_icon_activatable">False</property>
|
|
53
|
+
<property name="secondary_icon_activatable">False</property>
|
|
54
|
+
<property name="primary_icon_sensitive">True</property>
|
|
55
|
+
<property name="secondary_icon_sensitive">True</property>
|
|
56
|
+
</object>
|
|
57
|
+
<packing>
|
|
58
|
+
<property name="x">67</property>
|
|
59
|
+
<property name="y">286</property>
|
|
60
|
+
</packing>
|
|
61
|
+
</child>
|
|
62
|
+
<child>
|
|
63
|
+
<object class="GtkButton" id="add_button">
|
|
64
|
+
<property name="label" translatable="yes">Add</property>
|
|
65
|
+
<property name="width_request">49</property>
|
|
66
|
+
<property name="height_request">27</property>
|
|
67
|
+
<property name="visible">True</property>
|
|
68
|
+
<property name="can_focus">True</property>
|
|
69
|
+
<property name="receives_default">True</property>
|
|
70
|
+
<property name="use_action_appearance">False</property>
|
|
71
|
+
</object>
|
|
72
|
+
<packing>
|
|
73
|
+
<property name="x">16</property>
|
|
74
|
+
<property name="y">286</property>
|
|
75
|
+
</packing>
|
|
76
|
+
</child>
|
|
77
|
+
<child>
|
|
78
|
+
<object class="GtkTreeView" id="listview_allowed_domains">
|
|
79
|
+
<property name="width_request">263</property>
|
|
80
|
+
<property name="height_request">194</property>
|
|
81
|
+
<property name="visible">True</property>
|
|
82
|
+
<property name="can_focus">True</property>
|
|
83
|
+
</object>
|
|
84
|
+
<packing>
|
|
85
|
+
<property name="x">16</property>
|
|
86
|
+
<property name="y">84</property>
|
|
87
|
+
</packing>
|
|
88
|
+
</child>
|
|
89
|
+
<child>
|
|
90
|
+
<object class="GtkScrolledWindow" id="scrolledwindow_allowed_domains">
|
|
91
|
+
<property name="width_request">356</property>
|
|
92
|
+
<property name="height_request">197</property>
|
|
93
|
+
<property name="visible">True</property>
|
|
94
|
+
<property name="can_focus">True</property>
|
|
95
|
+
<property name="hscrollbar_policy">automatic</property>
|
|
96
|
+
<property name="vscrollbar_policy">automatic</property>
|
|
97
|
+
<child>
|
|
98
|
+
<placeholder/>
|
|
99
|
+
</child>
|
|
100
|
+
</object>
|
|
101
|
+
<packing>
|
|
102
|
+
<property name="x">16</property>
|
|
103
|
+
<property name="y">81</property>
|
|
104
|
+
</packing>
|
|
105
|
+
</child>
|
|
106
|
+
<child>
|
|
107
|
+
<object class="GtkButton" id="remove_button">
|
|
108
|
+
<property name="label" translatable="yes">Remove</property>
|
|
109
|
+
<property name="width_request">69</property>
|
|
110
|
+
<property name="height_request">27</property>
|
|
111
|
+
<property name="visible">True</property>
|
|
112
|
+
<property name="can_focus">True</property>
|
|
113
|
+
<property name="receives_default">True</property>
|
|
114
|
+
<property name="use_action_appearance">False</property>
|
|
115
|
+
</object>
|
|
116
|
+
<packing>
|
|
117
|
+
<property name="x">221</property>
|
|
118
|
+
<property name="y">286</property>
|
|
119
|
+
</packing>
|
|
120
|
+
</child>
|
|
121
|
+
<child>
|
|
122
|
+
<object class="GtkButton" id="remove_all_button">
|
|
123
|
+
<property name="label" translatable="yes">Remove all</property>
|
|
124
|
+
<property name="width_request">82</property>
|
|
125
|
+
<property name="height_request">27</property>
|
|
126
|
+
<property name="visible">True</property>
|
|
127
|
+
<property name="can_focus">True</property>
|
|
128
|
+
<property name="receives_default">True</property>
|
|
129
|
+
<property name="use_action_appearance">False</property>
|
|
130
|
+
</object>
|
|
131
|
+
<packing>
|
|
132
|
+
<property name="x">290</property>
|
|
133
|
+
<property name="y">286</property>
|
|
134
|
+
</packing>
|
|
135
|
+
</child>
|
|
136
|
+
</object>
|
|
137
|
+
<packing>
|
|
138
|
+
<property name="expand">True</property>
|
|
139
|
+
<property name="fill">True</property>
|
|
140
|
+
<property name="position">0</property>
|
|
141
|
+
</packing>
|
|
142
|
+
</child>
|
|
143
|
+
</object>
|
|
144
|
+
</child>
|
|
145
|
+
</object>
|
|
146
|
+
</interface>
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
|
|
2
|
+
WebApiPanel = Ext.extend(Ext.form.FormPanel, {
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
constructor: function(config) {
|
|
6
|
+
|
|
7
|
+
config = Ext.apply({
|
|
8
|
+
title: _('WebAPI'),
|
|
9
|
+
border: false,
|
|
10
|
+
labelWidth: 10,
|
|
11
|
+
autoHeight: true
|
|
12
|
+
}, config);
|
|
13
|
+
|
|
14
|
+
WebApiPanel.superclass.constructor.call(this, config);
|
|
15
|
+
},
|
|
16
|
+
initComponent: function() {
|
|
17
|
+
WebApiPanel.superclass.initComponent.call(this);
|
|
18
|
+
this.opts = new Deluge.OptionsManager();
|
|
19
|
+
|
|
20
|
+
var fieldset = this.add({
|
|
21
|
+
xtype: 'fieldset',
|
|
22
|
+
title: _('WebAPI Settings'),
|
|
23
|
+
defaultType: 'checkbox',
|
|
24
|
+
autoHeight: true
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
this.opts.bind('enable_cors', fieldset.add({
|
|
28
|
+
name: 'enable_cors',
|
|
29
|
+
id: 'enable_cors',
|
|
30
|
+
height: 22,
|
|
31
|
+
fieldLabel: '',
|
|
32
|
+
labelSeparator: '',
|
|
33
|
+
boxLabel: _('Enable CORS (cross-origin request)')
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
this.list = this.add({
|
|
37
|
+
xtype: 'listview',
|
|
38
|
+
height: 150,
|
|
39
|
+
store: new Ext.data.ArrayStore({
|
|
40
|
+
fields: [
|
|
41
|
+
{ name: 'domain', mapping: 0 }
|
|
42
|
+
]
|
|
43
|
+
}),
|
|
44
|
+
columns: [{
|
|
45
|
+
id: 'domain',
|
|
46
|
+
header: _('Allowed domain'),
|
|
47
|
+
width: 1,
|
|
48
|
+
sortable: true,
|
|
49
|
+
dataIndex: 'domain'
|
|
50
|
+
}],
|
|
51
|
+
singleSelect: true,
|
|
52
|
+
autoExpandColumn: 'domain',
|
|
53
|
+
listeners: {
|
|
54
|
+
selectionchange: { fn: this.onDomainSelect, scope: this }
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
this.panel = this.add({
|
|
59
|
+
region: 'center',
|
|
60
|
+
autoScroll: true,
|
|
61
|
+
items: [this.list]
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
this.domain_name = this.opts.bind('domain_name', fieldset.add({
|
|
65
|
+
fieldLabel: '',
|
|
66
|
+
xtype: 'textfield',
|
|
67
|
+
anchor: '50%',
|
|
68
|
+
name: 'domain_name',
|
|
69
|
+
id: 'domain_name',
|
|
70
|
+
autoWidth: true,
|
|
71
|
+
value: ''
|
|
72
|
+
}));
|
|
73
|
+
|
|
74
|
+
this.toolbar = this.add({
|
|
75
|
+
fieldLabel: _(''),
|
|
76
|
+
name: 'list_toolbar',
|
|
77
|
+
xtype: 'container',
|
|
78
|
+
layout: 'hbox',
|
|
79
|
+
items: [
|
|
80
|
+
{
|
|
81
|
+
xtype: 'button',
|
|
82
|
+
text: 'Add'
|
|
83
|
+
},
|
|
84
|
+
this.domain_name,
|
|
85
|
+
{
|
|
86
|
+
xtype: 'button',
|
|
87
|
+
text: 'Remove'
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
xtype: 'button',
|
|
91
|
+
text: 'Remove all'
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
this.toolbar.getComponent(0).setHandler(this.addDomain, this);
|
|
97
|
+
this.toolbar.getComponent(2).setHandler(this.removeDomain, this);
|
|
98
|
+
this.toolbar.getComponent(3).setHandler(this.removeAllDomain, this);
|
|
99
|
+
|
|
100
|
+
deluge.preferences.on('show', this.onPreferencesShow, this);
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
removeDomain: function() {
|
|
104
|
+
if (!this.selectedDomain) return;
|
|
105
|
+
var index = this.list.getStore().find('domain', this.selectedDomain);
|
|
106
|
+
if (index == -1) return;
|
|
107
|
+
this.list.getStore().removeAt(index);
|
|
108
|
+
index = this.allowedDomains.indexOf(this.selectedDomain);
|
|
109
|
+
if (index !== -1) this.allowedDomains.splice(index, 1);
|
|
110
|
+
this.selectedDomain = false;
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
removeAllDomain: function() {
|
|
114
|
+
this.list.getStore().removeAll();
|
|
115
|
+
this.allowedDomains = [];
|
|
116
|
+
this.selectedDomain = false;
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
onDomainSelect: function (dv, selections) {
|
|
120
|
+
if (selections.length === 0) return;
|
|
121
|
+
var r = dv.getRecords(selections)[0];
|
|
122
|
+
this.selectedDomain = r.get('domain');
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
addDomain: function() {
|
|
126
|
+
var changed = this.opts.getDirty();
|
|
127
|
+
if (!Ext.isObjectEmpty(changed)) {
|
|
128
|
+
if (!Ext.isEmpty(changed['domain_name'])) {
|
|
129
|
+
changed['domain_name'] = changed['domain_name'];
|
|
130
|
+
this.allowedDomains.push(changed['domain_name']);
|
|
131
|
+
this.updateDomainsGrid();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
updateDomainsGrid: function () {
|
|
137
|
+
var Domains = [];
|
|
138
|
+
Ext.each(this.allowedDomains, function (domain) {
|
|
139
|
+
Domains.push([domain]);
|
|
140
|
+
}, this);
|
|
141
|
+
this.list.getStore().loadData(Domains);
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
onPreferencesShow: function () {
|
|
145
|
+
deluge.client.webapi.get_config({
|
|
146
|
+
success: function (config) {
|
|
147
|
+
if (!Ext.isEmpty(config['enable_cors'])) {
|
|
148
|
+
config['enable_cors'] = config['enable_cors'];
|
|
149
|
+
}
|
|
150
|
+
if (!Ext.isEmpty(config['allowed_origin'])) {
|
|
151
|
+
config['allowed_origin'] = config['allowed_origin'];
|
|
152
|
+
}
|
|
153
|
+
this.allowedDomains = config['allowed_origin'];
|
|
154
|
+
this.updateDomainsGrid();
|
|
155
|
+
this.opts.set(config);
|
|
156
|
+
},
|
|
157
|
+
scope: this
|
|
158
|
+
});
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
onApply: function(e) {
|
|
162
|
+
var changed = this.opts.getDirty();
|
|
163
|
+
if (!Ext.isObjectEmpty(changed)) {
|
|
164
|
+
if (!Ext.isEmpty(changed['enable_cors'])) {
|
|
165
|
+
changed['enable_cors'] = changed['enable_cors'];
|
|
166
|
+
}
|
|
167
|
+
deluge.client.webapi.set_config(changed, {
|
|
168
|
+
success: this.onSetConfig,
|
|
169
|
+
scope: this
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
var config = {};
|
|
173
|
+
config['allowed_origin'] = this.allowedDomains;
|
|
174
|
+
console.log(config);
|
|
175
|
+
deluge.client.webapi.set_config(config);
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
onSetConfig: function() {
|
|
179
|
+
this.opts.commit();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
WebApiPlugin = Ext.extend(Deluge.Plugin, {
|
|
186
|
+
|
|
187
|
+
name: 'WebAPI',
|
|
188
|
+
|
|
189
|
+
onDisable: function() {
|
|
190
|
+
deluge.preferences.removePage(this.prefsPage);
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
onEnable: function() {
|
|
194
|
+
this.prefsPage = deluge.preferences.addPage(new WebApiPanel());
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
Deluge.registerPlugin('WebAPI', WebApiPlugin);
|