示例#1
0
def _create_account(session,
                    accountname,
                    password,
                    permissions,
                    typeclass=None,
                    email=None):
    """
    Helper function, creates an account of the specified typeclass.


    Contrary to the default `evennia.commands.default.unlogged._create_account`,
    the account isn't connected to the public chaannel.

    """
    try:
        new_account = create.create_account(accountname,
                                            email,
                                            password,
                                            permissions=permissions,
                                            typeclass=typeclass)

    except Exception as e:
        session.msg(
            "There was an error creating the Account:\n%s\n If this problem persists, contact an admin."
            % e)
        logger.log_trace()
        return False

    # This needs to be set so the engine knows this account is
    # logging in for the first time. (so it knows to call the right
    # hooks during login later)
    new_account.db.FIRST_LOGIN = True
    return new_account
示例#2
0
def _confirm_password(caller, user_input):
    password = caller.ndb.new_password
    menutree = caller.ndb._menutree
    if user_input == password:
        # Create the new player account
        playername = menutree.playername
        from evennia.commands.default import unloggedin
        # We make use of the helper functions from the default set here.
        # noinspection PyBroadException
        try:
            permissions = settings.PERMISSION_PLAYER_DEFAULT
            new_player = unloggedin._create_player(caller, playername,
                                                   password, permissions)
        except Exception:
            # We are in the middle between logged in and -not, so we have
            # to handle tracebacks ourselves at this point. If we don't, we
            # won't see any errors at all.
            caller.msg(LOGIN_ERROR)
            logger.log_trace()
        else:
            caller.ndb.passed_account_creation = True
            caller.msg(LOGIN_ACCOUNT_CREATED.format(playername))
            caller.sessionhandler.login(caller, new_player)
    else:
        caller.msg(LOGIN_PASSWORD_MISMATCH)
        caller.ndb.confirm_needed = False
示例#3
0
def create_password(caller, string_input):
    """Ask the user to create a password.

    This node is at the end of the menu for account creation.  If
    a proper MULTI_SESSION is configured, a character is also
    created with the same name (we try to login into it).

    """
    menutree = caller.ndb._menutree
    text = ""
    options = (
        {"key": "",
         "exec": lambda caller: caller.msg("", options={"echo": True}),
         "goto": "start"},
        {"key": "_default",
         "goto": "create_password"})

    password = string_input.strip()
    accountname = menutree.accountname

    if len(password) < LEN_PASSWD:
        # The password is too short
        text = dedent("""
            |rYour password must be at least {} characters long.|n
            Enter another password or leave it empty to go back.
        """.strip("\n")).format(LEN_PASSWD)
    else:
        # Everything's OK.  Create the new player account and
        # possibly the character, depending on the multisession mode
        from evennia.commands.default import unloggedin
        # We make use of the helper functions from the default set here.
        try:
            permissions = settings.PERMISSION_ACCOUNT_DEFAULT
            typeclass = settings.BASE_CHARACTER_TYPECLASS
            new_account = unloggedin._create_account(caller, accountname,
                                                     password, permissions)
            if new_account:
                if settings.MULTISESSION_MODE < 2:
                    default_home = ObjectDB.objects.get_id(
                        settings.DEFAULT_HOME)
                    unloggedin._create_character(caller, new_account,
                                                 typeclass, default_home, permissions)
        except Exception:
            # We are in the middle between logged in and -not, so we have
            # to handle tracebacks ourselves at this point. If we don't, we
            # won't see any errors at all.
            caller.msg(dedent("""
                |rAn error occurred.|n  Please e-mail an admin if
                the problem persists. Try another password or leave
                it empty to go back to the login screen.
            """.strip("\n")))
            logger.log_trace()
        else:
            text = ""
            caller.msg("|gWelcome, your new account has been created!|n")
            caller.msg("", options={"echo": True})
            caller.sessionhandler.login(caller, new_account)

    return text, options
示例#4
0
def confirm_password(caller, input):
    """Ask the user to confirm the account's password.

    The account's password has been saved in the session for the
    time being, as a hashed version.  If the hashed version of
    the retyped password matches, then the account is created.
    If not, ask for another password.

    """
    text = ""
    options = ({
        "key": "_default",
        "desc": "Enter your password.",
        "goto": "create_password",
    }, )

    password = input.strip()

    accountname = caller.db._accountname
    first_password = caller.db._password
    second_password = sha256(password.encode()).hexdigest()
    if first_password != second_password:
        text = dedent("""
            |rThe password you have specified doesn't match the first one.|n

            Enter a new password for this account.
        """.strip("\n"))
    else:
        # Creates the new account.
        caller.msg(echo=True)
        try:
            permissions = settings.PERMISSION_ACCOUNT_DEFAULT
            account = _create_account(caller, accountname, password,
                                      permissions)
        except Exception:
            # We are in the middle between logged in and -not, so we have
            # to handle tracebacks ourselves at this point. If we don't, we
            # won't see any errors at all.
            caller.msg(
                dedent("""
                |rAn error occurred.|n  Please email an admin if
                the problem persists.

                Please enter another password.
            """.strip("\n")))
            logger.log_trace()
        else:
            caller.db._account = account
            del caller.db._password
            text = "Your new account was successfully created!"
            text += "\n\n" + _text_email_address(account)
            options = ({
                "key": "_default",
                "desc": "Enter a valid email address.",
                "goto": "email_address",
            }, )

    return text, options
示例#5
0
def get_event_handler():
    """Return the event handler or None."""
    try:
        script = ScriptDB.objects.get(db_key="event_handler")
    except ScriptDB.DoesNotExist:
        logger.log_trace("Can't get the event handler.")
        script = None

    return script
示例#6
0
def get_event_handler():
    """Return the event handler or None."""
    try:
        script = ScriptDB.objects.get(db_key="event_handler")
    except ScriptDB.DoesNotExist:
        logger.log_trace("Can't get the event handler.")
        script = None

    return script
示例#7
0
文件: state.py 项目: evennia/evdemo
 def decorator(*args, **kwargs):
     try:
         return method(*args, **kwargs)
     except Exception:
         logger.log_trace(f"Error in State {__name__}")
         self.room.msg_room(
             None,
             f"|rThere was an unexpected error in State {__name__}. "
             "Please |wreport|r this as an issue.|n")
         raise  # TODO
示例#8
0
    def send(self, event):
        """Dispatches an event to each open quest.

        Arguments:
            event - an arbitrary entity communicating information to
                    the quests"""

        for quest in self.player.db.quests:
            try:
                quest.send(event)
            except Exception:
                logger.log_trace()
示例#9
0
 def goto(self, key):
     """
     Go to a key in the tree. This sets up the cmdsets on the
     caller so that they match the choices in that node.
     """
     if key == self.endnode:
         # if we was given the END node key, we clean up immediately.
         self.caller.cmdset.delete("menucmdset")
         del self.caller.db._menu_data
         if self.exec_end is not None:
             self.caller.execute_cmd(self.exec_end)
         return
     # not exiting, look for a valid code.
     node = self.tree.get(key, None)
     # make caller available on node
     node.caller = self.caller
     if node:
         # call on-node callback
         if node.callback:
             try:
                 node.callback()
             except Exception:
                 logger.log_trace()
                 self.caller.msg(
                     "{rNode callback could not be executed for node %s. Continuing anyway.{n"
                     % key)
         if node.code:
             # Execute eventual code active on this node. self.caller is available at this point.
             evennia.logger.log_depmsg(
                 "menusystem.code is deprecated. Use menusystem.callback.")
             try:
                 exec(node.code)
             except Exception:
                 self.caller.msg(
                     "{rCode could not be executed for node %s. Continuing anyway.{n"
                     % key)
         # initialize - this creates new cmdset
         node.init(self)
         # clean old menu cmdset and replace with the new one
         self.caller.cmdset.delete("menucmdset")
         self.caller.cmdset.add(node.cmdset)
         # set the menu flag data for the default commands
         self.caller.db._menu_data = {
             "help": node.helptext,
             "look": str(node.text)
         }
         # display the node
         self.caller.msg(node.text)
     else:
         self.caller.msg(
             "{rMenu node '%s' does not exist - maybe it's not created yet..{n"
             % key)
示例#10
0
    def func(self):
        "Execute  the command"
        password = self.args
        self.caller.msg(echo=False)
        if not hasattr(self.menutree, 'playername'):
            self.caller.msg(
                "{rSomething went wrong! Playername not remembered from previous step!{n"
            )
            self.menutree.goto("node2a")
            return
        playername = self.menutree.playername
        if len(password) < 3:
            # too short password
            string = "{rYour password must be at least 3 characters or longer."
            string += "\n\rFor best security, make it at least 8 characters "
            string += "long, avoid making it a real word and mix numbers "
            string += "into it.{n"
            self.caller.msg(string)
            self.menutree.goto("node2b")
            return
        # everything's ok. Create the new player account and possibly the character
        # depending on the multisession mode

        from evennia.commands.default import unloggedin
        # we make use of the helper functions from the default set here.
        try:
            permissions = settings.PERMISSION_PLAYER_DEFAULT
            typeclass = settings.BASE_CHARACTER_TYPECLASS
            new_player = unloggedin._create_player(self.caller, playername,
                                                   password, permissions)
            if new_player:
                if MULTISESSION_MODE < 2:
                    default_home = ObjectDB.objects.get_id(
                        settings.DEFAULT_HOME)
                    unloggedin._create_character(self.caller, new_player,
                                                 typeclass, default_home,
                                                 permissions)
            # tell the caller everything went well.
            string = "{gA new account '%s' was created. Now go log in from the menu!{n"
            self.caller.msg(string % (playername))
            self.menutree.goto("START")
        except Exception:
            # We are in the middle between logged in and -not, so we have
            # to handle tracebacks ourselves at this point. If we don't, we
            # won't see any errors at all.
            self.caller.msg(
                "An error occurred. Please e-mail an admin if the problem persists."
            )
            logger.log_trace()
示例#11
0
文件: state.py 项目: evennia/evdemo
    def load_state(self, statename):
        """
        Load state without initializing it
        """
        try:
            mod = utils.mod_import(f"{_ROOMSTATE_PACKAGE}.{statename}")
        except Exception as err:
            logger.log_trace()
            self.room.msg_room(
                None, f"|rBUG: Could not load state {statename}: {err}!")
            self.room.msg_room(
                None, f"|rBUG: Falling back to {self.current_state_name}")
            return

        state = mod.State(self, self.room)
        return state
示例#12
0
    def func(self):
        "Execute  the command"
        password = self.args
        self.caller.msg(echo=False)
        if not hasattr(self.menutree, 'playername'):
            self.caller.msg("{rSomething went wrong! Playername not remembered from previous step!{n")
            self.menutree.goto("node2a")
            return
        playername = self.menutree.playername
        if len(password) < 3:
            # too short password
            string = "{rYour password must be at least 3 characters or longer."
            string += "\n\rFor best security, make it at least 8 characters "
            string += "long, avoid making it a real word and mix numbers "
            string += "into it.{n"
            self.caller.msg(string)
            self.menutree.goto("node2b")
            return
        # everything's ok. Create the new player account and possibly the character
        # depending on the multisession mode

        from evennia.commands.default import unloggedin
        # we make use of the helper functions from the default set here.
        try:
            permissions = settings.PERMISSION_PLAYER_DEFAULT
            typeclass = settings.BASE_CHARACTER_TYPECLASS
            new_player = unloggedin._create_player(self.caller, playername,
                                               password, permissions)
            if new_player:
                if MULTISESSION_MODE < 2:
                    default_home = ObjectDB.objects.get_id(settings.DEFAULT_HOME)
                    unloggedin._create_character(self.caller, new_player, typeclass,
                                                 default_home, permissions)
            # tell the caller everything went well.
            string = "{gA new account '%s' was created. Now go log in from the menu!{n"
            self.caller.msg(string % (playername))
            self.menutree.goto("START")
        except Exception:
            # We are in the middle between logged in and -not, so we have
            # to handle tracebacks ourselves at this point. If we don't, we
            # won't see any errors at all.
            self.caller.msg("An error occurred. Please e-mail an admin if the problem persists.")
            logger.log_trace()
示例#13
0
 def goto(self, key):
     """
     Go to a key in the tree. This sets up the cmdsets on the
     caller so that they match the choices in that node.
     """
     if key == self.endnode:
         # if we was given the END node key, we clean up immediately.
         self.caller.cmdset.delete("menucmdset")
         del self.caller.db._menu_data
         if self.exec_end is not None:
             self.caller.execute_cmd(self.exec_end)
         return
     # not exiting, look for a valid code.
     node = self.tree.get(key, None)
     # make caller available on node
     node.caller = self.caller
     if node:
         # call on-node callback
         if node.callback:
             try:
                 node.callback()
             except Exception:
                 logger.log_trace()
                 self.caller.msg("{rNode callback could not be executed for node %s. Continuing anyway.{n" % key)
         if node.code:
             # Execute eventual code active on this node. self.caller is available at this point.
             evennia.logger.log_depmsg("menusystem.code is deprecated. Use menusystem.callback.")
             try:
                 exec(node.code)
             except Exception:
                 self.caller.msg("{rCode could not be executed for node %s. Continuing anyway.{n" % key)
         # initialize - this creates new cmdset
         node.init(self)
         # clean old menu cmdset and replace with the new one
         self.caller.cmdset.delete("menucmdset")
         self.caller.cmdset.add(node.cmdset)
         # set the menu flag data for the default commands
         self.caller.db._menu_data = {"help": node.helptext,
                                      "look": str(node.text)}
         # display the node
         self.caller.msg(node.text)
     else:
         self.caller.msg("{rMenu node '%s' does not exist - maybe it's not created yet..{n" % key)
示例#14
0
    def load(self):
        """
        Takes the provided save data, validates it, and gets this Option ready to use.

        Returns:
            Boolean: Whether loading was successful.

        """
        loadfunc = self.handler.loadfunc
        load_kwargs = self.handler.load_kwargs

        try:
            self.value_storage = self.deserialize(
                loadfunc(self.key, default=self.default_value, **load_kwargs))
        except Exception:
            logger.log_trace()
            return False
        self.loaded = True
        return True
示例#15
0
文件: scripts.py 项目: remy-r/evennia
def complete_task(task_id):
    """
    Mark the task in the event handler as complete.

    Args:
        task_id (int): the task ID.

    Note:
        This function should be called automatically for individual tasks.

    """
    try:
        script = ScriptDB.objects.get(db_key="event_handler")
    except ScriptDB.DoesNotExist:
        logger.log_trace("Can't get the event handler.")
        return

    if task_id not in script.db.tasks:
        logger.log_err("The task #{} was scheduled, but it cannot be " \
                "found".format(task_id))
        return

    delta, obj, callback_name, locals = script.db.tasks.pop(task_id)
    script.call(obj, callback_name, locals=locals)
示例#16
0
def complete_task(task_id):
    """
    Mark the task in the event handler as complete.

    Args:
        task_id (int): the task ID.

    Note:
        This function should be called automatically for individual tasks.

    """
    try:
        script = ScriptDB.objects.get(db_key="event_handler")
    except ScriptDB.DoesNotExist:
        logger.log_trace("Can't get the event handler.")
        return

    if task_id not in script.db.tasks:
        logger.log_err("The task #{} was scheduled, but it cannot be " \
                "found".format(task_id))
        return

    delta, obj, callback_name, locals = script.db.tasks.pop(task_id)
    script.call(obj, callback_name, locals=locals)
示例#17
0
def confirm_password(caller, input):
    """Ask the user to confirm the account's password.

    The account's password has been saved in the session for the
    time being, as a hashed version.  If the hashed version of
    the retyped password matches, then the player is created.
    If not, ask for another password.

    """
    text = ""
    options = (
        {
            "key": "b",
            "desc": "Go back to the password selection.",
            "goto": "create_password",
        },
        {
            "key": "_default",
            "desc": "Enter your password.",
            "goto": "confirm_password",
        },
    )

    caller.msg(echo=True)
    password = input.strip()

    playername = caller.db._playername
    first_password = caller.db._password
    second_password = sha256(password).hexdigest()
    if first_password != second_password:
        text = dedent("""
            |rThe password you have specified doesn't match the first one.|n
                Type |yb|n to choose a different password.
                Or type the confirmation password again.
        """.strip("\n"))
    else:
        # Creates the new player.
        from evennia.commands.default import unloggedin
        try:
            permissions = settings.PERMISSION_PLAYER_DEFAULT
            player = unloggedin._create_player(caller, playername, password,
                                               permissions)
        except Exception:
            # We are in the middle between logged in and -not, so we have
            # to handle tracebacks ourselves at this point. If we don't, we
            # won't see any errors at all.
            caller.msg(
                dedent("""
                |rAn error occurred.|n  Please e-mail an admin if
                the problem persists.
                    Type |yb|n to go back to the login screen.
                    Or enter another password.
            """.strip("\n")))
            logger.log_trace()
        else:
            caller.db._player = player
            del caller.db._password
            _login(caller, player)
            text = "Your new account was successfully created!"
            text += "\n\n" + text_email_address(player)
            options = ({
                "key": "_default",
                "desc": "Enter a valid e-mail address.",
                "goto": "email_address",
            }, )

    return text, options
示例#18
0
def confirm_password(caller, input):
    """Ask the user to confirm the account's password.

    The account's password has been saved in the session for the
    time being, as a hashed version.  If the hashed version of
    the retyped password matches, then the player is created.
    If not, ask for another password.

    """
    text = ""
    options = (
        {
            "key": "b",
            "desc": "Go back to the password selection.",
            "goto": "create_password",
        },
        {
            "key": "_default",
            "desc": "Enter your password.",
            "goto": "confirm_password",
        },
    )

    caller.msg(echo=True)
    password = input.strip()

    playername = caller.db._playername
    first_password = caller.db._password
    second_password = sha256(password).hexdigest()
    if first_password != second_password:
        text = dedent("""
            |rThe password you have specified doesn't match the first one.|n
                Type |yb|n to choose a different password.
                Or type the confirmation password again.
        """.strip("\n"))
    else:
        # Creates the new player.
        from evennia.commands.default import unloggedin
        try:
            permissions = settings.PERMISSION_PLAYER_DEFAULT
            player = unloggedin._create_player(caller, playername,
                    password, permissions)
        except Exception:
            # We are in the middle between logged in and -not, so we have
            # to handle tracebacks ourselves at this point. If we don't, we
            # won't see any errors at all.
            caller.msg(dedent("""
                |rAn error occurred.|n  Please e-mail an admin if
                the problem persists.
                    Type |yb|n to go back to the login screen.
                    Or enter another password.
            """.strip("\n")))
            logger.log_trace()
        else:
            caller.db._player = player
            del caller.db._password
            _login(caller, player)
            text = "Your new account was successfully created!"
            text += "\n\n" + text_email_address(player)
            options = (
                {
                    "key": "_default",
                    "desc": "Enter a valid e-mail address.",
                    "goto": "email_address",
                },
            )

    return text, options
示例#19
0
文件: scripts.py 项目: remy-r/evennia
    def call(self, obj, callback_name, *args, **kwargs):
        """
        Call the connected callbacks.

        Args:
            obj (Object): the Evennia typeclassed object.
            callback_name (str): the callback name to call.
            *args: additional variables for this callback.

        Kwargs:
            number (int, optional): call just a specific callback.
            parameters (str, optional): call a callback with parameters.
            locals (dict, optional): a locals replacement.

        Returns:
            True to report the callback was called without interruption,
            False otherwise.

        """
        # First, look for the callback type corresponding to this name
        number = kwargs.get("number")
        parameters = kwargs.get("parameters")
        locals = kwargs.get("locals")

        # Errors should not pass silently
        allowed = ("number", "parameters", "locals")
        if any(k for k in kwargs if k not in allowed):
            raise TypeError("Unknown keyword arguments were specified " \
                    "to call callbacks: {}".format(kwargs))

        event = self.get_events(obj).get(callback_name)
        if locals is None and not event:
            logger.log_err("The callback {} for the object {} (typeclass " \
                    "{}) can't be found".format(callback_name, obj, type(obj)))
            return False

        # Prepare the locals if necessary
        if locals is None:
            locals = self.ndb.fresh_locals.copy()
            for i, variable in enumerate(event[0]):
                try:
                    locals[variable] = args[i]
                except IndexError:
                    logger.log_trace("callback {} of {} ({}): need variable " \
                            "{} in position {}".format(callback_name, obj,
                            type(obj), variable, i))
                    return False
        else:
            locals = {key: value for key, value in locals.items()}

        callbacks = self.get_callbacks(obj).get(callback_name, [])
        if event:
            custom_call = event[2]
            if custom_call:
                callbacks = custom_call(callbacks, parameters)

        # Now execute all the valid callbacks linked at this address
        self.ndb.current_locals = locals
        for i, callback in enumerate(callbacks):
            if not callback["valid"]:
                continue

            if number is not None and callback["number"] != number:
                continue

            try:
                exec(callback["code"], locals, locals)
            except InterruptEvent:
                return False
            except Exception:
                etype, evalue, tb = sys.exc_info()
                trace = traceback.format_exception(etype, evalue, tb)
                self.handle_error(callback, trace)

        return True
示例#20
0
def create_password(caller, string_input):
    """Ask the user to create a password.

    This node is at the end of the menu for account creation.  If
    a proper MULTI_SESSION is configured, a character is also
    created with the same name (we try to login into it).

    """
    menutree = caller.ndb._menutree
    text = ""
    options = ({
        "key": "",
        "exec": lambda caller: caller.msg("", options={"echo": True}),
        "goto": "start"
    }, {
        "key": "_default",
        "goto": "create_password"
    })

    password = string_input.strip()
    accountname = menutree.accountname

    if len(password) < LEN_PASSWD:
        # The password is too short
        text = dedent("""
            |rYour password must be at least {} characters long.|n
            Enter another password or leave it empty to go back.
        """.strip("\n")).format(LEN_PASSWD)
    else:
        # Everything's OK.  Create the new player account and
        # possibly the character, depending on the multisession mode
        from evennia.commands.default import unloggedin
        # We make use of the helper functions from the default set here.
        try:
            permissions = settings.PERMISSION_ACCOUNT_DEFAULT
            typeclass = settings.BASE_CHARACTER_TYPECLASS
            new_account = unloggedin._create_account(caller, accountname,
                                                     password, permissions)
            if new_account:
                if settings.MULTISESSION_MODE < 2:
                    default_home = ObjectDB.objects.get_id(
                        settings.DEFAULT_HOME)
                    unloggedin._create_character(caller, new_account,
                                                 typeclass, default_home,
                                                 permissions)
        except Exception:
            # We are in the middle between logged in and -not, so we have
            # to handle tracebacks ourselves at this point. If we don't, we
            # won't see any errors at all.
            caller.msg(
                dedent("""
                |rAn error occurred.|n  Please e-mail an admin if
                the problem persists. Try another password or leave
                it empty to go back to the login screen.
            """.strip("\n")))
            logger.log_trace()
        else:
            text = ""
            caller.msg("|gWelcome, your new account has been created!|n")
            caller.msg("", options={"echo": True})
            caller.sessionhandler.login(caller, new_account)

    return text, options
示例#21
0
def get_next_wait(format):
    """
    Get the length of time in seconds before format.

    Args:
        format (str): a time format matching the set calendar.

    Returns:
        until (int or float): the number of seconds until the event.
        usual (int or float): the usual number of seconds between events.
        format (str): a string format representing the time.

    Notes:
        The time format could be something like "2018-01-08 12:00".  The
        number of units set in the calendar affects the way seconds are
        calculated.

    """
    calendar = getattr(settings, "EVENTS_CALENDAR", None)
    if calendar is None:
        logger.log_err("A time-related event has been set whereas " \
                "the gametime calendar has not been set in the settings.")
        return
    elif calendar == "standard":
        rsu = standard_rsu
        units = ["min", "hour", "day", "month", "year"]
    elif calendar == "custom":
        rsu = custom_rsu
        back = dict([(value, name) for name, value in UNITS.items()])
        sorted_units = sorted(back.items())
        del sorted_units[0]
        units = [n for v, n in sorted_units]

    params = {}
    for delimiter in ("-", ":"):
        format = format.replace(delimiter, " ")

    pieces = list(reversed(format.split()))
    details = []
    i = 0
    for uname in units:
        try:
            piece = pieces[i]
        except IndexError:
            break

        if not piece.isdigit():
            logger.log_trace("The time specified '{}' in {} isn't " \
                    "a valid number".format(piece, format))
            return

        # Convert the piece to int
        piece = int(piece)
        params[uname] = piece
        details.append("{}={}".format(uname, piece))
        if i < len(units):
            next_unit = units[i + 1]
        else:
            next_unit = None
        i += 1

    params["sec"] = 0
    details = " ".join(details)
    until = rsu(**params)
    usual = -1
    if next_unit:
        kwargs = {next_unit: 1}
        usual = gametime_to_realtime(**kwargs)
    return until, usual, details
示例#22
0
def create_password(caller, string_input):
    """Ask the user to create a password.

    This node is at the end of the menu for account creation.  If
    a proper MULTI_SESSION is configured, a character is also
    created with the same name (we try to login into it).

    """
    menutree = caller.ndb._menutree
    text = ""
    options = (
        {
            "key": "r",
            "exec": lambda caller: caller.msg("", options={"echo": True}),
            "goto": "start",
        },
        {
            "key": "_default",
            "goto": "create_password",
        },
    )

    password = string_input.strip()
    accountname = menutree.accountname

    if len(password) < LEN_PASSWD:
        # The password is too short
        text = dedent("""
            |rLe mot de passe doit comporter au moins {} caractères.|n
            Entrez un nouveau mot de passe ou entrez |yr|n pour revenir à l'écran d'accueil.
        """.strip("\n")).format(LEN_PASSWD)
    else:
        from evennia.commands.default import unloggedin
        try:
            permissions = settings.PERMISSION_ACCOUNT_DEFAULT
            typeclass = settings.BASE_CHARACTER_TYPECLASS
            new_account = unloggedin._create_account(caller, accountname,
                                                     password, permissions)
            if new_account:
                new_account.email = ""
                new_account.save()
                if settings.MULTISESSION_MODE < 2:
                    default_home = ObjectDB.objects.get_id(
                        settings.DEFAULT_HOME)
                    unloggedin._create_character(caller, new_account,
                                                 typeclass, default_home,
                                                 permissions)
        except Exception:
            # We are in the middle between logged in and -not, so we have
            # to handle tracebacks ourselves at this point. If we don't, we
            # won't see any errors at all.
            caller.msg(
                dedent("""
                |rUne erreur inattendue s'est produite..|n  S'il vous plaît, envoyez un e-mail
                à [email protected] pour signaler ce problème.
            """.strip("\n")))
            logger.log_trace()
        else:
            menutree.account = new_account
            caller.msg("", options={"echo": True})
            text = dedent("""
                Le nouvel utilisateur a bien été créé.

                Pour l'utiliser, il vous faut préciser une adresse e-mail valide. Un code
                de validation vous sera envoyé par e-mail. Vous devrez entrer ce code de
                validation dans votre client pour utiliser ce compte.

                Veuillez entrer une adresse e-mail valide :
            """).strip()
            options = ({
                "key": "_default",
                "goto": "create_email_address",
            }, )

    return text, options
示例#23
0
    def call(self, obj, callback_name, *args, **kwargs):
        """
        Call the connected callbacks.

        Args:
            obj (Object): the Evennia typeclassed object.
            callback_name (str): the callback name to call.
            *args: additional variables for this callback.

        Kwargs:
            number (int, optional): call just a specific callback.
            parameters (str, optional): call a callback with parameters.
            locals (dict, optional): a locals replacement.

        Returns:
            True to report the callback was called without interruption,
            False otherwise.

        """
        # First, look for the callback type corresponding to this name
        number = kwargs.get("number")
        parameters = kwargs.get("parameters")
        locals = kwargs.get("locals")

        # Errors should not pass silently
        allowed = ("number", "parameters", "locals")
        if any(k for k in kwargs if k not in allowed):
            raise TypeError("Unknown keyword arguments were specified " \
                    "to call callbacks: {}".format(kwargs))

        event = self.get_events(obj).get(callback_name)
        if locals is None and not event:
            logger.log_err("The callback {} for the object {} (typeclass " \
                    "{}) can't be found".format(callback_name, obj, type(obj)))
            return False

        # Prepare the locals if necessary
        if locals is None:
            locals = self.ndb.fresh_locals.copy()
            for i, variable in enumerate(event[0]):
                try:
                    locals[variable] = args[i]
                except IndexError:
                    logger.log_trace("callback {} of {} ({}): need variable " \
                            "{} in position {}".format(callback_name, obj,
                            type(obj), variable, i))
                    return False
        else:
            locals = {key: value for key, value in locals.items()}

        callbacks = self.get_callbacks(obj).get(callback_name, [])
        if event:
            custom_call = event[2]
            if custom_call:
                callbacks = custom_call(callbacks, parameters)

        # Now execute all the valid callbacks linked at this address
        self.ndb.current_locals = locals
        for i, callback in enumerate(callbacks):
            if not callback["valid"]:
                continue

            if number is not None and callback["number"] != number:
                continue

            try:
                exec(callback["code"], locals, locals)
            except InterruptEvent:
                return False
            except Exception:
                etype, evalue, tb = sys.exc_info()
                trace = traceback.format_exception(etype, evalue, tb)
                self.handle_error(callback, trace)

        return True
示例#24
0
def get_next_wait(format):
    """
    Get the length of time in seconds before format.

    Args:
        format (str): a time format matching the set calendar.

    Returns:
        until (int or float): the number of seconds until the event.
        usual (int or float): the usual number of seconds between events.
        format (str): a string format representing the time.

    Notes:
        The time format could be something like "2018-01-08 12:00".  The
        number of units set in the calendar affects the way seconds are
        calculated.

    """
    calendar = getattr(settings, "EVENTS_CALENDAR", None)
    if calendar is None:
        logger.log_err("A time-related event has been set whereas " \
                "the gametime calendar has not been set in the settings.")
        return
    elif calendar == "standard":
        rsu = standard_rsu
        units = ["min", "hour", "day", "month", "year"]
    elif calendar == "custom":
        rsu = custom_rsu
        back = dict([(value, name) for name, value in UNITS.items()])
        sorted_units = sorted(back.items())
        del sorted_units[0]
        units = [n for v, n in sorted_units]

    params = {}
    for delimiter in ("-", ":"):
        format = format.replace(delimiter, " ")

    pieces = list(reversed(format.split()))
    details = []
    i = 0
    for uname in units:
        try:
            piece = pieces[i]
        except IndexError:
            break

        if not piece.isdigit():
            logger.log_trace("The time specified '{}' in {} isn't " \
                    "a valid number".format(piece, format))
            return

        # Convert the piece to int
        piece = int(piece)
        params[uname] = piece
        details.append("{}={}".format(uname, piece))
        if i < len(units):
            next_unit = units[i + 1]
        else:
            next_unit = None
        i += 1

    params["sec"] = 0
    details = " ".join(details)
    until = rsu(**params)
    usual = -1
    if next_unit:
        kwargs = {next_unit: 1}
        usual = gametime_to_realtime(**kwargs)
    return until, usual, details