X-Git-Url: https://mudpy.org/gitweb?p=mudpy.git;a=blobdiff_plain;f=mudpy%2Fmisc.py;h=af5427a86a059c091c6a41e899d0790a960f887f;hp=3cb201cba90f5d676505744ece8447e43fc89e60;hb=11ae0d6e7e05cffb744f7b40f37309f07696d34a;hpb=5210334c47e97988ea55543d60a6b24985ebd140 diff --git a/mudpy/misc.py b/mudpy/misc.py index 3cb201c..af5427a 100644 --- a/mudpy/misc.py +++ b/mudpy/misc.py @@ -1,6 +1,6 @@ """Miscellaneous functions for the mudpy engine.""" -# Copyright (c) 2004-2016 Jeremy Stanley . Permission +# Copyright (c) 2004-2017 Jeremy Stanley . Permission # to use, copy, modify, and distribute this software is granted under # terms provided in the LICENSE file distributed with this software. @@ -154,6 +154,8 @@ class Element: def set(self, facet, value): """Set values.""" + if facet in ["loglevel"]: + value = int(value) if not self.has_facet(facet) or not self.get(facet) == value: if self.old_style: if self.key not in self.origin.data: @@ -162,7 +164,7 @@ class Element: else: node = ".".join((self.key, facet)) self.origin.data[node] = value - self.facethash[node] = self.origin.data[node] + self.facethash[facet] = self.origin.data[node] self.origin.modified = True def append(self, facet, value): @@ -297,7 +299,7 @@ class Element: def portals(self): """Map the portal directions for an area to neighbors.""" portals = {} - if re.match("""^area:-?\d+,-?\d+,-?\d+$""", self.key): + if re.match(r"""^area:-?\d+,-?\d+,-?\d+$""", self.key): coordinates = [(int(x)) for x in self.key.split(":")[1].split(",")] offsets = dict( @@ -402,7 +404,7 @@ class Universe: inactive_avatars.append(self.contents[avatar]) except KeyError: pending_loglines.append(( - "Missing avatar \"%s\", possible data corruption" % + 'Missing avatar "%s", possible data corruption' % avatar, 6)) for user in self.userlist: if user.avatar in inactive_avatars: @@ -534,9 +536,8 @@ class User: def check_idle(self): """Warn or disconnect idle users as appropriate.""" idletime = universe.get_time() - self.last_input - linkdead_dict = universe.categories["internal"]["time"].get( - "linkdead" - ) + linkdead_dict = universe.contents[ + "mudpy.timing.idle.disconnect"].facets() if self.state in linkdead_dict: linkdead_state = self.state else: @@ -558,7 +559,7 @@ class User: log(logline, 2) self.state = "disconnecting" self.menu_seen = False - idle_dict = universe.categories["internal"]["time"].get("idle") + idle_dict = universe.contents["mudpy.timing.idle.warn"].facets() if self.state in idle_dict: idle_state = self.state else: @@ -651,8 +652,8 @@ class User: if self.state is not "authenticated": log("User " + self.account.get("name") + " logged in.", 2) self.authenticated = True - if self.account.subkey in universe.contents["mudpy.limit"].get( - "admins"): + if ("mudpy.limit" in universe.contents and self.account.subkey in + universe.contents["mudpy.limit"].get("admins")): self.account.set("administrator", "True") def show_menu(self): @@ -959,7 +960,7 @@ class User: try: avatars.append(universe.contents[avatar].get("name")) except KeyError: - log("Missing avatar \"%s\", possible data corruption." % + log('Missing avatar "%s", possible data corruption.' % avatar, 6) return avatars @@ -974,9 +975,14 @@ def log(message, level=0): """Log a message.""" # a couple references we need - file_name = universe.contents["mudpy.log"].get("file") - max_log_lines = universe.contents["mudpy.log"].get("lines") - syslog_name = universe.contents["mudpy.log"].get("syslog") + if "mudpy.log" in universe.contents: + file_name = universe.contents["mudpy.log"].get("file", "") + max_log_lines = universe.contents["mudpy.log"].get("lines", 0) + syslog_name = universe.contents["mudpy.log"].get("syslog", "") + else: + file_name = "" + max_log_lines = 0 + syslog_name = "" timestamp = time.asctime()[4:19] # turn the message into a list of nonempty lines @@ -993,7 +999,8 @@ def log(message, level=0): file_descriptor.close() # send the timestamp and line to standard output - if universe.contents["mudpy.log"].get("stdout"): + if ("mudpy.log" in universe.contents and + universe.contents["mudpy.log"].get("stdout")): for line in lines: print(timestamp + " " + line) @@ -1300,7 +1307,7 @@ def replace_macros(user, text, is_input=False): replacement = replacement[:-2] else: replacement = "" - log("Couldn't read included " + incfile + " file.", 6) + log("Couldn't read included " + incfile + " file.", 7) # if we get here, log and replace it with null else: @@ -1363,9 +1370,7 @@ def on_pulse(): if not universe.categories["internal"]["counters"].get("mark"): log(str(len(universe.userlist)) + " connection(s)") universe.categories["internal"]["counters"].set( - "mark", universe.categories["internal"]["time"].get( - "frequency_log" - ) + "mark", universe.contents["mudpy.timing"].get("status") ) else: universe.categories["internal"]["counters"].set( @@ -1378,9 +1383,7 @@ def on_pulse(): if not universe.categories["internal"]["counters"].get("save"): universe.save() universe.categories["internal"]["counters"].set( - "save", universe.categories["internal"]["time"].get( - "frequency_save" - ) + "save", universe.contents["mudpy.timing"].get("save") ) else: universe.categories["internal"]["counters"].set( @@ -1390,8 +1393,7 @@ def on_pulse(): ) # pause for a configurable amount of time (decimal seconds) - time.sleep(universe.categories["internal"] - ["time"].get("increment")) + time.sleep(universe.contents["mudpy.timing"].get("increment")) # increase the elapsed increment counter universe.categories["internal"]["counters"].set( @@ -1710,6 +1712,12 @@ def handler_checking_password(user): # get the next waiting line of input input_data = user.input_queue.pop(0) + if "mudpy.limit" in universe.contents: + max_password_tries = universe.contents["mudpy.limit"].get( + "password_tries", 3) + else: + max_password_tries = 3 + # does the hashed input equal the stored hash? if mudpy.password.verify(input_data, user.account.get("passhash")): @@ -1719,8 +1727,7 @@ def handler_checking_password(user): user.state = "main_utility" # if at first your hashes don't match, try, try again - elif user.password_tries < universe.contents["mudpy.limit"].get( - "password_tries") - 1: + elif user.password_tries < max_password_tries - 1: user.password_tries += 1 user.error = "incorrect" @@ -1738,6 +1745,12 @@ def handler_entering_new_password(user): # get the next waiting line of input input_data = user.input_queue.pop(0) + if "mudpy.limit" in universe.contents: + max_password_tries = universe.contents["mudpy.limit"].get( + "password_tries", 3) + else: + max_password_tries = 3 + # make sure the password is strong--at least one upper, one lower and # one digit, seven or more characters in length if len(input_data) > 6 and len( @@ -1753,8 +1766,7 @@ def handler_entering_new_password(user): user.state = "verifying_new_password" # the password was weak, try again if you haven't tried too many times - elif user.password_tries < universe.contents["mudpy.limit"].get( - "password_tries") - 1: + elif user.password_tries < max_password_tries - 1: user.password_tries += 1 user.error = "weak" @@ -1773,6 +1785,12 @@ def handler_verifying_new_password(user): # get the next waiting line of input input_data = user.input_queue.pop(0) + if "mudpy.limit" in universe.contents: + max_password_tries = universe.contents["mudpy.limit"].get( + "password_tries", 3) + else: + max_password_tries = 3 + # hash the input and match it to storage if mudpy.password.verify(input_data, user.account.get("passhash")): user.authenticate() @@ -1783,8 +1801,7 @@ def handler_verifying_new_password(user): # go back to entering the new password as long as you haven't tried # too many times - elif user.password_tries < universe.contents["mudpy.limit"].get( - "password_tries") - 1: + elif user.password_tries < max_password_tries - 1: user.password_tries += 1 user.error = "differs" user.state = "entering_new_password" @@ -1869,7 +1886,7 @@ def command_reload(actor): log( "User " + actor.owner.account.get("name") + " reloaded the world.", - 8 + 6 ) # set a flag to reload @@ -1954,8 +1971,8 @@ def command_help(actor, parameters): else: output += " $(grn)" output += item + "$(nrm) - " + description + "$(eol)" - output += ("$(eol)Enter \"help COMMAND\" for help on a command " - "named \"COMMAND\".") + output += ('$(eol)Enter "help COMMAND" for help on a command ' + 'named "COMMAND".') # send the accumulated output to the user actor.send(output) @@ -1985,25 +2002,26 @@ def command_say(actor, parameters): # if the message is wrapped in quotes, remove them and leave contents # intact - if parameters.startswith("\"") and parameters.endswith("\""): + if parameters.startswith('"') and parameters.endswith('"'): message = parameters[1:-1] literal = True # otherwise, get rid of stray quote marks on the ends of the message else: - message = parameters.strip("\"'`") + message = parameters.strip('''"'`''') literal = False # the user entered a message if message: # match the punctuation used, if any, to an action - actions = universe.contents["mudpy.linguistic"].get( - "actions" - ) - default_punctuation = ( - universe.contents["mudpy.linguistic"].get( - "default_punctuation")) + if "mudpy.linguistic" in universe.contents: + actions = universe.contents["mudpy.linguistic"].get("actions", {}) + default_punctuation = (universe.contents["mudpy.linguistic"].get( + "default_punctuation", ".")) + else: + actions = {} + default_punctuation = "." action = "" # reverse sort punctuation options so the longest match wins @@ -2027,9 +2045,10 @@ def command_say(actor, parameters): message = message[0].lower() + message[1:] # iterate over all words in message, replacing typos - typos = universe.contents["mudpy.linguistic"].get( - "typos" - ) + if "mudpy.linguistic" in universe.contents: + typos = universe.contents["mudpy.linguistic"].get("typos", {}) + else: + typos = {} words = message.split() for index in range(len(words)): word = words[index] @@ -2047,9 +2066,9 @@ def command_say(actor, parameters): # tell the area if message: actor.echo_to_location( - actor.get("name") + " " + action + "s, \"" + message + "\"" + actor.get("name") + " " + action + 's, "' + message + '"' ) - actor.send("You " + action + ", \"" + message + "\"") + actor.send("You " + action + ', "' + message + '"') # there was no message else: @@ -2100,8 +2119,8 @@ def command_show(actor, parameters): if len(arguments) != 2: message = "You must specify one category." elif arguments[1] in universe.categories: - message = ("These are the elements in the \"" + arguments[1] - + "\" category:$(eol)") + message = ('These are the elements in the "' + arguments[1] + + '" category:$(eol)') elements = [ ( universe.categories[arguments[1]][x].key @@ -2111,27 +2130,27 @@ def command_show(actor, parameters): for element in elements: message += "$(eol) $(grn)" + element + "$(nrm)" else: - message = "Category \"" + arguments[1] + "\" does not exist." + message = 'Category "' + arguments[1] + '" does not exist.' elif arguments[0] == "file": if len(arguments) != 2: message = "You must specify one file." elif arguments[1] in universe.files: - message = ("These are the elements in the \"" + arguments[1] - + "\" file:$(eol)") + message = ('These are the elements in the "' + arguments[1] + + '" file:$(eol)') elements = universe.files[arguments[1]].data.keys() elements.sort() for element in elements: message += "$(eol) $(grn)" + element + "$(nrm)" else: - message = "Category \"" + arguments[1] + "\" does not exist." + message = 'Category "' + arguments[1] + '" does not exist.' elif arguments[0] == "element": if len(arguments) != 2: message = "You must specify one element." elif arguments[1].strip(".") in universe.contents: element = universe.contents[arguments[1].strip(".")] - message = ("These are the properties of the \"" + arguments[1] - + "\" element (in \"" + element.origin.filename - + "\"):$(eol)") + message = ('These are the properties of the "' + arguments[1] + + '" element (in "' + element.origin.filename + + '"):$(eol)') facets = element.facets() for facet in sorted(facets): if element.old_style: @@ -2141,7 +2160,7 @@ def command_show(actor, parameters): message += ("$(eol) $(grn)%s: $(red)%s$(nrm)" % (facet, str(facets[facet]))) else: - message = "Element \"" + arguments[1] + "\" does not exist." + message = 'Element "' + arguments[1] + '" does not exist.' elif arguments[0] == "result": if len(arguments) < 2: message = "You need to specify an expression." @@ -2153,21 +2172,21 @@ def command_show(actor, parameters): "$(eol)$(bld)%s$(nrm)" % e) elif arguments[0] == "log": if len(arguments) == 4: - if re.match("^\d+$", arguments[3]) and int(arguments[3]) >= 0: + if re.match(r"^\d+$", arguments[3]) and int(arguments[3]) >= 0: stop = int(arguments[3]) else: stop = -1 else: stop = 0 if len(arguments) >= 3: - if re.match("^\d+$", arguments[2]) and int(arguments[2]) > 0: + if re.match(r"^\d+$", arguments[2]) and int(arguments[2]) > 0: start = int(arguments[2]) else: start = -1 else: start = 10 if len(arguments) >= 2: - if (re.match("^\d+$", arguments[1]) + if (re.match(r"^\d+$", arguments[1]) and 0 <= int(arguments[1]) <= 9): level = int(arguments[1]) else: @@ -2182,7 +2201,7 @@ def command_show(actor, parameters): message = ("When specified, level must be 0-9 (default 1), " "start and stop must be >=1 (default 10 and 1).") else: - message = "I don't know what \"" + parameters + "\" is." + message = '''I don't know what "''' + parameters + '" is.' actor.send(message) @@ -2199,10 +2218,10 @@ def command_create(actor, parameters): if len(arguments) == 2: element, filename = arguments if element in universe.contents: - message = "The \"" + element + "\" element already exists." + message = 'The "' + element + '" element already exists.' else: - message = ("You create \"" + - element + "\" within the universe.") + message = ('You create "' + + element + '" within the universe.') logline = actor.owner.account.get( "name" ) + " created an element: " + element @@ -2210,7 +2229,7 @@ def command_create(actor, parameters): logline += " in file " + filename if filename not in universe.files: message += ( - " Warning: \"" + filename + "\" is not yet " + ' Warning: "' + filename + '" is not yet ' "included in any other file and will not be read " "on startup unless this is remedied.") Element(element, universe, filename, old_style=True) @@ -2227,11 +2246,11 @@ def command_destroy(actor, parameters): message = "You must specify an element to destroy." else: if parameters not in universe.contents: - message = "The \"" + parameters + "\" element does not exist." + message = 'The "' + parameters + '" element does not exist.' else: universe.contents[parameters].destroy() - message = ("You destroy \"" + parameters - + "\" within the universe.") + message = ('You destroy "' + parameters + + '" within the universe.') log( actor.owner.account.get( "name" @@ -2248,22 +2267,28 @@ def command_set(actor, parameters): else: arguments = parameters.split(" ", 2) if len(arguments) == 1: - message = ("What facet of element \"" + arguments[0] - + "\" would you like to set?") + message = ('What facet of element "' + arguments[0] + + '" would you like to set?') elif len(arguments) == 2: - message = ("What value would you like to set for the \"" + - arguments[1] + "\" facet of the \"" + arguments[0] - + "\" element?") + message = ('What value would you like to set for the "' + + arguments[1] + '" facet of the "' + arguments[0] + + '" element?') else: element, facet, value = arguments if element not in universe.contents: - message = "The \"" + element + "\" element does not exist." + message = 'The "' + element + '" element does not exist.' else: - universe.contents[element].set(facet, value) - message = ("You have successfully (re)set the \"" + facet - + "\" facet of element \"" + element - + "\". Try \"show element " + - element + "\" for verification.") + try: + universe.contents[element].set(facet, value) + except ValueError: + message = ('Value "%s" of type "%s" cannot be coerced ' + 'to the correct datatype for facet "%s".' % + (value, type(value), facet)) + else: + message = ('You have successfully (re)set the "' + facet + + '" facet of element "' + element + + '". Try "show element ' + + element + '" for verification.') actor.send(message) @@ -2274,23 +2299,23 @@ def command_delete(actor, parameters): else: arguments = parameters.split(" ") if len(arguments) == 1: - message = ("What facet of element \"" + arguments[0] - + "\" would you like to delete?") + message = ('What facet of element "' + arguments[0] + + '" would you like to delete?') elif len(arguments) != 2: message = "You may only specify an element and a facet." else: element, facet = arguments if element not in universe.contents: - message = "The \"" + element + "\" element does not exist." + message = 'The "' + element + '" element does not exist.' elif facet not in universe.contents[element].facets(): - message = ("The \"" + element + "\" element has no \"" + facet - + "\" facet.") + message = ('The "' + element + '" element has no "' + facet + + '" facet.') else: universe.contents[element].remove_facet(facet) - message = ("You have successfully deleted the \"" + facet - + "\" facet of element \"" + element - + "\". Try \"show element " + - element + "\" for verification.") + message = ('You have successfully deleted the "' + facet + + '" facet of element "' + element + + '". Try "show element ' + + element + '" for verification.') actor.send(message) @@ -2299,7 +2324,7 @@ def command_error(actor, input_data): # 90% of the time use a generic error if random.randrange(10): - message = "I'm not sure what \"" + input_data + "\" means..." + message = '''I'm not sure what "''' + input_data + '''" means...''' # 10% of the time use the classic diku error else: @@ -2313,7 +2338,8 @@ def daemonize(universe): """Fork and disassociate from everything.""" # only if this is what we're configured to do - if universe.contents["mudpy.process"].get("daemon"): + if "mudpy.process" in universe.contents and universe.contents[ + "mudpy.process"].get("daemon"): # log before we start forking around, so the terminal gets the message log("Disassociating from the controlling terminal.") @@ -2350,7 +2376,10 @@ def create_pidfile(universe): """Write a file containing the current process ID.""" pid = str(os.getpid()) log("Process ID: " + pid) - file_name = universe.contents["mudpy.process"].get("pidfile") + if "mudpy.process" in universe.contents: + file_name = universe.contents["mudpy.process"].get("pidfile", "") + else: + file_name = "" if file_name: if not os.path.isabs(file_name): file_name = os.path.join(universe.startdir, file_name) @@ -2362,7 +2391,10 @@ def create_pidfile(universe): def remove_pidfile(universe): """Remove the file containing the current process ID.""" - file_name = universe.contents["mudpy.process"].get("pidfile") + if "mudpy.process" in universe.contents: + file_name = universe.contents["mudpy.process"].get("pidfile", "") + else: + file_name = "" if file_name: if not os.path.isabs(file_name): file_name = os.path.join(universe.startdir, file_name)