dkmud/menus/login.py
Francesco Cappelli 5ef1b78c42 sistemati spells
2022-02-17 18:33:26 +01:00

203 lines
6.8 KiB
Python

from django.conf import settings
from evennia.utils import utils
from evennia.utils.evmenu import EvMenu
CONNECTION_SCREEN_MODULE = settings.CONNECTION_SCREEN_MODULE
_GUEST_ENABLED = settings.GUEST_ENABLED
_ACCOUNT = utils.class_from_module(settings.BASE_ACCOUNT_TYPECLASS)
_GUEST = utils.class_from_module(settings.BASE_GUEST_TYPECLASS)
_ACCOUNT_HELP = (
"Enter the name you used to log into the game before, " "or a new account-name if you are new."
)
_PASSWORD_HELP = (
"Password should be a minimum of 8 characters (preferably longer) and "
"can contain a mix of letters, spaces, digits and @/./+/-/_/'/, only."
)
def _show_help(caller, raw_string, **kwargs):
"""Echo help message, then re-run node that triggered it"""
help_entry = kwargs["help_entry"]
caller.msg(help_entry)
return None # re-run calling node
def node_enter_username(caller, raw_text, **kwargs):
"""
Start node of menu
Start login by displaying the connection screen and ask for a user name.
"""
def _check_input(caller, username, **kwargs):
"""
'Goto-callable', set up to be called from the _default option below.
Called when user enters a username string. Check if this username already exists and set the flag
'new_user' if not. Will also directly login if the username is 'guest'
and GUEST_ENABLED is True.
The return from this goto-callable determines which node we go to next
and what kwarg it will be called with.
"""
username = username.rstrip("\n")
if username == "guest" and _GUEST_ENABLED:
# do an immediate guest login
session = caller
address = session.address
account, errors = _GUEST.authenticate(ip=address)
if account:
return "node_quit_or_login", {"login": True, "account": account}
else:
session.msg("|R{}|n".format("\n".join(errors)))
return None # re-run the username node
try:
_ACCOUNT.objects.get(username__iexact=username)
except _ACCOUNT.DoesNotExist:
new_user = True
else:
new_user = False
# pass username/new_user into next node as kwargs
return "node_enter_password", {"new_user": new_user, "username": username}
"""Show the connect screen."""
callables = utils.callables_from_module(CONNECTION_SCREEN_MODULE)
if "connection_screen" in callables:
connection_screen = callables["connection_screen"]()
else:
connection_screen = utils.random_string_from_module(CONNECTION_SCREEN_MODULE)
if not connection_screen:
connection_screen = "No connection screen found. Please contact an admin."
if _GUEST_ENABLED:
text = "Enter a new or existing user name to login (write 'guest' for a guest login):"
else:
text = "Enter a new or existing user name to login:"
text = "{}\n\n{}".format(connection_screen, text)
options = (
{"key": "", "goto": "node_enter_username"},
{"key": ("quit", "q"), "goto": "node_quit_or_login"},
{"key": ("help", "h"), "goto": (_show_help, {"help_entry": _ACCOUNT_HELP, **kwargs})},
{"key": "_default", "goto": _check_input},
)
return text, options
def node_enter_password(caller, raw_string, **kwargs):
"""
Handle password input.
"""
def _check_input(caller, password, **kwargs):
"""
'Goto-callable', set up to be called from the _default option below.
Called when user enters a password string. Check username + password
viability. If it passes, the account will have been created and login
will be initiated.
The return from this goto-callable determines which node we go to next
and what kwarg it will be called with.
"""
# these flags were set by the goto-callable
username = kwargs["username"]
new_user = kwargs["new_user"]
password = password.rstrip("\n")
session = caller
address = session.address
if new_user:
# create a new account
account, errors = _ACCOUNT.create(
username=username, password=password, ip=address, session=session
)
else:
# check password against existing account
account, errors = _ACCOUNT.authenticate(
username=username, password=password, ip=address, session=session
)
if account:
if new_user:
session.msg("|gA new account |c{}|g was created. Welcome!|n".format(username))
# pass login info to login node
return "node_quit_or_login", {"login": True, "account": account}
else:
# restart due to errors
session.msg("|R{}".format("\n".join(errors)))
kwargs["retry_password"] = True
return "node_enter_password", kwargs
def _restart_login(caller, *args, **kwargs):
caller.msg("|yCancelled login.|n")
return "node_enter_username"
username = kwargs["username"]
if kwargs["new_user"]:
if kwargs.get("retry_password"):
# Attempting to fix password
text = "Enter a new password:"
else:
text = "Creating a new account |c{}|n. " "Enter a password (empty to abort):".format(username)
else:
text = "Enter the password for account |c{}|n (empty to abort):".format(username)
options = (
{"key": "", "goto": _restart_login},
{"key": ("quit", "q"), "goto": "node_quit_or_login"},
{"key": ("help", "h"), "goto": (_show_help, {"help_entry": _PASSWORD_HELP, **kwargs})},
{"key": "_default", "goto": (_check_input, kwargs)},
)
return text, options
def node_quit_or_login(caller, raw_text, **kwargs):
"""
Exit menu, either by disconnecting or logging in.
"""
session = caller
if kwargs.get("login"):
account = kwargs.get("account")
# TODO
# session.msg("|gLogging in ...|n")
# session.sessionhandler.login(session, account)
# # go OOC
# account.unpuppet_object(session)
EvMenu(
caller,
"menus.char_manager",
startnode="node_enter_char_management",
auto_look=False,
auto_quit=False,
cmd_on_exit=None,
node_formatter=plain_node_formatter,
account=account,
)
else:
session.sessionhandler.disconnect(session, "Goodbye! Logging off.")
return "", {}
def plain_node_formatter(nodetext, optionstext, caller=None):
"""Do not display the options, only the text.
This function is used by EvMenu to format the text of nodes. The menu login
is just a series of prompts, so we disable all automatic display decoration
and let the nodes handle everything on their own.
"""
return nodetext