Added new docs for Channels and Msg

This commit is contained in:
Griatch 2021-05-09 22:36:44 +02:00
parent 43651ac867
commit 7e2a446bda
9 changed files with 474 additions and 193 deletions

View file

@ -152,8 +152,8 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
def msg_channel(self, channel, message, **kwargs):
"""
Send a message to a given channel. At this point
any permissions should already be done.
Send a message to a given channel. This will check the 'send'
permission on the channel.
Args:
channel (Channel): The channel to send to.
@ -162,6 +162,10 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
all channel messaging hooks for custom overriding.
"""
if not channel.access(self.caller, "send"):
caller.msg(f"You are not allowed to send messages to channel {channel}")
return
channel.msg(message, senders=self.caller, **kwargs)
def get_channel_history(self, channel, start_index=0):
@ -587,7 +591,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
name = subscriber.get_display_name(caller)
conditions = ("muted" if subscriber in mute_list else "",
"offline" if subscriber not in online_list else "")
conditions = (cond for cond in conditions if cond)
conditions = [cond for cond in conditions if cond]
cond_text = "(" + ", ".join(conditions) + ")" if conditions else ""
who_list.append(f"{name}{cond_text}")

View file

@ -314,7 +314,7 @@ class DefaultChannel(ChannelDB, metaclass=TypeclassBase):
)
@classmethod
def create(cls, key, account=None, *args, **kwargs):
def create(cls, key, creator=None, *args, **kwargs):
"""
Creates a basic Channel with default parameters, unless otherwise
specified or extended.
@ -323,7 +323,8 @@ class DefaultChannel(ChannelDB, metaclass=TypeclassBase):
Args:
key (str): This must be unique.
account (Account): Account to attribute this object to.
creator (Account or Object): Entity to associate with this channel
(used for tracking)
Keyword Args:
aliases (list of str): List of alternative (likely shorter) keynames.
@ -351,8 +352,8 @@ class DefaultChannel(ChannelDB, metaclass=TypeclassBase):
# Record creator id and creation IP
if ip:
obj.db.creator_ip = ip
if account:
obj.db.creator_id = account.id
if creator:
obj.db.creator_id = creator.id
except Exception as exc:
errors.append("An error occurred while creating this '%s' object." % key)

View file

@ -14,6 +14,7 @@ _GA = object.__getattribute__
_AccountDB = None
_ObjectDB = None
_ChannelDB = None
_ScriptDB = None
_SESSIONS = None
# error class
@ -54,6 +55,8 @@ def identify_object(inp):
return inp, "object"
elif clsname == "ChannelDB":
return inp, "channel"
elif clsname == "ScriptDB":
return inp, "script"
if isinstance(inp, str):
return inp, "string"
elif dbref(inp):
@ -103,6 +106,14 @@ def to_object(inp, objtype="account"):
return _ChannelDB.objects.get(id=obj)
logger.log_err("%s %s %s %s %s" % (objtype, inp, obj, typ, type(inp)))
raise CommError()
elif objtype == "script":
if typ == "string":
return _ScriptDB.objects.get(db_key__iexact=obj)
if typ == "dbref":
return _ScriptDB.objects.get(id=obj)
logger.log_err("%s %s %s %s %s" % (objtype, inp, obj, typ, type(inp)))
raise CommError()
# an unknown
return None
@ -158,48 +169,30 @@ class MsgManager(TypedObjectManager):
except Exception:
return None
def get_messages_by_sender(self, sender, exclude_channel_messages=False):
def get_messages_by_sender(self, sender):
"""
Get all messages sent by one entity - this could be either a
account or an object
Args:
sender (Account or Object): The sender of the message.
exclude_channel_messages (bool, optional): Only return messages
not aimed at a channel (that is, private tells for example)
Returns:
messages (list): List of matching messages
QuerySet: Matching messages.
Raises:
CommError: For incorrect sender types.
"""
obj, typ = identify_object(sender)
if exclude_channel_messages:
# explicitly exclude channel recipients
if typ == "account":
return list(
self.filter(db_sender_accounts=obj, db_receivers_channels__isnull=True).exclude(
db_hide_from_accounts=obj
)
)
elif typ == "object":
return list(
self.filter(db_sender_objects=obj, db_receivers_channels__isnull=True).exclude(
db_hide_from_objects=obj
)
)
else:
raise CommError
if typ == "account":
return self.filter(db_sender_accounts=obj).exclude(db_hide_from_accounts=obj)
elif typ == "object":
return self.filter(db_sender_objects=obj).exclude(db_hide_from_objects=obj)
elif typ == "script":
return self.filter(db_sender_scripts=obj)
else:
# get everything, channel or not
if typ == "account":
return list(self.filter(db_sender_accounts=obj).exclude(db_hide_from_accounts=obj))
elif typ == "object":
return list(self.filter(db_sender_objects=obj).exclude(db_hide_from_objects=obj))
else:
raise CommError
raise CommError
def get_messages_by_receiver(self, recipient):
"""
@ -209,7 +202,7 @@ class MsgManager(TypedObjectManager):
recipient (Object, Account or Channel): The recipient of the messages to search for.
Returns:
messages (list): Matching messages.
Queryset: Matching messages.
Raises:
CommError: If the `recipient` is not of a valid type.
@ -217,26 +210,14 @@ class MsgManager(TypedObjectManager):
"""
obj, typ = identify_object(recipient)
if typ == "account":
return list(self.filter(db_receivers_accounts=obj).exclude(db_hide_from_accounts=obj))
return self.filter(db_receivers_accounts=obj).exclude(db_hide_from_accounts=obj)
elif typ == "object":
return list(self.filter(db_receivers_objects=obj).exclude(db_hide_from_objects=obj))
elif typ == "channel":
return list(self.filter(db_receivers_channels=obj).exclude(db_hide_from_channels=obj))
return self.filter(db_receivers_objects=obj).exclude(db_hide_from_objects=obj)
elif typ == 'script':
return self.filter(db_receivers_scripts=obj)
else:
raise CommError
def get_messages_by_channel(self, channel):
"""
Get all persistent messages sent to one channel.
Args:
channel (Channel): The channel to find messages for.
Returns:
messages (list): Persistent Msg objects saved for this channel.
"""
return self.filter(db_receivers_channels=channel).exclude(db_hide_from_channels=channel)
def search_message(self, sender=None, receiver=None, freetext=None, dbref=None):
"""
@ -244,7 +225,7 @@ class MsgManager(TypedObjectManager):
one of the arguments must be given to do a search.
Args:
sender (Object or Account, optional): Get messages sent by a particular account or object
sender (Object, Account or Script, optional): Get messages sent by a particular sender.
receiver (Object, Account or Channel, optional): Get messages
received by a certain account,object or channel
freetext (str): Search for a text string in a message. NOTE:
@ -255,14 +236,12 @@ class MsgManager(TypedObjectManager):
always gives only one match.
Returns:
messages (list or Msg): A list of message matches or a single match if `dbref` was given.
Queryset: Message matches.
"""
# unique msg id
if dbref:
msg = self.objects.filter(id=dbref)
if msg:
return msg[0]
return self.objects.filter(id=dbref)
# We use Q objects to gradually build up the query - this way we only
# need to do one database lookup at the end rather than gradually
@ -275,20 +254,23 @@ class MsgManager(TypedObjectManager):
sender_restrict = Q(db_sender_accounts=sender) & ~Q(db_hide_from_accounts=sender)
elif styp == "object":
sender_restrict = Q(db_sender_objects=sender) & ~Q(db_hide_from_objects=sender)
elif styp == 'script':
sender_restrict = Q(db_sender_scripts=sender)
else:
sender_restrict = Q()
# filter by receiver
receiver, rtyp = identify_object(receiver)
if rtyp == "account":
receiver_restrict = Q(db_receivers_accounts=receiver) & ~Q(
db_hide_from_accounts=receiver
)
receiver_restrict = (
Q(db_receivers_accounts=receiver) & ~Q(db_hide_from_accounts=receiver ))
elif rtyp == "object":
receiver_restrict = Q(db_receivers_objects=receiver) & ~Q(db_hide_from_objects=receiver)
elif rtyp == 'script':
receiver_restrict = Q(db_receivers_scripts=receiver)
elif rtyp == "channel":
receiver_restrict = Q(db_receivers_channels=receiver) & ~Q(
db_hide_from_channels=receiver
)
raise DeprecationWarning(
"Msg.objects.search don't accept channel recipients since "
"Channels no longer accepts Msg objects.")
else:
receiver_restrict = Q()
# filter by full text
@ -297,7 +279,7 @@ class MsgManager(TypedObjectManager):
else:
fulltext_restrict = Q()
# execute the query
return list(self.filter(sender_restrict & receiver_restrict & fulltext_restrict))
return self.filter(sender_restrict & receiver_restrict & fulltext_restrict)
# back-compatibility alias
message_search = search_message

View file

@ -157,6 +157,7 @@ class Msg(SharedMemoryModel):
db_hide_from_objects = models.ManyToManyField(
"objects.ObjectDB", related_name="hide_from_objects_set", blank=True
)
# NOTE: deprecated in 1.0. Not used for channels anymore
db_hide_from_channels = models.ManyToManyField(
"ChannelDB", related_name="hide_from_channels_set", blank=True
)
@ -263,9 +264,8 @@ class Msg(SharedMemoryModel):
elif clsname == "ScriptDB":
self.db_sender_accounts.remove(sender)
# receivers property
# @property
def __receivers_get(self):
@property
def receivers(self):
"""
Getter. Allows for value = self.receivers.
Returns four lists of receivers: accounts, objects, scripts and channels.
@ -277,8 +277,8 @@ class Msg(SharedMemoryModel):
+ list(self.db_receivers_channels.all())
)
# @receivers.setter
def __receivers_set(self, receivers):
@receivers.setter
def receivers(self, receivers):
"""
Setter. Allows for self.receivers = value.
This appends a new receiver to the message.
@ -298,8 +298,8 @@ class Msg(SharedMemoryModel):
elif clsname == "ChannelDB":
self.db_receivers_channels.add(receiver)
# @receivers.deleter
def __receivers_del(self):
@receivers.deleter
def receivers(self):
"Deleter. Clears all receivers"
self.db_receivers_accounts.clear()
self.db_receivers_objects.clear()
@ -307,7 +307,6 @@ class Msg(SharedMemoryModel):
self.db_receivers_channels.clear()
self.save()
receivers = property(__receivers_get, __receivers_set, __receivers_del)
def remove_receiver(self, receivers):
"""

View file

@ -360,22 +360,21 @@ help_entry = create_help_entry
def create_message(
senderobj, message, channels=None, receivers=None, locks=None, tags=None, header=None
):
senderobj, message, receivers=None, locks=None, tags=None,
header=None, **kwargs):
"""
Create a new communication Msg. Msgs represent a unit of
database-persistent communication between entites.
Args:
senderobj (Object or Account): The entity sending the Msg.
senderobj (Object, Account, Script, str or list): The entity (or
entities) sending the Msg. If a `str`, this is the id-string
for an external sender type.
message (str): Text with the message. Eventual headers, titles
etc should all be included in this text string. Formatting
will be retained.
channels (Channel, key or list): A channel or a list of channels to
send to. The channels may be actual channel objects or their
unique key strings.
receivers (Object, Account, str or list): An Account/Object to send
to, or a list of them. May be Account objects or accountnames.
receivers (Object, Account or list): An Account/Object to send
to, or a list of them.
locks (str): Lock definition string.
tags (list): A list of tags or tuples `(tag, category)`.
header (str): Mime-type or other optional information for the message
@ -387,6 +386,12 @@ def create_message(
limit this as desired.
"""
if 'channels' in kwargs:
raise DeprecationWarning(
"create_message() does not accept 'channel' kwarg anymore "
"- channels no longer accept Msg objects."
)
global _Msg
if not _Msg:
from evennia.comms.models import Msg as _Msg
@ -398,8 +403,6 @@ def create_message(
for sender in make_iter(senderobj):
new_message.senders = sender
new_message.header = header
for channel in make_iter(channels):
new_message.channels = channel
for receiver in make_iter(receivers):
new_message.receivers = receiver
if locks: