From dcc7f29a91bc58823e3934aff57d906fb68190e8 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 30 Aug 2012 00:05:00 +0200 Subject: [PATCH] OBS: run migrations! This changes the Msg model to work with ManyToManyFields rather than with custom string representations for storing multiple receivers or channels. It also expands the Msg object with a "title" field and various filter options. This should make it easier to implement mail-like operations using the comms system. --- src/commands/default/comms.py | 38 ++- src/comms/channelhandler.py | 3 +- src/comms/managers.py | 295 +++++++++--------- src/comms/migrations/0007_upgrading_msgs.py | 283 +++++++++++++++++ src/comms/models.py | 325 ++++++++++---------- src/utils/create.py | 49 +-- src/utils/dummyrunner_actions.py | 42 ++- src/utils/utils.py | 2 - 8 files changed, 656 insertions(+), 381 deletions(-) create mode 100644 src/comms/migrations/0007_upgrading_msgs.py diff --git a/src/commands/default/comms.py b/src/commands/default/comms.py index 9099637605..87ddfde998 100644 --- a/src/commands/default/comms.py +++ b/src/commands/default/comms.py @@ -651,23 +651,20 @@ class CmdPage(MuxCommandOOC): # this is a MuxCommandOOC, which means caller will be a Player. caller = self.caller - character = self.character - # get the messages we've sent - messages_we_sent = list(Msg.objects.get_messages_by_sender(caller)) - pages_we_sent = [msg for msg in messages_we_sent if msg.receivers] + # get the messages we've sent (not to channels) + pages_we_sent = Msg.objects.get_messages_by_sender(caller, exclude_channel_messages=True) # get last messages we've got - pages_we_got = list(Msg.objects.get_messages_by_receiver(caller)) + pages_we_got = Msg.objects.get_messages_by_receiver(caller) + if 'last' in self.switches: if pages_we_sent: - string = "You last paged {c%s{n." % (", ".join([obj.name - for obj in pages_we_sent[-1].receivers])) - caller.msg(string) + recv = ",".join(obj.key for obj in pages_we_sent[-1].receivers) + caller.msg("You last paged {c%s{n:%s" % (recv, pages_we_sent[-1].message)) return else: - string = "You haven't paged anyone yet." - caller.msg(string) + caller.msg("You haven't paged anyone yet.") return if not self.args or not self.rhs: @@ -687,11 +684,11 @@ class CmdPage(MuxCommandOOC): else: lastpages = pages - lastpages = "\n ".join(["{w%s{n {c%s{n to {c%s{n: %s" % (utils.datetime_format(page.date_sent), - page.sender.name, - "{n,{c ".join([obj.name for obj in page.receivers]), - page.message) - for page in lastpages]) + lastpages = "\n ".join("{w%s{n {c%s{n to {c%s{n: %s" % (utils.datetime_format(page.date_sent), + ",".join(obj.key for obj in page.senders), + "{n,{c ".join([obj.name for obj in page.receivers]), + page.message) + for page in lastpages) if lastpages: string = "Your latest pages:\n %s" % lastpages @@ -705,7 +702,7 @@ class CmdPage(MuxCommandOOC): if not self.lhs: # If there are no targets, then set the targets - # to the last person they paged. + # to the last person we paged. if pages_we_sent: receivers = pages_we_sent[-1].receivers else: @@ -723,9 +720,10 @@ class CmdPage(MuxCommandOOC): else: caller.msg("Who do you want to page?") return - recobjs.append(pobj) + if pobj: + recobjs.append(pobj) if not recobjs: - caller.msg("No players matching your target were found.") + caller.msg("Noone found to page.") return header = "{wPlayer{n {c%s{n {wpages:{n" % caller.key @@ -736,8 +734,8 @@ class CmdPage(MuxCommandOOC): message = "%s %s" % (caller.key, message.strip(':').strip()) # create the persistent message object - msg = create.create_message(caller, message, - receivers=recobjs) + create.create_message(caller, message, + receivers=recobjs) # tell the players they got a message. received = [] diff --git a/src/comms/channelhandler.py b/src/comms/channelhandler.py index cede1ff374..074fcdd767 100644 --- a/src/comms/channelhandler.py +++ b/src/comms/channelhandler.py @@ -85,8 +85,9 @@ class ChannelCommand(command.Command): except AttributeError: # this could happen if a player is calling directly. sender = caller.dbobj - msgobj = Msg(db_sender=sender, db_message=msg) + msgobj = Msg(db_message=msg) msgobj.save() + msgobj.senders = sender msgobj.channels = channel # send new message object to channel channel.msg(msgobj, from_obj=sender) diff --git a/src/comms/managers.py b/src/comms/managers.py index bf9b1a59aa..8d3057b254 100644 --- a/src/comms/managers.py +++ b/src/comms/managers.py @@ -4,14 +4,70 @@ These managers handles the import itertools from django.db import models +from django.db.models import Q from django.contrib.contenttypes.models import ContentType -from src.utils.utils import is_iter + +_PlayerDB = None +_ObjectDB = None +_Channel = None +_ExternalConnection = None +_User = None + +# error class class CommError(Exception): "Raise by comm system, to allow feedback to player when caught." pass -# helper function +# +# helper functions +# + +def dbref(dbref): + """ + Valid forms of dbref (database reference number) + are either a string '#N' or an integer N. + Output is the integer part. + """ + if isinstance(dbref, basestring): + dbref = dbref.lstrip('#') + try: + if int(dbref) < 0: + return None + except Exception: + return None + return dbref + +def identify_object(inp): + "identify if an object is a player or an object; return its database model" + # load global stores + global _PlayerDB, _ObjectDB, _Channel, _ExternalConnection, _User + if not _PlayerDB: + from src.players.models import PlayerDB as _PlayerDB + if not _ObjectDB: + from src.objects.models import ObjectDB as _ObjectDB + if not _Channel: + from src.comms.models import Channel as _Channel + if not _ExternalConnection: + from src.comms.models import ExternalChannelConnection as _ExternalConnection + if not _User: + from django.contrib.auth.models import User as _User + if not inp: + return inp, None + # try to identify the type + try: + obj = inp.dbobj # this works for all typeclassed entities + except AttributeError: + obj = inp + typ = type(obj) + if typ == _PlayerDB: return obj, "player" + if typ == _User: return obj.get_profile(), "player" + elif typ == _ObjectDB: return obj, "object" + elif typ == _Channel: return obj, "channel" + elif dbref(obj): return dbref(obj), "dbref" + elif typ == basestring: return obj, "string" + elif typ == _ExternalConnection: return obj, "external" + return obj, None # Something else def to_object(inp, objtype='player'): """ @@ -21,34 +77,31 @@ def to_object(inp, objtype='player'): inp - the input object/string objtype - 'player' or 'channel' """ - from src.players.models import PlayerDB + obj, typ = identify_object(inp) + if typ == objtype: + return obj 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] + if typ == 'object': return obj.player + if typ == 'string': return _PlayerDB.objects.get(user_username__iexact=obj) + if typ == 'dbref': return _PlayerDB.objects.get(id=obj) + print objtype, inp, obj, typ, type(inp) + raise CommError() + elif objtype == 'object': + if typ == 'player': return obj.obj + if typ == 'string': return _ObjectDB.objects.get(db_key__iexact=obj) + if typ == 'dbref': return _ObjectDB.objects.get(id=obj) + print objtype, inp, obj, typ, type(inp) + raise CommError() + elif objtype == 'channel': + if typ == 'string': return _Channel.objects.get(db_key__iexact=obj) + if typ == 'dbref': return _Channel.objects.get(id=obj) + print objtype, inp, obj, typ, type(inp) + raise CommError() elif objtype == 'external': - from src.comms.models import ExternalChannelConnection - if type (inp) == ExternalChannelConnection: - return inp - umatch = ExternalChannelConnection.objects.filter(db_key=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 + if typ == 'string': return _ExternalConnection.objects.get(db_key=inp) + if typ == 'dbref': return _ExternalConnection.objects.get(id=obj) + print objtype, inp, obj, typ, type(inp) + raise CommError() # # Msg manager @@ -76,106 +129,68 @@ class MsgManager(models.Manager): message_search (equivalent to ev.search_messages) """ + def identify_object(self, obj): + "method version for easy access" + return identify_object(obj) + def get_message_by_id(self, idnum): "Retrieve message by its id." try: - idnum = int(idnum) - return self.get(id=idnum) + return self.get(id=self.dbref(idnum)) except Exception: return None - def get_messages_by_sender(self, player): + def get_messages_by_sender(self, obj, exclude_channel_messages=False): """ - Get all messages sent by one player - """ - player = to_object(player, objtype='player') - if not player: - return None - return self.filter(db_sender=player).exclude(db_hide_from_sender=True) + Get all messages sent by one entity - this could be either a player or an object - def get_messages_by_receiver(self, receiver): + only_non_channel: only return messages -not- aimed at a channel (e.g. private tells) """ - Get all messages sent to one player + obj, typ = identify_object(obj) + if exclude_channel_messages: + # explicitly exclude channel recipients + if typ == 'player': + return list(self.filter(db_sender_players=obj, db_receivers_channels__isnull=True).exclude(db_hide_from_players=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 + else: + # get everything, channel or not + if typ == 'player': + return list(self.filter(db_sender_players=obj).exclude(db_hide_from_players=obj)) + elif typ == 'object': + return list(self.filter(db_sender_objects=obj).exclude(db_hide_from_objects=obj)) + else: + raise CommError + + def get_messages_by_receiver(self, obj): """ - receiver = to_object(receiver) - if not receiver: - return None - return [msg for msg in self.all() - if receiver in msg.receivers - and receiver not in msg.hide_from_receivers] + Get all messages sent to one give recipient + """ + obj, typ = identify_object(obj) + if typ == 'player': + return list(self.filter(db_receivers_players=obj).exclude(db_hide_from_players=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)) + else: + raise CommError 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 self.all() - if channel in msg.channels - and channel not in msg.hide_from_channels] + return self.filter(db_receivers_channels=channel).exclude(db_hide_from_channels=channel) - #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): + def message_search(self, sender=None, receiver=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 + sender - get messages sent by a particular player or object + receiver - get messages received by a certain player,object or channel 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. @@ -183,35 +198,41 @@ class MsgManager(models.Manager): all other search crieteria since it's unique and always gives a list with only one match. """ + # unique msg id if dbref: - return self.filter(id=dbref) + msg = self.objects.filter(id=dbref) + if msg: + return msg[0] + + # 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 refining with multiple filter:s. + # Django Note: Q objects can be combined with & and | (=AND,OR). ~ negates the queryset + + # filter by sender + sender, styp = identify_object(sender) + if styp == 'player': + sender_restrict = Q(db_sender_players=sender) & ~Q(db_hide_from_players=sender) + elif styp == 'object': + sender_restrict = Q(db_sender_objects=sender) & ~Q(db_hide_from_objects=sender) + else: + sender_restrict = Q() + # filter by receiver + receiver, rtyp = identify_object(receiver) + if rtyp == 'player': + receiver_restrict = Q(db_receivers_players=receiver) & ~Q(db_hide_from_players=receiver) + elif rtyp == 'object': + receiver_restrict = Q(db_receivers_objects=receiver) & ~Q(db_hide_from_objects=receiver) + elif rtyp == 'channel': + receiver_restrict = Q(db_receivers_channels=receiver) & ~Q(db_hide_from_channels=receiver) + else: + receiver_restrict = Q() + # filter by full text 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 + fulltext_restrict = Q(db_title__icontains=freetext) | Q(db_message__icontains=freetext) + else: + fulltext_restrict = Q() + # execute the query + return list(self.filter(sender_restrict & receiver_restrict & fulltext_restrict)) # # Channel manager @@ -339,10 +360,8 @@ class PlayerChannelConnectionManager(models.Manager): player = to_object(player) return self.filter(db_player=player) - def has_connection(self, player, channel): + def has_player_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 diff --git a/src/comms/migrations/0007_upgrading_msgs.py b/src/comms/migrations/0007_upgrading_msgs.py new file mode 100644 index 0000000000..1faffdfc17 --- /dev/null +++ b/src/comms/migrations/0007_upgrading_msgs.py @@ -0,0 +1,283 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models +from south import orm + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting field 'Msg.db_hide_from_channels' + db.delete_column('comms_msg', 'db_hide_from_channels') + + # Deleting field 'Msg.db_hide_from_receivers' + db.delete_column('comms_msg', 'db_hide_from_receivers') + + # Deleting field 'Msg.db_receivers' + db.delete_column('comms_msg', 'db_receivers') + + # Deleting field 'Msg.db_channels' + db.delete_column('comms_msg', 'db_channels') + + # Deleting field 'Msg.db_hide_from_sender' + db.delete_column('comms_msg', 'db_hide_from_sender') + + # Deleting field 'Msg.db_sender' + db.delete_column('comms_msg', 'db_sender_id') + + # Adding field 'Msg.db_title' + db.add_column('comms_msg', 'db_title', + self.gf('django.db.models.fields.CharField')(db_index=True, max_length=512, null=True, blank=True), + keep_default=False) + + # Adding M2M table for field db_sender_players on 'Msg' + db.create_table('comms_msg_db_sender_players', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('msg', models.ForeignKey(orm['comms.msg'], null=False)), + ('playerdb', models.ForeignKey(orm['players.playerdb'], null=False)) + )) + db.create_unique('comms_msg_db_sender_players', ['msg_id', 'playerdb_id']) + + # Adding M2M table for field db_sender_objects on 'Msg' + db.create_table('comms_msg_db_sender_objects', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('msg', models.ForeignKey(orm['comms.msg'], null=False)), + ('objectdb', models.ForeignKey(orm['objects.objectdb'], null=False)) + )) + db.create_unique('comms_msg_db_sender_objects', ['msg_id', 'objectdb_id']) + + # Adding M2M table for field db_receivers_players on 'Msg' + db.create_table('comms_msg_db_receivers_players', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('msg', models.ForeignKey(orm['comms.msg'], null=False)), + ('playerdb', models.ForeignKey(orm['players.playerdb'], null=False)) + )) + db.create_unique('comms_msg_db_receivers_players', ['msg_id', 'playerdb_id']) + + # Adding M2M table for field db_receivers_objects on 'Msg' + db.create_table('comms_msg_db_receivers_objects', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('msg', models.ForeignKey(orm['comms.msg'], null=False)), + ('objectdb', models.ForeignKey(orm['objects.objectdb'], null=False)) + )) + db.create_unique('comms_msg_db_receivers_objects', ['msg_id', 'objectdb_id']) + + # Adding M2M table for field db_receivers_channels on 'Msg' + db.create_table('comms_msg_db_receivers_channels', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('msg', models.ForeignKey(orm['comms.msg'], null=False)), + ('channel', models.ForeignKey(orm['comms.channel'], null=False)) + )) + db.create_unique('comms_msg_db_receivers_channels', ['msg_id', 'channel_id']) + + # Adding M2M table for field db_hide_from_players on 'Msg' + db.create_table('comms_msg_db_hide_from_players', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('msg', models.ForeignKey(orm['comms.msg'], null=False)), + ('playerdb', models.ForeignKey(orm['players.playerdb'], null=False)) + )) + db.create_unique('comms_msg_db_hide_from_players', ['msg_id', 'playerdb_id']) + + # Adding M2M table for field db_hide_from_objects on 'Msg' + db.create_table('comms_msg_db_hide_from_objects', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('msg', models.ForeignKey(orm['comms.msg'], null=False)), + ('objectdb', models.ForeignKey(orm['objects.objectdb'], null=False)) + )) + db.create_unique('comms_msg_db_hide_from_objects', ['msg_id', 'objectdb_id']) + + # Adding M2M table for field db_hide_from_channles on 'Msg' + db.create_table('comms_msg_db_hide_from_channles', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('msg', models.ForeignKey(orm['comms.msg'], null=False)), + ('channel', models.ForeignKey(orm['comms.channel'], null=False)) + )) + db.create_unique('comms_msg_db_hide_from_channles', ['msg_id', 'channel_id']) + + # Adding index on 'Msg', fields ['db_date_sent'] + db.create_index('comms_msg', ['db_date_sent']) + + # Adding index on 'Msg', fields ['db_sender_external'] + db.create_index('comms_msg', ['db_sender_external']) + + # moving data to new fields + + if not db.dry_run: + if orm["comms.Msg"].objects.count(): + print "deleting old Msgs before migrating ..." + for msg in orm["comms.Msg"].objects.all(): + msg.delete() + + def backwards(self, orm): + # Removing index on 'Msg', fields ['db_sender_external'] + db.delete_index('comms_msg', ['db_sender_external']) + + # Removing index on 'Msg', fields ['db_date_sent'] + db.delete_index('comms_msg', ['db_date_sent']) + + # Adding field 'Msg.db_hide_from_channels' + db.add_column('comms_msg', 'db_hide_from_channels', + self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True), + keep_default=False) + + # Adding field 'Msg.db_hide_from_receivers' + db.add_column('comms_msg', 'db_hide_from_receivers', + self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True), + keep_default=False) + + # Adding field 'Msg.db_receivers' + db.add_column('comms_msg', 'db_receivers', + self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True), + keep_default=False) + + # Adding field 'Msg.db_channels' + db.add_column('comms_msg', 'db_channels', + self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True), + keep_default=False) + + # Adding field 'Msg.db_hide_from_sender' + db.add_column('comms_msg', 'db_hide_from_sender', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'Msg.db_sender' + db.add_column('comms_msg', 'db_sender', + self.gf('django.db.models.fields.related.ForeignKey')(related_name='sender_set', null=True, to=orm['players.PlayerDB']), + keep_default=False) + + # Deleting field 'Msg.db_title' + db.delete_column('comms_msg', 'db_title') + + # Removing M2M table for field db_sender_players on 'Msg' + db.delete_table('comms_msg_db_sender_players') + + # Removing M2M table for field db_sender_objects on 'Msg' + db.delete_table('comms_msg_db_sender_objects') + + # Removing M2M table for field db_receivers_players on 'Msg' + db.delete_table('comms_msg_db_receivers_players') + + # Removing M2M table for field db_receivers_objects on 'Msg' + db.delete_table('comms_msg_db_receivers_objects') + + # Removing M2M table for field db_receivers_channels on 'Msg' + db.delete_table('comms_msg_db_receivers_channels') + + # Removing M2M table for field db_hide_from_players on 'Msg' + db.delete_table('comms_msg_db_hide_from_players') + + # Removing M2M table for field db_hide_from_objects on 'Msg' + db.delete_table('comms_msg_db_hide_from_objects') + + # Removing M2M table for field db_hide_from_channles on 'Msg' + db.delete_table('comms_msg_db_hide_from_channles') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'comms.channel': { + 'Meta': {'object_name': 'Channel'}, + 'db_aliases': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}), + 'db_keep_log': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'comms.externalchannelconnection': { + 'Meta': {'object_name': 'ExternalChannelConnection'}, + 'db_channel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['comms.Channel']"}), + 'db_external_config': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_external_key': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'db_external_send_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_is_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'comms.msg': { + 'Meta': {'object_name': 'Msg'}, + 'db_date_sent': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), + 'db_hide_from_channles': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hide_from_channels_set'", 'null': 'True', 'to': "orm['comms.Channel']"}), + 'db_hide_from_objects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hide_from_objects_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}), + 'db_hide_from_players': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hide_from_players_set'", 'null': 'True', 'to': "orm['players.PlayerDB']"}), + 'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), + 'db_message': ('django.db.models.fields.TextField', [], {}), + 'db_receivers_channels': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'channel_set'", 'null': 'True', 'to': "orm['comms.Channel']"}), + 'db_receivers_objects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'receiver_object_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}), + 'db_receivers_players': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'receiver_player_set'", 'null': 'True', 'to': "orm['players.PlayerDB']"}), + 'db_sender_external': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_index': 'True'}), + 'db_sender_objects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'sender_object_set'", 'null': 'True', 'db_index': 'True', 'to': "orm['objects.ObjectDB']"}), + 'db_sender_players': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'sender_player_set'", 'null': 'True', 'db_index': 'True', 'to': "orm['players.PlayerDB']"}), + 'db_title': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '512', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'comms.playerchannelconnection': { + 'Meta': {'object_name': 'PlayerChannelConnection'}, + 'db_channel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['comms.Channel']"}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'objects.objectdb': { + 'Meta': {'object_name': 'ObjectDB'}, + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}), + 'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}), + 'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + } + } + + complete_apps = ['comms'] diff --git a/src/comms/models.py b/src/comms/models.py index f432a61d51..4411dca226 100644 --- a/src/comms/models.py +++ b/src/comms/models.py @@ -1,7 +1,12 @@ """ -Models for the comsystem. +Models for the comsystem. The Commsystem is intended to be +used by Players (thematic IC communication is probably +best handled by custom commands instead). -The comsystem's main component is the Message, which +The comm system could take the form of channels, but can also +be adopted for storing tells or in-game mail. + +The comsystem's main component is the Message (Msg), which carries the actual information between two parties. Msgs are stored in the database and usually not deleted. @@ -17,46 +22,12 @@ be able to delete connections on the fly). from django.db import models from src.utils.idmapper.models import SharedMemoryModel from src.comms import managers +from src.comms.managers import identify_object from src.locks.lockhandler import LockHandler from src.utils import logger -from src.utils.utils import is_iter, to_str -from src.utils.utils import dbref as is_dbref +from src.utils.utils import is_iter, to_str, crop __all__ = ("Msg", "TempMsg", "Channel", "PlayerChannelConnection", "ExternalChannelConnection") -#------------------------------------------------------------ -# -# Utils -# -#------------------------------------------------------------ - -def _obj_to_id(inp): - """ - Converts input object to an id string. - """ - dbref = is_dbref(inp) - if dbref: - return str(dbref) - if hasattr(inp, 'id'): - return str(inp.id) - if hasattr(inp, 'dbobj') and hasattr(inp.dbobj, 'id'): - return str(inp.dbobj.id) - return str(inp) - -def _id_to_obj(dbref, db_model='PlayerDB'): - """ - loads from dbref to object. Uses the db_model to search - for the id. - """ - if db_model == 'PlayerDB': - from src.players.models import PlayerDB as db_model - else: - db_model = Channel - try: - dbref = int(dbref.strip()) - return db_model.objects.get(id=dbref) - except Exception: - return None - #------------------------------------------------------------ # # Msg @@ -87,37 +58,50 @@ class Msg(SharedMemoryModel): # These databse fields are all set using their corresponding properties, # named same as the field, but withtout the db_* prefix. - # There must always be one sender of the message. - db_sender = models.ForeignKey("players.PlayerDB", related_name='sender_set', null=True, verbose_name='sender') - # in the case of external senders, no Player object might be available - db_sender_external = models.CharField('external sender', max_length=255, null=True, blank=True, + # 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 = models.CharField('receivers', max_length=255, null=True, blank=True, - help_text='comma-separated list of object dbrefs this message is aimed at.') - # The channels this message was sent to. Stored as a - # comma-separated string of channel dbrefs. A message can both - # have channel targets and destination objects. - db_channels = models.CharField('channels', max_length=255, null=True, blank=True, - help_text='comma-separated list of channel dbrefs this message is aimed at.') + 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") + + # The actual message and a timestamp. The message field # should itself handle eventual headers etc. + db_title = models.CharField('title', max_length=512, null=True, blank=True, db_index=True) db_message = models.TextField('messsage') - db_date_sent = models.DateTimeField('date sent', editable=False, auto_now_add=True) + db_date_sent = models.DateTimeField('date sent', editable=False, auto_now_add=True, db_index=True) # lock storage db_lock_storage = models.CharField('locks', max_length=512, blank=True, help_text='access locks on this message.') - # These are settable by senders/receivers/channels respectively. - # Stored as a comma-separated string of dbrefs. Can be used by the - # game to mask out messages from being visible in the archive (no - # messages are actually deleted) - db_hide_from_sender = models.BooleanField(default=False) - db_hide_from_receivers = models.CharField(max_length=255, null=True, blank=True) - db_hide_from_channels = models.CharField(max_length=255, null=True, blank=True) - # Storage of lock strings - #db_lock_storage = models.TextField(null=True) + + # 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) + + ## These are settable by senders/receivers/channels respectively. + ## Stored as a comma-separated string of dbrefs. Can be used by the + ## game to mask out messages from being visible in the archive (no + ## messages are actually deleted) + #db_hide_from_sender = models.BooleanField(default=False) + #db_hide_from_receivers = models.CharField(max_length=255, null=True, blank=True) + #db_hide_from_channels = models.CharField(max_length=255, null=True, blank=True) + ## Storage of lock strings + ##db_receivers = models.CharField('receivers', max_length=255, null=True, blank=True, + ## help_text='comma-separated list of object dbrefs this message is aimed at.') + ### The channels this message was sent to. Stored as a + ### comma-separated string of channel dbrefs. A message can both + ### have channel targets and destination objects. + ##db_channels = models.CharField('channels', max_length=255, null=True, blank=True, + ## help_text='comma-separated list of channel dbrefs this message is aimed at.') # Database manager objects = managers.MsgManager() @@ -138,80 +122,120 @@ class Msg(SharedMemoryModel): # value = self.attr and del self.attr respectively (where self # is the object in question). - # sender property (wraps db_sender) + # sender property (wraps db_sender_*) #@property - def __sender_get(self): + def __senders_get(self): "Getter. Allows for value = self.sender" - return self.db_sender + return list(self.db_sender_players.all()) + list(self.db_sender_objects.all()) #@sender.setter - def __sender_set(self, value): + def __senders_set(self, value): "Setter. Allows for self.sender = value" - self.db_sender = value + obj, typ = identify_object(value) + 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 self.save() #@sender.deleter - def __sender_del(self): - "Deleter. Allows for del self.sender" - raise Exception("You cannot delete the sender of a message!") - sender = property(__sender_get, __sender_set, __sender_del) - - # sender_external property (wraps db_sender_external) - #@property - def __sender_external_get(self): - "Getter. Allows for value = self.sender_external" - return self.db_sender_external - #@sender_external.setter - def __sender_external_set(self, value): - "Setter. Allows for self.sender_external = value" - self.db_sender_external = value + 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, obj): + "Remove a single sender" + obj, typ = identify_object(obj) + 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 self.save() - #@sender_external.deleter - def __sender_external_del(self): - "Deleter. Allows for del self.sender_external" - raise Exception("You cannot delete the sender_external of a message!") - sender_external = property(__sender_external_get, __sender_external_set, __sender_external_del) # receivers property #@property def __receivers_get(self): - "Getter. Allows for value = self.receivers. Returns a list of receivers." - if self.db_receivers: - return [_id_to_obj(dbref) for dbref in self.db_receivers.split(',')] - return [] + "Getter. Allows for value = self.receivers. Returns three lists of receivers: players, objects and channels." + return 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. Stores as a comma-separated string." - if is_iter(value): - value = ",".join([_obj_to_id(val) for val in value]) - self.db_receivers = _obj_to_id(value) + "Setter. Allows for self.receivers = value. This appends a new receiver to the message." + obj, typ = identify_object(value) + 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. Allows for del self.receivers" - self.db_receivers = "" + "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." - if self.db_channels: - return [_id_to_obj(dbref, 'Channel') for dbref in self.db_channels.split(',')] - return [] + return self.db_receivers_channels.all() #@channels.setter def __channels_set(self, value): - "Setter. Allows for self.channels = value. Stores as a comma-separated string." - if is_iter(value): - value = ",".join([_obj_to_id(val) for val in value]) - self.db_channels = _obj_to_id(value) - self.save() + "Setter. Allows for self.channels = value. Requires a channel to be added." + if value: + self.db_receivers_channels.add(value) #@channels.deleter def __channels_del(self): "Deleter. Allows for del self.channels" - self.db_channels = "" + self.db_receivers_channels.clear() self.save() channels = property(__channels_get, __channels_set, __channels_del) + # title property (wraps db_title) + #@property + def __title_get(self): + "Getter. Allows for value = self.message" + return self.db_title + #@message.setter + def __title_set(self, value): + "Setter. Allows for self.message = value" + if value: + self.db_title = value + self.save() + #@message.deleter + def __title_del(self): + "Deleter. Allows for del self.message" + self.db_title = "" + self.save() + title = property(__title_get, __title_set, __title_del) + # message property (wraps db_message) #@property def __message_get(self): @@ -244,64 +268,32 @@ class Msg(SharedMemoryModel): raise Exception("You cannot delete the date_sent property!") date_sent = property(__date_sent_get, __date_sent_set, __date_sent_del) - # hide_from_sender property + # hide_from property #@property - def __hide_from_sender_get(self): - "Getter. Allows for value = self.hide_from_sender." - return self.db_hide_from_sender + 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_sender_set(self, value): - "Setter. Allows for self.hide_from_senders = value." - self.db_hide_from_sender = value + 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_sender_del(self): + def __hide_from_del(self): "Deleter. Allows for del self.hide_from_senders" - self.db_hide_from_sender = False + self.db_hide_from_players.clear() + self.db_hide_from_objects.clear() + self.db_hide_from_channels.clear() self.save() - hide_from_sender = property(__hide_from_sender_get, __hide_from_sender_set, __hide_from_sender_del) - - # hide_from_receivers property - #@property - def __hide_from_receivers_get(self): - "Getter. Allows for value = self.hide_from_receivers. Returns a list of hide_from_receivers." - if self.db_hide_from_receivers: - return [_id_to_obj(dbref) for dbref in self.db_hide_from_receivers.split(',')] - return [] - #@hide_from_receivers.setter - def __hide_from_receivers_set(self, value): - "Setter. Allows for self.hide_from_receivers = value. Stores as a comma-separated string." - if is_iter(value): - value = ",".join([_obj_to_id(val) for val in value]) - self.db_hide_from_receivers = _obj_to_id(value) - self.save() - #@hide_from_receivers.deleter - def __hide_from_receivers_del(self): - "Deleter. Allows for del self.hide_from_receivers" - self.db_hide_from_receivers = "" - self.save() - hide_from_receivers = property(__hide_from_receivers_get, __hide_from_receivers_set, __hide_from_receivers_del) - - # hide_from_channels property - #@property - def __hide_from_channels_get(self): - "Getter. Allows for value = self.hide_from_channels. Returns a list of hide_from_channels." - if self.db_hide_from_channels: - return [_id_to_obj(dbref) for dbref in self.db_hide_from_channels.split(',')] - return [] - #@hide_from_channels.setter - def __hide_from_channels_set(self, value): - "Setter. Allows for self.hide_from_channels = value. Stores as a comma-separated string." - if is_iter(value): - value = ",".join([_obj_to_id(val) for val in value]) - self.db_hide_from_channels = _obj_to_id(value) - self.save() - #@hide_from_channels.deleter - def __hide_from_channels_del(self): - "Deleter. Allows for del self.hide_from_channels" - self.db_hide_from_channels = "" - self.save() - hide_from_channels = property(__hide_from_channels_get, __hide_from_channels_set, __hide_from_channels_del) + hide_from = property(__hide_from_get, __hide_from_set, __hide_from_del) # lock_storage property (wraps db_lock_storage) #@property @@ -326,15 +318,11 @@ class Msg(SharedMemoryModel): # def __str__(self): - "Print text" - if self.channels: - return "%s -> %s: %s" % (self.sender.key, - ", ".join([chan.key for chan in self.channels]), - self.message) - else: - return "%s -> %s: %s" % (self.sender.key, - ", ".join([rec.key for rec in self.receivers]), - self.message) + "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. @@ -360,13 +348,11 @@ class TempMsg(object): """ def __init__(self, sender=None, receivers=[], channels=[], message="", permissions=[]): - self.sender = sender + self.senders = sender self.receivers = receivers self.message = message self.permissions = permissions - self.hide_from_sender = False - self.hide_from_sender = receivers = False - self.hide_from_channels = False + self.hide_from = None #------------------------------------------------------------ # @@ -408,6 +394,7 @@ class Channel(SharedMemoryModel): # Storage of lock definitions db_lock_storage = models.CharField('locks', max_length=512, blank=True) + # Database manager objects = managers.ChannelManager() @@ -533,7 +520,7 @@ class Channel(SharedMemoryModel): Checks so this player is actually listening to this channel. """ - return PlayerChannelConnection.objects.has_connection(player, self) + return PlayerChannelConnection.objects.has_player_connection(player, self) def msg(self, msgobj, from_obj=None): """ @@ -582,7 +569,7 @@ class Channel(SharedMemoryModel): message - a Msg object or a text string. """ - if type(msgobj) == Msg: + if type(message) == Msg: # extract only the string message = message.message return self.msg(message) diff --git a/src/utils/create.py b/src/utils/create.py index 2da1b775c5..7722b22a48 100644 --- a/src/utils/create.py +++ b/src/utils/create.py @@ -21,12 +21,12 @@ Models covered: Channel Players """ -from twisted.internet.defer import inlineCallbacks, returnValue from django.conf import settings from django.contrib.auth.models import User from django.db import IntegrityError from src.utils.idmapper.models import SharedMemoryModel from src.utils import utils, logger +from src.utils.utils import make_iter # delayed imports _User = None @@ -306,7 +306,7 @@ help_entry = create_help_entry # def create_message(senderobj, message, channels=None, - receivers=None, locks=None): + receivers=None, locks=None, title=None): """ Create a new communication message. Msgs are used for all player-to-player communication, both between individual players @@ -326,52 +326,25 @@ def create_message(senderobj, message, channels=None, at the same time, it's up to the command definitions to limit this as desired. """ - global _Msg, _PlayerDB, _to_object + global _Msg if not _Msg: from src.comms.models import Msg as _Msg - if not _PlayerDB: - from src.players.models import PlayerDB as _PlayerDB - if not _to_object: - from src.comms.managers import to_object as _to_object - - def to_player(obj): - "Make sure the object is a player object" - if isinstance(obj, _PlayerDB): - return obj - elif hasattr(obj, 'user'): - return obj.dbobj - elif hasattr(obj, 'db_player'): - return obj.db_player - else: - return None - if not message: # we don't allow empty messages. return - - new_message = _Msg() - new_message.sender = to_player(senderobj) - new_message.message = message + new_message = _Msg(db_message=message) new_message.save() - if channels: - if not utils.is_iter(channels): - channels = [channels] - new_message.channels = [channel for channel in - [_to_object(channel, objtype='channel') - for channel in channels] if channel] - if receivers: - #print "Found receiver:", receivers - if not utils.is_iter(receivers): - receivers = [receivers] - #print "to_player: %s" % to_player(receivers[0]) - new_message.receivers = [to_player(receiver) for receiver in - [_to_object(receiver) for receiver in receivers] - if receiver] + for sender in make_iter(senderobj): + new_message.senders = sender + new_message.title = title + for channel in make_iter(channels): + new_message.channels = channel + for receiver in make_iter(receivers): + new_message.receivers = receiver if locks: new_message.locks.add(locks) new_message.save() return new_message - message = create_message def create_channel(key, aliases=None, desc=None, diff --git a/src/utils/dummyrunner_actions.py b/src/utils/dummyrunner_actions.py index ee08195778..cd7521d9c2 100644 --- a/src/utils/dummyrunner_actions.py +++ b/src/utils/dummyrunner_actions.py @@ -134,6 +134,15 @@ def c_creates_button(client): '@desc %s = test red button!' % objname) return cmd, "creates button ..." +def c_socialize(client): + "socializechats on channel" + cmd = ('ooc Hello!', + 'ooc Testing ...', + 'ooc Testing ... times 2', + 'say Yo!', + 'emote stands looking around.') + return cmd, "socializes ..." + def c_moves(client): "moves to a previously created room, using the stored exits" cmd = client.exits # try all exits - finally one will work @@ -151,17 +160,7 @@ def c_moves(client): # otherwise the system will normalize them. # -# "heavy" builder definition -ACTIONS = ( c_login, - c_logout, - (0.2, c_looks), - (0.1, c_examines), - (0.2, c_help), - (0.1, c_digs), - (0.1, c_creates_obj), - #(0.01, c_creates_button), - (0.2, c_moves)) -# "normal builder" definition +## "normal builder" definition #ACTIONS = ( c_login, # c_logout, # (0.5, c_looks), @@ -171,7 +170,17 @@ ACTIONS = ( c_login, # (0.01, c_creates_obj), # #(0.1, c_creates_button), # (0.3, c_moves)) -# "passive player" definition +## "heavy" builder definition +#ACTIONS = ( c_login, +# c_logout, +# (0.2, c_looks), +# (0.1, c_examines), +# (0.2, c_help), +# (0.1, c_digs), +# (0.1, c_creates_obj), +# #(0.01, c_creates_button), +# (0.2, c_moves)) +## "passive player" definition #ACTIONS = ( c_login, # c_logout, # (0.7, c_looks), @@ -181,4 +190,11 @@ ACTIONS = ( c_login, # #(0.1, c_creates_obj), # #(0.1, c_creates_button), # #(0.4, c_moves)) - +## "socializing heavy builder" definition +ACTIONS = (c_login, + c_logout, + (0.3, c_socialize), + (0.1, c_looks), + (0.1, c_help), + (0.2, c_digs), + (0.3, c_moves)) diff --git a/src/utils/utils.py b/src/utils/utils.py index 2d3570ec2b..d705a31c43 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -724,7 +724,5 @@ def string_suggestions(string, vocabulary, cutoff=0.6, maxnum=3): Returns: list of suggestions from vocabulary (could be empty if there are no matches) """ - #if string in vocabulary: - # return [string] return [tup[1] for tup in sorted([(string_similarity(string, sugg), sugg) for sugg in vocabulary], key=lambda tup: tup[0], reverse=True) if tup[0] >= cutoff][:maxnum]