Esempio n. 1
0
 def __init__(self, **kwargs):
     """the lockhandler works the same as for objects.
     optional kwargs will be set as properties on the Command at runtime,
     overloading evential same-named class properties."""
     if kwargs:
         _init_command(self, **kwargs)
     self.lockhandler = LockHandler(self)
Esempio n. 2
0
 def __init__(self, **kwargs):
     """the lockhandler works the same as for objects.
     optional kwargs will be set as properties on the Command at runtime,
     overloading evential same-named class properties."""
     if kwargs:
         _init_command(self, **kwargs)
     self.lockhandler = LockHandler(self)
Esempio n. 3
0
class TempMsg(object):
    """
    This is a non-persistent object for sending
    temporary messages that will not be stored.
    It mimics the "real" Msg object, but don't require
    sender to be given.
    """
    def __init__(self,
                 senders=None,
                 receivers=None,
                 channels=None,
                 message="",
                 header="",
                 type="",
                 lockstring="",
                 hide_from=None):
        self.senders = senders and make_iter(senders) or []
        self.receivers = receivers and make_iter(receivers) or []
        self.channels = channels and make_iter(channels) or []
        self.type = type
        self.header = header
        self.message = message
        self.lock_storage = lockstring
        self.locks = LockHandler(self)
        self.hide_from = hide_from and make_iter(hide_from) or []
        self.date_sent = datetime.now()

    def __str__(self):
        "This handles what is shown when e.g. printing the message"
        senders = ",".join(obj.key for obj in self.senders)
        receivers = ",".join(["[%s]" % obj.key for obj in self.channels] +
                             [obj.key for obj in self.receivers])
        return "%s->%s: %s" % (senders, receivers, crop(self.message,
                                                        width=40))

    def remove_sender(self, obj):
        "Remove a sender or a list of senders"
        for o in make_iter(obj):
            try:
                self.senders.remove(o)
            except ValueError:
                pass  # nothing to remove

    def remove_receiver(self, obj):
        "Remove a sender or a list of senders"
        for o in make_iter(obj):
            try:
                self.senders.remove(o)
            except ValueError:
                pass  # nothing to remove

    def access(self, accessing_obj, access_type='read', default=False):
        "checks lock access"
        return self.locks.check(accessing_obj,
                                access_type=access_type,
                                default=default)
Esempio n. 4
0
 def __init__(self,
              senders=None,
              receivers=None,
              channels=None,
              message="",
              header="",
              type="",
              lockstring="",
              hide_from=None):
     self.senders = senders and make_iter(senders) or []
     self.receivers = receivers and make_iter(receivers) or []
     self.channels = channels and make_iter(channels) or []
     self.type = type
     self.header = header
     self.message = message
     self.lock_storage = lockstring
     self.locks = LockHandler(self)
     self.hide_from = hide_from and make_iter(hide_from) or []
     self.date_sent = datetime.now()
Esempio n. 5
0
 def __init__(self, senders=None, receivers=None, channels=None, message="", header="", type="", lockstring="", hide_from=None):
     self.senders = senders and make_iter(senders) or []
     self.receivers = receivers and make_iter(receivers) or []
     self.channels = channels and make_iter(channels) or []
     self.type = type
     self.header = header
     self.message = message
     self.lock_storage = lockstring
     self.locks = LockHandler(self)
     self.hide_from = hide_from and make_iter(hide_from) or []
     self.date_sent = datetime.now()
Esempio n. 6
0
class TempMsg(object):
    """
    This is a non-persistent object for sending
    temporary messages that will not be stored.
    It mimics the "real" Msg object, but don't require
    sender to be given.
    """
    def __init__(self, senders=None, receivers=None, channels=None, message="", header="", type="", lockstring="", hide_from=None):
        self.senders = senders and make_iter(senders) or []
        self.receivers = receivers and make_iter(receivers) or []
        self.channels = channels and make_iter(channels) or []
        self.type = type
        self.header = header
        self.message = message
        self.lock_storage = lockstring
        self.locks = LockHandler(self)
        self.hide_from = hide_from and make_iter(hide_from) or []
        self.date_sent = datetime.now()

    def __str__(self):
        "This handles what is shown when e.g. printing the message"
        senders = ",".join(obj.key for obj in self.senders)
        receivers = ",".join(["[%s]" % obj.key for obj in self.channels] + [obj.key for obj in self.receivers])
        return "%s->%s: %s" % (senders, receivers, crop(self.message, width=40))

    def remove_sender(self, obj):
        "Remove a sender or a list of senders"
        for o in make_iter(obj):
            try:
                self.senders.remove(o)
            except ValueError:
                pass  # nothing to remove

    def remove_receiver(self, obj):
        "Remove a sender or a list of senders"
        for o in make_iter(obj):
            try:
                self.senders.remove(o)
            except ValueError:
                pass  # nothing to remove

    def access(self, accessing_obj, access_type='read', default=False):
        "checks lock access"
        return self.locks.check(accessing_obj,
                                access_type=access_type, default=default)
Esempio n. 7
0
 def locks(self):
     return LockHandler(self)
Esempio n. 8
0
 def __init__(self, *args, **kwargs):
     SharedMemoryModel.__init__(self, *args, **kwargs)
     self.locks = LockHandler(self)
Esempio n. 9
0
class Channel(SharedMemoryModel):
    """
    This is the basis of a comm channel, only implementing
    the very basics of distributing messages.

    The Channel class defines the following properties:
      key - main name for channel
      desc - optional description of channel
      aliases - alternative names for the channel
      keep_log - bool if the channel should remember messages
      permissions - perm strings

    """

    #
    # Channel database model setup
    #
    #
    # These databse fields are all set using their corresponding properties,
    # named same as the field, but withtout the db_* prefix.

    # unique identifier for this channel
    db_key = models.CharField('key', max_length=255, unique=True, db_index=True)
    # optional description of channel
    db_desc = models.CharField('description', max_length=80, blank=True, null=True)
    # aliases for the channel. These are searched by cmdhandler
    # as well to determine if a command is the name of a channel.
    # Several aliases are separated by commas.
    db_aliases = models.CharField('aliases', max_length=255)
    # Whether this channel should remember its past messages
    db_keep_log = models.BooleanField(default=True)
    # Storage of lock definitions
    db_lock_storage = models.TextField('locks', blank=True)


    # Database manager
    objects = managers.ChannelManager()

    class Meta:
        "Define Django meta options"
        verbose_name = "Channel"

    def __init__(self, *args, **kwargs):
        SharedMemoryModel.__init__(self, *args, **kwargs)
        self.locks = LockHandler(self)

    # Wrapper properties to easily set database fields. These are
    # @property decorators that allows to access these fields using
    # normal python operations (without having to remember to save()
    # etc). So e.g. a property 'attr' has a get/set/del decorator
    # defined that allows the user to do self.attr = value,
    # value = self.attr and del self.attr respectively (where self
    # is the object in question).

    # key property (wraps db_key)
    #@property
    def key_get(self):
        "Getter. Allows for value = self.key"
        return self.db_key
    #@key.setter
    def key_set(self, value):
        "Setter. Allows for self.key = value"
        self.db_key = value
        self.save()
    #@key.deleter
    def key_del(self):
        "Deleter. Allows for del self.key"
        raise Exception("You cannot delete the channel key!")
    key = property(key_get, key_set, key_del)

    # desc property (wraps db_desc)
    #@property
    def desc_get(self):
        "Getter. Allows for value = self.desc"
        return self.db_desc
    #@desc.setter
    def desc_set(self, value):
        "Setter. Allows for self.desc = value"
        self.db_desc = value
        self.save()
    #@desc.deleter
    def desc_del(self):
        "Deleter. Allows for del self.desc"
        self.db_desc = ""
        self.save()
    desc = property(desc_get, desc_set, desc_del)

    # aliases property
    #@property
    def aliases_get(self):
        "Getter. Allows for value = self.aliases. Returns a list of aliases."
        if self.db_aliases:
            return [perm.strip() for perm in self.db_aliases.split(',')]
        return []
    #@aliases.setter
    def aliases_set(self, value):
        "Setter. Allows for self.aliases = value. Stores as a comma-separated string."
        if is_iter(value):
            value = ",".join([str(val).strip().lower() for val in value])
        self.db_aliases = value
        self.save()
    #@aliases_del.deleter
    def aliases_del(self):
        "Deleter. Allows for del self.aliases"
        self.db_aliases = ""
        self.save()
    aliases = property(aliases_get, aliases_set, aliases_del)

    # keep_log property (wraps db_keep_log)
    #@property
    def keep_log_get(self):
        "Getter. Allows for value = self.keep_log"
        return self.db_keep_log
    #@keep_log.setter
    def keep_log_set(self, value):
        "Setter. Allows for self.keep_log = value"
        self.db_keep_log = value
        self.save()
    #@keep_log.deleter
    def keep_log_del(self):
        "Deleter. Allows for del self.keep_log"
        self.db_keep_log = False
        self.save()
    keep_log = property(keep_log_get, keep_log_set, keep_log_del)

    # lock_storage property (wraps db_lock_storage)
    #@property
    def lock_storage_get(self):
        "Getter. Allows for value = self.lock_storage"
        return self.db_lock_storage
    #@nick.setter
    def lock_storage_set(self, value):
        """Saves the lock_storagetodate. This is usually not called directly, but through self.lock()"""
        self.db_lock_storage = value
        self.save()
    #@nick.deleter
    def lock_storage_del(self):
        "Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead"""
        logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self)
    lock_storage = property(lock_storage_get, lock_storage_set, lock_storage_del)

    db_model_name = "channel" # used by attributes to safely store objects

    class Meta:
        "Define Django meta options"
        verbose_name = "Channel"
        verbose_name_plural = "Channels"

    #
    # Channel class methods
    #

    def __str__(self):
        return "Channel '%s' (%s)" % (self.key, self.desc)

    def has_connection(self, player):
        """
        Checks so this player is actually listening
        to this channel.
        """
        # also handle object.player calls
        player, typ = identify_object(player)
        if typ == 'object':
            player = player.player
            player, typ = identify_object(player)
        if player and not typ == "player":
            logger.log_errmsg("Channel.has_connection received object of type '%s'. It only accepts players/characters." % typ)
            return
        # do the check
        return PlayerChannelConnection.objects.has_player_connection(player, self)

    def msg(self, msgobj, header=None, senders=None, persistent=True, online=False):
        """
        Send the given message to all players connected to channel. Note that
        no permission-checking is done here; it is assumed to have been
        done before calling this method. The optional keywords are not used if persistent is False.

        msgobj - a Msg/TempMsg instance or a message string. If one of the former, the remaining
              keywords will be ignored. If a string, this will either be sent as-is (if persistent=False) or
              it will be used together with header and senders keywords to create a Msg instance on the fly.
        senders (object, player or a list of objects or players) - ignored if msgobj is a Msg or TempMsg, or if
                 persistent=False.
        persistent (bool) - ignored if msgobj is a Msg or TempMsg. If True, a Msg will be created, using
                header and senders keywords. If False, other keywords will be ignored.
        online (bool) - If this is set true, only messages people who are online. Otherwise, messages all players
                connected. This can make things faster, but may not trigger listeners on players that are offline.
        """

        if isinstance(msgobj, basestring):
            # given msgobj is a string
            if persistent:
                msg = msgobj
                msgobj = Msg()
                msgobj.save()
                if senders:
                    msgobj.senders = make_iter(senders)
                msgobj.header = header
                msgobj.message = msg
                msgobj.channels = [self] # add this channel
            else:
                # just use the msg as-is
                msg = msgobj
        else:
            # already in a Msg/TempMsg
            msg = msgobj.message

        # get all players connected to this channel and send to them
        for conn in Channel.objects.get_all_connections(self, online=online):
            try:
                conn.player.msg(msg, senders)
            except AttributeError:
                try:
                    conn.to_external(msg, senders, from_channel=self)
                except Exception:
                    logger.log_trace("Cannot send msg to connection '%s'" % conn)
        return True

    def tempmsg(self, message, header=None, senders=None):
        """
        A wrapper for sending non-persistent messages.
        """
        self.msg(message, senders=senders, header=header, persistent=False)

    def connect_to(self, player):
        "Connect the user to this channel"
        if not self.access(player, 'listen'):
            return False
        player = player.dbobj
        conn = PlayerChannelConnection.objects.create_connection(player, self)
        if conn:
            return True
        return False

    def disconnect_from(self, player):
        "Disconnect user from this channel."
        PlayerChannelConnection.objects.break_connection(player, self)

    def delete(self):
        "Clean out all connections to this channel and delete it."
        for connection in Channel.objects.get_all_connections(self):
            connection.delete()
        super(Channel, self).delete()
    def access(self, accessing_obj, access_type='listen', default=False):
        """
        Determines if another object has permission to access.
        accessing_obj - object trying to access this one
        access_type - type of access sought
        default - what to return if no lock of access_type was found
        """
        return self.locks.check(accessing_obj, access_type=access_type, default=default)
Esempio n. 10
0
class Msg(SharedMemoryModel):
    """
    A single message. This model describes all ooc messages
    sent in-game, both to channels and between players.

    The Msg class defines the following properties:
      sender - sender of message
      receivers - list of target objects for message
      channels - list of channels message was sent to
      message - the text being sent
      date_sent - time message was sent
      hide_from_sender - bool if message should be hidden from sender
      hide_from_receivers - list of receiver objects to hide message from
      hide_from_channels - list of channels objects to hide message from
      permissions - perm strings

    """
    #
    # Msg database model setup
    #
    #
    # These databse fields are all set using their corresponding properties,
    # named same as the field, but withtout the db_* prefix.

    # Sender is either a player, an object or an external sender, like an IRC channel
    # normally there is only one, but if co-modification of a message is allowed, there
    # may be more than one "author"
    db_sender_players = models.ManyToManyField("players.PlayerDB", related_name='sender_player_set', null=True, verbose_name='sender(player)', db_index=True)
    db_sender_objects = models.ManyToManyField("objects.ObjectDB", related_name='sender_object_set', null=True, verbose_name='sender(object)', db_index=True)
    db_sender_external = models.CharField('external sender', max_length=255, null=True, db_index=True,
          help_text="identifier for external sender, for example a sender over an IRC connection (i.e. someone who doesn't have an exixtence in-game).")
    # The destination objects of this message. Stored as a
    # comma-separated string of object dbrefs. Can be defined along
    # with channels below.
    db_receivers_players = models.ManyToManyField('players.PlayerDB', related_name='receiver_player_set', null=True, help_text="player receivers")
    db_receivers_objects = models.ManyToManyField('objects.ObjectDB', related_name='receiver_object_set', null=True, help_text="object receivers")
    db_receivers_channels = models.ManyToManyField("Channel", related_name='channel_set', null=True, help_text="channel recievers")

    # header could be used for meta-info about the message if your system needs it, or as a separate
    # store for the mail subject line maybe.
    db_header = models.TextField('header', null=True, blank=True)
    # the message body itself
    db_message = models.TextField('messsage')
    # send date
    db_date_sent = models.DateTimeField('date sent', editable=False, auto_now_add=True, db_index=True)
    # lock storage
    db_lock_storage = models.TextField('locks', blank=True,
                                       help_text='access locks on this message.')

    # these can be used to filter/hide a given message from supplied objects/players/channels
    db_hide_from_players = models.ManyToManyField("players.PlayerDB", related_name='hide_from_players_set', null=True)
    db_hide_from_objects = models.ManyToManyField("objects.ObjectDB", related_name='hide_from_objects_set', null=True)
    db_hide_from_channles = models.ManyToManyField("Channel", related_name='hide_from_channels_set', null=True)

    # Database manager
    objects = managers.MsgManager()

    def __init__(self, *args, **kwargs):
        SharedMemoryModel.__init__(self, *args, **kwargs)
        self.locks = LockHandler(self)

    class Meta:
        "Define Django meta options"
        verbose_name = "Message"

    # Wrapper properties to easily set database fields. These are
    # @property decorators that allows to access these fields using
    # normal python operations (without having to remember to save()
    # etc). So e.g. a property 'attr' has a get/set/del decorator
    # defined that allows the user to do self.attr = value,
    # value = self.attr and del self.attr respectively (where self
    # is the object in question).

    # sender property (wraps db_sender_*)
    #@property
    def __senders_get(self):
        "Getter. Allows for value = self.sender"
        return [hasattr(o, "typeclass") and o.typeclass or o for o in
                list(self.db_sender_players.all()) + list(self.db_sender_objects.all())]
    #@sender.setter
    def __senders_set(self, value):
        "Setter. Allows for self.sender = value"
        for val in (v for v in make_iter(value) if v):
            obj, typ = identify_object(val)
            if typ == 'player':
                self.db_sender_players.add(obj)
            elif typ == 'object':
                self.db_sender_objects.add(obj)
            elif isinstance(typ, basestring):
                self.db_sender_external = obj
            elif not obj:
                return
            else:
                raise ValueError(obj)
            self.save()
    #@sender.deleter
    def __senders_del(self):
        "Deleter. Clears all senders"
        self.db_sender_players.clear()
        self.db_sender_objects.clear()
        self.db_sender_external = ""
        self.save()
    senders = property(__senders_get, __senders_set, __senders_del)

    def remove_sender(self, value):
        "Remove a single sender or a list of senders"
        for val in make_iter(value):
            obj, typ = identify_object(val)
            if typ == 'player':
                self.db_sender_players.remove(obj)
            elif typ == 'object':
                self.db_sender_objects.remove(obj)
            elif isinstance(obj, basestring) and self.db_sender_external == obj:
                self.db_sender_external = ""
            else:
                raise ValueError(obj)
            self.save()

    # receivers property
    #@property
    def __receivers_get(self):
        "Getter. Allows for value = self.receivers. Returns three lists of receivers: players, objects and channels."
        return [hasattr(o, "typeclass") and o.typeclass or o for o in
                list(self.db_receivers_players.all()) + list(self.db_receivers_objects.all())]
    #@receivers.setter
    def __receivers_set(self, value):
        "Setter. Allows for self.receivers = value. This appends a new receiver to the message."
        for val in (v for v in make_iter(value) if v):
            obj, typ = identify_object(val)
            if typ == 'player':
                self.db_receivers_players.add(obj)
            elif typ == 'object':
                self.db_receivers_objects.add(obj)
            elif not obj:
                return
            else:
                raise ValueError
            self.save()
    #@receivers.deleter
    def __receivers_del(self):
        "Deleter. Clears all receivers"
        self.db_receivers_players.clear()
        self.db_receivers_objects.clear()
        self.save()
    receivers = property(__receivers_get, __receivers_set, __receivers_del)

    def remove_receiver(self, obj):
        "Remove a single recevier"
        obj, typ = identify_object(obj)
        if typ == 'player':
            self.db_receivers_players.remove(obj)
        elif typ == 'object':
            self.db_receivers_objects.remove(obj)
        else:
            raise ValueError
        self.save()

    # channels property
    #@property
    def __channels_get(self):
        "Getter. Allows for value = self.channels. Returns a list of channels."
        return self.db_receivers_channels.all()
    #@channels.setter
    def __channels_set(self, value):
        "Setter. Allows for self.channels = value. Requires a channel to be added."
        for val in (v for v in make_iter(value) if v):
            self.db_receivers_channels.add(val)
    #@channels.deleter
    def __channels_del(self):
        "Deleter. Allows for del self.channels"
        self.db_receivers_channels.clear()
        self.save()
    channels = property(__channels_get, __channels_set, __channels_del)

    # header property (wraps db_header)
    #@property
    def __header_get(self):
        "Getter. Allows for value = self.message"
        return self.db_header
    #@message.setter
    def __header_set(self, value):
        "Setter. Allows for self.message = value"
        if value:
            self.db_header = value
            self.save()
    #@message.deleter
    def __header_del(self):
        "Deleter. Allows for del self.message"
        self.db_header = ""
        self.save()
    header = property(__header_get, __header_set, __header_del)

    # message property (wraps db_message)
    #@property
    def __message_get(self):
        "Getter. Allows for value = self.message"
        return self.db_message
    #@message.setter
    def __message_set(self, value):
        "Setter. Allows for self.message = value"
        self.db_message = value
        self.save()
    #@message.deleter
    def __message_del(self):
        "Deleter. Allows for del self.message"
        self.db_message = ""
        self.save()
    message = property(__message_get, __message_set, __message_del)

    # date_sent property (wraps db_date_sent)
    #@property
    def __date_sent_get(self):
        "Getter. Allows for value = self.date_sent"
        return self.db_date_sent
    #@date_sent.setter
    def __date_sent_set(self, value):
        "Setter. Allows for self.date_sent = value"
        raise Exception("You cannot edit date_sent!")
    #@date_sent.deleter
    def __date_sent_del(self):
        "Deleter. Allows for del self.date_sent"
        raise Exception("You cannot delete the date_sent property!")
    date_sent = property(__date_sent_get, __date_sent_set, __date_sent_del)

    # hide_from property
    #@property
    def __hide_from_get(self):
        "Getter. Allows for value = self.hide_from. Returns 3 lists of players, objects and channels"
        return self.db_hide_from_players.all(), self.db_hide_from_objects.all(), self.db_hide_from_channels.all()
    #@hide_from_sender.setter
    def __hide_from_set(self, value):
        "Setter. Allows for self.hide_from = value. Will append to hiders"
        obj, typ = identify_object(value)
        if typ == "player":
            self.db_hide_from_players.add(obj)
        elif typ == "object":
            self.db_hide_from_objects.add(obj)
        elif typ == "channel":
            self.db_hide_from_channels.add(obj)
        else:
            raise ValueError
        self.save()
    #@hide_from_sender.deleter
    def __hide_from_del(self):
        "Deleter. Allows for del self.hide_from_senders"
        self.db_hide_from_players.clear()
        self.db_hide_from_objects.clear()
        self.db_hide_from_channels.clear()
        self.save()
    hide_from = property(__hide_from_get, __hide_from_set, __hide_from_del)

    # lock_storage property (wraps db_lock_storage)
    #@property
    def __lock_storage_get(self):
        "Getter. Allows for value = self.lock_storage"
        return self.db_lock_storage
    #@nick.setter
    def __lock_storage_set(self, value):
        """Saves the lock_storagetodate. This is usually not called directly, but through self.lock()"""
        self.db_lock_storage = value
        self.save()
    #@nick.deleter
    def __lock_storage_del(self):
        "Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead"""
        logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self)
    lock_storage = property(__lock_storage_get, __lock_storage_set, __lock_storage_del)

    _db_model_name = "msg" # used by attributes to safely store objects

    #
    # Msg class methods
    #

    def __str__(self):
        "This handles what is shown when e.g. printing the message"
        senders = ",".join(obj.key for obj in self.senders)
        receivers = ",".join(["[%s]" % obj.key for obj in self.channels] + [obj.key for obj in self.receivers])
        return "%s->%s: %s" % (senders, receivers, crop(self.message, width=40))

    def access(self, accessing_obj, access_type='read', default=False):
        """
        Determines if another object has permission to access.
        accessing_obj - object trying to access this one
        access_type - type of access sought
        default - what to return if no lock of access_type was found
        """
        return self.locks.check(accessing_obj, access_type=access_type, default=default)
Esempio n. 11
0
class Command(object):
    """
    Base command

    Usage:
      command [args]

    This is the base command class. Inherit from this
    to create new commands.

    The cmdhandler makes the following variables available to the
    command methods (so you can always assume them to be there):
    self.caller - the game object calling the command
    self.cmdstring - the command name used to trigger this command (allows
                     you to know which alias was used, for example)
    cmd.args - everything supplied to the command following the cmdstring
               (this is usually what is parsed in self.parse())
    cmd.cmdset - the cmdset from which this command was matched (useful only
                seldomly, notably for help-type commands, to create dynamic
                help entries and lists)
    cmd.obj - the object on which this command is defined. If a default command,
                 this is usually the same as caller.

    The following class properties can/should be defined on your child class:

    key - identifier for command (e.g. "look")
    aliases - (optional) list of aliases (e.g. ["l", "loo"])
    locks - lock string (default is "cmd:all()")
    help_category - how to organize this help entry in help system
                    (default is "General")
    auto_help - defaults to True. Allows for turning off auto-help generation
    arg_regex - (optional) raw string regex defining how the argument part of
                the command should look in order to match for this command
                (e.g. must it be a space between cmdname and arg?)

    (Note that if auto_help is on, this initial string is also used by the
    system to create the help entry for the command, so it's a good idea to
    format it similar to this one)
    """
    # Tie our metaclass, for some convenience cleanup
    __metaclass__ = CommandMeta

    # the main way to call this command (e.g. 'look')
    key = "command"
    # alternative ways to call the command (e.g. 'l', 'glance', 'examine')
    aliases = []
    # a list of lock definitions on the form
    #   cmd:[NOT] func(args) [ AND|OR][ NOT] func2(args)
    locks = ""
    # used by the help system to group commands in lists.
    help_category = "general"

    # This allows to turn off auto-help entry creation for individual commands.
    auto_help = True
    # auto-set (by Evennia on command instantiation) are:
    #   obj - which object this command is defined on
    #   sessid - which session-id (if any) is responsible for
    # triggering this command
    #

    def __init__(self, **kwargs):
        """the lockhandler works the same as for objects.
        optional kwargs will be set as properties on the Command at runtime,
        overloading evential same-named class properties."""
        if kwargs:
            _init_command(self, **kwargs)
        self.lockhandler = LockHandler(self)

    def __str__(self):
        "Print the command"
        return self.key

    def __eq__(self, cmd):
        """
        Compare two command instances to each other by matching their
        key and aliases.
        input can be either a cmd object or the name of a command.
        """
        try:
            # first assume input is a command (the most common case)
            return cmd.key in self._matchset
        except AttributeError:
            # probably got a string
            return cmd in self._matchset

    def __ne__(self, cmd):
        """
        The logical negation of __eq__. Since this is one of the
        most called methods in Evennia (along with __eq__) we do some
        code-duplication here rather than issuing a method-lookup to __eq__.
        """
        try:
            return not cmd.key in self._matcheset
        except AttributeError:
            return not cmd in self._matchset

    def __contains__(self, query):
        """
        This implements searches like 'if query in cmd'. It's a fuzzy matching
        used by the help system, returning True if query can be found
        as a substring of the commands key or its aliases.

        query (str) - query to match against. Should be lower case.

        """
        return any(query in keyalias for keyalias in self._keyaliases)

    def match(self, cmdname):
        """
        This is called by the system when searching the available commands,
        in order to determine if this is the one we wanted. cmdname was
        previously extracted from the raw string by the system.

        cmdname (str) is always lowercase when reaching this point.

        """
        return cmdname in self._matchset

    def access(self, srcobj, access_type="cmd", default=False):
        """
        This hook is called by the cmdhandler to determine if srcobj
        is allowed to execute this command. It should return a boolean
        value and is not normally something that need to be changed since
        it's using the Evennia permission system directly.
        """
        return self.lockhandler.check(srcobj, access_type, default=default)

    def msg(self, msg="", to_obj=None, from_obj=None,
            sessid=None, all_sessions=False, **kwargs):
        """
        This is a shortcut instad of calling msg() directly on an object - it
        will detect if caller is an Object or a Player and also appends
        self.sessid automatically.

        msg - text string of message to send
        to_obj - target object of message. Defaults to self.caller
        from_obj - source of message. Defaults to to_obj
        data - optional dictionary of data
        sessid - supply data only to a unique sessid (normally not used -
           this is only potentially useful if to_obj is a Player object
           different from self.caller or self.caller.player)
        all_sessions (bool) - default is to send only to the session
           connected to the target object
        """
        from_obj = from_obj or self.caller
        to_obj = to_obj or from_obj
        if not sessid:
            if hasattr(to_obj, "sessid"):
                # this is the case when to_obj is e.g. a Character
                sessid = all_sessions and None or to_obj.sessid
            elif to_obj == self.caller:
                # this is the case if to_obj is the calling Player
                sessid = all_sessions and None or self.sessid
            else:
                # if to_obj is a different Player, all their sessions
                # will be notified unless sessid was given specifically
                sessid = None
        to_obj.msg(msg, from_obj=from_obj, sessid=sessid, **kwargs)

    # Common Command hooks

    def at_pre_cmd(self):
        """
        This hook is called before self.parse() on all commands
        """
        pass

    def at_post_cmd(self):
        """
        This hook is called after the command has finished executing
        (after self.func()).
        """
        pass

    def parse(self):
        """
        Once the cmdhandler has identified this as the command we
        want, this function is run. If many of your commands have
        a similar syntax (for example 'cmd arg1 = arg2') you should simply
        define this once and just let other commands of the same form
        inherit from this. See the docstring of this module for
        which object properties are available to use
        (notably self.args).
        """
        pass

    def func(self):
        """
        This is the actual executing part of the command.
        It is called directly after self.parse(). See the docstring
        of this module for which object properties are available
        (beyond those set in self.parse())
        """
        # a simple test command to show the available properties
        string = "-" * 50
        string += "\n{w%s{n - Command variables from evennia:\n" % self.key
        string += "-" * 50
        string += "\nname of cmd (self.key): {w%s{n\n" % self.key
        string += "cmd aliases (self.aliases): {w%s{n\n" % self.aliases
        string += "cmd perms (self.permissions): {w%s{n\n" % self.permissions
        string += "help category (self.help_category): {w%s{n\n" % self.help_category
        string += "object calling (self.caller): {w%s{n\n" % self.caller
        string += "object storing cmdset (self.obj): {w%s{n\n" % self.obj
        string += "command string given (self.cmdstring): {w%s{n\n" % self.cmdstring
        # show cmdset.key instead of cmdset to shorten output
        string += fill("current cmdset (self.cmdset): {w%s{n\n" % self.cmdset)

        self.caller.msg(string)
Esempio n. 12
0
 def __init__(self, *args, **kwargs):
     SharedMemoryModel.__init__(self, *args, **kwargs)
     self.locks = LockHandler(self)
     self.tags = TagHandler(self)
Esempio n. 13
0
 def __init__(self):
     "the lockhandler works the same as for objects."
     self.lockhandler = LockHandler(self)
Esempio n. 14
0
 def __init__(self, *args, **kwargs):
     SharedMemoryModel.__init__(self, *args, **kwargs)
     self.locks = LockHandler(self)
     self.extra_senders = []
Esempio n. 15
0
class Command(object):
    """
    Base command

    Usage:
      command [args]

    This is the base command class. Inherit from this
    to create new commands.

    The cmdhandler makes the following variables available to the
    command methods (so you can always assume them to be there):
    self.caller - the game object calling the command
    self.cmdstring - the command name used to trigger this command (allows
                     you to know which alias was used, for example)
    cmd.args - everything supplied to the command following the cmdstring
               (this is usually what is parsed in self.parse())
    cmd.cmdset - the cmdset from which this command was matched (useful only
                seldomly, notably for help-type commands, to create dynamic
                help entries and lists)
    cmd.obj - the object on which this command is defined. If a default command,
                 this is usually the same as caller.

    The following class properties can/should be defined on your child class:

    key - identifier for command (e.g. "look")
    aliases - (optional) list of aliases (e.g. ["l", "loo"])
    locks - lock string (default is "cmd:all()")
    help_category - how to organize this help entry in help system
                    (default is "General")
    auto_help - defaults to True. Allows for turning off auto-help generation
    arg_regex - (optional) raw string regex defining how the argument part of
                the command should look in order to match for this command
                (e.g. must it be a space between cmdname and arg?)

    (Note that if auto_help is on, this initial string is also used by the
    system to create the help entry for the command, so it's a good idea to
    format it similar to this one)
    """
    # Tie our metaclass, for some convenience cleanup
    __metaclass__ = CommandMeta

    # the main way to call this command (e.g. 'look')
    key = "command"
    # alternative ways to call the command (e.g. 'l', 'glance', 'examine')
    aliases = []
    # a list of lock definitions on the form
    #   cmd:[NOT] func(args) [ AND|OR][ NOT] func2(args)
    locks = ""
    # used by the help system to group commands in lists.
    help_category = "general"

    # This allows to turn off auto-help entry creation for individual commands.
    auto_help = True

    # auto-set (by Evennia on command instantiation) are:
    #   obj - which object this command is defined on
    #   sessid - which session-id (if any) is responsible for
    # triggering this command
    #

    def __init__(self, **kwargs):
        """the lockhandler works the same as for objects.
        optional kwargs will be set as properties on the Command at runtime,
        overloading evential same-named class properties."""
        if kwargs:
            _init_command(self, **kwargs)
        self.lockhandler = LockHandler(self)

    def __str__(self):
        "Print the command"
        return self.key

    def __eq__(self, cmd):
        """
        Compare two command instances to each other by matching their
        key and aliases.
        input can be either a cmd object or the name of a command.
        """
        try:
            # first assume input is a command (the most common case)
            return cmd.key in self._matchset
        except AttributeError:
            # probably got a string
            return cmd in self._matchset

    def __ne__(self, cmd):
        """
        The logical negation of __eq__. Since this is one of the
        most called methods in Evennia (along with __eq__) we do some
        code-duplication here rather than issuing a method-lookup to __eq__.
        """
        try:
            return not cmd.key in self._matcheset
        except AttributeError:
            return not cmd in self._matchset

    def __contains__(self, query):
        """
        This implements searches like 'if query in cmd'. It's a fuzzy matching
        used by the help system, returning True if query can be found
        as a substring of the commands key or its aliases.

        query (str) - query to match against. Should be lower case.

        """
        return any(query in keyalias for keyalias in self._keyaliases)

    def match(self, cmdname):
        """
        This is called by the system when searching the available commands,
        in order to determine if this is the one we wanted. cmdname was
        previously extracted from the raw string by the system.

        cmdname (str) is always lowercase when reaching this point.

        """
        return cmdname in self._matchset

    def access(self, srcobj, access_type="cmd", default=False):
        """
        This hook is called by the cmdhandler to determine if srcobj
        is allowed to execute this command. It should return a boolean
        value and is not normally something that need to be changed since
        it's using the Evennia permission system directly.
        """
        return self.lockhandler.check(srcobj, access_type, default=default)

    def msg(self,
            msg="",
            to_obj=None,
            from_obj=None,
            sessid=None,
            all_sessions=False,
            **kwargs):
        """
        This is a shortcut instad of calling msg() directly on an object - it
        will detect if caller is an Object or a Player and also appends
        self.sessid automatically.

        msg - text string of message to send
        to_obj - target object of message. Defaults to self.caller
        from_obj - source of message. Defaults to to_obj
        data - optional dictionary of data
        sessid - supply data only to a unique sessid (normally not used -
           this is only potentially useful if to_obj is a Player object
           different from self.caller or self.caller.player)
        all_sessions (bool) - default is to send only to the session
           connected to the target object
        """
        from_obj = from_obj or self.caller
        to_obj = to_obj or from_obj
        if not sessid:
            if hasattr(to_obj, "sessid"):
                # this is the case when to_obj is e.g. a Character
                sessid = all_sessions and None or to_obj.sessid
            elif to_obj == self.caller:
                # this is the case if to_obj is the calling Player
                sessid = all_sessions and None or self.sessid
            else:
                # if to_obj is a different Player, all their sessions
                # will be notified unless sessid was given specifically
                sessid = None
        to_obj.msg(msg, from_obj=from_obj, sessid=sessid, **kwargs)

    # Common Command hooks

    def at_pre_cmd(self):
        """
        This hook is called before self.parse() on all commands
        """
        pass

    def at_post_cmd(self):
        """
        This hook is called after the command has finished executing
        (after self.func()).
        """
        pass

    def parse(self):
        """
        Once the cmdhandler has identified this as the command we
        want, this function is run. If many of your commands have
        a similar syntax (for example 'cmd arg1 = arg2') you should simply
        define this once and just let other commands of the same form
        inherit from this. See the docstring of this module for
        which object properties are available to use
        (notably self.args).
        """
        pass

    def func(self):
        """
        This is the actual executing part of the command.
        It is called directly after self.parse(). See the docstring
        of this module for which object properties are available
        (beyond those set in self.parse())
        """
        # a simple test command to show the available properties
        string = "-" * 50
        string += "\n{w%s{n - Command variables from evennia:\n" % self.key
        string += "-" * 50
        string += "\nname of cmd (self.key): {w%s{n\n" % self.key
        string += "cmd aliases (self.aliases): {w%s{n\n" % self.aliases
        string += "cmd perms (self.permissions): {w%s{n\n" % self.permissions
        string += "help category (self.help_category): {w%s{n\n" % self.help_category
        string += "object calling (self.caller): {w%s{n\n" % self.caller
        string += "object storing cmdset (self.obj): {w%s{n\n" % self.obj
        string += "command string given (self.cmdstring): {w%s{n\n" % self.cmdstring
        # show cmdset.key instead of cmdset to shorten output
        string += fill("current cmdset (self.cmdset): {w%s{n\n" % self.cmdset)

        self.caller.msg(string)
Esempio n. 16
0
class HelpEntry(SharedMemoryModel):
    """
    A generic help entry.

    An HelpEntry object has the following properties defined:
      key - main name of entry
      help_category - which category entry belongs to (defaults to General)
      entrytext - the actual help text
      permissions - perm strings

    Method:
      access

    """

    #
    # HelpEntry Database Model setup
    #
    #
    # These database fields are all set using their corresponding properties,
    # named same as the field, but withtout the db_* prefix.

    # title of the help
    db_key = models.CharField('help key', max_length=255, unique=True, help_text='key to search for')
    # help category
    db_help_category = models.CharField("help category", max_length=255, default="General",
        help_text='organizes help entries in lists')
    # the actual help entry text, in any formatting.
    db_entrytext = models.TextField('help entry', blank=True, help_text='the main body of help text')
    # a string of permissionstrings, separated by commas. Not used by help entries.
    db_permissions = models.CharField('permissions', max_length=255, blank=True)
    # lock string storage
    db_lock_storage = models.TextField('locks', blank=True, help_text='normally view:all().')
    # (deprecated, only here to allow MUX helpfile load (don't use otherwise)).
    # TODO: remove this when not needed anymore.
    db_staff_only = models.BooleanField(default=False)

    # Database manager
    objects = HelpEntryManager()

    def __init__(self, *args, **kwargs):
        SharedMemoryModel.__init__(self, *args, **kwargs)
        self.locks = LockHandler(self)

    class Meta:
        "Define Django meta options"
        verbose_name = "Help Entry"
        verbose_name_plural = "Help Entries"

    # used by Attributes to safely retrieve stored object
    _db_model_name = "helpentry"

    # Wrapper properties to easily set database fields. These are
    # @property decorators that allows to access these fields using
    # normal python operations (without having to remember to save()
    # etc). So e.g. a property 'attr' has a get/set/del decorator
    # defined that allows the user to do self.attr = value,
    # value = self.attr and del self.attr respectively (where self
    # is the object in question).

    # key property (wraps db_key)
    #@property
    def __key_get(self):
        "Getter. Allows for value = self.key"
        return self.db_key
    #@key.setter
    def __key_set(self, value):
        "Setter. Allows for self.key = value"
        self.db_key = value
        self.save()
    #@key.deleter
    def __key_del(self):
        "Deleter. Allows for del self.key. Deletes entry."
        self.delete()
    key = property(__key_get, __key_set, __key_del)

    # help_category property (wraps db_help_category)
    #@property
    def __help_category_get(self):
        "Getter. Allows for value = self.help_category"
        return self.db_help_category
    #@help_category.setter
    def __help_category_set(self, value):
        "Setter. Allows for self.help_category = value"
        self.db_help_category = value
        self.save()
    #@help_category.deleter
    def __help_category_del(self):
        "Deleter. Allows for del self.help_category"
        self.db_help_category = "General"
        self.save()
    help_category = property(__help_category_get, __help_category_set, __help_category_del)

    # entrytext property (wraps db_entrytext)
    #@property
    def __entrytext_get(self):
        "Getter. Allows for value = self.entrytext"
        return self.db_entrytext
    #@entrytext.setter
    def __entrytext_set(self, value):
        "Setter. Allows for self.entrytext = value"
        self.db_entrytext = value
        self.save()
    #@entrytext.deleter
    def __entrytext_del(self):
        "Deleter. Allows for del self.entrytext"
        self.db_entrytext = ""
        self.save()
    entrytext = property(__entrytext_get, __entrytext_set, __entrytext_del)

    # permissions property
    #@property
    def __permissions_get(self):
        "Getter. Allows for value = self.permissions. Returns a list of permissions."
        return [perm.strip() for perm in self.db_permissions.split(',')]
    #@permissions.setter
    def __permissions_set(self, value):
        "Setter. Allows for self.permissions = value. Stores as a comma-separated string."
        if is_iter(value):
            value = ",".join([str(val).strip().lower() for val in value])
        self.db_permissions = value
        self.save()
    #@permissions.deleter
    def __permissions_del(self):
        "Deleter. Allows for del self.permissions"
        self.db_permissions = ""
        self.save()
    permissions = property(__permissions_get, __permissions_set, __permissions_del)

        # lock_storage property (wraps db_lock_storage)
    #@property
    def __lock_storage_get(self):
        "Getter. Allows for value = self.lock_storage"
        return self.db_lock_storage
    #@nick.setter
    def __lock_storage_set(self, value):
        """Saves the lock_storagetodate. This is usually not called directly, but through self.lock()"""
        self.db_lock_storage = value
        self.save()
    #@nick.deleter
    def __lock_storage_del(self):
        "Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead"""
        logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self)
    lock_storage = property(__lock_storage_get, __lock_storage_set, __lock_storage_del)


    #
    #
    # HelpEntry main class methods
    #
    #

    def __str__(self):
        return self.key

    def __unicode__(self):
        return u'%s' % self.key

    def access(self, accessing_obj, access_type='read', default=False):
        """
        Determines if another object has permission to access.
        accessing_obj - object trying to access this one
        access_type - type of access sought
        default - what to return if no lock of access_type was found
        """
        return self.locks.check(accessing_obj, access_type=access_type, default=default)
Esempio n. 17
0
class HelpEntry(SharedMemoryModel):
    """
    A generic help entry.

    An HelpEntry object has the following properties defined:
      key - main name of entry
      help_category - which category entry belongs to (defaults to General)
      entrytext - the actual help text
      permissions - perm strings

    Method:
      access

    """

    #
    # HelpEntry Database Model setup
    #
    #
    # These database fields are all set using their corresponding properties,
    # named same as the field, but withtout the db_* prefix.

    # title of the help entry
    db_key = models.CharField('help key',
                              max_length=255,
                              unique=True,
                              help_text='key to search for')
    # help category
    db_help_category = models.CharField(
        "help category",
        max_length=255,
        default="General",
        help_text='organizes help entries in lists')
    # the actual help entry text, in any formatting.
    db_entrytext = models.TextField('help entry',
                                    blank=True,
                                    help_text='the main body of help text')
    # lock string storage
    db_lock_storage = models.TextField('locks',
                                       blank=True,
                                       help_text='normally view:all().')
    # tags are primarily used for permissions
    db_tags = models.ManyToManyField(
        Tag,
        null=True,
        help_text=
        'tags on this object. Tags are simple string markers to identify, group and alias objects.'
    )
    # (deprecated, only here to allow MUX helpfile load (don't use otherwise)).
    # TODO: remove this when not needed anymore.
    db_staff_only = models.BooleanField(default=False)

    # Database manager
    objects = HelpEntryManager()

    def __init__(self, *args, **kwargs):
        SharedMemoryModel.__init__(self, *args, **kwargs)
        self.locks = LockHandler(self)
        self.tags = TagHandler(self)

    class Meta:
        "Define Django meta options"
        verbose_name = "Help Entry"
        verbose_name_plural = "Help Entries"

    # Wrapper properties to easily set database fields. These are
    # @property decorators that allows to access these fields using
    # normal python operations (without having to remember to save()
    # etc). So e.g. a property 'attr' has a get/set/del decorator
    # defined that allows the user to do self.attr = value,
    # value = self.attr and del self.attr respectively (where self
    # is the object in question).

    # key property (wraps db_key)
    #@property
    #def __key_get(self):
    #    "Getter. Allows for value = self.key"
    #    return self.db_key
    ##@key.setter
    #def __key_set(self, value):
    #    "Setter. Allows for self.key = value"
    #    self.db_key = value
    #    self.save()
    ##@key.deleter
    #def __key_del(self):
    #    "Deleter. Allows for del self.key. Deletes entry."
    #    self.delete()
    #key = property(__key_get, __key_set, __key_del)

    ## help_category property (wraps db_help_category)
    ##@property
    #def __help_category_get(self):
    #    "Getter. Allows for value = self.help_category"
    #    return self.db_help_category
    ##@help_category.setter
    #def __help_category_set(self, value):
    #    "Setter. Allows for self.help_category = value"
    #    self.db_help_category = value
    #    self.save()
    ##@help_category.deleter
    #def __help_category_del(self):
    #    "Deleter. Allows for del self.help_category"
    #    self.db_help_category = "General"
    #    self.save()
    #help_category = property(__help_category_get, __help_category_set, __help_category_del)

    ## entrytext property (wraps db_entrytext)
    ##@property
    #def __entrytext_get(self):
    #    "Getter. Allows for value = self.entrytext"
    #    return self.db_entrytext
    ##@entrytext.setter
    #def __entrytext_set(self, value):
    #    "Setter. Allows for self.entrytext = value"
    #    self.db_entrytext = value
    #    self.save()
    ##@entrytext.deleter
    #def __entrytext_del(self):
    #    "Deleter. Allows for del self.entrytext"
    #    self.db_entrytext = ""
    #    self.save()
    #entrytext = property(__entrytext_get, __entrytext_set, __entrytext_del)

    ## permissions property
    ##@property
    #def __permissions_get(self):
    #    "Getter. Allows for value = self.permissions. Returns a list of permissions."
    #    return [perm.strip() for perm in self.db_permissions.split(',')]
    ##@permissions.setter
    #def __permissions_set(self, value):
    #    "Setter. Allows for self.permissions = value. Stores as a comma-separated string."
    #    if is_iter(value):
    #        value = ",".join([str(val).strip().lower() for val in value])
    #    self.db_permissions = value
    #    self.save()
    ##@permissions.deleter
    #def __permissions_del(self):
    #    "Deleter. Allows for del self.permissions"
    #    self.db_permissions = ""
    #    self.save()
    #permissions = property(__permissions_get, __permissions_set, __permissions_del)

    # lock_storage property (wraps db_lock_storage)
    ##@property
    #def __lock_storage_get(self):
    #    "Getter. Allows for value = self.lock_storage"
    #    return self.db_lock_storage
    ##@nick.setter
    #def __lock_storage_set(self, value):
    #    """Saves the lock_storagetodate. This is usually not called directly, but through self.lock()"""
    #    self.db_lock_storage = value
    #    self.save()
    ##@nick.deleter
    #def __lock_storage_del(self):
    #    "Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead"""
    #    logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self)
    #lock_storage = property(__lock_storage_get, __lock_storage_set, __lock_storage_del)

    #
    #
    # HelpEntry main class methods
    #
    #

    def __str__(self):
        return self.key

    def __unicode__(self):
        return u'%s' % self.key

    def access(self, accessing_obj, access_type='read', default=False):
        """
        Determines if another object has permission to access.
        accessing_obj - object trying to access this one
        access_type - type of access sought
        default - what to return if no lock of access_type was found
        """
        return self.locks.check(accessing_obj,
                                access_type=access_type,
                                default=default)