refactor+enhance json api
This commit is contained in:
parent
9b12c231da
commit
6a216c0122
|
@ -53,6 +53,25 @@ from utils import dict_cb
|
||||||
from lib import json
|
from lib import json
|
||||||
|
|
||||||
|
|
||||||
|
def json_response(result, id):
|
||||||
|
print json.write({
|
||||||
|
"version":"1.1",
|
||||||
|
"result":result,
|
||||||
|
"id":id
|
||||||
|
})
|
||||||
|
|
||||||
|
def json_error(message , id , msg_number=123):
|
||||||
|
log.error("JSON-error:%s" % message)
|
||||||
|
print json.write({
|
||||||
|
"version":"1.1",
|
||||||
|
"id":id,
|
||||||
|
"error":{
|
||||||
|
"number":msg_number,
|
||||||
|
"message":message,
|
||||||
|
"error":message
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
class json_rpc:
|
class json_rpc:
|
||||||
"""
|
"""
|
||||||
== Full client api ==
|
== Full client api ==
|
||||||
|
@ -60,6 +79,10 @@ class json_rpc:
|
||||||
* rpc-api : http://en.wikipedia.org/wiki/JSON-RPC#Version_1.0
|
* rpc-api : http://en.wikipedia.org/wiki/JSON-RPC#Version_1.0
|
||||||
* methods : http://dev.deluge-torrent.org/wiki/Development/UiClient#Remoteapi
|
* methods : http://dev.deluge-torrent.org/wiki/Development/UiClient#Remoteapi
|
||||||
"""
|
"""
|
||||||
|
#extra exposed methods
|
||||||
|
json_exposed = ["update_ui","get_stats","system_listMethods"]
|
||||||
|
|
||||||
|
|
||||||
def GET(self):
|
def GET(self):
|
||||||
print '{"error":"only POST is supported"}'
|
print '{"error":"only POST is supported"}'
|
||||||
|
|
||||||
|
@ -67,38 +90,30 @@ class json_rpc:
|
||||||
def POST(self , name=None):
|
def POST(self , name=None):
|
||||||
web.header("Content-Type", "application/x-json")
|
web.header("Content-Type", "application/x-json")
|
||||||
ck = cookies()
|
ck = cookies()
|
||||||
if not(ck.has_key("session_id") and ck["session_id"] in utils.SESSIONS):
|
|
||||||
print """{"error":{
|
|
||||||
"number":1,
|
|
||||||
"message":"not authenticated",
|
|
||||||
"error":"not authenticated"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
return
|
|
||||||
id = 0
|
id = 0
|
||||||
|
if not(ck.has_key("session_id") and ck["session_id"] in utils.SESSIONS):
|
||||||
|
return json_error("not authenticated", id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
log.debug("json-data:")
|
log.debug("json-data:")
|
||||||
log.debug(webapi.data())
|
log.debug(webapi.data())
|
||||||
json_data = json.read(webapi.data())
|
json_data = json.read(webapi.data())
|
||||||
id = json_data["id"]
|
id = json_data["id"]
|
||||||
method = json_data["method"]
|
method = json_data["method"].replace(".", "_")
|
||||||
params = json_data["params"]
|
params = json_data["params"]
|
||||||
|
|
||||||
if method.startswith('_'):
|
if method.startswith('_'):
|
||||||
raise Exception('_ methods are illegal.')
|
raise Exception('_ methods are illegal.')
|
||||||
|
|
||||||
if method.startswith("system."):
|
elif method in self.json_exposed:
|
||||||
result = self.exec_system_method(method, params,id)
|
func = getattr(self, method)
|
||||||
elif method == ("list_torrents"):
|
result = func(*params)
|
||||||
result = self.list_torrents(method, params,id)
|
|
||||||
elif method == ("get_stats"):
|
|
||||||
result = self.exec_get_stats(method, params,id)
|
|
||||||
else:
|
else:
|
||||||
result = self.exec_client_method(method, params,id)
|
result = self.exec_client_method(method, params)
|
||||||
|
|
||||||
log.debug("JSON-result:%s(%s)[%s] = %s" % (method, params, id, result))
|
#log.debug("JSON-result:%s(%s)[%s] = %s" % (method, params, id, result))
|
||||||
print json.write(result)
|
|
||||||
|
return json_response(result, id)
|
||||||
|
|
||||||
except Exception,e:
|
except Exception,e:
|
||||||
#verbose because you don't want exeptions in the error-handler.
|
#verbose because you don't want exeptions in the error-handler.
|
||||||
|
@ -106,42 +121,24 @@ class json_rpc:
|
||||||
if hasattr(e,"message"):
|
if hasattr(e,"message"):
|
||||||
message = e.message
|
message = e.message
|
||||||
log.debug(format_exc())
|
log.debug(format_exc())
|
||||||
log.error("JSON-error:%s:%s %s" % (e, message, id))
|
return json_error("%s:%s" % (e, message), id)
|
||||||
print json.write({
|
|
||||||
"version":"1.1",
|
|
||||||
"id":id,
|
|
||||||
"error":{
|
|
||||||
"number":123,
|
|
||||||
"message":"%s:%s %s" % (e, message, id),
|
|
||||||
"error":format_exc()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
def exec_client_method(self, method, params, id):
|
def exec_client_method(self, method, params):
|
||||||
if not hasattr(sclient,method):
|
if not hasattr(sclient,method):
|
||||||
raise Exception('Unknown method:%s', method)
|
raise Exception('Unknown method:%s', method)
|
||||||
|
|
||||||
#Call:
|
#Call:
|
||||||
func = getattr(sclient, method)
|
func = getattr(sclient, method)
|
||||||
result = func(*params)
|
return func(*params)
|
||||||
|
|
||||||
return {
|
#
|
||||||
"version":"1.1",
|
#Extra exposed methods:
|
||||||
"result":result,
|
#
|
||||||
"id":id
|
def system_listMethods(self):
|
||||||
}
|
"system.list_methods() see json/xmlrpc docs"
|
||||||
|
return sclient.list_methods() + self.json_exposed
|
||||||
|
|
||||||
def exec_system_method(self, method, params, id):
|
def get_stats(self):
|
||||||
if method == "system.listMethods":
|
|
||||||
methods = sclient.list_methods()
|
|
||||||
return {
|
|
||||||
"version":"1.1",
|
|
||||||
"result":methods + ["get_stats"],
|
|
||||||
"id":id
|
|
||||||
}
|
|
||||||
raise Exception('Unknown method:%s', method)
|
|
||||||
|
|
||||||
def exec_get_stats(self, method, params, id):
|
|
||||||
stats = {}
|
stats = {}
|
||||||
|
|
||||||
aclient.get_download_rate(dict_cb('download_rate',stats))
|
aclient.get_download_rate(dict_cb('download_rate',stats))
|
||||||
|
@ -157,81 +154,45 @@ class json_rpc:
|
||||||
|
|
||||||
aclient.force_call(block=True)
|
aclient.force_call(block=True)
|
||||||
|
|
||||||
return {
|
return stats
|
||||||
"version":"1.1",
|
|
||||||
"result":stats,
|
|
||||||
"id":id
|
|
||||||
}
|
|
||||||
|
|
||||||
|
def update_ui(self, keys ,filter_dict , cache_id = None ):
|
||||||
|
|
||||||
def list_torrents(self,params,id):
|
|
||||||
"""
|
"""
|
||||||
== torrent_list ==
|
|
||||||
Composite call.
|
Composite call.
|
||||||
Goal : limit the number of ajax calls
|
Goal : limit the number of ajax calls
|
||||||
|
filter is only effective if the label plugin is enabled.
|
||||||
filter is only effective if the organize plugin is enabled.
|
|
||||||
label is redirected to the tracker column, there will be a label feature in the future.
|
|
||||||
cache_id = future feature, not effective yet.
|
cache_id = future feature, not effective yet.
|
||||||
|
|
||||||
=== input ===
|
=== input ===
|
||||||
{{{
|
{{{
|
||||||
{
|
keys: see get_torrent_status
|
||||||
keys: [<like get_torrent_status>],
|
filter_dict: see label_get_filtered_ids
|
||||||
filter: {
|
cache_id: # todo
|
||||||
/*ommitted keys are ignored*/
|
|
||||||
"keyword":string
|
|
||||||
"label":string,
|
|
||||||
"state":string
|
|
||||||
} ,
|
|
||||||
cache_id: int
|
|
||||||
}
|
}
|
||||||
}}}
|
}}}
|
||||||
|
|
||||||
=== output ===
|
=== output ===
|
||||||
{{{
|
{{{
|
||||||
{
|
{
|
||||||
torrents:
|
"torrents": see get_torrent_status
|
||||||
[ {"id":string,"name":string, ..}, ..]
|
"filters": see label_get_filters
|
||||||
states:
|
"stats": see get_stats
|
||||||
[('string',int), ..]
|
"cache_id":int # todo
|
||||||
trackers:
|
|
||||||
[('string',int), ..]
|
|
||||||
stats:
|
|
||||||
[upload_rate, download_rate, nu_connections, num_dht_nodes]
|
|
||||||
}
|
|
||||||
cache_id:int
|
|
||||||
}
|
}
|
||||||
}}}
|
}}}
|
||||||
"""
|
"""
|
||||||
"""filter = params["filter"]
|
if 'Label' in sclient.get_enabled_plugins():
|
||||||
keys = params["keys"]
|
|
||||||
cache_id = params["cache_id"]
|
|
||||||
organize_filters = {}
|
|
||||||
|
|
||||||
if 'Organize' in proxy.get_enabled_plugins():
|
|
||||||
filter_dict = {}
|
filter_dict = {}
|
||||||
|
torrent_ids = sclient.label_get_filtered_ids(filter_dict)
|
||||||
for filter_name in ["state","tracker","keyword"]:
|
filters = sclient.label_filter_items()
|
||||||
value = get(filter,filter_name)
|
|
||||||
if value and value <> "All":
|
|
||||||
filter_dict[filter_name] = value
|
|
||||||
|
|
||||||
torrent_ids = proxy.organize_get_session_state(filter_dict)
|
|
||||||
organize_filters = Storage(proxy.organize_all_filter_items())
|
|
||||||
else:
|
else:
|
||||||
torrent_ids = proxy.get_session_state()
|
torrent_ids = proxy.get_session_state()
|
||||||
organize_filters = {"state":[["All",-1]],"tracker":[]}
|
organize_filters = {"state":[["All",-1]],"tracker":[]}
|
||||||
|
|
||||||
result = {
|
return {
|
||||||
"torrents":sclient.get_torrents_status(torrent_ids, keys),
|
"torrents":sclient.get_torrents_status(torrent_ids, keys),
|
||||||
"state":organize_filters["state"],
|
"filters":filters,
|
||||||
"tracker":organize_filters["tracker"],
|
"stats":self.get_stats(),
|
||||||
"stats":[0, 1, 2, 3], #todo
|
"cache_id":-1
|
||||||
"cache_id":cache_id
|
|
||||||
}
|
}
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -407,6 +407,8 @@ route("/template_style.css", template_style)
|
||||||
class pixmaps:
|
class pixmaps:
|
||||||
"use the deluge-images. located in data/pixmaps"
|
"use the deluge-images. located in data/pixmaps"
|
||||||
def GET(self, name):
|
def GET(self, name):
|
||||||
|
if name.startswith("flags") and not name.endswith('.png'):
|
||||||
|
name = name + ".png"
|
||||||
if not name.endswith('.png'):
|
if not name.endswith('.png'):
|
||||||
if name == 'paused':
|
if name == 'paused':
|
||||||
name = 'inactive'
|
name = 'inactive'
|
||||||
|
|
|
@ -64,7 +64,7 @@ function update_torrent(torrent) {
|
||||||
function get_stats() {
|
function get_stats() {
|
||||||
service.get_stats({params:[],
|
service.get_stats({params:[],
|
||||||
onSuccess:function(stats){
|
onSuccess:function(stats){
|
||||||
alert(stats.download_rate);
|
alert(service.__toJSON(stats));
|
||||||
},
|
},
|
||||||
onException:function(errorObj){
|
onException:function(errorObj){
|
||||||
alert("Error: " + errorObj);
|
alert("Error: " + errorObj);
|
||||||
|
@ -74,19 +74,32 @@ function get_stats() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function update_ui() {
|
||||||
|
service.update_ui({params:[ ["name","state","label","tracker_host"],{"state":"Seeding"} ],
|
||||||
|
onSuccess:function(data){
|
||||||
|
alert(service.__toJSON(data));
|
||||||
|
},
|
||||||
|
onException:function(errorObj){
|
||||||
|
alert("Error: " + errorObj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<h1>sclient:</h1>
|
||||||
<button onclick="get_session_state()">get_session_state()</button>
|
<button onclick="get_session_state()">get_session_state()</button>
|
||||||
|
|
||||||
<button onclick="list_torrents()">List torrents</button>
|
<button onclick="list_torrents()">List torrents using get_session_state() + get_torrents_status()</button> <br>
|
||||||
|
<h1>json extra:</h1>
|
||||||
<button onclick="get_stats()">get_stats()</button>
|
<button onclick="get_stats()">get_stats()</button>
|
||||||
|
|
||||||
|
<button onclick="update_ui()">update_ui() filter on "Seeding"</button>
|
||||||
|
|
||||||
|
|
||||||
<div id="torrent_list">
|
<div id="torrent_list">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,20 +5,21 @@ $def with (torrent)
|
||||||
|
|
||||||
$altrow(True)
|
$altrow(True)
|
||||||
<tr class="head">
|
<tr class="head">
|
||||||
<th>$_("Ip")</th>
|
<th> <!--country-flag--></th>
|
||||||
<th>$_("Up Speed")</th>
|
<th>$_("Address")</th>
|
||||||
<th>$_("Down Speed")</th>
|
<th>$_("Down Speed")</th>
|
||||||
<th>$_("Country")</th>
|
<th>$_("Up Speed")</th>
|
||||||
<th>$_("Client")</th>
|
<th>$_("Client")</th>
|
||||||
<th>$_("Progress")</th>
|
<!--<th>$_("Progress")</th>-->
|
||||||
</tr>
|
</tr>
|
||||||
$for peer in torrent.peers:
|
$for peer in torrent.peers:
|
||||||
<tr class="tab_$altrow()" >
|
<tr class="tab_$altrow()" >
|
||||||
|
<td><img src="$base/pixmaps/flags/$(peer['country'].lower())" /></td>
|
||||||
<td>$peer['ip']</td>
|
<td>$peer['ip']</td>
|
||||||
<td>$fspeed(peer['up_speed'])</td>
|
|
||||||
<td>$fspeed(peer['down_speed'])</td>
|
<td>$fspeed(peer['down_speed'])</td>
|
||||||
<td>$peer['country']</td>
|
<td>$fspeed(peer['up_speed'])</td>
|
||||||
<td>$peer['client']</td>
|
<td>$peer['client']</td>
|
||||||
|
<!--not in gtk-ui anymore, broken?
|
||||||
<td class="progress_bar">
|
<td class="progress_bar">
|
||||||
$if peer.get('progress'):
|
$if peer.get('progress'):
|
||||||
<div class="progress_bar_outer">
|
<div class="progress_bar_outer">
|
||||||
|
@ -31,6 +32,7 @@ $for peer in torrent.peers:
|
||||||
? %
|
? %
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
-->
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
|
|
Loading…
Reference in New Issue