I18n string cleanup and refactoring

This commit is contained in:
Griatch 2021-05-26 21:55:05 +02:00
parent 59dd0b007a
commit 7ff8cbb341
62 changed files with 890 additions and 738 deletions

View file

@ -93,7 +93,10 @@ def loads(data):
def _get_logger():
"Delay import of logger until absolutely necessary"
"""
Delay import of logger until absolutely necessary
"""
global _LOGGER
if not _LOGGER:
from evennia.utils import logger as _LOGGER
@ -102,7 +105,10 @@ def _get_logger():
@wraps
def catch_traceback(func):
"Helper decorator"
"""
Helper decorator
"""
def decorator(*args, **kwargs):
try:
@ -353,6 +359,7 @@ class AMPMultiConnectionProtocol(amp.AMP):
def dataReceived(self, data):
"""
Handle non-AMP messages, such as HTTP communication.
"""
# print("dataReceived: {}".format(data))
if data[:1] == NUL:
@ -413,6 +420,7 @@ class AMPMultiConnectionProtocol(amp.AMP):
that is irrelevant. If a true connection error happens, the
portal will continuously try to reconnect, showing the problem
that way.
"""
# print("ConnectionLost: {}: {}".format(self, reason))
try:
@ -422,20 +430,20 @@ class AMPMultiConnectionProtocol(amp.AMP):
# Error handling
def errback(self, e, info):
def errback(self, err, info):
"""
Error callback.
Handles errors to avoid dropping connections on server tracebacks.
Args:
e (Failure): Deferred error instance.
err (Failure): Deferred error instance.
info (str): Error string.
"""
e.trap(Exception)
err.trap(Exception)
_get_logger().log_err(
"AMP Error from {info}: {trcbck} {err}".format(
info=info, trcbck=e.getTraceback(), err=e.getErrorMessage()
info=info, trcbck=err.getTraceback(), err=err.getErrorMessage()
)
)

View file

@ -43,7 +43,10 @@ class AMPServerFactory(protocol.ServerFactory):
noisy = False
def logPrefix(self):
"How this is named in logs"
"""
How this is named in logs
"""
return "AMP"
def __init__(self, portal):

View file

@ -335,7 +335,7 @@ class GrapevineClient(WebSocketClientProtocol, Session):
# incoming broadcast from network
payload = data["payload"]
print("channels/broadcast:", payload["channel"], self.channel)
# print("channels/broadcast:", payload["channel"], self.channel)
if str(payload["channel"]) != self.channel:
# only echo from channels this particular bot actually listens to
return

View file

@ -183,6 +183,7 @@ class Portal(object):
Returns:
server_twistd_cmd (list): An instruction for starting the server, to pass to Popen.
"""
server_twistd_cmd = [
"twistd",
@ -196,7 +197,10 @@ class Portal(object):
return server_twistd_cmd
def get_info_dict(self):
"Return the Portal info, for display."
"""
Return the Portal info, for display.
"""
return INFO_DICT
def shutdown(self, _reactor_stopping=False, _stop_server=False):
@ -354,7 +358,8 @@ if SSH_ENABLED:
for port in SSH_PORTS:
pstring = "%s:%s" % (ifacestr, port)
factory = ssh.makeFactory(
{"protocolFactory": _ssh_protocol, "protocolArgs": (), "sessions": PORTAL_SESSIONS,}
{"protocolFactory": _ssh_protocol,
"protocolArgs": (), "sessions": PORTAL_SESSIONS}
)
factory.noisy = False
ssh_service = internet.TCPServer(port, factory, interface=interface)
@ -390,7 +395,7 @@ if WEBSERVER_ENABLED:
if WEBSOCKET_CLIENT_ENABLED and not websocket_started:
# start websocket client port for the webclient
# we only support one websocket client
from evennia.server.portal import webclient
from evennia.server.portal import webclient # noqa
from autobahn.twisted.websocket import WebSocketServerFactory
w_interface = WEBSOCKET_CLIENT_INTERFACE
@ -417,10 +422,13 @@ if WEBSERVER_ENABLED:
if WEB_PLUGINS_MODULE:
try:
web_root = WEB_PLUGINS_MODULE.at_webproxy_root_creation(web_root)
except Exception as e: # Legacy user has not added an at_webproxy_root_creation function in existing web plugins file
except Exception:
# Legacy user has not added an at_webproxy_root_creation function in existing
# web plugins file
INFO_DICT["errors"] = (
"WARNING: WEB_PLUGINS_MODULE is enabled but at_webproxy_root_creation() not found - "
"copy 'evennia/game_template/server/conf/web_plugins.py to mygame/server/conf."
"WARNING: WEB_PLUGINS_MODULE is enabled but at_webproxy_root_creation() "
"not found copy 'evennia/game_template/server/conf/web_plugins.py to "
"mygame/server/conf."
)
web_root = Website(web_root, logPath=settings.HTTP_LOG_FILE)
web_root.is_portal = True
@ -435,4 +443,3 @@ for plugin_module in PORTAL_SERVICES_PLUGIN_MODULES:
# external plugin services to start
if plugin_module:
plugin_module.start_plugin_services(PORTAL)

View file

@ -1,5 +1,6 @@
"""
Sessionhandler for portal sessions
Sessionhandler for portal sessions.
"""
@ -11,6 +12,7 @@ from evennia.server.sessionhandler import SessionHandler
from evennia.server.portal.amp import PCONN, PDISCONN, PCONNSYNC, PDISCONNALL
from evennia.utils.logger import log_trace
from evennia.utils.utils import class_from_module
from django.utils.translation import gettext as _
# module import
_MOD_IMPORT = None
@ -35,6 +37,8 @@ DUMMYSESSION = namedtuple("DummySession", ["sessid"])(0)
# Portal-SessionHandler class
# -------------------------------------------------------------
DOS_PROTECTION_MSG = _("{servername} DoS protection is active. You are queued to connect in {num} seconds ...")
class PortalSessionHandler(SessionHandler):
"""
@ -111,16 +115,12 @@ class PortalSessionHandler(SessionHandler):
_CONNECTION_QUEUE.appendleft(session)
if len(_CONNECTION_QUEUE) > 1:
session.data_out(
text=[
[
"%s DoS protection is active. You are queued to connect in %g seconds ..."
% (
settings.SERVERNAME,
len(_CONNECTION_QUEUE) * _MIN_TIME_BETWEEN_CONNECTS,
)
],
text=(
(DOS_PROTECTION_MSG.format(
servername=settings.SERVERNAME,
num=len(_CONNECTION_QUEUE) * _MIN_TIME_BETWEEN_CONNECTS),),
{},
]
)
)
now = time.time()
if (
@ -220,6 +220,7 @@ class PortalSessionHandler(SessionHandler):
def disconnect_all(self):
"""
Disconnect all sessions, informing the Server.
"""
def _callback(result, sessionhandler):
@ -478,5 +479,4 @@ class PortalSessionHandler(SessionHandler):
_PORTAL_SESSION_HANDLER_CLASS = class_from_module(settings.PORTAL_SESSION_HANDLER_CLASS)
PORTAL_SESSIONS = _PORTAL_SESSION_HANDLER_CLASS()

View file

@ -145,6 +145,7 @@ class RSSBotFactory(object):
def start(self):
"""
Called by portalsessionhandler. Starts the bot.
"""
def errback(fail):

View file

@ -61,24 +61,25 @@ CTRL_D = "\x04"
CTRL_BACKSLASH = "\x1c"
CTRL_L = "\x0c"
_NO_AUTOGEN = """
_NO_AUTOGEN = f"""
Evennia could not generate SSH private- and public keys ({{err}})
Using conch default keys instead.
If this error persists, create the keys manually (using the tools for your OS)
and put them here:
{}
{}
""".format(
_PRIVATE_KEY_FILE, _PUBLIC_KEY_FILE
)
{_PRIVATE_KEY_FILE}
{_PUBLIC_KEY_FILE}
"""
_BASE_SESSION_CLASS = class_from_module(settings.BASE_SESSION_CLASS)
# not used atm
class SSHServerFactory(protocol.ServerFactory):
"This is only to name this better in logs"
"""
This is only to name this better in logs
"""
noisy = False
def logPrefix(self):

View file

@ -50,6 +50,7 @@ class SSLProtocol(_TELNET_PROTOCOL_CLASS):
"""
Communication is the same as telnet, except data transfer
is done with encryption.
"""
def __init__(self, *args, **kwargs):
@ -62,6 +63,7 @@ def verify_SSL_key_and_cert(keyfile, certfile):
This function looks for RSA key and certificate in the current
directory. If files ssl.key and ssl.cert does not exist, they
are created.
"""
if not (os.path.exists(keyfile) and os.path.exists(certfile)):
@ -74,10 +76,11 @@ def verify_SSL_key_and_cert(keyfile, certfile):
try:
# create the RSA key and store it.
KEY_LENGTH = 1024
rsaKey = Key(RSA.generate(KEY_LENGTH))
keyString = rsaKey.toString(type="OPENSSH")
file(keyfile, "w+b").write(keyString)
KEY_LENGTH = 2048
rsa_key = Key(RSA.generate(KEY_LENGTH))
key_string = rsa_key.toString(type="OPENSSH")
with open(keyfile, "w+b") as fil:
fil.write(key_string)
except Exception as err:
print(NO_AUTOGEN.format(err=err, keyfile=keyfile))
sys.exit(5)

View file

@ -59,7 +59,10 @@ _BASE_SESSION_CLASS = class_from_module(settings.BASE_SESSION_CLASS)
class TelnetServerFactory(protocol.ServerFactory):
"This is only to name this better in logs"
"""
This exists only to name this better in logs.
"""
noisy = False
def logPrefix(self):
@ -71,6 +74,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
Each player connecting over telnet (ie using most traditional mud
clients) gets a telnet protocol instance assigned to them. All
communication between game and player goes through here.
"""
def __init__(self, *args, **kwargs):
@ -81,6 +85,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
"""
Unused by default, but a good place to put debug printouts
of incoming data.
"""
# print(f"telnet dataReceived: {data}")
try:
@ -145,11 +150,15 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
Client refuses do(linemode). This is common for MUD-specific
clients, but we must ask for the sake of raw telnet. We ignore
this error.
"""
pass
def _send_nop_keepalive(self):
"""Send NOP keepalive unless flag is set"""
"""
Send NOP keepalive unless flag is set
"""
if self.protocol_flags.get("NOPKEEPALIVE"):
self._write(IAC + NOP)
@ -158,7 +167,8 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
Allow to toggle the NOP keepalive for those sad clients that
can't even handle a NOP instruction. This is turned off by the
protocol_flag NOPKEEPALIVE (settable e.g. by the default
`@option` command).
`option` command).
"""
if self.nop_keep_alive and self.nop_keep_alive.running:
self.nop_keep_alive.stop()
@ -172,6 +182,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
When all have reported, a sync with the server is performed.
The system will force-call this sync after a small time to handle
clients that don't reply to handshakes at all.
"""
if timeout:
if self.handshakes > 0:
@ -186,6 +197,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
def at_login(self):
"""
Called when this session gets authenticated by the server.
"""
pass
@ -321,7 +333,10 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
self.data_in(text=dat + b"\n")
def _write(self, data):
"""hook overloading the one used in plain telnet"""
"""
Hook overloading the one used in plain telnet
"""
data = data.replace(b"\n", b"\r\n").replace(b"\r\r\n", b"\r\n")
super()._write(mccp_compress(self, data))
@ -347,7 +362,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
def disconnect(self, reason=""):
"""
generic hook for the engine to call in order to
Generic hook for the engine to call in order to
disconnect this protocol.
Args:
@ -376,6 +391,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
Keyword Args:
kwargs (any): Options to the protocol
"""
self.sessionhandler.data_out(self, **kwargs)
@ -442,7 +458,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
prompt = mxp_parse(prompt)
prompt = to_bytes(prompt, self)
prompt = prompt.replace(IAC, IAC + IAC).replace(b"\n", b"\r\n")
if not self.protocol_flags.get("NOPROMPTGOAHEAD",
if not self.protocol_flags.get("NOPROMPTGOAHEAD",
self.protocol_flags.get("NOGOAHEAD", True)):
prompt += IAC + GA
self.transport.write(mccp_compress(self, prompt))
@ -488,6 +504,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
def send_default(self, cmdname, *args, **kwargs):
"""
Send other oob data
"""
if not cmdname == "options":
self.oob.data_out(cmdname, *args, **kwargs)

View file

@ -46,32 +46,29 @@ _CERTIFICATE_ISSUER = {
# messages
NO_AUTOGEN = """
NO_AUTOGEN = f"""
Evennia could not auto-generate the SSL private- and public keys ({{err}}).
If this error persists, create them manually (using the tools for your OS). The files
should be placed and named like this:
{}
{}
""".format(
_PRIVATE_KEY_FILE, _PUBLIC_KEY_FILE
)
{_PRIVATE_KEY_FILE}
{_PUBLIC_KEY_FILE}
"""
NO_AUTOCERT = """
Evennia's could not auto-generate the SSL certificate ({{err}}).
The private key already exists here:
{}
{_PRIVATE_KEY_FILE}
If this error persists, create the certificate manually (using the private key and
the tools for your OS). The file should be placed and named like this:
{}
""".format(
_PRIVATE_KEY_FILE, _CERTIFICATE_FILE
)
{_CERTIFICATE_FILE}
"""
class SSLProtocol(TelnetProtocol):
"""
Communication is the same as telnet, except data transfer
is done with encryption set up by the portal at start time.
"""
def __init__(self, *args, **kwargs):

View file

@ -44,6 +44,7 @@ _BASE_SESSION_CLASS = class_from_module(settings.BASE_SESSION_CLASS)
class WebSocketClient(WebSocketServerProtocol, _BASE_SESSION_CLASS):
"""
Implements the server-side of the Websocket connection.
"""
# nonce value, used to prevent the webclient from erasing the
@ -155,7 +156,7 @@ class WebSocketClient(WebSocketServerProtocol, _BASE_SESSION_CLASS):
# in case anyone wants to expose this functionality later.
#
# sendClose() under autobahn/websocket/interfaces.py
ret = self.sendClose(CLOSE_NORMAL, reason)
self.sendClose(CLOSE_NORMAL, reason)
def onClose(self, wasClean, code=None, reason=None):
"""

View file

@ -15,6 +15,7 @@ http://localhost:4001/webclient.)
The WebClient resource in this module will
handle these requests and act as a gateway
to sessions connected over the webclient.
"""
import json
import re
@ -27,7 +28,7 @@ from django.utils.functional import Promise
from django.conf import settings
from evennia.utils.ansi import parse_ansi
from evennia.utils import utils
from evennia.utils.utils import to_bytes, to_str
from evennia.utils.utils import to_bytes
from evennia.utils.text2html import parse_html
from evennia.server import session
@ -223,10 +224,13 @@ class AjaxWebClient(resource.Resource):
return jsonify({"msg": host_string, "csessid": csessid})
def mode_keepalive(self, request):
"""
This is called by render_POST when the
client is replying to the keepalive.
Args:
request (Request): Incoming request.
"""
csessid = self.get_client_sessid(request)
self.last_alive[csessid] = (time.time(), False)