# encrypted_channels.py
from evennia import DefaultChannel
class EncryptedChannel(DefaultChannel):
def msg(self, msgobj, header=None, senders=None, sender_strings=None,
keep_log=None, online=False, emit=False, external=False):
"""
Send the given message to all accounts 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.
Args:
msgobj (Msg, TempMsg or str): If a Msg/TempMsg, the remaining
keywords will be ignored (since the Msg/TempMsg object already
has all the data). 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.
header (str, optional): A header for building the message.
senders (Object, Account or list, optional): Optional if persistent=False, used
to build senders for the message.
sender_strings (list, optional): Name strings of senders. Used for external
connections where the sender is not an account or object.
When this is defined, external will be assumed.
keep_log (bool or None, optional): This allows to temporarily change the logging status of
this channel message. If `None`, the Channel's `keep_log` Attribute will
be used. If `True` or `False`, that logging status will be used for this
message only (note that for unlogged channels, a `True` value here will
create a new log file only for this message).
online (bool, optional) - If this is set true, only messages people who are
online. Otherwise, messages all accounts connected. This can
make things faster, but may not trigger listeners on accounts
that are offline.
emit (bool, optional) - Signals to the message formatter that this message is
not to be directly associated with a name.
external (bool, optional): Treat this message as being
agnostic of its sender.
Returns:
success (bool): Returns `True` if message sending was
successful, `False` otherwise.
"""
senders = make_iter(senders) if senders else []
if isinstance(msgobj, basestring):
# given msgobj is a string - convert to msgobject (always TempMsg)
if senders and hasattr(senders[0], "db"):
__channel_passwords = senders[0].db.__channel_passwords
if type(__channel_passwords) is dict:
password = __channel_passwords.get(self)
lockstring = "read:decrypt({})".format(password) if password else "read:true()"
msgobj = TempMsg(senders=senders, header=header, message=msgobj, channels=[self], lockstring=lockstring or "read:true()")
# we store the logging setting for use in distribute_message()
msgobj.keep_log = keep_log if keep_log is not None else self.db.keep_log
# start the sending
msgobj = self.pre_send_message(msgobj)
if not msgobj:
return False
msgobj = self.message_transform(msgobj, emit=emit,
sender_strings=sender_strings,
external=external)
self.distribute_message(msgobj, online=online)
self.post_send_message(msgobj)
return True
def distribute_message(self, msgobj, online=False, **kwargs):
"""
Method for grabbing all listeners that a message should be
sent to on this channel, and sending them a message.
Args:
msgobj (Msg or TempMsg): Message to distribute.
online (bool): Only send to receivers who are actually online
(not currently used):
**kwargs (dict): Arbitrary, optional arguments for users
overriding the call (unused by default).
Notes:
This is also where logging happens, if enabled.
"""
# get all accounts or objects connected to this channel and send to them
if online:
subs = self.subscriptions.online()
else:
subs = self.subscriptions.all()
for entity in subs:
# if the entity is muted, we don't send them a message
if entity in self.mutelist:
continue
try:
# note our addition of the from_channel keyword here. This could be checked
# by a custom account.msg() to treat channel-receives differently.
if msgobj.access(entity, "read"):
entity.msg(msgobj.message, from_obj=msgobj.senders, options={"from_channel": self.id})
else:
entity.msg("[scrambled message]", from_obj=msgobj.senders, options={"from_channel": self.id})
except AttributeError as e:
logger.log_trace("%s\nCannot send msg to '%s'." % (e, entity))
if msgobj.keep_log:
# log to file
logger.log_file(msgobj.message, self.attributes.get("log_file") or "channel_%s.log" % self.key)
Comments