Imported from archive.
[mudpy.git] / muff / muffcmds.py
diff --git a/muff/muffcmds.py b/muff/muffcmds.py
deleted file mode 100644 (file)
index da061fa..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-"""Command objects for the MUFF Engine"""
-
-# Copyright (c) 2005 mudpy, Jeremy Stanley <fungi@yuggoth.org>, 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)
-