.BANCHO. .FIX. Better support for username with spaces and underscores in IRC

This commit is contained in:
Nyo 2016-09-16 18:20:32 +02:00
parent 47ce794bfc
commit 6020f7cc47
2 changed files with 47 additions and 31 deletions

View File

@ -297,6 +297,17 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
""" IRC-Bancho Connect/Disconnect/Join/Part interfaces""" """ IRC-Bancho Connect/Disconnect/Join/Part interfaces"""
def fixUsernameForBancho(username): def fixUsernameForBancho(username):
# If there are no spaces or underscores in the name
# return it
if " " not in username and "_" not in username:
return username
# Exact match first
result = glob.db.fetch("SELECT id FROM users WHERE username = %s LIMIT 1", [username])
if result is not None:
return username
# Username not found, replace _ with space
return username.replace("_", " ") return username.replace("_", " ")
def fixUsernameForIRC(username): def fixUsernameForIRC(username):

View File

@ -42,7 +42,7 @@ class Client:
self.server = server self.server = server
self.socket = sock self.socket = sock
(self.ip, self.port) = sock.getpeername() (self.ip, self.port) = sock.getpeername()
self.username = "" self.IRCUsername = ""
self.banchoUsername = "" self.banchoUsername = ""
self.supposedUsername = "" self.supposedUsername = ""
self.joinedChannels = [] self.joinedChannels = []
@ -91,7 +91,7 @@ class Client:
channel -- optional channel -- optional
""" """
if nickname == "": if nickname == "":
nickname = self.username nickname = self.IRCUsername
if channel != "": if channel != "":
channel = " "+channel channel = " "+channel
self.reply("{code:03d} {nickname}{channel} :{message}".format(code=code, nickname=nickname, channel=channel, message=message)) self.reply("{code:03d} {nickname}{channel} :{message}".format(code=code, nickname=nickname, channel=channel, message=message))
@ -132,7 +132,7 @@ class Client:
# Bancho logout # Bancho logout
if callLogout: if callLogout:
chat.IRCDisconnect(self.username) chat.IRCDisconnect(self.IRCUsername)
def readSocket(self): def readSocket(self):
@ -253,7 +253,7 @@ class Client:
tokenHash = m.hexdigest() tokenHash = m.hexdigest()
supposedUsername = glob.db.fetch("SELECT users.username FROM users LEFT JOIN irc_tokens ON users.id = irc_tokens.userid WHERE irc_tokens.token = %s LIMIT 1", [tokenHash]) supposedUsername = glob.db.fetch("SELECT users.username FROM users LEFT JOIN irc_tokens ON users.id = irc_tokens.userid WHERE irc_tokens.token = %s LIMIT 1", [tokenHash])
if supposedUsername: if supposedUsername:
self.supposedUsername = supposedUsername["username"] self.supposedUsername = chat.fixUsernameForIRC(supposedUsername["username"])
self.__handleCommand = self.registerHandler self.__handleCommand = self.registerHandler
else: else:
# Wrong IRC Token # Wrong IRC Token
@ -271,12 +271,13 @@ class Client:
nick = arguments[0] nick = arguments[0]
# Make sure this is the first time we set our nickname # Make sure this is the first time we set our nickname
if self.username != "": if self.IRCUsername != "":
self.reply("432 * %s :Erroneous nickname" % nick) self.reply("432 * %s :Erroneous nickname" % nick)
return return
# Make sure the IRC token was correct: # Make sure the IRC token was correct:
if nick.lower() != chat.fixUsernameForIRC(self.supposedUsername.lower()): # (self.supposedUsername is already fixed for IRC)
if nick.lower() != self.supposedUsername.lower():
self.reply("464 :Password incorrect") self.reply("464 :Password incorrect")
return return
@ -288,13 +289,13 @@ class Client:
# Make sure we are not already connected from IRC with that name # Make sure we are not already connected from IRC with that name
for _, value in self.server.clients.items(): for _, value in self.server.clients.items():
if value.username == self.username and value != self: if value.IRCUsername == self.IRCUsername and value != self:
self.reply("433 * {} :Nickname is already in use".format(nick)) self.reply("433 * {} :Nickname is already in use".format(nick))
return return
# Everything seems fine, set username (nickname) # Everything seems fine, set username (nickname)
self.username = nick self.IRCUsername = nick # username for IRC
self.banchoUsername = chat.fixUsernameForBancho(self.username) self.banchoUsername = chat.fixUsernameForBancho(self.IRCUsername) # username for bancho
elif command == "USER": elif command == "USER":
# Ignore USER command, we use nickname only # Ignore USER command, we use nickname only
return return
@ -307,7 +308,7 @@ class Client:
return return
# If we now have a valid username, connect to bancho and send IRC welcome stuff # If we now have a valid username, connect to bancho and send IRC welcome stuff
if self.username != "": if self.IRCUsername != "":
# Bancho connection # Bancho connection
chat.IRCConnect(self.banchoUsername) chat.IRCConnect(self.banchoUsername)
@ -322,7 +323,7 @@ class Client:
def quitHandler(self, command, arguments): def quitHandler(self, command, arguments):
"""QUIT command handler""" """QUIT command handler"""
self.disconnect(self.username if len(arguments) < 1 else arguments[0]) self.disconnect(self.IRCUsername if len(arguments) < 1 else arguments[0])
def joinHandler(self, command, arguments): def joinHandler(self, command, arguments):
"""JOIN command handler""" """JOIN command handler"""
@ -362,7 +363,7 @@ class Client:
self.joinedChannels.append(channel) self.joinedChannels.append(channel)
# Let everyone in this channel know that we've joined # Let everyone in this channel know that we've joined
self.messageChannel(channel, "{} JOIN".format(self.username), channel, True) self.messageChannel(channel, "{} JOIN".format(self.IRCUsername), channel, True)
# Send channel description (topic) # Send channel description (topic)
description = glob.channels.channels[channel].description description = glob.channels.channels[channel].description
@ -381,7 +382,7 @@ class Client:
usernames.append(chat.fixUsernameForIRC(token.username)) usernames.append(chat.fixUsernameForIRC(token.username))
usernames = " ".join(usernames) usernames = " ".join(usernames)
# Send IRC users lis # Send IRC users list
self.replyCode(353, usernames, channel="= {}".format(channel)) self.replyCode(353, usernames, channel="= {}".format(channel))
self.replyCode(366, "End of NAMES list", channel=channel) self.replyCode(366, "End of NAMES list", channel=channel)
elif response == 403: elif response == 403:
@ -431,36 +432,40 @@ class Client:
if len(arguments) == 1: if len(arguments) == 1:
self.replyCode(412, "No text to send") self.replyCode(412, "No text to send")
return return
recipient = arguments[0] recipientIRC = arguments[0]
message = arguments[1] message = arguments[1]
# Send the message to bancho and reply # Send the message to bancho and reply
recipient = chat.fixUsernameForBancho(recipient) if not recipientIRC.startswith("#"):
response = chat.sendMessage(self.banchoUsername, recipient, message, toIRC=False) print("PMPMPM!!!!!!!!!!")
recipientBancho = chat.fixUsernameForBancho(recipientIRC)
else:
recipientBancho = recipientIRC
response = chat.sendMessage(self.banchoUsername, recipientBancho, message, toIRC=False)
if response == 404: if response == 404:
self.replyCode(404, "Cannot send to channel", channel=recipient) self.replyCode(404, "Cannot send to channel", channel=recipientIRC)
return return
elif response == 403: elif response == 403:
self.replyCode(403, "No such channel", channel=recipient) self.replyCode(403, "No such channel", channel=recipientIRC)
return return
elif response == 401: elif response == 401:
self.replyCode(401, "No such nick/channel", channel=recipient) self.replyCode(401, "No such nick/channel", channel=recipientIRC)
return return
# Send the message to IRC and bancho # Send the message to IRC and bancho
if recipient.startswith("#"): if recipientIRC.startswith("#"):
# Public message (IRC) # Public message (IRC)
if recipient not in glob.channels.channels: if recipientIRC not in glob.channels.channels:
self.replyCode(401, "No such nick/channel", channel=recipient) self.replyCode(401, "No such nick/channel", channel=recipientIRC)
return return
for _, value in self.server.clients.items(): for _, value in self.server.clients.items():
if recipient in value.joinedChannels and value != self: if recipientIRC in value.joinedChannels and value != self:
value.message(":{} PRIVMSG {} :{}".format(self.username, recipient, message)) value.message(":{} PRIVMSG {} :{}".format(self.IRCUsername, recipientIRC, message))
else: else:
# Private message (IRC) # Private message (IRC)
for _, value in self.server.clients.items(): for _, value in self.server.clients.items():
if value.username == recipient: if value.IRCUsername == recipientIRC:
value.message(":{} PRIVMSG {} :{}".format(self.username, recipient, message)) value.message(":{} PRIVMSG {} :{}".format(self.IRCUsername, recipientIRC, message))
def motdHandler(self, command, arguments): def motdHandler(self, command, arguments):
"""MOTD command handler""" """MOTD command handler"""
@ -523,14 +528,14 @@ class Server:
self.clients = {} # Socket --> Client instance. self.clients = {} # Socket --> Client instance.
self.motd = ["Welcome to pep.py's embedded IRC server!", "This is a VERY simple IRC server and it's still in beta.", "Expect things to crash and not work as expected :("] self.motd = ["Welcome to pep.py's embedded IRC server!", "This is a VERY simple IRC server and it's still in beta.", "Expect things to crash and not work as expected :("]
def forceDisconnection(self, username): def forceDisconnection(self, username, isBanchoUsername=True):
""" """
Disconnect someone from IRC if connected Disconnect someone from IRC if connected
username -- victim username -- victim
""" """
for _, value in self.clients.items(): for _, value in self.clients.items():
if value.username == username: if (value.IRCUsername == username and not isBanchoUsername) or (value.banchoUsername == username and isBanchoUsername):
value.disconnect(callLogout=False) value.disconnect(callLogout=False)
break # or dictionary changes size during iteration break # or dictionary changes size during iteration
@ -571,12 +576,12 @@ class Server:
if to.startswith("#"): if to.startswith("#"):
# Public message # Public message
for _, value in self.clients.items(): for _, value in self.clients.items():
if to in value.joinedChannels and value.username != fro: if to in value.joinedChannels and value.IRCUsername != fro:
value.message(":{} PRIVMSG {} :{}".format(fro, to, message)) value.message(":{} PRIVMSG {} :{}".format(fro, to, message))
else: else:
# Private message # Private message
for _, value in self.clients.items(): for _, value in self.clients.items():
if value.username == to and value.username != fro: if value.IRCUsername == to and value.IRCUsername != fro:
value.message(":{} PRIVMSG {} :{}".format(fro, to, message)) value.message(":{} PRIVMSG {} :{}".format(fro, to, message))