Example #1
0
def main():
    """Main Program
    """
    print("Dennis 2D Database Updater v1 -> v2")

    # Check command line arguments, and give help if needed.
    if len(sys.argv) != 2 or sys.argv[1] in [
            "help", "-h", "--help", "-help", "?", "-?"
    ]:
        print(
            "This updater adds entrance records to rooms for the `list entrances` command."
        )
        print("Usage: {0} <database>".format(sys.argv[0]))
        return 0

    # Make sure the database file exists.
    if not path.exists(sys.argv[1]):
        print("Database file does not exist: {0}".format(sys.argv[1]))
        return 1

    # Start up DatabaseManager and tell it we're accepting a v1 database for migration.
    dbman = database.DatabaseManager(sys.argv[1], Log())
    dbman._UPDATE_FROM_VERSION = 1
    sres = dbman._startup()
    if not sres:
        return 1

    # Run the updates for this migration.
    dbupdate_v1_to_v2(dbman)

    # Finished.
    print("Successfully updated database from v1 to v2: {0}".format(
        sys.argv[1]))
    dbman._unlock()
Example #2
0
def main():
    """Main Program
    """
    print("Dennis 2D Database Updater v3 -> v4")

    # Check command line arguments, and give help if needed.
    if len(sys.argv) != 2 or sys.argv[1] in [
            "help", "-h", "--help", "-help", "?", "-?"
    ]:
        print(
            "This updater adds neutral pronouns fields to users for formatting posturing text."
        )
        print("Usage: {0} <database>".format(sys.argv[0]))
        return 0

    # Make sure the database file exists.
    if not path.exists(sys.argv[1]):
        print("Database file does not exist: {0}".format(sys.argv[1]))
        return 2

    # Start up DatabaseManager and tell it we're accepting a v3 database for migration to v4.
    dbman = database.DatabaseManager(sys.argv[1], Log())
    dbman._UPDATE_FROM_VERSION = 3
    sres = dbman._startup()
    if not sres:
        return 3

    # Run the updates for this migration.
    print("Performing database updates...")
    dbupdate_v3_to_v4(dbman)

    # Finished.
    print("Successfully updated database from v3 to v4: {0}".format(
        sys.argv[1]))
    dbman._unlock()
Example #3
0
def main():
    """Startup tasks, mainloop entry, and shutdown tasks.
    """
    # Load the configuration.
    config = _config.ConfigManager(single=False)
    builtins.CONFIG = config

    print("Welcome to {0}, Multi-Player Server.".format(_config.VERSION))
    print("Starting up...")

    # Initialize the logger.
    logger.init(config)
    log = logger.Logger("server")

    # Rotate database backups, if enabled.
    # Unfortunately this has to be done before loading the database, because Windows.
    if os.path.exists(config["database"]["filename"]):
        try:
            if config["database"]["backups"]:
                backupnumbers = sorted(range(1, config["database"]["backups"]),
                                       reverse=True)
                for bn in backupnumbers:
                    if os.path.exists("{0}.bk{1}".format(
                            config["database"]["filename"], bn)):
                        shutil.copyfile(
                            "{0}.bk{1}".format(config["database"]["filename"],
                                               bn),
                            "{0}.bk{1}".format(config["database"]["filename"],
                                               bn + 1))
                shutil.copyfile(
                    config["database"]["filename"],
                    "{0}.bk1".format(config["database"]["filename"]))
        except:
            log.error("Could not finish rotating backups for database: {file}",
                      file=config["database"]["filename"])
            log.error(traceback.format_exc(1))

    # Initialize the Database Manager and load the world database.
    log.info("Initializing database manager...")
    dbman = database.DatabaseManager(config["database"]["filename"],
                                     config.defaults)
    _dbres = dbman._startup()
    if not _dbres:
        # On failure, only remove the lockfile if its existence wasn't the cause.
        if _dbres is not None:
            dbman._unlock()
        return 3
    log.info("Finished initializing database manager.")

    # Initialize the router.
    router = Router(config, dbman)

    # initialize the command shell.
    command_shell = shell.Shell(dbman, router)
    router.shell = command_shell

    # Start the services.
    log.info("Initializing services...")
    if not init_services(config, router, log):
        dbman._unlock()
        return 4
    log.info("Finished initializing services.")

    # Graceful shutdown on SIGINT (ctrl-c).
    # The shutdown command does the same thing.
    # To shut down quickly but cleanly, send the TERM signal.
    def shutdown(signal_received, frame):
        if not router.shutting_down:
            if config["shutdown_delay"]:
                command_shell.broadcast(
                    "<<<DENNIS IS SHUTTING DOWN IN {0} SECONDS>>>".format(
                        config["shutdown_delay"]))
            else:
                command_shell.broadcast("<<<DENNIS IS SHUTTING DOWN>>>")
            reactor.callLater(config["shutdown_delay"], reactor.stop)
            router.shutting_down = True

    signal.signal(signal.SIGINT, shutdown)

    # Start the Twisted Reactor.
    log.info("Finished startup tasks.")
    router._reactor = reactor
    reactor.run()

    # Shutting down.
    dbman._unlock()
    print("End Program.")
    return 0
Example #4
0
def main():
    # When this is False, Dennis will shut down.
    _running = True

    # Load the configuration.
    config = _config.ConfigManager(single=True)
    builtins.CONFIG = config

    print("Welcome to {0}, Single User Mode.".format(_config.VERSION))
    print("Starting up...")

    # Initialize the logger.
    logger.init(config)
    log = logger.Logger("singleuser")

    # Rotate database backups, if enabled.
    # Unfortunately this has to be done before loading the database, because Windows.
    if os.path.exists(config["database"]["filename"]):
        try:
            if config["database"]["backups"]:
                backupnumbers = sorted(range(1, config["database"]["backups"]), reverse=True)
                for bn in backupnumbers:
                    if os.path.exists("{0}.bk{1}".format(config["database"]["filename"], bn)):
                        shutil.copyfile("{0}.bk{1}".format(config["database"]["filename"], bn),
                                        "{0}.bk{1}".format(config["database"]["filename"], bn + 1))
                shutil.copyfile(config["database"]["filename"], "{0}.bk1".format(config["database"]["filename"]))
        except:
            log.error("Could not finish rotating backups for database: {0}".format(config["database"]["filename"]))
            log.error(traceback.format_exc(1))

    # Initialize the database manager, and create the "database" alias for use in Debug Mode.
    log.info("Initializing database manager...")
    dbman = _database.DatabaseManager(config["database"]["filename"], config.defaults)
    if not dbman._startup():
        return 3
    log.info("Finished initializing database manager.")
    database = dbman

    # Initialize the router.
    router = Router(log)

    # Initialize the command shell, and create the "shell" alias for use in Debug Mode.
    command_shell = _shell.Shell(dbman, router)
    router.shell = command_shell
    shell = command_shell

    # Initialize the command console, and log in as the root user. Promote to wizard if it was somehow demoted.
    # Create the "console" alias for use in Debug Mode. Also add us to the current room.
    dennis = _console.Console(router, command_shell, "<world>", dbman, log)
    dennis.user = dbman.user_by_name("<world>")
    dbman._users_online.append("<world>")
    thisroom = dbman.room_by_id(dennis.user["room"])
    if thisroom and "<world>" not in thisroom["users"]:
        thisroom["users"].append("<world>")
        dbman.upsert_room(thisroom)
    if not dennis.user["wizard"]:
        dennis.user["wizard"] = True
        dbman.upsert_user(dennis.user)
    console = dennis

    # Register our console with the router.
    router.users["<world>"] = {"service": "singleuser", "console": dennis}

    # Try to start a command prompt session with a history file.
    # Otherwise start a sessionless prompt without history.
    try:
        command_prompt = PromptSession(history=FileHistory(config["prompt"]["history"])).prompt
    except:
        log.error("Could not open prompt history file: {0}".format(config["prompt"]["history"]))
        log.error(traceback.format_exc(1))
        command_prompt = prompt

    # Stop Dennis. We use this instead of just a variable so that Dennis can be stopped from within a Python file
    # executed by load() in debug mode.
    def shutdown():
        """Stop Dennis."""
        nonlocal _running
        _running = False

    # Insert a simplified wrapper around dennis.shell.call() here so that it can access the current console
    # without us having to pass it as an argument.
    def call(command, args):
        """Simplified wrapper around dennis.shell.call().

        This shorthand function allows calling a command from Debug Mode
        without having to pass the current console as an argument.
        It can also take either a list or a string for args.

        :param command: The name of the command to call.
        :param args: A list or string of args to pass.

        :return: True if succeeded, False if failed.
        """
        if type(args) is str:
            args = args.split(' ')
        return dennis.shell.call(dennis, command, args)

    # Save the main scope for load().
    mainscope = locals()

    # Insert a function for Debug Mode to load and execute a Python file inside the main scope.
    def load(filename):
        """Load and execute a Python file inside the main scope.

        This is the same as running a series of lines in Debug mode.
        It can be called as a function from Debug mode, or as a command.

        Usage: `load <filename>`.

        :param filename: The filename of the Python file to execute.

        :return: True if succeeded, False if failed.
        """
        # Try to evaluate the given file.
        try:
            file = open(filename)
        except:
            log.write("[singleuser#error] load: Failed to load Python file: {0}".format(filename))
            log.write(traceback.format_exc(1))
            return False
        try:
            exec(file.read(), globals(), mainscope)
        except:
            log.write("[singleuser#error] load: Execution error inside file: {0}".format(filename))
            log.write(traceback.format_exc(1))
            return False
        return True

    # Welcome!
    log.write("You are now logged in as the administrative user \"<world>\".")

    # # # # # # # # # #
    # This is the command loop for the Single User Mode Command Line Interface. It works almost the same as connecting
    # to a Multi User server through Telnet, with a few differences:
    # * The return status of commands will echo in the console.
    # * You play as the system administrator user <world>, who is always a wizard, and owns the first room.
    # * Other users can't share the session with you.
    # * You have access to the following special commands:
    #   - `quit`             : Quits the CLI.
    #   - `debug`            : Enters a PDB Debug Mode session inside the main scope.
    #   - `load <filename>`  : Loads and executes an external Python file inside the main scope.
    #
    # * You have access to the following special functions inside Debug Mode:
    #   - shutdown()          : Cleanly shuts down the engine.
    #   - call(command, args) : Calls the named command with a string or list of arguments.
    #   - load(filename)      : Same as the `load <filename>` command.
    #
    # * You have access to the following special keypress actions:
    #   - Ctrl+C              : Cleanly shuts down the engine.
    #   - Ctrl+D              : Enters a PDB Debug Mode session inside the main scope.
    #
    # * You can return from Debug Mode to normal operation by entering "continue".
    # # # # # # # # # #
    while _running:
        try:
            cmd = command_prompt("> ")
            if cmd == "quit":
                break
            elif cmd.startswith("quit ") or cmd == "help quit":
                log.write("Usage: quit")
                continue
            elif cmd == "debug":
                pdb.set_trace()
                continue
            elif cmd.startswith("debug ") or cmd == "help debug":
                log.write("Usage: debug")
                continue
            elif cmd.startswith("load "):
                log.write(load(cmd[5:]))
                continue
            elif cmd == "load" or cmd == "help load":
                log.write("Usage: load <filename>")
                continue
            log.write(command_shell.command(dennis, cmd))
        except KeyboardInterrupt:
            break
        except EOFError:
            pdb.set_trace()
            continue

    # Just before shutdown.
    dbman._unlock()
    log.write("End Program.")
    return 0