X-Git-Url: https://mudpy.org/gitweb?p=mudpy.git;a=blobdiff_plain;f=muff%2Fmuffcmds.py;fp=muff%2Fmuffcmds.py;h=0000000000000000000000000000000000000000;hp=da061fa30d3d616aee0bb71083c08357aefdec3f;hb=7b8056e7b2eac4fb4e87708afa3de90c3fc02032;hpb=fecd4c0fc49593052697b8cf199603cf1fac2b61 diff --git a/muff/muffcmds.py b/muff/muffcmds.py deleted file mode 100644 index da061fa..0000000 --- a/muff/muffcmds.py +++ /dev/null @@ -1,379 +0,0 @@ -"""Command objects for the MUFF Engine""" - -# Copyright (c) 2005 mudpy, Jeremy Stanley , all rights reserved. -# Licensed per terms in the LICENSE file distributed with this software. - -# command data like descriptions, help text, limits, et cetera, are stored in -# ini-style configuration files supported by the ConfigParser module -import ConfigParser - -# md5 hashing is used for verification of account passwords -import md5 - -# the os module is used to we can get a directory listing and build lists of -# multiple config files in one directory -import os - -# the random module is useful for creating random conditional output -import random - -# string.split is used extensively to tokenize user input (break up command -# names and parameters) -import string - -# bit of a hack to load all modules in the muff package -import muff -for module in muff.__all__: - exec("import " + module) - -def handle_user_input(user): - """The main handler, branches to a state-specific handler.""" - - # check to make sure the state is expected, then call that handler - if "handler_" + user.state in globals(): - exec("handler_" + user.state + "(user)") - else: - generic_menu_handler(user) - - # since we got input, flag that the menu/prompt needs to be redisplayed - user.menu_seen = False - - # if the user's client echo is off, send a blank line for aesthetics - if not user.echoing: user.send("", "") - -def generic_menu_handler(user): - """A generic menu choice handler.""" - - # get a lower-case representation of the next line of input - if user.input_queue: - choice = user.input_queue.pop(0) - if choice: choice = choice.lower() - else: choice = "" - - # run any script related to this choice - exec(muffmenu.get_choice_action(user, choice)) - - # move on to the next state or return an error - new_state = muffmenu.get_choice_branch(user, choice) - if new_state: user.state = new_state - else: user.error = "default" - -def handler_entering_account_name(user): - """Handle the login account name.""" - - # get the next waiting line of input - input_data = user.input_queue.pop(0) - - # did the user enter anything? - if input_data: - - # keep only the first word and convert to lower-case - name = input_data.lower() - - # fail if there are non-alphanumeric characters - if name != filter(lambda x: x>="0" and x<="9" or x>="a" and x<="z", name): - user.error = "bad_name" - - # if that account exists, time to request a password - elif name in muffuniv.universe.categories["account"]: - user.account = muffuniv.universe.categories["account"][name] - user.state = "checking_password" - - # otherwise, this could be a brand new user - else: - user.account = muffuniv.Element("account:" + name, muffuniv.universe) - user.account.set("name", name) - muffmisc.log("New user: " + name) - user.state = "checking_new_account_name" - - # if the user entered nothing for a name, then buhbye - else: - user.state = "disconnecting" - -def handler_checking_password(user): - """Handle the login account password.""" - - # get the next waiting line of input - input_data = user.input_queue.pop(0) - - # does the hashed input equal the stored hash? - if md5.new(user.account.get("name") + input_data).hexdigest() == user.account.get("passhash"): - - # if so, set the username and load from cold storage - if not user.replace_old_connections(): - user.authenticate() - user.state = "main_utility" - - # if at first your hashes don't match, try, try again - elif user.password_tries < muffuniv.universe.categories["internal"]["general"].getint("password_tries"): - user.password_tries += 1 - user.error = "incorrect" - - # we've exceeded the maximum number of password failures, so disconnect - else: - user.send("$(eol)$(red)Too many failed password attempts...$(nrm)$(eol)") - user.state = "disconnecting" - -def handler_checking_new_account_name(user): - """Handle input for the new user menu.""" - - # get the next waiting line of input - input_data = user.input_queue.pop(0) - - # if there's input, take the first character and lowercase it - if input_data: - choice = input_data.lower()[0] - - # if there's no input, use the default - else: - choice = muffmenu.get_default_menu_choice(user.state) - - # user selected to disconnect - if choice == "d": - user.account.delete() - user.state = "disconnecting" - - # go back to the login screen - elif choice == "g": - user.account.delete() - user.state = "entering_account_name" - - # new user, so ask for a password - elif choice == "n": - user.state = "entering_new_password" - - # user entered a non-existent option - else: - user.error = "default" - -def handler_entering_new_password(user): - """Handle a new password entry.""" - - # get the next waiting line of input - input_data = user.input_queue.pop(0) - - # 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(filter(lambda x: x>="0" and x<="9", input_data)) and len(filter(lambda x: x>="A" and x<="Z", input_data)) and len(filter(lambda x: x>="a" and x<="z", input_data)): - - # hash and store it, then move on to verification - user.account.set("passhash", md5.new(user.account.get("name") + input_data).hexdigest()) - user.state = "verifying_new_password" - - # the password was weak, try again if you haven't tried too many times - elif user.password_tries < muffuniv.universe.categories["internal"]["general"].getint("password_tries"): - user.password_tries += 1 - user.error = "weak" - - # too many tries, so adios - else: - user.send("$(eol)$(red)Too many failed password attempts...$(nrm)$(eol)") - user.account.delete() - user.state = "disconnecting" - -def handler_verifying_new_password(user): - """Handle the re-entered new password for verification.""" - - # get the next waiting line of input - input_data = user.input_queue.pop(0) - - # hash the input and match it to storage - if md5.new(user.account.get("name") + input_data).hexdigest() == user.account.get("passhash"): - user.authenticate() - - # the hashes matched, so go active - if not user.replace_old_connections(): user.state = "main_utility" - - # go back to entering the new password as long as you haven't tried - # too many times - elif user.password_tries < muffuniv.universe.categories["internal"]["general"].getint("password_tries"): - user.password_tries += 1 - user.error = "differs" - user.state = "entering_new_password" - - # otherwise, sayonara - else: - user.send("$(eol)$(red)Too many failed password attempts...$(nrm)$(eol)") - user.account.delete() - user.state = "disconnecting" - -def handler_active(user): - """Handle input for active users.""" - - # get the next waiting line of input - input_data = user.input_queue.pop(0) - - # split out the command (first word) and parameters (everything else) - if input_data.find(" ") > 0: - command, parameters = input_data.split(" ", 1) - else: - command = input_data - parameters = "" - - # lowercase the command - command = command.lower() - - # the command matches a command word for which we have data - if command in muffuniv.universe.categories["command"]: - exec(muffuniv.universe.categories["command"][command].get("action")) - - # no data matching the entered command word - elif command: command_error(user, command, parameters) - -def command_halt(user, command="", parameters=""): - """Halt the world.""" - - # see if there's a message or use a generic one - if parameters: message = "Halting: " + parameters - else: message = "User " + user.account.get("name") + " halted the world." - - # let everyone know - muffmisc.broadcast(message) - muffmisc.log(message) - - # set a flag to terminate the world - muffvars.terminate_world = True - -def command_reload(user, command="", parameters=""): - """Reload all code modules, configs and data.""" - - # let the user know and log - user.send("Reloading all code modules, configs and data.") - muffmisc.log("User " + user.account.get("name") + " reloaded the world.") - - # set a flag to reload - muffvars.reload_modules = True - -def command_quit(user, command="", parameters=""): - """Quit the world.""" - user.state = "disconnecting" - -def command_help(user, command="", parameters=""): - """List available commands and provide help for commands.""" - - # did the user ask for help on a specific command word? - if parameters: - - # is the command word one for which we have data? - if parameters in muffuniv.universe.categories["command"]: - - # add a description if provided - description = muffuniv.universe.categories["command"][parameters].get("description") - if not description: - description = "(no short description provided)" - output = "$(grn)" + parameters + "$(nrm) - " + description + "$(eol)$(eol)" - - # add the help text if provided - help_text = muffuniv.universe.categories["command"][parameters].get("help") - if not help_text: - help_text = "No help is provided for this command." - output += help_text - - # no data for the requested command word - else: - output = "That is not an available command." - - # no specific command word was indicated - else: - - # give a sorted list of commands with descriptions if provided - output = "These are the commands available to you:$(eol)$(eol)" - sorted_commands = muffuniv.universe.categories["command"].keys() - sorted_commands.sort() - for item in sorted_commands: - description = muffuniv.universe.categories["command"][item].get("description") - if not description: - description = "(no short description provided)" - output += " $(grn)" + item + "$(nrm) - " + description + "$(eol)" - output += "$(eol)Enter \"help COMMAND\" for help on a command named \"COMMAND\"." - - # send the accumulated output to the user - user.send(output) - -def command_say(user, command="", parameters=""): - """Speak to others in the same room.""" - - # check for replacement macros - if muffmisc.replace_macros(user, parameters, True) != parameters: - user.send("You cannot speak $_(replacement macros).") - - # the user entered a message - elif parameters: - - # get rid of quote marks on the ends of the message and - # capitalize the first letter - message = parameters.strip("\"'`").capitalize() - - # a dictionary of punctuation:action pairs - actions = {} - for facet in muffuniv.universe.categories["internal"]["language"].facets(): - if facet.startswith("punctuation_"): - action = facet.split("_")[1] - for mark in muffuniv.universe.categories["internal"]["language"].get(facet).split(): - actions[mark] = action - - # match the punctuation used, if any, to an action - default_punctuation = muffuniv.universe.categories["internal"]["language"].get("default_punctuation") - action = actions[default_punctuation] - for mark in actions.keys(): - if message.endswith(mark) and mark != default_punctuation: - action = actions[mark] - break - - # if the action is default and there is no mark, add one - if action == actions[default_punctuation] and not message.endswith(default_punctuation): - message += default_punctuation - - # capitalize a list of words within the message - capitalize = muffuniv.universe.categories["internal"]["language"].get("capitalize").split() - for word in capitalize: - message = message.replace(" " + word + " ", " " + word.capitalize() + " ") - - # tell the room - # TODO: we won't be using broadcast once there are actual rooms - muffmisc.broadcast(user.account.get("name") + " " + action + "s, \"" + message + "\"") - - # there was no message - else: - user.send("What do you want to say?") - -def command_show(user, command="", parameters=""): - """Show program data.""" - if parameters == "avatars": - message = "These are the avatars managed by your account:$(eol)" - avatars = user.list_avatar_names() - avatars.sort() - for avatar in avatars: message += "$(eol) $(grn)" + avatar + "$(nrm)" - elif parameters == "files": - message = "These are the current files containing the universe:$(eol)" - keys = muffuniv.universe.files.keys() - keys.sort() - for key in keys: message += "$(eol) $(grn)" + key + "$(nrm)" - elif parameters == "universe": - message = "These are the current elements in the universe:$(eol)" - keys = muffuniv.universe.contents.keys() - keys.sort() - for key in keys: message += "$(eol) $(grn)" + key + "$(nrm)" - elif parameters == "time": - message = muffuniv.universe.categories["internal"]["counters"].get("elapsed") + " increments elapsed since the world was created." - elif parameters: message = "I don't know what \"" + parameters + "\" is." - else: message = "What do you want to show?" - user.send(message) - -def command_error(user, command="", parameters=""): - """Generic error for an unrecognized command word.""" - - # 90% of the time use a generic error - if random.randrange(10): - message = "I'm not sure what \"" + command - if parameters: - message += " " + parameters - message += "\" means..." - - # 10% of the time use the classic diku error - else: - message = "Arglebargle, glop-glyf!?!" - - # send the error message - user.send(message) -