Merge branch 'develop' into develop-muxcommand

This commit is contained in:
BlauFeuer 2018-03-05 13:36:39 -05:00 committed by GitHub
commit 111b1c5136
10 changed files with 149 additions and 41 deletions

View file

@ -594,6 +594,9 @@ class CmdDesc(COMMAND_DEFAULT_CLASS):
if not obj: if not obj:
return return
if not (obj.access(self.caller, 'control') or obj.access(self.caller, 'edit')):
self.caller.msg("You don't have permission to edit the description of %s." % obj.key)
self.caller.db.evmenu_target = obj self.caller.db.evmenu_target = obj
# launch the editor # launch the editor
EvEditor(self.caller, loadfunc=_desc_load, savefunc=_desc_save, EvEditor(self.caller, loadfunc=_desc_load, savefunc=_desc_save,
@ -623,7 +626,7 @@ class CmdDesc(COMMAND_DEFAULT_CLASS):
if not obj: if not obj:
return return
desc = self.args desc = self.args
if obj.access(caller, "edit"): if (obj.access(self.caller, 'control') or obj.access(self.caller, 'edit')):
obj.db.desc = desc obj.db.desc = desc
caller.msg("The description was set on %s." % obj.get_display_name(caller)) caller.msg("The description was set on %s." % obj.get_display_name(caller))
else: else:
@ -1646,6 +1649,10 @@ class CmdSetAttribute(ObjManipCommand):
result = [] result = []
if "edit" in self.switches: if "edit" in self.switches:
# edit in the line editor # edit in the line editor
if not (obj.access(self.caller, 'control') or obj.access(self.caller, 'edit')):
caller.msg("You don't have permission to edit %s." % obj.key)
return
if len(attrs) > 1: if len(attrs) > 1:
caller.msg("The Line editor can only be applied " caller.msg("The Line editor can only be applied "
"to one attribute at a time.") "to one attribute at a time.")
@ -1666,12 +1673,18 @@ class CmdSetAttribute(ObjManipCommand):
return return
else: else:
# deleting the attribute(s) # deleting the attribute(s)
if not (obj.access(self.caller, 'control') or obj.access(self.caller, 'edit')):
caller.msg("You don't have permission to edit %s." % obj.key)
return
for attr in attrs: for attr in attrs:
if not self.check_attr(obj, attr): if not self.check_attr(obj, attr):
continue continue
result.append(self.rm_attr(obj, attr)) result.append(self.rm_attr(obj, attr))
else: else:
# setting attribute(s). Make sure to convert to real Python type before saving. # setting attribute(s). Make sure to convert to real Python type before saving.
if not (obj.access(self.caller, 'control') or obj.access(self.caller, 'edit')):
caller.msg("You don't have permission to edit %s." % obj.key)
return
for attr in attrs: for attr in attrs:
if not self.check_attr(obj, attr): if not self.check_attr(obj, attr):
continue continue
@ -1905,9 +1918,16 @@ class CmdLock(ObjManipCommand):
obj = caller.search(objname) obj = caller.search(objname)
if not obj: if not obj:
return return
if not (obj.access(caller, 'control') or obj.access(caller, "edit")): has_control_access = obj.access(caller, 'control')
if access_type == 'control' and not has_control_access:
# only allow to change 'control' access if you have 'control' access already
caller.msg("You need 'control' access to change this type of lock.")
return
if not has_control_access or obj.access(caller, "edit"):
caller.msg("You are not allowed to do that.") caller.msg("You are not allowed to do that.")
return return
lockdef = obj.locks.get(access_type) lockdef = obj.locks.get(access_type)
if lockdef: if lockdef:
@ -2386,7 +2406,7 @@ class CmdTeleport(COMMAND_DEFAULT_CLASS):
Examples: Examples:
@tel Limbo @tel Limbo
@tel/quiet box Limbo @tel/quiet box = Limbo
@tel/tonone box @tel/tonone box
Switches: Switches:
@ -2402,7 +2422,8 @@ class CmdTeleport(COMMAND_DEFAULT_CLASS):
loc - teleport object to the target's location instead of its contents loc - teleport object to the target's location instead of its contents
Teleports an object somewhere. If no object is given, you yourself Teleports an object somewhere. If no object is given, you yourself
is teleported to the target location. """ is teleported to the target location.
"""
key = "@tel" key = "@tel"
aliases = "@teleport" aliases = "@teleport"
options = ("quiet", "intoexit", "tonone", "loc") options = ("quiet", "intoexit", "tonone", "loc")

View file

@ -11,7 +11,7 @@ command method rather than caller.msg().
from evennia.commands.cmdset import CmdSet from evennia.commands.cmdset import CmdSet
from evennia.commands.default import help, comms, admin, system from evennia.commands.default import help, comms, admin, system
from evennia.commands.default import building, account from evennia.commands.default import building, account, general
class AccountCmdSet(CmdSet): class AccountCmdSet(CmdSet):
@ -39,6 +39,9 @@ class AccountCmdSet(CmdSet):
self.add(account.CmdColorTest()) self.add(account.CmdColorTest())
self.add(account.CmdQuell()) self.add(account.CmdQuell())
# nicks
self.add(general.CmdNick())
# testing # testing
self.add(building.CmdExamine()) self.add(building.CmdExamine())

View file

@ -143,14 +143,14 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
return re.sub(r"(\$[0-9]+|\*|\?|\[.+?\])", r"|Y\1|n", string) return re.sub(r"(\$[0-9]+|\*|\?|\[.+?\])", r"|Y\1|n", string)
caller = self.caller caller = self.caller
account = self.caller.account or caller
switches = self.switches switches = self.switches
nicktypes = [switch for switch in switches if switch in ( nicktypes = [switch for switch in switches if switch in ("object", "account", "inputline")]
"object", "account", "inputline")] or ["inputline"] specified_nicktype = bool(nicktypes)
nicktypes = nicktypes if specified_nicktype else ["inputline"]
nicklist = (utils.make_iter(caller.nicks.get(category="inputline", return_obj=True) or []) + nicklist = (utils.make_iter(caller.nicks.get(category="inputline", return_obj=True) or []) +
utils.make_iter(caller.nicks.get(category="object", return_obj=True) or []) + utils.make_iter(caller.nicks.get(category="object", return_obj=True) or []) +
utils.make_iter(account.nicks.get(category="account", return_obj=True) or [])) utils.make_iter(caller.nicks.get(category="account", return_obj=True) or []))
if 'list' in switches or self.cmdstring in ("nicks", "@nicks"): if 'list' in switches or self.cmdstring in ("nicks", "@nicks"):
@ -173,29 +173,99 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
if 'delete' in switches or 'del' in switches: if 'delete' in switches or 'del' in switches:
if not self.args or not self.lhs: if not self.args or not self.lhs:
caller.msg("usage nick/delete #num ('nicks' for list)") caller.msg("usage nick/delete <nick> or <#num> ('nicks' for list)")
return return
# see if a number was given # see if a number was given
arg = self.args.lstrip("#") arg = self.args.lstrip("#")
oldnicks = []
if arg.isdigit(): if arg.isdigit():
# we are given a index in nicklist # we are given a index in nicklist
delindex = int(arg) delindex = int(arg)
if 0 < delindex <= len(nicklist): if 0 < delindex <= len(nicklist):
oldnick = nicklist[delindex - 1] oldnicks.append(nicklist[delindex - 1])
_, _, old_nickstring, old_replstring = oldnick.value
else: else:
caller.msg("Not a valid nick index. See 'nicks' for a list.") caller.msg("Not a valid nick index. See 'nicks' for a list.")
return return
nicktype = oldnick.category else:
nicktypestr = "%s-nick" % nicktype.capitalize() if not specified_nicktype:
nicktypes = ("object", "account", "inputline")
for nicktype in nicktypes:
oldnicks.append(caller.nicks.get(arg, category=nicktype, return_obj=True))
if nicktype == "account": oldnicks = [oldnick for oldnick in oldnicks if oldnick]
account.nicks.remove(old_nickstring, category=nicktype) if oldnicks:
else: for oldnick in oldnicks:
nicktype = oldnick.category
nicktypestr = "%s-nick" % nicktype.capitalize()
_, _, old_nickstring, old_replstring = oldnick.value
caller.nicks.remove(old_nickstring, category=nicktype) caller.nicks.remove(old_nickstring, category=nicktype)
caller.msg("%s removed: '|w%s|n' -> |w%s|n." % ( caller.msg("%s removed: '|w%s|n' -> |w%s|n." % (
nicktypestr, old_nickstring, old_replstring)) nicktypestr, old_nickstring, old_replstring))
return else:
caller.msg("No matching nicks to remove.")
return
if not self.rhs and self.lhs:
# check what a nick is set to
strings = []
if not specified_nicktype:
nicktypes = ("object", "account", "inputline")
for nicktype in nicktypes:
nicks = utils.make_iter(caller.nicks.get(category=nicktype, return_obj=True))
for nick in nicks:
_, _, nick, repl = nick.value
if nick.startswith(self.lhs):
strings.append("{}-nick: '{}' -> '{}'".format(
nicktype.capitalize(), nick, repl))
if strings:
caller.msg("\n".join(strings))
else:
caller.msg("No nicks found matching '{}'".format(self.lhs))
return
if not self.rhs and self.lhs:
# check what a nick is set to
strings = []
if not specified_nicktype:
nicktypes = ("object", "account", "inputline")
for nicktype in nicktypes:
if nicktype == "account":
obj = account
else:
obj = caller
nicks = utils.make_iter(obj.nicks.get(category=nicktype, return_obj=True))
for nick in nicks:
_, _, nick, repl = nick.value
if nick.startswith(self.lhs):
strings.append("{}-nick: '{}' -> '{}'".format(
nicktype.capitalize(), nick, repl))
if strings:
caller.msg("\n".join(strings))
else:
caller.msg("No nicks found matching '{}'".format(self.lhs))
return
if not self.rhs and self.lhs:
# check what a nick is set to
strings = []
if not specified_nicktype:
nicktypes = ("object", "account", "inputline")
for nicktype in nicktypes:
if nicktype == "account":
obj = account
else:
obj = caller
nicks = utils.make_iter(obj.nicks.get(category=nicktype, return_obj=True))
for nick in nicks:
_, _, nick, repl = nick.value
if nick.startswith(self.lhs):
strings.append("{}-nick: '{}' -> '{}'".format(
nicktype.capitalize(), nick, repl))
if strings:
caller.msg("\n".join(strings))
else:
caller.msg("No nicks found matching '{}'".format(self.lhs))
return
if not self.args or not self.lhs: if not self.args or not self.lhs:
caller.msg("Usage: nick[/switches] nickname = [realname]") caller.msg("Usage: nick[/switches] nickname = [realname]")
@ -214,16 +284,11 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
errstring = "" errstring = ""
string = "" string = ""
for nicktype in nicktypes: for nicktype in nicktypes:
if nicktype == "account":
obj = account
else:
obj = caller
nicktypestr = "%s-nick" % nicktype.capitalize() nicktypestr = "%s-nick" % nicktype.capitalize()
old_nickstring = None old_nickstring = None
old_replstring = None old_replstring = None
oldnick = obj.nicks.get(key=nickstring, category=nicktype, return_obj=True) oldnick = caller.nicks.get(key=nickstring, category=nicktype, return_obj=True)
if oldnick: if oldnick:
_, _, old_nickstring, old_replstring = oldnick.value _, _, old_nickstring, old_replstring = oldnick.value
if replstring: if replstring:
@ -238,7 +303,7 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
else: else:
string += "\n%s '|w%s|n' mapped to '|w%s|n'." % (nicktypestr, nickstring, replstring) string += "\n%s '|w%s|n' mapped to '|w%s|n'." % (nicktypestr, nickstring, replstring)
try: try:
obj.nicks.add(nickstring, replstring, category=nicktype) caller.nicks.add(nickstring, replstring, category=nicktype)
except NickTemplateInvalid: except NickTemplateInvalid:
caller.msg("You must use the same $-markers both in the nick and in the replacement.") caller.msg("You must use the same $-markers both in the nick and in the replacement.")
return return

View file

@ -132,8 +132,8 @@ class TestGeneral(CommandTest):
self.call(general.CmdNick(), "/object testalias = testaliasedstring3", self.call(general.CmdNick(), "/object testalias = testaliasedstring3",
"Objectnick 'testalias' mapped to 'testaliasedstring3'.") "Objectnick 'testalias' mapped to 'testaliasedstring3'.")
self.assertEqual(u"testaliasedstring1", self.char1.nicks.get("testalias")) self.assertEqual(u"testaliasedstring1", self.char1.nicks.get("testalias"))
self.assertEqual(None, self.char1.nicks.get("testalias", category="account")) self.assertEqual(u"testaliasedstring2", self.char1.nicks.get("testalias", category="account"))
self.assertEqual(u"testaliasedstring2", self.char1.account.nicks.get("testalias", category="account")) self.assertEqual(None, self.char1.account.nicks.get("testalias", category="account"))
self.assertEqual(u"testaliasedstring3", self.char1.nicks.get("testalias", category="object")) self.assertEqual(u"testaliasedstring3", self.char1.nicks.get("testalias", category="object"))
def test_get_and_drop(self): def test_get_and_drop(self):

View file

@ -159,7 +159,7 @@ class ChannelHandler(object):
""" """
The ChannelHandler manages all active in-game channels and The ChannelHandler manages all active in-game channels and
dynamically creates channel commands for users so that they can dynamically creates channel commands for users so that they can
just give the channek's key or alias to write to it. Whenever a just give the channel's key or alias to write to it. Whenever a
new channel is created in the database, the update() method on new channel is created in the database, the update() method on
this handler must be called to sync it with the database (this is this handler must be called to sync it with the database (this is
done automatically if creating the channel with done automatically if creating the channel with

View file

@ -527,7 +527,6 @@ class SubscriptionHandler(object):
for subscriber in make_iter(entity): for subscriber in make_iter(entity):
if subscriber: if subscriber:
clsname = subscriber.__dbclass__.__name__ clsname = subscriber.__dbclass__.__name__
print("subscriber:", subscriber, clsname) # DEBUG
# chooses the right type # chooses the right type
if clsname == "ObjectDB": if clsname == "ObjectDB":
self.obj.db_object_subscriptions.add(subscriber) self.obj.db_object_subscriptions.add(subscriber)
@ -585,9 +584,7 @@ class SubscriptionHandler(object):
for obj in self.all(): for obj in self.all():
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
try: try:
if hasattr(obj, 'account'): if hasattr(obj, 'account') and obj.account:
if not obj.account:
continue
obj = obj.account obj = obj.account
if not obj.is_connected: if not obj.is_connected:
continue continue

View file

@ -210,6 +210,14 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
def sessions(self): def sessions(self):
return ObjectSessionHandler(self) return ObjectSessionHandler(self)
@property
def is_connected(self):
# we get an error for objects subscribed to channels without this
if self.account: # seems sane to pass on the account
return self.account.is_connected
else:
return False
@property @property
def has_account(self): def has_account(self):
""" """
@ -553,6 +561,7 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
obj.at_msg_send(text=text, to_obj=self, **kwargs) obj.at_msg_send(text=text, to_obj=self, **kwargs)
except Exception: except Exception:
logger.log_trace() logger.log_trace()
kwargs["options"] = options
try: try:
if not self.at_msg_receive(text=text, **kwargs): if not self.at_msg_receive(text=text, **kwargs):
# if at_msg_receive returns false, we abort message to this object # if at_msg_receive returns false, we abort message to this object
@ -560,7 +569,6 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
except Exception: except Exception:
logger.log_trace() logger.log_trace()
kwargs["options"] = options
if text and not (isinstance(text, basestring) or isinstance(text, tuple)): if text and not (isinstance(text, basestring) or isinstance(text, tuple)):
# sanitize text before sending across the wire # sanitize text before sending across the wire

View file

@ -282,6 +282,8 @@ class AttributeHandler(object):
"attribute__db_attrtype": self._attrtype, "attribute__db_attrtype": self._attrtype,
"attribute__db_key__iexact": key.lower(), "attribute__db_key__iexact": key.lower(),
"attribute__db_category__iexact": category.lower() if category else None} "attribute__db_category__iexact": category.lower() if category else None}
if not self.obj.pk:
return []
conn = getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query) conn = getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query)
if conn: if conn:
attr = conn[0].attribute attr = conn[0].attribute

View file

@ -8,6 +8,8 @@ import shlex
from django.db.models import Q from django.db.models import Q
from evennia.utils import idmapper from evennia.utils import idmapper
from evennia.utils.utils import make_iter, variable_from_module, to_unicode from evennia.utils.utils import make_iter, variable_from_module, to_unicode
from evennia.typeclasses.attributes import Attribute
from evennia.typeclasses.tags import Tag
__all__ = ("TypedObjectManager", ) __all__ = ("TypedObjectManager", )
_GA = object.__getattribute__ _GA = object.__getattribute__
@ -56,17 +58,19 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
dbmodel = self.model.__dbclass__.__name__.lower() dbmodel = self.model.__dbclass__.__name__.lower()
query = [("attribute__db_attrtype", attrtype), ("attribute__db_model", dbmodel)] query = [("attribute__db_attrtype", attrtype), ("attribute__db_model", dbmodel)]
if obj: if obj:
query.append(("%s__id" % self.model.__name__.lower(), obj.id)) query.append(("%s__id" % self.model.__dbclass__.__name__.lower(), obj.id))
if key: if key:
query.append(("attribute__db_key", key)) query.append(("attribute__db_key", key))
if category: if category:
query.append(("attribute__db_category", category)) query.append(("attribute__db_category", category))
if strvalue: if strvalue:
query.append(("attribute__db_strvalue", strvalue)) query.append(("attribute__db_strvalue", strvalue))
elif value: if value:
# strvalue and value are mutually exclusive # no reason to make strvalue/value mutually exclusive at this level
query.append(("attribute__db_value", value)) query.append(("attribute__db_value", value))
return [th.attribute for th in self.model.db_attributes.through.objects.filter(**dict(query))] return Attribute.objects.filter(
pk__in=self.model.db_attributes.through.objects.filter(
**dict(query)).values_list("attribute_id", flat=True))
def get_nick(self, key=None, category=None, value=None, strvalue=None, obj=None): def get_nick(self, key=None, category=None, value=None, strvalue=None, obj=None):
""" """
@ -189,7 +193,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
query.append(("tag__db_key", key)) query.append(("tag__db_key", key))
if category: if category:
query.append(("tag__db_category", category)) query.append(("tag__db_category", category))
return [th.tag for th in self.model.db_tags.through.objects.filter(**dict(query))] return Tag.objects.filter(
pk__in=self.model.db_tags.through.objects.filter(
**dict(query)).values_list("tag_id", flat=True))
def get_permission(self, key=None, category=None, obj=None): def get_permission(self, key=None, category=None, obj=None):
""" """

View file

@ -25,7 +25,7 @@ JQuery available.
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
if(!window.jQuery) { if(!window.jQuery) {
document.write("<div class='err'>jQuery library not found or the online version could not be reached.</div>"); document.write("<div class='err'>jQuery library not found or the online version could not be reached. Check so Javascript is not blocked in your browser.</div>");
} }
</script> </script>
@ -57,6 +57,12 @@ JQuery available.
{% endblock %} {% endblock %}
<script src="https://cdn.rawgit.com/ejci/favico.js/master/favico-0.3.10.min.js" language="javascript" type="text/javascript" charset="utf-8"></script> <script src="https://cdn.rawgit.com/ejci/favico.js/master/favico-0.3.10.min.js" language="javascript" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
if(!window.Favico) {
document.write("<div class='err'>Favico.js library not found or the online version could not be reached. Check so Javascript is not blocked in your browser.</div>");
}
</script>
</head> </head>
<body> <body>