Starting reworking the webclient to use the new oob system format.
This commit is contained in:
parent
a24b79bb97
commit
850c5effaa
3 changed files with 145 additions and 54 deletions
|
|
@ -236,9 +236,9 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
|
||||||
return
|
return
|
||||||
if "oob" in kwargs and "OOB" in self.protocol_flags:
|
if "oob" in kwargs and "OOB" in self.protocol_flags:
|
||||||
# oob is a list of [(cmdname, arg, kwarg), ...]
|
# oob is a list of [(cmdname, arg, kwarg), ...]
|
||||||
for cmdname, args, kwargs in kwargs["oob"]:
|
for cmdname, args, okwargs in kwargs["oob"]:
|
||||||
#print "telnet oob data_out:", cmdname, args, kwargs
|
#print "telnet oob data_out:", cmdname, args, kwargs
|
||||||
self.oob.data_out(cmdname, *args, **kwargs)
|
self.oob.data_out(cmdname, *args, **okwargs)
|
||||||
|
|
||||||
# parse **kwargs, falling back to ttype if nothing is given explicitly
|
# parse **kwargs, falling back to ttype if nothing is given explicitly
|
||||||
ttype = self.protocol_flags.get('TTYPE', {})
|
ttype = self.protocol_flags.get('TTYPE', {})
|
||||||
|
|
|
||||||
|
|
@ -78,27 +78,48 @@ class WebSocketClient(Protocol, Session):
|
||||||
OOB - This is an Out-of-band instruction. If so,
|
OOB - This is an Out-of-band instruction. If so,
|
||||||
the remaining string should be a json-packed
|
the remaining string should be a json-packed
|
||||||
string on the form {oobfuncname: [args, ], ...}
|
string on the form {oobfuncname: [args, ], ...}
|
||||||
any other prefix (or lack of prefix) is considered
|
CMD - plain text data, to be treated like a game
|
||||||
plain text data, to be treated like a game
|
|
||||||
input command.
|
input command.
|
||||||
"""
|
"""
|
||||||
if string[:3] == "OOB":
|
mode = string[:3]
|
||||||
string = string[3:]
|
data = string[3:]
|
||||||
try:
|
|
||||||
oobdata = json.loads(string)
|
if mode == "OOB":
|
||||||
for (key, args) in oobdata.items():
|
# an out-of-band command
|
||||||
#print "oob data in:", (key, args)
|
self.decode_json(data)
|
||||||
self.data_in(text=None, oob=(key, make_iter(args)))
|
elif mode == "CMD":
|
||||||
except Exception:
|
|
||||||
log_trace("Websocket malformed OOB request: %s" % string)
|
|
||||||
else:
|
|
||||||
# plain text input
|
# plain text input
|
||||||
self.data_in(text=string)
|
self.data_in(text=data)
|
||||||
|
|
||||||
def sendLine(self, line):
|
def sendLine(self, line):
|
||||||
"send data to client"
|
"send data to client"
|
||||||
return self.transport.write(line)
|
return self.transport.write(line)
|
||||||
|
|
||||||
|
def json_decode(self, data):
|
||||||
|
"""
|
||||||
|
Decodes incoming data from the client
|
||||||
|
|
||||||
|
[cmdname, [args],{kwargs}] -> cmdname *args **kwargs
|
||||||
|
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
cmdname, args, kwargs = json.loads(data)
|
||||||
|
except Exception:
|
||||||
|
log_trace("Websocket malformed OOB request: %s" % data)
|
||||||
|
raise
|
||||||
|
self.sessionhandler.data_in(oob=(cmdname, args, kwargs))
|
||||||
|
|
||||||
|
def json_encode(self, cmdname, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Encode OOB data for sending to client
|
||||||
|
|
||||||
|
cmdname *args -> cmdname [json array]
|
||||||
|
cmdname **kwargs -> cmdname {json object}
|
||||||
|
|
||||||
|
"""
|
||||||
|
cmdtuple = [cmdname, list(args), kwargs]
|
||||||
|
self.sendLine("OOB" + json.dumps(cmdtuple))
|
||||||
|
|
||||||
def data_in(self, text=None, **kwargs):
|
def data_in(self, text=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Data Websocket -> Server
|
Data Websocket -> Server
|
||||||
|
|
@ -121,9 +142,9 @@ class WebSocketClient(Protocol, Session):
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
self.sendLine(str(e))
|
self.sendLine(str(e))
|
||||||
if "oob" in kwargs:
|
if "oob" in kwargs:
|
||||||
oobstruct = self.sessionhandler.oobstruct_parser(kwargs.pop("oob"))
|
for cmdname, args, okwargs in kwargs["oob"]:
|
||||||
#print "oob data_out:", "OOB" + json.dumps(oobstruct)
|
self.encode_json(cmdname, *args, **okwargs)
|
||||||
self.sendLine("OOB" + json.dumps(oobstruct))
|
|
||||||
raw = kwargs.get("raw", False)
|
raw = kwargs.get("raw", False)
|
||||||
nomarkup = kwargs.get("nomarkup", False)
|
nomarkup = kwargs.get("nomarkup", False)
|
||||||
if "prompt" in kwargs:
|
if "prompt" in kwargs:
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,14 @@ function list (args, kwargs) {
|
||||||
|
|
||||||
function send (args, kwargs) {
|
function send (args, kwargs) {
|
||||||
// show in main window. SEND returns kwargs {name:value}.
|
// show in main window. SEND returns kwargs {name:value}.
|
||||||
for (sendvalue in kwargs) {
|
for (var sendvalue in kwargs) {
|
||||||
doShow("out", sendvalue + " = " + kwargs[sendvalue]);}
|
doShow("out", sendvalue + " = " + kwargs[sendvalue]);}
|
||||||
}
|
}
|
||||||
|
|
||||||
function report (args, kwargs) {
|
function report (args, kwargs) {
|
||||||
// show in main window. REPORT returns kwargs
|
// show in main window. REPORT returns kwargs
|
||||||
// {attrfieldname:value}
|
// {attrfieldname:value}
|
||||||
for (name in kwargs) {
|
for (var name in kwargs) {
|
||||||
doShow("out", name + " = " + kwargs[name]) }
|
doShow("out", name + " = " + kwargs[name]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,6 +55,8 @@ function err (args, kwargs) {
|
||||||
// display error
|
// display error
|
||||||
doShow("err", args) }
|
doShow("err", args) }
|
||||||
|
|
||||||
|
// Map above functions with oob command names
|
||||||
|
var CMD_MAP = {"ECHO":echo, "LIST":list, "SEND":send, "REPORT":report, "error":err};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Webclient code
|
// Webclient code
|
||||||
|
|
@ -86,34 +88,60 @@ function onClose(evt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMessage(evt) {
|
function onMessage(evt) {
|
||||||
// called when the Evennia is sending data to client
|
// called when the Evennia is sending data to client.
|
||||||
var inmsg = evt.data
|
// Such data is always prepended by a 3-letter marker
|
||||||
if (inmsg.length > 3 && inmsg.substr(0, 3) == "OOB") {
|
// OOB, PRT or CMD, defining its operation
|
||||||
|
var inmsg = evt.data;
|
||||||
|
if (inmsg.length < 4) return;
|
||||||
|
var mode = inmsg.substr(0, 3);
|
||||||
|
var message = inmsg.slice(3);
|
||||||
|
if (mode == "OOB") {
|
||||||
// dynamically call oob methods, if available
|
// dynamically call oob methods, if available
|
||||||
|
// The variables are come on the form [(cmname, [args], {kwargs}), ...]
|
||||||
|
var oobcmds = JSON.parse(message);
|
||||||
|
var errmsg = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var oobarray = JSON.parse(inmsg.slice(3));} // everything after OOB }
|
if (oobcmds instanceof Array == false) {
|
||||||
catch(err) {
|
errmsg = "oob instruction's outermost level must be an Array.";
|
||||||
// not JSON packed - a normal text
|
throw
|
||||||
doShow('out', inmsg);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (typeof oobarray != "undefined") {
|
for (var icmd = 0; i < oobcmds.length; icmd++) {
|
||||||
for (var ind in oobarray) {
|
// call each command tuple in turn
|
||||||
try {
|
var cmdname = oobcmds[icmd][0];
|
||||||
window[oobarray[ind][0]](oobarray[ind][1], oobarray[ind][2]) }
|
var args = oobcmds[icmd][1];
|
||||||
catch(err) {
|
var kwargs = oobcmds[icmd][2];
|
||||||
doShow("err", "Could not execute js OOB function '" + oobarray[ind][0] + "(" + oobarray[ind][1] + oobarray[ind][2] + ")'") }
|
// match cmdname with a command existing in the
|
||||||
|
// CMD_MAP mapping
|
||||||
|
if (cmdname in CMD_MAP == false) {
|
||||||
|
errmsg = "oob command " + cmdname + " is not supported by client.";
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
// we have a matching oob command in CMD_MAP.
|
||||||
|
// Prepare the error message beforehand
|
||||||
|
errmsg = "Client could not execute OOB function" + "cmdname" + "(" + args + kwargs + ").";
|
||||||
|
// Execute
|
||||||
|
CMD_MAP[cmdname](args, kwargs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
catch(error) {
|
||||||
else if (inmsg.length >= 6 && inmsg.substr(0, 6) == "PROMPT") {
|
if (errmsg) {
|
||||||
// handle prompt
|
doShow("err", errmsg);
|
||||||
var game_prompt = inmsg.slice(6);
|
|
||||||
doPrompt("prompt", game_prompt);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
doShow("err", "Client could not execute OOB function in " + oobcmds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mode == "PRT") {
|
||||||
|
// handle prompt
|
||||||
|
doPrompt("prompt", message);
|
||||||
|
}
|
||||||
|
else if (mode == "CMD") {
|
||||||
|
// normal command operation
|
||||||
// normal message
|
// normal message
|
||||||
doShow('out', inmsg); }
|
doShow('out', message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onError(evt) {
|
function onError(evt) {
|
||||||
|
|
@ -123,15 +151,17 @@ function onError(evt) {
|
||||||
|
|
||||||
function doSend(){
|
function doSend(){
|
||||||
// relays data from client to Evennia.
|
// relays data from client to Evennia.
|
||||||
// If OOB_debug is set, allows OOB test data on the
|
// If OOB_debug is set, allows OOB test data using the syntax
|
||||||
// form ##OOB{func:args}
|
// ##OOB[funcname, args, kwargs]
|
||||||
outmsg = $("#inputfield").val();
|
outmsg = $("#inputfield").val();
|
||||||
history_add(outmsg);
|
history_add(outmsg);
|
||||||
HISTORY_POS = 0;
|
HISTORY_POS = 0;
|
||||||
$('#inputform')[0].reset(); // clear input field
|
$('#inputform')[0].reset(); // clear input field
|
||||||
|
|
||||||
if (OOB_debug && outmsg.length > 4 && outmsg.substr(0, 5) == "##OOB") {
|
if (OOB_debug && outmsg.length > 4 && outmsg.substr(0, 5) == "##OOB") {
|
||||||
if (outmsg == "##OOBUNITTEST") {
|
// OOB direct input
|
||||||
|
var outmsg = outmsg.slice(5);
|
||||||
|
if (outmsg == "UNITTEST") {
|
||||||
// unittest mode
|
// unittest mode
|
||||||
doShow("out", "OOB testing mode ...");
|
doShow("out", "OOB testing mode ...");
|
||||||
doOOB(JSON.parse('{"ECHO":"Echo test"}'));
|
doOOB(JSON.parse('{"ECHO":"Echo test"}'));
|
||||||
|
|
@ -144,26 +174,66 @@ function doSend(){
|
||||||
doShow("out", "... OOB testing mode done.");
|
doShow("out", "... OOB testing mode done.");
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// test OOB messaging
|
// send a manual OOB instruction
|
||||||
try {
|
try {
|
||||||
doShow("out", "OOB input: " + outmsg.slice(5));
|
doShow("out", "OOB input: " + outmsg);
|
||||||
if (outmsg.length == 5) {
|
if (outmsg.length == 5) {
|
||||||
doShow("err", "OOB testing syntax: ##OOB{\"cmdname:args, ...}"); }
|
doShow("err", "OOB syntax: ##OOB[\"cmdname\", [args], {kwargs}]"); }
|
||||||
else {
|
else {
|
||||||
doOOB(JSON.parse(outmsg.slice(5))); } }
|
doOOB(JSON.parse(outmsg.slice(5))); }
|
||||||
|
}
|
||||||
catch(err) {
|
catch(err) {
|
||||||
doShow("err", err) }
|
doShow("err", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// normal output
|
// normal output
|
||||||
websocket.send(outmsg); }
|
websocket.send("CMD" + outmsg); }
|
||||||
}
|
}
|
||||||
|
|
||||||
function doOOB(oobdict){
|
function doOOB(cmdstring){
|
||||||
// Send OOB data from client to Evennia.
|
// Send OOB data from client to Evennia.
|
||||||
// Takes input on form {funcname:[args], funcname: [args], ... }
|
// Takes input strings with syntax ["cmdname", args, kwargs]
|
||||||
var oobmsg = JSON.stringify(oobdict);
|
var errmsg = "";
|
||||||
|
try {
|
||||||
|
var cmdtuple = JSON.parse(cmdstring);
|
||||||
|
var oobmsg = "";
|
||||||
|
if (cmdtuple instanceof Array == false) {
|
||||||
|
// a single command instruction without arguments
|
||||||
|
oobmsg = [cmdtuple, (), {}];
|
||||||
|
}
|
||||||
|
else if {
|
||||||
|
switch (cmdtuple.length) {
|
||||||
|
case 0:
|
||||||
|
throw;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// [cmdname]
|
||||||
|
oobmsg = [cmdtuple[0], (), {}];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// [cmdname, args]
|
||||||
|
oobmsg = [cmdtuple[0], cmdtuple[1], {}];
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// [cmdname, args, kwargs]
|
||||||
|
oobmsg = [cmdtuple[0], cmdtuple[1], cmdtuple[2]];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errmsg = "Malformed OOB instruction:" + cmdstring
|
||||||
|
}
|
||||||
|
// convert to string and send it to the server
|
||||||
|
oobmsg = JSON.stringify(oobmsg);
|
||||||
websocket.send("OOB" + oobmsg);
|
websocket.send("OOB" + oobmsg);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
if (errmsg) {
|
||||||
|
doSend("err", errmsg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
doSend("err", "OOB output " + cmdtuple + " is not on the right form.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doShow(type, msg){
|
function doShow(type, msg){
|
||||||
|
|
@ -352,6 +422,6 @@ $(document).ready(function(){
|
||||||
}, 500);
|
}, 500);
|
||||||
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
|
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
|
||||||
setInterval(function() {
|
setInterval(function() {
|
||||||
websocket.send("idle");
|
doSend("idle")
|
||||||
}, 60000*3);
|
}, 60000*3);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue