From e544b508661531713b5f2495354bf2f93525792d Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 10 Dec 2023 19:58:57 +0100 Subject: [PATCH] Fix load error with the new overridable ajax webclient --- evennia/server/portal/webclient_ajax.py | 285 ++++++++++++------------ 1 file changed, 142 insertions(+), 143 deletions(-) diff --git a/evennia/server/portal/webclient_ajax.py b/evennia/server/portal/webclient_ajax.py index 24279b3215..9ec5211cdb 100644 --- a/evennia/server/portal/webclient_ajax.py +++ b/evennia/server/portal/webclient_ajax.py @@ -24,14 +24,13 @@ import time from django.conf import settings from django.utils.functional import Promise -from twisted.internet.task import LoopingCall -from twisted.web import resource, server - from evennia.server import session from evennia.utils import utils from evennia.utils.ansi import parse_ansi from evennia.utils.text2html import parse_html -from evennia.utils.utils import to_bytes, class_from_module, ip_from_request +from evennia.utils.utils import class_from_module, ip_from_request, to_bytes +from twisted.internet.task import LoopingCall +from twisted.web import resource, server _CLIENT_SESSIONS = utils.mod_import(settings.SESSION_ENGINE).SessionStore _RE_SCREENREADER_REGEX = re.compile( @@ -58,6 +57,145 @@ def jsonify(obj): return to_bytes(json.dumps(obj, ensure_ascii=False, cls=LazyEncoder)) +# +# A session type handling communication over the +# web client interface. +# + + +class AjaxWebClientSession(session.Session): + """ + This represents a session running in an AjaxWebclient. + """ + + def __init__(self, *args, **kwargs): + self.protocol_key = "webclient/ajax" + super().__init__(*args, **kwargs) + + def get_client_session(self): + """ + Get the Client browser session (used for auto-login based on browser session) + + Returns: + csession (ClientSession): This is a django-specific internal representation + of the browser session. + + """ + if self.csessid: + return _CLIENT_SESSIONS(session_key=self.csessid) + + def disconnect(self, reason="Server disconnected."): + """ + Disconnect from server. + + Args: + reason (str): Motivation for the disconnect. + """ + csession = self.get_client_session() + + if csession: + csession["webclient_authenticated_uid"] = None + csession.save() + self.logged_in = False + self.client.lineSend(self.csessid, ["connection_close", [reason], {}]) + self.client.client_disconnect(self.csessid) + self.sessionhandler.disconnect(self) + + def at_login(self): + csession = self.get_client_session() + if csession: + csession["webclient_authenticated_uid"] = self.uid + csession.save() + + def data_in(self, **kwargs): + """ + Data User -> Evennia + + Keyword Args: + kwargs (any): Incoming data. + + """ + self.sessionhandler.data_in(self, **kwargs) + + def data_out(self, **kwargs): + """ + Data Evennia -> User + + Keyword Args: + kwargs (any): Options to the protocol + """ + self.sessionhandler.data_out(self, **kwargs) + + def send_text(self, *args, **kwargs): + """ + Send text data. This will pre-process the text for + color-replacement, conversion to html etc. + + Args: + text (str): Text to send. + + Keyword Args: + options (dict): Options-dict with the following keys understood: + - raw (bool): No parsing at all (leave ansi-to-html markers unparsed). + - nocolor (bool): Remove all color. + - screenreader (bool): Use Screenreader mode. + - send_prompt (bool): Send a prompt with parsed html + + """ + if args: + args = list(args) + text = args[0] + if text is None: + return + else: + return + + flags = self.protocol_flags + text = utils.to_str(text) + + options = kwargs.pop("options", {}) + raw = options.get("raw", flags.get("RAW", False)) + xterm256 = options.get("xterm256", flags.get("XTERM256", True)) + useansi = options.get("ansi", flags.get("ANSI", True)) + nocolor = options.get("nocolor", flags.get("NOCOLOR") or not (xterm256 or useansi)) + screenreader = options.get("screenreader", flags.get("SCREENREADER", False)) + prompt = options.get("send_prompt", False) + + if screenreader: + # screenreader mode cleans up output + text = parse_ansi(text, strip_ansi=True, xterm256=False, mxp=False) + text = _RE_SCREENREADER_REGEX.sub("", text) + cmd = "prompt" if prompt else "text" + if raw: + args[0] = text + else: + args[0] = parse_html(text, strip_ansi=nocolor) + + # send to client on required form [cmdname, args, kwargs] + self.client.lineSend(self.csessid, [cmd, args, kwargs]) + + def send_prompt(self, *args, **kwargs): + kwargs["options"].update({"send_prompt": True}) + self.send_text(*args, **kwargs) + + def send_default(self, cmdname, *args, **kwargs): + """ + Data Evennia -> User. + + Args: + cmdname (str): The first argument will always be the oob cmd name. + *args (any): Remaining args will be arguments for `cmd`. + + Keyword Args: + options (dict): These are ignored for oob commands. Use command + arguments (which can hold dicts) to send instructions to the + client instead. + + """ + if not cmdname == "options": + self.client.lineSend(self.csessid, [cmdname, args, kwargs]) + + # # AjaxWebClient resource - this is called by the ajax client # using POST requests to /webclientdata. @@ -344,142 +482,3 @@ class AjaxWebClient(resource.Resource): else: # This should not happen if client sends valid data. return b'""' - - -# -# A session type handling communication over the -# web client interface. -# - - -class AjaxWebClientSession(session.Session): - """ - This represents a session running in an AjaxWebclient. - """ - - def __init__(self, *args, **kwargs): - self.protocol_key = "webclient/ajax" - super().__init__(*args, **kwargs) - - def get_client_session(self): - """ - Get the Client browser session (used for auto-login based on browser session) - - Returns: - csession (ClientSession): This is a django-specific internal representation - of the browser session. - - """ - if self.csessid: - return _CLIENT_SESSIONS(session_key=self.csessid) - - def disconnect(self, reason="Server disconnected."): - """ - Disconnect from server. - - Args: - reason (str): Motivation for the disconnect. - """ - csession = self.get_client_session() - - if csession: - csession["webclient_authenticated_uid"] = None - csession.save() - self.logged_in = False - self.client.lineSend(self.csessid, ["connection_close", [reason], {}]) - self.client.client_disconnect(self.csessid) - self.sessionhandler.disconnect(self) - - def at_login(self): - csession = self.get_client_session() - if csession: - csession["webclient_authenticated_uid"] = self.uid - csession.save() - - def data_in(self, **kwargs): - """ - Data User -> Evennia - - Keyword Args: - kwargs (any): Incoming data. - - """ - self.sessionhandler.data_in(self, **kwargs) - - def data_out(self, **kwargs): - """ - Data Evennia -> User - - Keyword Args: - kwargs (any): Options to the protocol - """ - self.sessionhandler.data_out(self, **kwargs) - - def send_text(self, *args, **kwargs): - """ - Send text data. This will pre-process the text for - color-replacement, conversion to html etc. - - Args: - text (str): Text to send. - - Keyword Args: - options (dict): Options-dict with the following keys understood: - - raw (bool): No parsing at all (leave ansi-to-html markers unparsed). - - nocolor (bool): Remove all color. - - screenreader (bool): Use Screenreader mode. - - send_prompt (bool): Send a prompt with parsed html - - """ - if args: - args = list(args) - text = args[0] - if text is None: - return - else: - return - - flags = self.protocol_flags - text = utils.to_str(text) - - options = kwargs.pop("options", {}) - raw = options.get("raw", flags.get("RAW", False)) - xterm256 = options.get("xterm256", flags.get("XTERM256", True)) - useansi = options.get("ansi", flags.get("ANSI", True)) - nocolor = options.get("nocolor", flags.get("NOCOLOR") or not (xterm256 or useansi)) - screenreader = options.get("screenreader", flags.get("SCREENREADER", False)) - prompt = options.get("send_prompt", False) - - if screenreader: - # screenreader mode cleans up output - text = parse_ansi(text, strip_ansi=True, xterm256=False, mxp=False) - text = _RE_SCREENREADER_REGEX.sub("", text) - cmd = "prompt" if prompt else "text" - if raw: - args[0] = text - else: - args[0] = parse_html(text, strip_ansi=nocolor) - - # send to client on required form [cmdname, args, kwargs] - self.client.lineSend(self.csessid, [cmd, args, kwargs]) - - def send_prompt(self, *args, **kwargs): - kwargs["options"].update({"send_prompt": True}) - self.send_text(*args, **kwargs) - - def send_default(self, cmdname, *args, **kwargs): - """ - Data Evennia -> User. - - Args: - cmdname (str): The first argument will always be the oob cmd name. - *args (any): Remaining args will be arguments for `cmd`. - - Keyword Args: - options (dict): These are ignored for oob commands. Use command - arguments (which can hold dicts) to send instructions to the - client instead. - - """ - if not cmdname == "options": - self.client.lineSend(self.csessid, [cmdname, args, kwargs])