Add support for MSDP LIST/REPORT/UNREPORT. Resolves #1507.
This commit is contained in:
parent
7bf4874f7e
commit
fccb128952
4 changed files with 110 additions and 25 deletions
16
CHANGELOG.md
16
CHANGELOG.md
|
|
@ -93,18 +93,17 @@ Web/Django standard initiative (@strikaco)
|
||||||
+ `validate_password`: Mechanism for validating a password based on predefined Django validators.
|
+ `validate_password`: Mechanism for validating a password based on predefined Django validators.
|
||||||
+ `set_password`: Apply password to account, using validation checks.
|
+ `set_password`: Apply password to account, using validation checks.
|
||||||
|
|
||||||
|
### Server
|
||||||
|
|
||||||
|
- Convert ServerConf model to store its values as a Picklefield (same as Attributes) instead of using a custom solution.
|
||||||
|
- OOB: Add support for MSDP LIST, REPORT, UNREPORT commands (re-mapped to `msdp_list`,
|
||||||
|
`msdp_report`, `msdp_unreport` inlinefuncs_)
|
||||||
|
|
||||||
### Utils
|
### Utils
|
||||||
|
|
||||||
- `evennia` launcher now fully handles all django-admin commands, like running tests in parallel.
|
- `evennia` launcher now fully handles all django-admin commands, like running tests in parallel.
|
||||||
- `evennia.utils.create.account` now also takes `tags` and `attrs` keywords.
|
- `evennia.utils.create.account` now also takes `tags` and `attrs` keywords.
|
||||||
- Added many more unit tests.
|
- Added many more unit tests.
|
||||||
|
|
||||||
### Server
|
|
||||||
|
|
||||||
- Convert ServerConf model to store its values as a Picklefield (same as Attributes) instead of using a custom solution.
|
|
||||||
|
|
||||||
### Utils
|
|
||||||
|
|
||||||
- Swap argument order of `evennia.set_trace` to `set_trace(term_size=(140, 40), debugger='auto')`
|
- Swap argument order of `evennia.set_trace` to `set_trace(term_size=(140, 40), debugger='auto')`
|
||||||
since the size is more likely to be changed on the command line.
|
since the size is more likely to be changed on the command line.
|
||||||
- `utils.to_str(text, session=None)` now acts as the old `utils.to_unicode` (which was removed).
|
- `utils.to_str(text, session=None)` now acts as the old `utils.to_unicode` (which was removed).
|
||||||
|
|
@ -113,7 +112,8 @@ Web/Django standard initiative (@strikaco)
|
||||||
`force_string` flag was removed and assumed always set).
|
`force_string` flag was removed and assumed always set).
|
||||||
- `utils.to_bytes(text, session=None)` replaces the old `utils.to_str()` functionality and converts
|
- `utils.to_bytes(text, session=None)` replaces the old `utils.to_str()` functionality and converts
|
||||||
str to bytes.
|
str to bytes.
|
||||||
|
- `evennia.MONITOR_HANDLER.all` now takes keyword argument `obj` to only retrieve monitors from that specific
|
||||||
|
Object (rather than all monitors in the entire handler).
|
||||||
|
|
||||||
|
|
||||||
### Contribs
|
### Contribs
|
||||||
|
|
|
||||||
|
|
@ -172,16 +172,21 @@ class MonitorHandler(object):
|
||||||
"""
|
"""
|
||||||
self.monitors = defaultdict(lambda: defaultdict(dict))
|
self.monitors = defaultdict(lambda: defaultdict(dict))
|
||||||
|
|
||||||
def all(self):
|
def all(self, obj=None):
|
||||||
"""
|
"""
|
||||||
List all monitors.
|
List all monitors or all monitors of a given object.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj (Object): The object on which to list all monitors.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
monitors (list): The handled monitors.
|
monitors (list): The handled monitors.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
output = []
|
output = []
|
||||||
for obj in self.monitors:
|
objs = [obj] if obj else self.monitors
|
||||||
|
|
||||||
|
for obj in objs:
|
||||||
for fieldname in self.monitors[obj]:
|
for fieldname in self.monitors[obj]:
|
||||||
for idstring, (callback, persistent, kwargs) in self.monitors[obj][fieldname].items():
|
for idstring, (callback, persistent, kwargs) in self.monitors[obj][fieldname].items():
|
||||||
output.append((obj, fieldname, idstring, persistent, kwargs))
|
output.append((obj, fieldname, idstring, persistent, kwargs))
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ Functions for processing input commands.
|
||||||
|
|
||||||
All global functions in this module whose name does not start with "_"
|
All global functions in this module whose name does not start with "_"
|
||||||
is considered an inputfunc. Each function must have the following
|
is considered an inputfunc. Each function must have the following
|
||||||
callsign:
|
callsign (where inputfunc name is always lower-case, no matter what the
|
||||||
|
OOB input name looked like):
|
||||||
|
|
||||||
inputfunc(session, *args, **kwargs)
|
inputfunc(session, *args, **kwargs)
|
||||||
|
|
||||||
|
|
@ -138,6 +139,11 @@ def default(session, cmdname, *args, **kwargs):
|
||||||
log_err(err)
|
log_err(err)
|
||||||
|
|
||||||
|
|
||||||
|
_CLIENT_OPTIONS = \
|
||||||
|
("ANSI", "XTERM256", "MXP", "UTF-8", "SCREENREADER", "ENCODING", "MCCP",
|
||||||
|
"SCREENHEIGHT", "SCREENWIDTH", "INPUTDEBUG", "RAW", "NOCOLOR", "NOGOAHEAD")
|
||||||
|
|
||||||
|
|
||||||
def client_options(session, *args, **kwargs):
|
def client_options(session, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
This allows the client an OOB way to inform us about its name and capabilities.
|
This allows the client an OOB way to inform us about its name and capabilities.
|
||||||
|
|
@ -165,12 +171,7 @@ def client_options(session, *args, **kwargs):
|
||||||
if not kwargs or kwargs.get("get", False):
|
if not kwargs or kwargs.get("get", False):
|
||||||
# return current settings
|
# return current settings
|
||||||
options = dict((key, old_flags[key]) for key in old_flags
|
options = dict((key, old_flags[key]) for key in old_flags
|
||||||
if key.upper() in ("ANSI", "XTERM256", "MXP",
|
if key.upper() in _CLIENT_OPTIONS)
|
||||||
"UTF-8", "SCREENREADER", "ENCODING",
|
|
||||||
"MCCP", "SCREENHEIGHT",
|
|
||||||
"SCREENWIDTH", "INPUTDEBUG",
|
|
||||||
"RAW", "NOCOLOR",
|
|
||||||
"NOGOAHEAD"))
|
|
||||||
session.msg(client_options=options)
|
session.msg(client_options=options)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -239,11 +240,6 @@ def client_options(session, *args, **kwargs):
|
||||||
{session.sessid: {"protocol_flags": flags}})
|
{session.sessid: {"protocol_flags": flags}})
|
||||||
|
|
||||||
|
|
||||||
# GMCP alias
|
|
||||||
hello = client_options
|
|
||||||
supports_set = client_options
|
|
||||||
|
|
||||||
|
|
||||||
def get_client_options(session, *args, **kwargs):
|
def get_client_options(session, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Alias wrapper for getting options.
|
Alias wrapper for getting options.
|
||||||
|
|
@ -368,10 +364,14 @@ def _on_monitor_change(**kwargs):
|
||||||
obj = kwargs["obj"]
|
obj = kwargs["obj"]
|
||||||
name = kwargs["name"]
|
name = kwargs["name"]
|
||||||
session = kwargs["session"]
|
session = kwargs["session"]
|
||||||
|
outputfunc_name = kwargs['outputfunc_name']
|
||||||
|
|
||||||
# the session may be None if the char quits and someone
|
# the session may be None if the char quits and someone
|
||||||
# else then edits the object
|
# else then edits the object
|
||||||
|
|
||||||
if session:
|
if session:
|
||||||
session.msg(monitor={"name": name, "value": _GA(obj, fieldname)})
|
callsign = {outputfunc_name: {"name": name, "value": _GA(obj, fieldname)}}
|
||||||
|
session.msg(**callsign)
|
||||||
|
|
||||||
|
|
||||||
def monitor(session, *args, **kwargs):
|
def monitor(session, *args, **kwargs):
|
||||||
|
|
@ -384,10 +384,14 @@ def monitor(session, *args, **kwargs):
|
||||||
in the _monitorable dict earlier in this module
|
in the _monitorable dict earlier in this module
|
||||||
are accepted.
|
are accepted.
|
||||||
stop (bool): Stop monitoring the above name.
|
stop (bool): Stop monitoring the above name.
|
||||||
|
outputfunc_name (str, optional): Change the name of
|
||||||
|
the outputfunc name. This is used e.g. by MSDP which
|
||||||
|
has its own specific output format.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from evennia.scripts.monitorhandler import MONITOR_HANDLER
|
from evennia.scripts.monitorhandler import MONITOR_HANDLER
|
||||||
name = kwargs.get("name", None)
|
name = kwargs.get("name", None)
|
||||||
|
outputfunc_name = kwargs("outputfunc_name", "monitor")
|
||||||
if name and name in _monitorable and session.puppet:
|
if name and name in _monitorable and session.puppet:
|
||||||
field_name = _monitorable[name]
|
field_name = _monitorable[name]
|
||||||
obj = session.puppet
|
obj = session.puppet
|
||||||
|
|
@ -396,7 +400,8 @@ def monitor(session, *args, **kwargs):
|
||||||
else:
|
else:
|
||||||
# the handler will add fieldname and obj to the kwargs automatically
|
# the handler will add fieldname and obj to the kwargs automatically
|
||||||
MONITOR_HANDLER.add(obj, field_name, _on_monitor_change, idstring=session.sessid,
|
MONITOR_HANDLER.add(obj, field_name, _on_monitor_change, idstring=session.sessid,
|
||||||
persistent=False, name=name, session=session)
|
persistent=False, name=name, session=session,
|
||||||
|
outputfunc_name=outputfunc_name)
|
||||||
|
|
||||||
|
|
||||||
def unmonitor(session, *args, **kwargs):
|
def unmonitor(session, *args, **kwargs):
|
||||||
|
|
@ -407,6 +412,17 @@ def unmonitor(session, *args, **kwargs):
|
||||||
monitor(session, *args, **kwargs)
|
monitor(session, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def monitored(session, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Report on what is being monitored
|
||||||
|
|
||||||
|
"""
|
||||||
|
from evennia.scripts.monitorhandler import MONITOR_HANDLER
|
||||||
|
obj = session.puppet
|
||||||
|
monitors = MONITOR_HANDLER.all(obj=obj)
|
||||||
|
session.msg(monitored=(monitors, {}))
|
||||||
|
|
||||||
|
|
||||||
def _on_webclient_options_change(**kwargs):
|
def _on_webclient_options_change(**kwargs):
|
||||||
"""
|
"""
|
||||||
Called when the webclient options stored on the account changes.
|
Called when the webclient options stored on the account changes.
|
||||||
|
|
@ -469,3 +485,60 @@ def webclient_options(session, *args, **kwargs):
|
||||||
# kwargs provided: persist them to the account object
|
# kwargs provided: persist them to the account object
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
clientoptions[key] = value
|
clientoptions[key] = value
|
||||||
|
|
||||||
|
|
||||||
|
# OOB protocol-specific aliases and wrappers
|
||||||
|
|
||||||
|
# GMCP aliases
|
||||||
|
hello = client_options
|
||||||
|
supports_set = client_options
|
||||||
|
|
||||||
|
|
||||||
|
# MSDP aliases (some of the the generic MSDP commands defined in the MSDP spec are prefixed
|
||||||
|
# by msdp_ at the protocol level)
|
||||||
|
# See https://tintin.sourceforge.io/protocols/msdp/
|
||||||
|
|
||||||
|
|
||||||
|
def msdp_list(session, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
MSDP LIST command
|
||||||
|
|
||||||
|
"""
|
||||||
|
from evennia.scripts.monitorhandler import MONITOR_HANDLER
|
||||||
|
args_lower = [arg.lower() for arg in args]
|
||||||
|
if "commands" in args_lower:
|
||||||
|
inputfuncs = [key[5:] if key.startswith("msdp_") else key
|
||||||
|
for key in session.sessionhandler.get_inputfuncs().keys()]
|
||||||
|
session.msg(commands=(inputfuncs, {}))
|
||||||
|
if "lists" in args_lower:
|
||||||
|
session.msg(lists=(['commands', 'lists', 'configurable_variables', 'reportable_variables',
|
||||||
|
'reported_variables', 'sendable_variables'], {}))
|
||||||
|
if "configurable_variables" in args_lower:
|
||||||
|
session.msg(configurable_variables=(_CLIENT_OPTIONS, {}))
|
||||||
|
if "reportable_variables" in args_lower:
|
||||||
|
session.msg(reportable_variables=(_monitorable, {}))
|
||||||
|
if "reported_variables" in args_lower:
|
||||||
|
obj = session.puppet
|
||||||
|
monitor_infos = MONITOR_HANDLER.all(obj=obj)
|
||||||
|
fieldnames = [tup[1] for tup in monitor_infos]
|
||||||
|
session.msg(reported_variables=(fieldnames, {}))
|
||||||
|
if "sendable_variables" in args_lower:
|
||||||
|
# no default sendable variables
|
||||||
|
session.msg(sendable_variables=([], {}))
|
||||||
|
|
||||||
|
|
||||||
|
def msdp_report(session, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
MSDP REPORT command
|
||||||
|
|
||||||
|
"""
|
||||||
|
kwargs['outputfunc_name': 'report']
|
||||||
|
monitor(session, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def msdp_unreport(session, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
MSDP UNREPORT command
|
||||||
|
|
||||||
|
"""
|
||||||
|
unmonitor(session, *args, **kwargs)
|
||||||
|
|
|
||||||
|
|
@ -350,6 +350,13 @@ class TelnetOOB(object):
|
||||||
for key, var in variables.items():
|
for key, var in variables.items():
|
||||||
cmds[key] = [[var], {}]
|
cmds[key] = [[var], {}]
|
||||||
|
|
||||||
|
# remap the 'generic msdp commands' to avoid colliding with builtins etc
|
||||||
|
# by prepending "msdp_"
|
||||||
|
lower_case = {key.lower(): key for key in cmds}
|
||||||
|
for remap in ("list", "report", "reset", "send", "unreport"):
|
||||||
|
if remap in lower_case:
|
||||||
|
cmds["msdp_{}".format(remap)] = cmds.pop(lower_case[remap])
|
||||||
|
|
||||||
# print("msdp data in:", cmds) # DEBUG
|
# print("msdp data in:", cmds) # DEBUG
|
||||||
self.protocol.data_in(**cmds)
|
self.protocol.data_in(**cmds)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue