-
Notifications
You must be signed in to change notification settings - Fork 22
/
login_parser.py
154 lines (134 loc) · 6.08 KB
/
login_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import gsb
from MailChecker import MailChecker
import os
import re
from sqlalchemy import func
from ..constants import RE_NICKNAME
from .. import globals
from .. import models
from .. import parser
from ..player import Player
class login_parser(parser.Parser):
nickname_re = re.compile(RE_NICKNAME)
def on_attach(self, connection, old_parser=None):
connection.login_state = ("nickname", "Nickname (or new to create a new account):")
self.prompt(gsb.Caller(connection=connection))
def huh(self, caller):
state_fn = getattr(self, "handle_"+caller.connection.login_state[0])
state_fn(caller)
def prompt(self, caller, text=None):
if text:
caller.connection.notify(text)
caller.connection.notify(caller.connection.login_state[1])
def handle_nickname(self, caller):
if caller.text == 'new':
caller.connection.notify("Please enter a nickname. Your nickname is what you will be known by while playing.")
caller.connection.login_state = ("new", "Enter desired nickname:")
return self.prompt(caller)
# here we are checking for special commands
# that can only be executed from localhost
if caller.connection.transport.getPeer().host == "127.0.0.1":
if globals.server.handle_localhost_commands(caller):
return
nickname = caller.text.capitalize()
account = self.find_account(caller.connection.session, nickname)
if not account:
return self.prompt(caller, "That account doesn't exist. Type new to create a new account.")
caller.connection.login_state = ('password', "Password:", account)
return self.prompt(caller)
def handle_password(self, caller):
account = caller.connection.login_state[2]
if account.check_password(caller.text):
if account.banned:
caller.connection.notify("You have been banned and thus may not log in.")
# lets update the ip address
account.ip_address = caller.connection.host
caller.connection.session.commit()
globals.server.disconnect(caller.connection)
return
self.login(caller.connection, account)
else:
caller.connection.notify("Wrong password.")
globals.server.disconnect(caller.connection)
def handle_new(self, caller):
if not caller.text:
return self.prompt(caller)
if not 3 <= len(caller.text) <= 15:
return self.prompt(caller, "Nicknames must be between 3 and 15 characters.")
nickname = caller.text.capitalize()
if not self.nickname_re.match(nickname):
return self.prompt(caller, "Nicknames must start with a letter and consist of letters and digits.")
existing_account = self.find_account(caller.connection.session, nickname)
caller.connection.session.commit()
if existing_account:
return self.prompt(caller, "An account with that name already exists.")
caller.connection.account = models.Account(name=nickname)
caller.connection.login_state = ("new_password", "Enter a password for the account:")
return self.prompt(caller)
def handle_new_password(self, caller):
password = caller.text
if len(password) < 6:
return self.prompt(caller, "Passwords must be at least 6 characters.")
caller.connection.account.temp_password = password
caller.connection.login_state = ("confirm_password", "Please re-enter password:")
return self.prompt(caller)
def handle_confirm_password(self, caller):
if caller.text != caller.connection.account.temp_password:
caller.connection.notify("Passwords do not match.")
caller.connection.login_state = ("new_password", "Enter a password for the account:")
return self.prompt(caller)
del caller.connection.account.temp_password
caller.connection.account.set_password(caller.text)
caller.connection.notify("Please enter your email address. An email address is required in case the game administrators need to contact you.")
caller.connection.login_state = ("email", "E-mail address:")
self.prompt(caller)
def handle_email(self, caller):
if not caller.text or '@' not in caller.text or not MailChecker.is_valid(caller.text.strip()):
return self.prompt(caller, "Invalid email address.")
caller.connection.account.email = caller.text.strip()
caller.connection.session.add(caller.connection.account)
caller.connection.session.commit()
caller.connection.notify("Account created.")
self.login(caller.connection, caller.connection.account)
def find_account(self, session, nickname):
return session.query(models.Account).filter_by(name=nickname).first()
def login(self, connection, account):
if not connection.web:
connection.encode_args = (account.encoding, 'replace')
connection.decode_args = (account.encoding, 'ignore')
pl = globals.server.get_player(account.name.lower())
if pl:
if pl.connection is not None:
connection.notify(pl._("Disconnecting old connection."))
globals.server.connections.remove(pl.connection)
pl.connection.dont_process = True
globals.server.disconnect(pl.connection)
connection.parser = pl.connection.parser
pl.detach_connection()
connection.player = pl
pl.attach_connection(connection)
else:
connection.notify(pl._("Reconnecting..."))
for opl in [p for p in globals.server.get_all_players() if p is not pl]:
opl.notify(opl._("%s reconnected.")%(pl.nickname))
connection.player = pl
pl.attach_connection(connection)
if pl.duel is not None:
pl.duel.player_reconnected(pl)
else:
connection.player = Player(account.name)
connection.player.attach_connection(connection)
connection.player.set_parser('LobbyParser')
connection.player.is_admin = account.is_admin
connection.player.set_language(globals.language_handler.get_long(account.language))
for i in account.ignores:
connection.player.ignores.add(i.ignored_account.name)
for opl in globals.server.get_all_players():
opl.notify(opl._("%s logged in.") % connection.player.nickname)
globals.server.add_player(connection.player)
connection.notify(connection.player.motd)
connection.account = None
account.ip_address = connection.host
account.last_logged_in = func.now()
connection.session.commit()
LoginParser = login_parser()