Trunk: Merged the Devel-branch (branches/griatch) into /trunk. This constitutes a major refactoring of Evennia. Development will now continue in trunk. See the wiki and the past posts to the mailing list for info. /Griatch
This commit is contained in:
parent
df29defbcd
commit
f83c2bddf8
222 changed files with 22304 additions and 14371 deletions
322
src/comms/managers.py
Normal file
322
src/comms/managers.py
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
"""
|
||||
These managers handles the
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
from src.players.models import PlayerDB
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from src.utils.utils import is_iter
|
||||
|
||||
class CommError(Exception):
|
||||
"Raise by comm system, to allow feedback to player when caught."
|
||||
pass
|
||||
|
||||
# helper function
|
||||
|
||||
def to_object(inp, objtype='player'):
|
||||
"""
|
||||
Locates the object related to the given
|
||||
playername or channel key. If input was already
|
||||
the correct object, return it.
|
||||
inp - the input object/string
|
||||
objtype - 'player' or 'channel'
|
||||
"""
|
||||
if objtype == 'player':
|
||||
if type(inp) == PlayerDB:
|
||||
return inp
|
||||
if hasattr(inp, 'player'):
|
||||
return inp.player
|
||||
else:
|
||||
umatch = PlayerDB.objects.filter(user__username__iexact=inp)
|
||||
if umatch:
|
||||
return umatch[0]
|
||||
else:
|
||||
# have to import this way to avoid circular imports
|
||||
from src.comms.models import Channel
|
||||
#= ContentType.objects.get(app_label="comms",
|
||||
# model="channel").model_class()
|
||||
if type(inp) == Channel:
|
||||
return inp
|
||||
cmatch = Channel.objects.filter(db_key__iexact=inp)
|
||||
if cmatch:
|
||||
return cmatch[0]
|
||||
return None
|
||||
|
||||
#
|
||||
# Msg manager
|
||||
#
|
||||
|
||||
class MsgManager(models.Manager):
|
||||
"""
|
||||
Handle msg database
|
||||
"""
|
||||
|
||||
def get_message_by_id(self, idnum):
|
||||
"Retrieve message by its id."
|
||||
try:
|
||||
idnum = int(idnum)
|
||||
return self.get(id=id)
|
||||
except:
|
||||
return None
|
||||
|
||||
def get_messages_by_sender(self, sender):
|
||||
"""
|
||||
Get all messages sent by one player
|
||||
"""
|
||||
sender = to_object(sender)
|
||||
if not sender:
|
||||
return None
|
||||
return [msg for msg in sender.sender_set.all()
|
||||
if sender not in msg.hide_from_senders.all()]
|
||||
|
||||
def get_messages_by_receiver(self, receiver):
|
||||
"""
|
||||
Get all messages sent to one player
|
||||
"""
|
||||
receiver = to_object(receiver)
|
||||
if not receiver:
|
||||
return None
|
||||
return [msg for msg in receiver.receiver_set.all()
|
||||
if receiver not in msg.hide_from_receivers.all()]
|
||||
|
||||
def get_messages_by_channel(self, channel):
|
||||
"""
|
||||
Get all messages sent to one channel
|
||||
"""
|
||||
channel = to_object(channel, objtype='channel')
|
||||
if not channel:
|
||||
return None
|
||||
return [msg for msg in channel.channel_set.all()
|
||||
if channel not in msg.hide_from_channels.all()]
|
||||
|
||||
|
||||
#TODO add search limited by send_times
|
||||
def text_search(self, searchstring, filterdict=None):
|
||||
"""
|
||||
Returns all messages that contain the matching
|
||||
search string. To avoid too many results, and also
|
||||
since this can be a very computing-
|
||||
heavy operation, it's recommended to be filtered
|
||||
by at least channel or sender/receiver.
|
||||
searchstring - string to search for
|
||||
filterdict -
|
||||
{'channels':[list],
|
||||
'senders':[list],
|
||||
'receivers':[list]}
|
||||
lists can contain either the name/keys of the
|
||||
objects or the actual objects to filter by.
|
||||
"""
|
||||
|
||||
if filterdict:
|
||||
# obtain valid objects for all filters
|
||||
channels = [chan for chan in
|
||||
[to_object(chan, objtype='channel')
|
||||
for chan in filterdict.get('channels',[])]
|
||||
if chan]
|
||||
senders = [sender for sender in
|
||||
[to_object(sender)
|
||||
for sender in filterdict.get('senders',[])]
|
||||
if sender]
|
||||
receivers = [receiver for receiver in
|
||||
[to_object(receiver)
|
||||
for receiver in filterdict.get('receivers',[])]
|
||||
if receiver]
|
||||
# filter the messages lazily using the filter objects
|
||||
msgs = []
|
||||
for sender in senders:
|
||||
msgs = list(sender.message_set.filter(
|
||||
db_message__icontains=searchstring))
|
||||
for receiver in receivers:
|
||||
rec_msgs = receiver.message_set.filter(
|
||||
db_message__icontains=searchstring)
|
||||
if msgs:
|
||||
msgs = [msg for msg in rec_msgs if msg in msgs]
|
||||
else:
|
||||
msgs = rec_msgs
|
||||
for channel in channels:
|
||||
chan_msgs = list(channel.message_set.filter(
|
||||
db_message__icontains=searchstring))
|
||||
if msgs:
|
||||
msgs = [msg for msg in chan_msgs if msg in msgs]
|
||||
else:
|
||||
msgs = chan_msgs
|
||||
return list(set(msgs))
|
||||
return list(self.all().filter(db_message__icontains=searchstring))
|
||||
|
||||
def message_search(self, sender=None, receiver=None, channel=None, freetext=None, dbref=None):
|
||||
"""
|
||||
Search the message database for particular messages. At least one
|
||||
of the arguments must be given to do a search.
|
||||
|
||||
sender - get messages sent by a particular player
|
||||
receiver - get messages received by a certain player or players
|
||||
channel - get messages sent to a particular channel or channels
|
||||
freetext - Search for a text string in a message.
|
||||
NOTE: This can potentially be slow, so make sure to supply
|
||||
one of the other arguments to limit the search.
|
||||
dbref - (int) the exact database id of the message. This will override
|
||||
all other search crieteria since it's unique and
|
||||
always gives a list with only one match.
|
||||
"""
|
||||
if dbref:
|
||||
return self.filter(id=dbref)
|
||||
if freetext:
|
||||
if sender:
|
||||
sender = [sender]
|
||||
if receiver and not is_iter(receiver):
|
||||
receiver = [receiver]
|
||||
if channel and not is_iter(channel):
|
||||
channel = [channel]
|
||||
filterdict = {"senders":sender,
|
||||
"receivers":receiver,
|
||||
"channels":channel}
|
||||
return self.textsearch(freetext, filterdict)
|
||||
msgs = []
|
||||
if sender:
|
||||
msgs = self.get_messages_by_sender(sender)
|
||||
if receiver:
|
||||
rec_msgs = self.get_messages_by_receiver(receiver)
|
||||
if msgs:
|
||||
msgs = [msg for msg in rec_msgs if msg in msgs]
|
||||
else:
|
||||
msgs = rec_msgs
|
||||
if channel:
|
||||
chan_msgs = self.get_messaqge_by_channel(channel)
|
||||
if msgs:
|
||||
msgs = [msg for msg in chan_msgs if msg in msgs]
|
||||
else:
|
||||
msgs = chan_msgs
|
||||
return msgs
|
||||
|
||||
#
|
||||
# Channel manager
|
||||
#
|
||||
|
||||
class ChannelManager(models.Manager):
|
||||
"""
|
||||
Handle channel database
|
||||
"""
|
||||
|
||||
def get_all_channels(self):
|
||||
"""
|
||||
Returns all channels in game.
|
||||
"""
|
||||
return self.all()
|
||||
|
||||
def get_channel(self, channelkey):
|
||||
"""
|
||||
Return the channel object if given its key.
|
||||
Also searches its aliases.
|
||||
"""
|
||||
# first check the channel key
|
||||
channels = self.filter(db_key__iexact=channelkey)
|
||||
if not channels:
|
||||
# also check aliases
|
||||
channels = [channel for channel in self.all()
|
||||
if channelkey in channel.aliases]
|
||||
if channels:
|
||||
return channels[0]
|
||||
return None
|
||||
|
||||
def del_channel(self, channelkey):
|
||||
"""
|
||||
Delete channel matching channelkey.
|
||||
Also cleans up channelhandler.
|
||||
"""
|
||||
channels = self.filter(db_key__iexact=channelkey)
|
||||
if not channels:
|
||||
# no aliases allowed for deletion.
|
||||
return False
|
||||
for channel in channels:
|
||||
channel.delete()
|
||||
from src.comms.channelhandler import CHANNELHANDLER
|
||||
CHANNELHANDLER.update()
|
||||
return None
|
||||
|
||||
def has_connection(self, player, channel):
|
||||
"Check so the player is really listening to this channel."
|
||||
ChannelConnection = ContentType.objects.get(app_label="comms",
|
||||
model="channelconnection").model_class()
|
||||
return ChannelConnection.objects.has_connection(player, channel)
|
||||
|
||||
def get_all_connections(self, channel):
|
||||
"""
|
||||
Return the connections of all players listening
|
||||
to this channel
|
||||
"""
|
||||
# import here to avoid circular imports
|
||||
from src.comms.models import ChannelConnection
|
||||
#= ContentType.objects.get(app_label="comms",
|
||||
# model="channelconnection").model_class()
|
||||
return ChannelConnection.objects.get_all_connections(channel)
|
||||
|
||||
def channel_search(self, ostring):
|
||||
"""
|
||||
Search the channel database for a particular channel.
|
||||
|
||||
ostring - the key or database id of the channel.
|
||||
"""
|
||||
channels = []
|
||||
try:
|
||||
# try an id match first
|
||||
dbref = int(ostring.strip('#'))
|
||||
channels = self.filter(id=dbref)
|
||||
except Exception:
|
||||
pass
|
||||
if not channels:
|
||||
# no id match. Search on the key.
|
||||
channels = self.filter(db_key=ostring)
|
||||
return channels
|
||||
|
||||
#
|
||||
# ChannelConnection manager
|
||||
#
|
||||
class ChannelConnectionManager(models.Manager):
|
||||
"""
|
||||
This handles all connections between a player and
|
||||
a channel.
|
||||
"""
|
||||
|
||||
def get_all_player_connections(self, player):
|
||||
"Get all connections that the given player has."
|
||||
player = to_object(player)
|
||||
return self.filter(db_player=player)
|
||||
|
||||
def has_connection(self, player, channel):
|
||||
"Checks so a connection exists player<->channel"
|
||||
player = to_object(player)
|
||||
channel = to_object(channel, objtype="channel")
|
||||
if player and channel:
|
||||
return self.filter(db_player=player).filter(db_channel=channel).count() > 0
|
||||
return False
|
||||
|
||||
def get_all_connections(self, channel):
|
||||
"""
|
||||
Get all connections for a channel
|
||||
"""
|
||||
channel = to_object(channel, objtype='channel')
|
||||
return self.filter(db_channel=channel)
|
||||
|
||||
def create_connection(self, player, channel):
|
||||
"""
|
||||
Connect a player to a channel. player and channel
|
||||
can be actual objects or keystrings.
|
||||
"""
|
||||
player = to_object(player)
|
||||
channel = to_object(channel, objtype='channel')
|
||||
if not player or not channel:
|
||||
raise CommError("NOTFOUND")
|
||||
new_connection = self.model(db_player=player, db_channel=channel)
|
||||
new_connection.save()
|
||||
return new_connection
|
||||
|
||||
def break_connection(self, player, channel):
|
||||
"Remove link between player and channel"
|
||||
player = to_object(player)
|
||||
channel = to_object(channel, objtype='channel')
|
||||
if not player or not channel:
|
||||
raise CommError("NOTFOUND")
|
||||
conns = self.filter(db_player=player).filter(db_channel=channel)
|
||||
for conn in conns:
|
||||
conn.delete()
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue