mirror of
https://git.deluge-torrent.org/deluge
synced 2025-04-20 19:44:52 +00:00
switch over to using twisted-web
This commit is contained in:
parent
ea734931d7
commit
e96b4c4f58
5 changed files with 118 additions and 98 deletions
|
@ -7,11 +7,14 @@ html, body {
|
|||
height:100%;
|
||||
}
|
||||
|
||||
.deluge-torrents td {
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.deluge-torrents .torrent-name {
|
||||
padding-left: 20px;
|
||||
background-repeat: no-repeat;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.deluge-torrents .deluge-torrent-progress {
|
||||
|
@ -64,3 +67,4 @@ html, body {
|
|||
|
||||
.deluge-status dd.torrent_name, .deluge-status dd.tracker, .deluge-status dd.path {
|
||||
width: 500px;
|
||||
}
|
|
@ -3,55 +3,55 @@ Deluge.ToolBar = new Ext.Toolbar({
|
|||
{
|
||||
id: 'create',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: 'Create',
|
||||
text: _('Create'),
|
||||
icon: '/icons/16/create.png',
|
||||
handler: torrentAction
|
||||
},{
|
||||
id: 'add',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: 'Add',
|
||||
text: _('Add'),
|
||||
icon: '/icons/16/add.png',
|
||||
handler: torrentAction
|
||||
},{
|
||||
id: 'remove',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: 'Remove',
|
||||
text: _('Remove'),
|
||||
icon: '/icons/16/remove.png',
|
||||
handler: torrentAction
|
||||
},{
|
||||
id: 'pause',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: 'Pause',
|
||||
text: _('Pause'),
|
||||
icon: '/icons/16/pause.png',
|
||||
handler: torrentAction
|
||||
},{
|
||||
id: 'resume',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: 'Resume',
|
||||
text: _('Resume'),
|
||||
icon: '/icons/16/start.png',
|
||||
handler: torrentAction
|
||||
},{
|
||||
id: 'up',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: 'Up',
|
||||
text: _('Up'),
|
||||
icon: '/icons/16/up.png',
|
||||
handler: torrentAction
|
||||
},{
|
||||
id: 'down',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: 'Down',
|
||||
text: _('Down'),
|
||||
icon: '/icons/16/down.png',
|
||||
handler: torrentAction
|
||||
},{
|
||||
id: 'preferences',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: 'Preferences',
|
||||
text: _('Preferences'),
|
||||
icon: '/icons/16/preferences.png',
|
||||
handler: torrentAction
|
||||
},{
|
||||
id: 'connectionman',
|
||||
cls: 'x-btn-text-icon',
|
||||
text: 'Connection Manager',
|
||||
text: _('Connection Manager'),
|
||||
icon: '/icons/16/connection_manager.png',
|
||||
handler: torrentAction
|
||||
}
|
||||
|
@ -105,10 +105,11 @@ function torrentAction(item) {
|
|||
}
|
||||
|
||||
Deluge.SideBar = {
|
||||
region:'west',
|
||||
id:'west-panel',
|
||||
title:'Sidebar',
|
||||
split:true,
|
||||
region: 'west',
|
||||
id: 'sidebar',
|
||||
cls: 'deluge-sidebar',
|
||||
title: _('Sidebar'),
|
||||
split: true,
|
||||
width: 200,
|
||||
minSize: 175,
|
||||
collapsible: true,
|
||||
|
|
|
@ -36,4 +36,8 @@ Deluge.Details.Status.add({
|
|||
id: 'status-details',
|
||||
cls: 'deluge-status',
|
||||
border: false
|
||||
});
|
||||
});
|
||||
|
||||
Deluge.Details.update = function(torrentId) {
|
||||
Deluge.Details.getActiveTab().update(torrent);
|
||||
}
|
|
@ -13,6 +13,12 @@ Deluge.Ui = {
|
|||
bbar: Deluge.StatusBar
|
||||
});
|
||||
|
||||
Deluge.SideBar = this.MainPanel.items.get('sidebar');
|
||||
Deluge.SideBar.on('collapse', function(bar) {
|
||||
|
||||
//alert(JSON.encode($('sidebar').getSize()));
|
||||
});
|
||||
|
||||
this.Viewport = new Ext.Viewport({
|
||||
layout: 'fit',
|
||||
items: [this.MainPanel]
|
||||
|
|
|
@ -37,10 +37,9 @@ if sys.version_info > (2, 6):
|
|||
else:
|
||||
import simplejson as json
|
||||
|
||||
from twisted.application import service, internet
|
||||
from twisted.internet.defer import Deferred
|
||||
from twisted.application import service, strports
|
||||
from twisted.web2 import static, wsgi, resource, responsecode
|
||||
from twisted.web2 import stream, http, http_headers, server, channel
|
||||
from twisted.web import http, resource, server, static
|
||||
|
||||
from mako.template import Template as MakoTemplate
|
||||
|
||||
|
@ -60,14 +59,14 @@ class Template(MakoTemplate):
|
|||
|
||||
class JSONException(Exception): pass
|
||||
|
||||
class JSON(resource.PostableResource):
|
||||
class JSON(resource.Resource):
|
||||
"""
|
||||
A Twisted Web2 resource that exposes a JSON-RPC interface for web clients
|
||||
A Twisted Web resource that exposes a JSON-RPC interface for web clients
|
||||
to use.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
resource.PostableResource.__init__(self)
|
||||
resource.Resource.__init__(self)
|
||||
self._remote_methods = []
|
||||
self._local_methods = {
|
||||
"web.update_ui": self.update_ui,
|
||||
|
@ -76,12 +75,16 @@ class JSON(resource.PostableResource):
|
|||
"web.add_torrents": self.add_torrents
|
||||
}
|
||||
for entry in open(common.get_default_config_dir("auth")):
|
||||
username, password = entry.split(":")
|
||||
parts = entry.split(":")
|
||||
if len(parts) > 1:
|
||||
username, password = parts[0], parts[1]
|
||||
else:
|
||||
continue
|
||||
|
||||
if username != "localclient":
|
||||
continue
|
||||
self.local_username = username
|
||||
self.local_password = password
|
||||
print username, password
|
||||
self.connect()
|
||||
|
||||
def connect(self, host="localhost", username=None, password=None):
|
||||
|
@ -159,21 +162,22 @@ class JSON(resource.PostableResource):
|
|||
except Exception, e:
|
||||
raise JSONException(str(e))
|
||||
|
||||
def _on_rpc_request_finished(self, result, response):
|
||||
def _on_rpc_request_finished(self, result, response, request):
|
||||
"""
|
||||
Sends the response of any rpc calls back to the json-rpc client.
|
||||
"""
|
||||
response["result"] = result
|
||||
return self._send_response(response)
|
||||
return self._send_response(request, response)
|
||||
|
||||
def _on_rpc_request_failed(self, reason, response):
|
||||
def _on_rpc_request_failed(self, reason, response, request):
|
||||
"""
|
||||
Handles any failures that occured while making an rpc call.
|
||||
"""
|
||||
print reason
|
||||
return http.Response(responsecode.INTERNAL_SERVER_ERROR)
|
||||
request.setResponseCode(http.INTERNAL_SERVER_ERROR)
|
||||
return ""
|
||||
|
||||
def _on_json_request(self, result, request):
|
||||
def _on_json_request(self, request):
|
||||
"""
|
||||
Handler to take the json data as a string and pass it on to the
|
||||
_handle_request method for further processing.
|
||||
|
@ -181,8 +185,8 @@ class JSON(resource.PostableResource):
|
|||
log.debug("json-request: %s", request.json)
|
||||
response = {"result": None, "error": None, "id": None}
|
||||
d, response["id"] = self._handle_request(request.json)
|
||||
d.addCallback(self._on_rpc_request_finished, response)
|
||||
d.addErrback(self._on_rpc_request_failed, response)
|
||||
d.addCallback(self._on_rpc_request_finished, response, request)
|
||||
d.addErrback(self._on_rpc_request_failed, response, request)
|
||||
return d
|
||||
|
||||
def _on_json_request_failed(self, reason, request):
|
||||
|
@ -190,38 +194,31 @@ class JSON(resource.PostableResource):
|
|||
Errback handler to return a HTTP code of 500.
|
||||
"""
|
||||
print reason
|
||||
return http.Response(responsecode.INTERNAL_SERVER_ERROR)
|
||||
request.setResponseCode(http.INTERNAL_SERVER_ERROR)
|
||||
return ""
|
||||
|
||||
def _send_response(self, response):
|
||||
def _send_response(self, request, response):
|
||||
response = json.dumps(response)
|
||||
return http.Response(responsecode.OK,
|
||||
{"content-type": http_headers.MimeType("application", "x-json")},
|
||||
stream=response)
|
||||
request.setHeader("content-type", "application/x-json")
|
||||
request.write(response)
|
||||
request.finish()
|
||||
|
||||
def http_POST(self, request):
|
||||
def render(self, request):
|
||||
"""
|
||||
Handles all the POST requests made to the /json controller.
|
||||
"""
|
||||
request.json = ""
|
||||
def handle_data(data):
|
||||
request.json += data
|
||||
|
||||
d = stream.readStream(request.stream, handle_data)
|
||||
d.addCallbacks(
|
||||
self._on_json_request,
|
||||
self._on_json_request_failed,
|
||||
callbackArgs=(request,),
|
||||
errbackArgs=(request,)
|
||||
)
|
||||
|
||||
d.addErrback(self._on_json_request_failed, request)
|
||||
return d
|
||||
|
||||
def render(self, request):
|
||||
"""
|
||||
Block all other HTTP methods.
|
||||
"""
|
||||
return http.Response(responsecode.NOT_ALLOWED)
|
||||
if request.method != "POST":
|
||||
request.setResponseCode(http.NOT_ALLOWED)
|
||||
return ""
|
||||
|
||||
try:
|
||||
request.content.seek(0)
|
||||
request.json = request.content.read()
|
||||
d = self._on_json_request(request)
|
||||
return server.NOT_DONE_YET
|
||||
except Exception, e:
|
||||
return self._on_json_request_failed(e, request)
|
||||
|
||||
def update_ui(self, keys, filter_dict, cache_id=None):
|
||||
|
||||
|
@ -302,16 +299,14 @@ class JSON(resource.PostableResource):
|
|||
|
||||
|
||||
class GetText(resource.Resource):
|
||||
headers = {
|
||||
"content-type": http_headers.MimeType("text", "javascript")
|
||||
}
|
||||
def render(self, request):
|
||||
request.setHeader("content-type", "text/javascript")
|
||||
template = Template(filename="gettext.js")
|
||||
return http.Response(responsecode.OK, self.headers, template.render())
|
||||
return template.render()
|
||||
|
||||
class Upload(resource.PostableResource):
|
||||
class Upload(resource.Resource):
|
||||
"""
|
||||
Twisted Web2 resource to handle file uploads
|
||||
Twisted Web resource to handle file uploads
|
||||
"""
|
||||
|
||||
def http_POST(self, request):
|
||||
|
@ -330,72 +325,81 @@ class Upload(resource.PostableResource):
|
|||
f = open(fn, upload[2].mode)
|
||||
shutil.copyfileobj(upload[2], f)
|
||||
filenames.append(fn)
|
||||
return http.Response(responsecode.OK, stream="\n".join(filenames))
|
||||
return http.Response(http.OK, stream="\n".join(filenames))
|
||||
|
||||
def render(self, request):
|
||||
"""
|
||||
Block all other HTTP methods.
|
||||
"""
|
||||
return http.Response(responsecode.NOT_ALLOWED)
|
||||
return http.Response(http.NOT_ALLOWED)
|
||||
|
||||
class Render(resource.Resource):
|
||||
|
||||
headers = {
|
||||
"Content-type": http_headers.MimeType("text", "html")
|
||||
}
|
||||
|
||||
def locateChild(self, request, segments):
|
||||
request.render_file = segments[0]
|
||||
return self, ()
|
||||
def getChild(self, path, request):
|
||||
request.render_file = path
|
||||
return self
|
||||
|
||||
def render(self, request):
|
||||
if not hasattr(request, "render_file"):
|
||||
return http.Response(responsecode.INTERNAL_SERVER_ERROR)
|
||||
request.setResponseCode(http.INTERNAL_SERVER_ERROR)
|
||||
return ""
|
||||
|
||||
filename = os.path.join("render", request.render_file)
|
||||
template = Template(filename=filename)
|
||||
return http.Response(responsecode.OK, self.headers, template.render())
|
||||
request.setHeader("content-type", "text/html")
|
||||
request.setResponseCode(http.OK)
|
||||
return template.render()
|
||||
|
||||
class Tracker(resource.Resource):
|
||||
tracker_icons = TrackerIcons()
|
||||
|
||||
def locateChild(self, request, segments):
|
||||
request.tracker_name = "/".join(segments)
|
||||
return self, ()
|
||||
def getChild(self, path, request):
|
||||
request.tracker_name = path
|
||||
return self
|
||||
|
||||
def render(self, request):
|
||||
headers = {}
|
||||
filename = self.tracker_icons.get(request.tracker_name)
|
||||
if filename:
|
||||
http_headers.He
|
||||
#headers["cache-control"] = "public, must-revalidate, max-age=86400"
|
||||
request.setHeader("cache-control", "public, must-revalidate, max-age=86400")
|
||||
if filename.endswith(".ico"):
|
||||
headers["content-type"] = http_headers.MimeType("image", "x-icon")
|
||||
request.setHeader("content-type", "image/x-icon")
|
||||
elif filename.endwith(".png"):
|
||||
headers["content-type"] = http_headers.MimeType("image", "png")
|
||||
request.setHeader("content-type", "image/png")
|
||||
data = open(filename, "rb")
|
||||
return http.Response(responsecode.OK, headers, data.read())
|
||||
request.setResponseCode(http.OK)
|
||||
return data.read()
|
||||
else:
|
||||
return http.Response(responsecode.NOT_FOUND)
|
||||
request.setResponseCode(http.NOT_FOUND)
|
||||
return ""
|
||||
|
||||
class TopLevel(resource.Resource):
|
||||
|
||||
addSlash = True
|
||||
child_json = JSON()
|
||||
child_upload = Upload()
|
||||
child_test = static.File("test.html")
|
||||
child_js = static.File("js")
|
||||
child_images = static.File("images")
|
||||
child_icons = static.File("icons")
|
||||
child_css = static.File("css")
|
||||
child_themes = static.File("themes")
|
||||
child_gettext = GetText()
|
||||
child_render = Render()
|
||||
child_tracker = Tracker()
|
||||
|
||||
def __init__(self):
|
||||
resource.Resource.__init__(self)
|
||||
self.putChild("css", static.File("css"))
|
||||
self.putChild("gettext.js", GetText())
|
||||
self.putChild("icons", static.File("icons"))
|
||||
self.putChild("images", static.File("images"))
|
||||
self.putChild("js", static.File("js"))
|
||||
self.putChild("json", JSON())
|
||||
self.putChild("upload", Upload())
|
||||
self.putChild("render", Render())
|
||||
self.putChild("test", static.File("test.html"))
|
||||
self.putChild("themes", static.File("themes"))
|
||||
self.putChild("tracker", Tracker())
|
||||
|
||||
def getChild(self, path, request):
|
||||
if path == "":
|
||||
return self
|
||||
else:
|
||||
return resource.Resource.getChild(self, path, request)
|
||||
|
||||
def render(self, request):
|
||||
template = Template(filename="index.html")
|
||||
return http.Response(responsecode.OK, stream=template.render())
|
||||
request.setHeader("content-type", "text/html; charset=utf-8")
|
||||
return template.render()
|
||||
|
||||
setupLogger(level="debug")
|
||||
|
||||
|
@ -411,8 +415,9 @@ try:
|
|||
gettext.install("deluge", pkg_resources.resource_filename("deluge", "i18n"))
|
||||
except Exception, e:
|
||||
log.error("Unable to initialize gettext/locale: %s", e)
|
||||
|
||||
|
||||
site = server.Site(TopLevel())
|
||||
application = service.Application("DelugeWeb")
|
||||
s = strports.service("tcp:8112", channel.HTTPFactory(site))
|
||||
s.setServiceParent(application)
|
||||
sc = service.IServiceCollection(application)
|
||||
i = internet.TCPServer(8112, site)
|
||||
i.setServiceParent(sc)
|
||||
|
|
Loading…
Add table
Reference in a new issue