Run Migrate. Implemented @search functionality with limits as per MUX (as part of the @find command). Added some more channel-related commands and changed locks for channels to have a "control" lock type rather than "admin". The migration converts this in existing channels..

This commit is contained in:
Griatch 2011-04-20 22:40:27 +00:00
parent 23462c626c
commit 7f7016ad7d
16 changed files with 324 additions and 515 deletions

View file

@ -9,6 +9,9 @@ from src.objects.models import ObjectDB, ObjAttribute
from src.utils import create, utils, debug
from src.commands.default.muxcommand import MuxCommand
# used by @find
CHAR_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS
class ObjManipCommand(MuxCommand):
"""
This is a parent class for some of the defining objmanip commands
@ -1562,35 +1565,92 @@ class CmdFind(MuxCommand):
find objects
Usage:
@find <searchname>
@find[/switches] <name or dbref or *player> [= dbrefmin[ dbrefmax]]
Switches:
room - only look for rooms (location=None)
exit - only look for exits (destination!=None)
char - only look for characters (BASE_CHARACTER_TYPECLASS)
Searches the database for an object of a particular name or dbref.
Use *playername to search for a player. The switches allows for
limiting matches to certain game entities. Dbrefmin and dbrefmax
limits matches to within the given dbrefs, or above/below if only one is given.
"""
Searches for an object of a particular name.
"""
key = "@find"
aliases = "@locate, find, locate"
aliases = "find, @search, search, @locate, locate"
locks = "cmd:perm(find) or perm(Builders)"
help_category = "Building"
def func(self):
"Search functionality"
caller = self.caller
arglist = self.arglist
switches = self.switches
if not arglist:
caller.msg("Usage: @find <name>")# [,low [,high]]")
if not self.args:
caller.msg("Usage: @find <string> [= low [high]]")
return
searchstring = arglist[0]
if len(arglist) > 1:
low = arglist[1]
if len(arglist) > 2:
high = arglist[2]
#TODO: Implement efficient db search with limits
result = caller.search(searchstring, global_search=True)
if not result:
return
string = "%s(#%s) - %s" % (result.name, result.id, result)
caller.msg(string)
searchstring = self.lhs
low, high = 1, ObjectDB.objects.all().order_by("-id")[0].id
if self.rhs:
if "-" in self.rhs:
# also support low-high syntax
limlist = [part.strip() for part in self.rhs.split("-", 1)]
else:
# otherwise split by space
limlist = self.rhs.split(None, 1)
if limlist and limlist[0].isdigit():
low = max(low, int(limlist[0]))
if len(limlist) > 1 and limlist[1].isdigit():
high = min(high, int(limlist[1]))
low = min(low, high)
high = max(low, high)
if searchstring.startswith("*") or utils.dbref(searchstring):
# A player/dbref search.
# run a normal player- or dbref search. This should be unique.
string = "{wMatch{n(#%i-#%i):" % (low, high)
result = caller.search(searchstring, global_search=True)
if not result:
return
if not low <= int(result.id) <= high:
string += "\n {RNo match found for '%s' within the given dbref limits.{n" % searchstring
else:
string += "\n{g %s(%s) - %s{n" % (result.key, result.dbref, result.typeclass)
else:
# Not a player/dbref search but a wider search; build a queryset.
results = ObjectDB.objects.filter(db_key__istartswith=searchstring, id__gte=low, id__lte=high)
if "room" in switches:
results = results.filter(db_location__isnull=True)
if "exit" in switches:
results = results.filter(db_destination__isnull=False)
if "char" in switches:
results = results.filter(db_typeclass_path=CHAR_TYPECLASS)
nresults = results.count()
restrictions = ""
if self.switches:
restrictions = ", %s" % (",".join(self.switches))
if nresults:
# convert result to typeclasses. Database is not hit until this point!
results = [result.typeclass(result) for result in results]
if nresults > 1:
string = "{w%i Matches{n(#%i-#%i%s):" % (nresults, low, high, restrictions)
for res in results:
string += "\n {g%s(%s) - %s{n" % (res.key, res.dbref, res.typeclass)
else:
string = "{wOne Match{n(#%i-#%i%s):" % (low, high, restrictions)
string += "\n {g%s(%s) - %s{n" % (results[0].key, results[0].dbref, results[0].typeclass)
else:
string = "{wMatch{n(#%i-#%i%s):" % (low, high, restrictions)
string += "\n {RNo matches found for '%s'{n" % searchstring
# send result
caller.msg(string.strip())
class CmdTeleport(MuxCommand):

View file

@ -83,6 +83,7 @@ class DefaultCmdSet(CmdSet):
# Comm commands
self.add(comms.CmdAddCom())
self.add(comms.CmdDelCom())
self.add(comms.CmdAllCom())
self.add(comms.CmdChannels())
self.add(comms.CmdCdestroy())
self.add(comms.CmdChannelCreate())

View file

@ -70,7 +70,7 @@ class CmdAddCom(MuxCommand):
# check permissions
if not channel.access(player, 'listen'):
caller.msg("You are not allowed to listen to this channel.")
caller.msg("%s: You are not allowed to listen to this channel." % channel.key)
return
string = ""
@ -78,18 +78,20 @@ class CmdAddCom(MuxCommand):
# we want to connect as well.
if not channel.connect_to(player):
# if this would have returned True, the player is connected
caller.msg("You are not allowed to join this channel.")
caller.msg("%s: You are not allowed to join this channel." % channel.key)
return
else:
string += "You now listen to the channel %s. " % channel.key
else:
string += "You are already connected to channel %s." % channel.key
if alias:
# create a nick and add it to the caller.
caller.nicks.add(alias, channel.key, nick_type="channel")
string += "You can now refer to the channel %s with the alias '%s'."
string += " You can now refer to the channel %s with the alias '%s'."
caller.msg(string % (channel.key, alias))
else:
string += "No alias added."
string += " No alias added."
caller.msg(string)
@ -125,7 +127,7 @@ class CmdDelCom(MuxCommand):
if channel:
# we have given a channel name - unsubscribe
if not channel.has_connection(player):
caller.msg("You are listening to that channel.")
caller.msg("You are not listening to that channel.")
return
chkey = channel.key.lower()
# find all nicks linked to this channel and delete them
@ -145,97 +147,66 @@ class CmdDelCom(MuxCommand):
caller.nicks.delete(ostring, nick_type="channel")
caller.msg("Your alias '%s' for channel %s was cleared." % (ostring, channel.key))
# def cmd_allcom(command):
# """
# allcom - operate on all channels
class CmdAllCom(MuxCommand):
"""
allcom - operate on all channels
# Usage:
# allcom [on | off | who | clear]
Usage:
allcom [on | off | who | destroy]
# Allows the user to universally turn off or on all channels they are on,
# as well as perform a 'who' for all channels they are on. Clear deletes
# all channels.
Allows the user to universally turn off or on all channels they are on,
as well as perform a 'who' for all channels they are on. Destroy deletes
all channels that you control.
# Without argument, works like comlist.
# """
Without argument, works like comlist.
"""
# caller = self.caller
# arg = self.args
# if not arg:
# cmd_comlist(command)
# caller.msg("(allcom arguments: 'on', 'off', 'who' and 'clear'.)")
# return
# arg = arg.strip()
# if arg == 'clear':
# cmd_clearcom(command)
# return
key = "allcom"
locks = "cmd: not perm(channel_banned)"
help_category = "Comms"
# #get names and alias of all subscribed channels
# chandict = comsys.plr_get_cdict(self.session)
# aliaslist = chandict.keys()
# aliaslist.sort()
# if arg == "on":
# for alias in aliaslist:
# comsys.plr_chan_on(self.session, alias)
# elif arg == "off":
# for alias in aliaslist:
# comsys.plr_chan_off(self.session, alias)
# elif arg == "who":
# s = ""
# if not aliaslist:
# s += " (No channels) "
# for alias in aliaslist:
# s += "-- %s (alias: %s)\n" % (chandict[alias][0],alias)
# sess_list = comsys.get_cwho_list(chandict[alias][0])
# objlist = [sess.get_pobject() for sess in sess_list]
# plist = [p.get_name(show_dbref=caller.sees_dbrefs())
# for p in filter(lambda o: o.is_player(), objlist)]
# olist = [o.get_name(show_dbref=caller.sees_dbrefs())
# for o in filter(lambda o: not o.is_player(), objlist)]
# plist.sort()
# olist.sort()
# if plist:
# s += " Players:\n "
# for pname in plist:
# s += "%s, " % pname
# s = s[:-2] + "\n"
# if olist:
# s += " Objects:\n "
# for oname in olist:
# s += "%s, " % oname
# s = s[:-2] + "\n"
# s = s[:-1]
# caller.msg(s)
# GLOBAL_CMD_TABLE.add_self("allcom", cmd_allcom, help_category="Comms")
## def cmd_clearcom(self):
## """
## clearcom - removes all channels
def func(self):
"Runs the function"
## Usage:
## clearcom
caller = self.caller
args = self.args
if not args:
caller.execute_cmd("@channels")
caller.msg("(Usage: allcom on | off | who | destroy)")
return
## Effectively runs delcom on all channels the user is on. It will remove
## their aliases, remove them from the channel, and clear any titles they
## have set.
## """
## caller = self.caller
## #get aall subscribed channel memberships
## memberships = caller.channel_membership_set.all()
## if not memberships:
## s = "No channels to delete. "
## else:
## s = "Deleting all channels in your subscriptions ...\n"
## for membership in memberships:
## chan_name = membership.channel.get_name()
## s += "You have left %s.\n" % chan_name
## comsys.plr_del_channel(caller, membership.user_alias)
## comsys.send_cmessage(chan_name, "%s has left the channel." % caller.get_name(show_dbref=False))
## s = s[:-1]
## caller.msg(s)
## GLOBAL_CMD_TABLE.add_self("clearcom", cmd_clearcom)
if args == "on":
# get names of all channels available to listen to and activate them all
channels = [chan for chan in Channel.objects.get_all_channels() if chan.access(caller, 'listen')]
for channel in channels:
caller.execute_cmd("addcom %s" % channel.key)
elif args == "off":
#get names all subscribed channels and disconnect from them all
channels = [conn.channel for conn in PlayerChannelConnection.objects.get_all_player_connections(caller.player)]
for channel in channels:
caller.execute_cmd("delcom %s" % channel.key)
elif args == "destroy":
# destroy all channels you control
channels = [chan for chan in Channel.objects.get_all_channels() if chan.access(caller, 'control')]
for channel in channels:
caller.execute_cmd("@cdestroy %s" % channel.key)
elif args == "who":
# run a who, listing the subscribers on visible channels.
string = "\n{CChannel subscriptions{n"
channels = [chan for chan in Channel.objects.get_all_channels() if chan.access(caller, 'listen')]
if not channels:
string += "No channels."
for channel in channels:
string += "\n{w%s:{n\n" % channel.key
conns = PlayerChannelConnection.objects.get_all_connections(channel)
if conns:
string += " " + ", ".join([conn.player.key for conn in conns])
else:
string += " <None>"
caller.msg(string.strip())
else:
# wrong input
caller.msg("Usage: allcom on | off | who | clear")
class CmdChannels(MuxCommand):
"""
@ -246,7 +217,7 @@ class CmdChannels(MuxCommand):
@clist
comlist
Lists all available channels available to you, wether you listen to them or not.
Lists all channels available to you, wether you listen to them or not.
Use 'comlist" to only view your current channel subscriptions.
"""
key = "@channels"
@ -262,7 +233,7 @@ class CmdChannels(MuxCommand):
# all channels we have available to listen to
channels = [chan for chan in Channel.objects.get_all_channels() if chan.access(caller, 'listen')]
if not channels:
caller.msg("No channels available")
caller.msg("No channels available.")
return
# all channel we are already subscribed to
subs = [conn.channel for conn in PlayerChannelConnection.objects.get_all_player_connections(caller.player)]
@ -333,7 +304,7 @@ class CmdCdestroy(MuxCommand):
if not channel:
caller.msg("Could not find channel %s." % self.args)
return
if not channel.access(caller, 'admin'):
if not channel.access(caller, 'control'):
caller.msg("You are not allowed to do that.")
return
@ -606,7 +577,7 @@ class CmdChannelCreate(MuxCommand):
caller.msg("A channel with that name already exists.")
return
# Create and set the channel up
lockstring = "send:all();listen:all();admin:id(%s)" % caller.id
lockstring = "send:all();listen:all();control:id(%s)" % caller.id
new_chan = create.create_channel(channame, aliases, description, locks=lockstring)
new_chan.connect_to(caller)
caller.msg("Created channel %s and connected to it." % new_chan.key)
@ -683,7 +654,7 @@ class CmdCdesc(MuxCommand):
caller.msg("Channel '%s' not found." % self.lhs)
return
#check permissions
if not caller.access(caller, 'admin'):
if not caller.access(caller, 'control'):
caller.msg("You cant admin this channel.")
return
# set the description

View file

@ -432,57 +432,6 @@ class CmdSay(MuxCommand):
caller.location.msg_contents(emit_string,
exclude=caller)
## def cmd_fsay(command):
## """
## @fsay - make an object say something
## Usage:
## @fsay <obj> = <text to say>
## Make an object talk to its current location.
## """
## caller = command.caller
## args = command.command_argument
## if not args or not "=" in args:
## caller.msg("Usage: @fsay <obj> = <text to say>")
## return
## target, speech = [arg.strip() for arg in args.split("=",1)]
## # find object
## if target in ['here']:
## results = [caller.location]
## elif target in ['me','my']:
## results = [caller]
## else:
## results = Object.objects.global_object_name_search(target)
## if not results:
## caller.msg("No matches found for '%s'." % target)
## return
## if len(results) > 1:
## string = "There are multiple matches. Please use #dbref to be more specific."
## for result in results:
## string += "\n %s" % results.name
## caller.msg(string)
## return
## target = results[0]
## # permission check
## if not caller.controls_other(target):
## caller.msg("Cannot pose %s (you don's control it)" % target.name)
## return
## # Feedback for the object doing the talking.
## caller.msg("%s says, '%s%s'" % (target.name,
## speech,
## ANSITable.ansi['normal']))
## # Build the string to emit to neighbors.
## emit_string = "%s says, '%s'" % (target.name,
## speech)
## target.location.msg_contents(emit_string,
## exclude=caller)
## GLOBAL_CMD_TABLE.add_command("@fsay", cmd_fsay)
class CmdPose(MuxCommand):
"""
@ -525,64 +474,6 @@ class CmdPose(MuxCommand):
msg = "%s%s" % (self.caller.name, self.args)
self.caller.location.msg_contents(msg)
## def cmd_fpose(command):
## """
## @fpose - force an object to pose
## Usage:
## @fpose[/switches] <obj> = <pose text>
## Switches:
## nospace : put no text between the object's name
## and the start of the pose.
## Describe an action being taken as performed by obj.
## The pose text will automatically begin with the name
## of the object.
## """
## caller = command.caller
## args = command.command_argument
## if not args or not "=" in args:
## caller.msg("Usage: @fpose <obj> = <pose text>")
## return
## target, pose_string = [arg.strip() for arg in args.split("=",1)]
## # find object
## if target in ['here']:
## results = [caller.location]
## elif target in ['me','my']:
## results = [caller]
## else:
## results = Object.objects.global_object_name_search(target)
## if not results:
## caller.msg("No matches found for '%s'." % target)
## return
## if len(results) > 1:
## string = "There are multiple matches. Please use #dbref to be more specific."
## for result in results:
## string += "\n %s" % results.name
## caller.msg(string)
## return
## target = results[0]
## # permission check
## if not caller.controls_other(target):
## caller.msg("Cannot pose %s (you don's control it)" % target.name)
## return
## if "nospace" in command.command_switches:
## # Output without a space between the player name and the emote.
## sent_msg = "%s%s" % (target.name,
## pose_string)
## else:
## # No switches, default.
## sent_msg = "%s %s" % (target.name,
## pose_string)
## caller.location.msg_contents(sent_msg)
## GLOBAL_CMD_TABLE.add_command("@fpose", cmd_fpose)
class CmdEncoding(MuxCommand):
"""
encoding - set a custom text encoding
@ -666,23 +557,3 @@ class CmdAccess(MuxCommand):
if hasattr(caller, 'player'):
string += "\nPlayer %s: %s" % (caller.player.key, ", ".join(caller.player.permissions))
caller.msg(string)
## def cmd_apropos(command):
## """
## apropos - show rough help matches
## Usage:
## apropos <text>
## or
## suggest <text>
## This presents a list of topics very loosely matching your
## search text. Use this command when you are searching for
## help on a certain concept but don't know any exact
## command names. You can also use the normal help command
## with the /apropos switch to get the same functionality.
## """
## arg = command.command_argument
## command.caller.execute_cmd("help/apropos %s" % arg)
## GLOBAL_CMD_TABLE.add_command("apropos", cmd_apropos)
## GLOBAL_CMD_TABLE.add_command("suggest", cmd_apropos)

View file

@ -13,24 +13,25 @@ from src.utils import create
from src.commands.default.muxcommand import MuxCommand
LIST_ARGS = ["list", "all"]
SEP = "{C" + "-"*78 + "{n"
def format_help_entry(title, help_text, aliases=None,
suggested=None):
"""
This visually formats the help entry.
"""
string = "-"*78 + "\n"
string = SEP + "\n"
if title:
string += "Help topic for {w%s{n" % (title.capitalize())
string += "{CHelp topic for {w%s{n" % (title.capitalize())
if aliases:
string += " (aliases: %s)" % (", ".join(aliases))
string += " {C(aliases: {w%s{n{C){n" % (", ".join(aliases))
if help_text:
string += "\n%s" % dedent(help_text.rstrip())
if suggested:
string += "\nSuggested:\n"
string += fill(", ".join(suggested))
string += "\n\n{CSuggested:{n "
string += "{w%s{n" % fill(", ".join(suggested))
string.strip()
string += "\n" + "-"*78
string += "\n" + SEP
return string
def format_help_list(hdict_cmds, hdict_db):
@ -39,16 +40,15 @@ def format_help_list(hdict_cmds, hdict_db):
"""
string = ""
if hdict_cmds and hdict_cmds.values():
string += "\n\r" + "-"*70 + "\n\r {gCommand help entries{n\n" + "-"*70
string += "\n" + SEP + "\n {CCommand help entries{n\n" + SEP
for category in sorted(hdict_cmds.keys()):
string += "\n {w%s{n:\n" % \
(str(category).capitalize())
string += fill(", ".join(sorted(hdict_cmds[category])))
string += "\n {w%s{n:\n" % (str(category).capitalize())
string += "{G" + fill(", ".join(sorted(hdict_cmds[category]))) + "{n"
if hdict_db and hdict_db.values():
string += "\n\r\n\r" + "-"*70 + "\n\r {gOther help entries{n\n" + '-'*70
string += "\n\n" + SEP + "\n\r {COther help entries{n\n" + SEP
for category in sorted(hdict_db.keys()):
string += "\n\r {w%s{n:\n" % (str(category).capitalize())
string += fill(", ".join(sorted([str(topic) for topic in hdict_db[category]])))
string += "{G" + fill(", ".join(sorted([str(topic) for topic in hdict_db[category]]))) + "{n"
return string
class CmdHelp(Command):
@ -72,7 +72,7 @@ class CmdHelp(Command):
def parse(self):
"""
inp is a string containing the command or topic match.
input is a string containing the command or topic to match.
"""
self.original_args = self.args.strip()
self.args = self.args.strip().lower()

View file

@ -295,8 +295,8 @@ class CmdObjects(MuxCommand):
srow = "{w%s{n" % srow
string += srow
string += "\n\n{wLast %s Objects created:{n" % nlim
objs = ObjectDB.objects.all()[max(0, nobjs-nlim):]
string += "\n\n{wLast %s Objects created:{n" % min(nobjs, nlim)
objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs-nlim):]
table = [["Created"], ["dbref"], ["name"], ["typeclass"]]
for i, obj in enumerate(objs):

View file

@ -1,235 +0,0 @@
"""
Implementation of the @search command that resembles MUX2.
"""
from django.db.models import Q
#from src.objects.models import Object
from src.utils import OBJECT as Object
from src import defines_global
from src.cmdtable import GLOBAL_CMD_TABLE
def _parse_restriction_split(source_object, restriction_split, search_low_dbnum,
search_high_dbnum):
"""
Parses a split restriction string and sets some needed variables.
Returns a tuple in the form of: (low dbnum, high dbnum)
"""
restriction_size = len(restriction_split)
if restriction_size >= 2:
try:
search_low_dbnum = int(restriction_split[1].strip())
except ValueError:
source_object.msg("Invalid value for low dbref limit.")
return False
if restriction_size >= 3:
try:
search_high_dbnum = int(restriction_split[2].strip())
except ValueError:
source_object.msg("Invalid value for high dbref limit.")
return False
return search_low_dbnum, search_high_dbnum
def display_results(source_object, search_query):
"""
Display the results to the searcher.
"""
# Lists to hold results by type. There may be a better way to do this
thing_list = []
room_list = []
exit_list = []
player_list = []
# this bits gotta get totally redone
for obj in search_query:
thing_list.append(obj)
# Render each section for different object types
if thing_list:
source_object.msg("\n\rTHINGS:")
for thing in thing_list:
source_object.msg(thing.name)
if exit_list:
source_object.msg("\n\rEXITS:")
for exit in exit_list:
source_object.msg(exit.name)
if room_list:
source_object.msg("\n\rROOMS:")
for room in room_list:
source_object.msg(room.name)
if player_list:
source_object.msg("\n\rPLAYER:")
for player in player_list:
source_object.msg(player.name)
# Show the total counts by type
source_object.msg("\n\rFound: Rooms...%d Exits...%d Things...%d Players...%d" % (
len(room_list),
len(exit_list),
len(thing_list),
len(player_list)))
def build_query(source_object, search_query, search_player, search_type,
search_restriction, search_low_dbnum, search_high_dbnum):
"""
Builds and returns a QuerySet object, or None if an error occurs.
"""
# Look up an Object matching the player search query
if search_player:
# Replace the string variable with an Object reference
search_player = source_object.search_for_object(search_player)
# Use standard_objsearch to handle duplicate/nonexistant results
if not search_player:
return None
# Searching by player, chain filter
search_query = search_query.filter(owner=search_player)
# Check to ensure valid search types
if search_type == "type":
if search_restriction == "room":
search_query = search_query.filter(type=defines_global.OTYPE_ROOM)
elif search_restriction == "thing":
search_query = search_query.filter(type=defines_global.OTYPE_THING)
elif search_restriction == "exit":
search_query = search_query.filter(type=defines_global.OTYPE_EXIT)
elif search_restriction == "player":
search_query = search_query.filter(type=defines_global.OTYPE_PLAYER)
else:
source_object.msg("Invalid class. See 'help SEARCH CLASSES'.")
return None
elif search_type == "parent":
search_query = search_query.filter(script_parent__iexact=search_restriction)
elif search_type == "object" or search_type == "thing":
search_query = search_query.filter(name__icontains=search_restriction,
type=defines_global.OTYPE_THING)
elif search_type == "rooms":
search_query = search_query.filter(name__icontains=search_restriction,
type=defines_global.OTYPE_ROOM)
elif search_type == "exits":
search_query = search_query.filter(name__icontains=search_restriction,
type=defines_global.OTYPE_EXIT)
elif search_type == "players":
search_query = search_query.filter(name__icontains=search_restriction,
type=defines_global.OTYPE_PLAYER)
elif search_type == "zone":
zone_obj = source_object.search_for_object(search_restriction)
# Use search_for_object to handle duplicate/nonexistant results.
if not zone_obj:
return None
search_query = search_query.filter(zone=zone_obj)
elif search_type == "power":
# TODO: Need this once we have powers implemented.
source_object.msg("To be implemented...")
return None
elif search_type == "flags":
flag_list = search_restriction.split()
#source_object.msg("restriction: %s" % flag_list)
for flag in flag_list:
search_query = search_query.filter(Q(flags__icontains=flag) | Q(nosave_flags__icontains=flag))
if search_low_dbnum:
search_query = search_query.filter(id__gte=search_low_dbnum)
if search_high_dbnum:
search_query = search_query.filter(id__lte=search_high_dbnum)
return search_query
def cmd_search(command):
"""
search
Usage:
search <name>
Searches for owned objects as per MUX2.
"""
source_object = command.source_object
search_player = None
search_type = None
search_restriction = None
search_low_dbnum = None
search_high_dbnum = None
if not command.command_argument:
search_player = "#" + str(source_object.id)
else:
first_check_split = command.command_argument.split(' ', 1)
if '=' in first_check_split[0]:
# @search class=restriction...
eq_split = command.command_argument.split('=', 1)
search_type = eq_split[0]
restriction_split = eq_split[1].split(',')
search_restriction = restriction_split[0].strip()
#source_object.msg("@search class=restriction")
#source_object.msg("eq_split: %s" % eq_split)
#source_object.msg("restriction_split: %s" % restriction_split)
try:
search_low_dbnum, search_high_dbnum = _parse_restriction_split(source_object,
restriction_split,
search_low_dbnum,
search_high_dbnum)
except TypeError:
return
else:
# @search player
if len(first_check_split) == 1:
#source_object.msg("@search player")
#source_object.msg(first_check_split)
search_player = first_check_split[0]
else:
#source_object.msg("@search player class=restriction")
#source_object.msg(first_check_split)
search_player = first_check_split[0]
eq_split = first_check_split[1].split('=', 1)
search_type = eq_split[0]
#source_object.msg("eq_split: %s" % eq_split)
restriction_split = eq_split[1].split(',')
search_restriction = restriction_split[0]
#source_object.msg("restriction_split: %s" % restriction_split)
try:
search_low_dbnum, search_high_dbnum = _parse_restriction_split(source_object,
restriction_split,
search_low_dbnum,
search_high_dbnum)
except TypeError:
return
search_query = Object.objects.all()
#source_object.msg("search_player: %s" % search_player)
#source_object.msg("search_type: %s" % search_type)
#source_object.msg("search_restriction: %s" % search_restriction)
#source_object.msg("search_lowdb: %s" % search_low_dbnum)
#source_object.msg("search_highdb: %s" % search_high_dbnum)
# Clean up these variables for comparisons.
try:
search_type = search_type.strip().lower()
except AttributeError:
pass
try:
search_restriction = search_restriction.strip().lower()
except AttributeError:
pass
# Build the search query.
search_query = build_query(source_object, search_query, search_player, search_type,
search_restriction, search_low_dbnum,
search_high_dbnum)
# Something bad happened in query construction, die here.
if search_query is None:
return
display_results(source_object, search_query)
GLOBAL_CMD_TABLE.add_command("@search", cmd_search,
priv_tuple=("objects.info",),
help_category="Building")

View file

@ -41,11 +41,11 @@ IMC2_CHANLIST = IMC2ChanList()
def msg_info(message):
"""
Send info to default info channel
"""
message = '[%s][IMC2]: %s' % (INFOCHANNEL[0].key, message)
"""
try:
INFOCHANNEL[0].msg(message)
except AttributeError:
message = '[%s][IMC2]: %s' % (INFOCHANNEL[0].key, message)
except Exception:
logger.log_infomsg("MUDinfo (imc2): %s" % message)
#

View file

@ -0,0 +1,129 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
# fixes a changed syntax in the locks.
def forwards(self, orm):
"Write your forwards methods here."
for channel in orm.Channel.objects.all():
lockstring = channel.db_lock_storage
lockstring = lockstring.replace("admin:", "control:")
channel.db_lock_storage = lockstring
channel.save()
def backwards(self, orm):
"Write your backwards methods here."
for channel in orm.Channel.objects.all():
lockstring = channel.db_lock_storage
lockstring = lockstring.replace("control:", "admin:")
channel.db_lock_storage = lockstring
channel.save()
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_lock_storage': ('django.db.models.fields.TextField', [], {'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_channels': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'db_date_sent': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_hide_from_channels': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'db_hide_from_receivers': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'db_hide_from_sender': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'db_message': ('django.db.models.fields.TextField', [], {}),
'db_receivers': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'db_sender': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sender_set'", 'null': 'True', 'to': "orm['players.PlayerDB']"}),
'db_sender_external': ('django.db.models.fields.CharField', [], {'max_length': '255', '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.TextField', [], {'null': '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_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.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', '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_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', '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']

View file

@ -2,7 +2,7 @@
Custom manager for HelpEntry objects.
"""
from django.db import models
from src.utils import logger
from src.utils import logger, utils
class HelpEntryManager(models.Manager):
"""
@ -12,8 +12,8 @@ class HelpEntryManager(models.Manager):
"""
Searches for matching topics based on player's input.
"""
if topicstr.isdigit():
return self.filter(id=topicstr)
if utils.dbref(topicstr):
return self.filter(id=utils.dbref(topicstr))
topics = self.filter(db_key__iexact=topicstr)
if not topics and not exact:
topics = self.filter(db_key__istartswith=topicstr)

View file

@ -103,6 +103,14 @@ import re, inspect
from django.conf import settings
from src.utils import logger, utils
#
# Exception class
#
class LockException(Exception):
pass
#
# Cached lock functions
#
@ -181,7 +189,8 @@ class LockHandler(object):
return locks
nlocks = storage_lockstring.count(';') + 1
duplicates = 0
elist = []
elist = [] # errors
wlist = [] # warnings
for raw_lockstring in storage_lockstring.split(';'):
lock_funcs = []
access_type, rhs = (part.strip() for part in raw_lockstring.split(':', 1))
@ -211,11 +220,13 @@ class LockHandler(object):
continue
if access_type in locks:
duplicates += 1
elist.append("Lock: access type '%s' changed from '%s' to '%s' " % \
(access_type, locks[access_type][2], raw_lockstring))
wlist.append("Lock: access type '%s' changed from '%s' to '%s' " % \
(access_type, locks[access_type][2], raw_lockstring))
locks[access_type] = (evalstring, tuple(lock_funcs), raw_lockstring)
if wlist:
self._log_error("\n".join(wlist))
if elist:
self._log_error("\n".join(elist))
raise LockException("\n".join(elist))
self.no_errors = False
return locks
@ -304,12 +315,14 @@ class LockHandler(object):
self._cache_locks(self.obj.lock_storage)
self.reset_flag = False
if (not no_superuser_bypass and (hasattr(accessing_obj, 'player')
and hasattr(accessing_obj.player, 'is_superuser') and accessing_obj.player.is_superuser)
or (hasattr(accessing_obj, 'get_player') and (accessing_obj.get_player()==None or accessing_obj.get_player().is_superuser))):
if (not no_superuser_bypass
and ((hasattr(accessing_obj, 'is_superuser') and accessing_obj.is_superuser)
or (hasattr(accessing_obj, 'player') and hasattr(accessing_obj.player, 'is_superuser') and accessing_obj.player.is_superuser)
or (hasattr(accessing_obj, 'get_player') and (accessing_obj.get_player()==None or accessing_obj.get_player().is_superuser)))):
# we grant access to superusers and also to protocol instances that not yet has any player assigned to them (the
# latter is a safety feature since superuser cannot be authenticated at some point during the connection).
return True
if access_type in self.locks:
# we have a lock, test it.
evalstring, func_tup, raw_string = self.locks[access_type]

View file

@ -249,15 +249,14 @@ LOCK_FUNC_MODULES = ("src.locks.lockfuncs",)
# where aliases may be a tuple too, and locks is
# a valid lockstring definition.
# Default user channel for communication
CHANNEL_PUBLIC = ("Public", 'ooc', 'Public discussion',
"admin:perm(Wizards);listen:all();send:all()")
CHANNEL_PUBLIC = ("Public", ('ooc',), 'Public discussion',
"control:perm(Wizards);listen:all();send:all()")
# General info about the server
CHANNEL_MUDINFO = ("MUDinfo", '', 'Informative messages',
"admin:perm(Immortals);listen:perm(Immortals);send:false()")
"control:perm(Immortals);listen:perm(Immortals);send:false()")
# Channel showing when new people connecting
CHANNEL_CONNECTINFO = ("MUDconnections", ('connections, mud_conns'),
'Connection log',
"admin:perm(Immortals);listen:perm(Wizards);send:false()")
CHANNEL_CONNECTINFO = ("MUDconnections", '', 'Connection log',
"control:perm(Immortals);listen:perm(Wizards);send:false()")
###################################################
# External Channel connections

View file

@ -95,8 +95,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
if isinstance(dbref, basestring):
dbref = dbref.lstrip('#')
try:
dbref = int(dbref)
if dbref < 1:
if int(dbref) < 1:
return None
except Exception:
return None

View file

@ -49,6 +49,7 @@ def debug_script(script_path, obj=None, auto_delete=True):
try: scriptobj.delete()
except: pass
return string
string += "\nRunning syntax check ..."
try:
string += "\nTesting syntax of at_script_creation(self) ... "

View file

@ -210,7 +210,7 @@ def dbref(dbref):
(database reference number) are either a string '#N' or
an integer N. Output is the integer part.
"""
if type(dbref) == str:
if isinstance(dbref, basestring):
dbref = dbref.lstrip('#')
try:
dbref = int(dbref)