.BANCHO. Add support for tournament client

This commit is contained in:
Nyo 2016-10-05 23:28:26 +02:00
parent 795b6f09be
commit 996287f871
13 changed files with 91 additions and 25 deletions

View File

@ -143,3 +143,12 @@ def transferHost(stream):
def matchInvite(stream): def matchInvite(stream):
return packetHelper.readPacketData(stream, [["userID", dataTypes.UINT32]]) return packetHelper.readPacketData(stream, [["userID", dataTypes.UINT32]])
def tournamentMatchInfoRequest(stream):
return packetHelper.readPacketData(stream, [["matchID", dataTypes.UINT32]])
def tournamentJoinMatchChannel(stream):
return packetHelper.readPacketData(stream, [["matchID", dataTypes.UINT32]])
def tournamentLeaveMatchChannel(stream):
return packetHelper.readPacketData(stream, [["matchID", dataTypes.UINT32]])

View File

@ -89,3 +89,6 @@ class loginLockedException(Exception):
class unknownStreamException(Exception): class unknownStreamException(Exception):
pass pass
class userTournamentException(Exception):
pass

View File

@ -74,7 +74,9 @@ server_channelInfoEnd = 89
client_matchChangePassword = 90 client_matchChangePassword = 90
server_matchChangePassword = 91 server_matchChangePassword = 91
server_silenceEnd = 92 server_silenceEnd = 92
client_specialMatchInfoRequest = 93
server_userSilenced = 94 server_userSilenced = 94
server_userPresenceBundle = 96 server_userPresenceBundle = 96
client_userPanelRequest = 97 client_userPanelRequest = 97
client_tournamentMatchInfoRequest = 93
client_tournamentJoinMatchChannel = 108
client_tournamentLeaveMatchChannel = 109

View File

@ -50,9 +50,10 @@ def mainMenuIcon(icon):
def userSupporterGMT(supporter, GMT): def userSupporterGMT(supporter, GMT):
result = 1 result = 1
if supporter: if supporter:
result += 4 result |= userRanks.SUPPORTER
if GMT: if GMT:
result += 2 result |= userRanks.BAT
result |= userRanks.TOURNAMENT_STAFF
return packetHelper.buildPacket(packetIDs.server_supporterGMT, [[result, dataTypes.UINT32]]) return packetHelper.buildPacket(packetIDs.server_supporterGMT, [[result, dataTypes.UINT32]])
def friendList(userID): def friendList(userID):
@ -78,9 +79,7 @@ def userLogout(userID):
def userPanel(userID, force = False): def userPanel(userID, force = False):
# Connected and restricted check # Connected and restricted check
userToken = glob.tokens.getTokenFromUserID(userID) userToken = glob.tokens.getTokenFromUserID(userID)
if userToken is None: if userToken is None or ((userToken.restricted) and not force):
return bytes()
if userToken.restricted == True and force == False:
return bytes() return bytes()
# Get user data # Get user data
@ -93,16 +92,17 @@ def userPanel(userID, force = False):
# Get username color according to rank # Get username color according to rank
# Only admins and normal users are currently supported # Only admins and normal users are currently supported
userRank = 0
if username == "FokaBot": if username == "FokaBot":
userRank = userRanks.MOD userRank |= userRanks.MOD
elif userUtils.isInPrivilegeGroup(userID, "community manager"): elif userUtils.isInPrivilegeGroup(userID, "community manager"):
userRank = userRanks.MOD userRank |= userRanks.MOD
elif userUtils.isInPrivilegeGroup(userID, "developer"): elif userUtils.isInPrivilegeGroup(userID, "developer"):
userRank = userRanks.ADMIN userRank |= userRanks.ADMIN
elif (userToken.privileges & privileges.USER_DONOR) > 0: elif (userToken.privileges & privileges.USER_DONOR) > 0:
userRank = userRanks.SUPPORTER userRank |= userRanks.SUPPORTER
else: else:
userRank = userRanks.NORMAL userRank |= userRanks.NORMAL
return packetHelper.buildPacket(packetIDs.server_userPanel, return packetHelper.buildPacket(packetIDs.server_userPanel,
[ [
@ -120,10 +120,7 @@ def userPanel(userID, force = False):
def userStats(userID, force = False): def userStats(userID, force = False):
# Get userID's token from tokens list # Get userID's token from tokens list
userToken = glob.tokens.getTokenFromUserID(userID) userToken = glob.tokens.getTokenFromUserID(userID)
if userToken is None or ((userToken.restricted or userToken.irc or userToken.tournament) and not force):
if userToken is None:
return bytes()
if (userToken.restricted == True or userToken.irc == True) and force == False:
return bytes() return bytes()
return packetHelper.buildPacket(packetIDs.server_userStats, return packetHelper.buildPacket(packetIDs.server_userStats,
@ -204,6 +201,7 @@ def createMatch(matchID):
match = glob.matches.matches[matchID] match = glob.matches.matches[matchID]
return packetHelper.buildPacket(packetIDs.server_newMatch, match.getMatchData()) return packetHelper.buildPacket(packetIDs.server_newMatch, match.getMatchData())
# TODO: Add match object argument to save some CPU
def updateMatch(matchID): def updateMatch(matchID):
# Make sure the match exists # Make sure the match exists
if matchID not in glob.matches.matches: if matchID not in glob.matches.matches:

View File

@ -1,8 +1,9 @@
"""Bancho user ranks""" """Bancho user ranks"""
NORMAL = 0 NORMAL = 0
PLAYER = 1 PLAYER = 1
BAT = 2
SUPPORTER = 4 SUPPORTER = 4
MOD = 6 MOD = 6
PEPPY = 8 PEPPY = 8
ADMIN = 16 ADMIN = 16
TOURNAMENTSTAFF = 32 TOURNAMENT_STAFF = 32

View File

@ -104,8 +104,10 @@ def handle(tornadoRequest):
userUtils.logIP(userID, requestIP) userUtils.logIP(userID, requestIP)
# Delete old tokens for that user and generate a new one # Delete old tokens for that user and generate a new one
glob.tokens.deleteOldTokens(userID) isTournament = "tourney" in osuVersion
responseToken = glob.tokens.addToken(userID, requestIP, timeOffset=timeOffset) if not isTournament:
glob.tokens.deleteOldTokens(userID)
responseToken = glob.tokens.addToken(userID, requestIP, timeOffset=timeOffset, tournament=isTournament)
responseTokenString = responseToken.token responseTokenString = responseToken.token
# Check restricted mode (and eventually send message) # Check restricted mode (and eventually send message)
@ -205,7 +207,7 @@ def handle(tornadoRequest):
if userUtils.getCountry(userID) == "XX": if userUtils.getCountry(userID) == "XX":
userUtils.setCountry(userID, countryLetters) userUtils.setCountry(userID, countryLetters)
# Send to everyone our userpanel if we are not restricted # Send to everyone our userpanel if we are not restricted or tournament
if not responseToken.restricted: if not responseToken.restricted:
glob.streams.broadcast("main", serverPackets.userPanel(userID)) glob.streams.broadcast("main", serverPackets.userPanel(userID))

View File

@ -0,0 +1,11 @@
from constants import clientPackets
from objects import glob
from helpers import chatHelper as chat
def handle(userToken, packetData):
packetData = clientPackets.tournamentJoinMatchChannel(packetData)
matchID = packetData["matchID"]
if matchID not in glob.matches.matches:
return
userToken.matchID = matchID
chat.joinChannel(token=userToken, channel="#multi_{}".format(matchID))

View File

@ -0,0 +1,11 @@
from constants import clientPackets
from objects import glob
from helpers import chatHelper as chat
def handle(userToken, packetData):
packetData = clientPackets.tournamentLeaveMatchChannel(packetData)
matchID = packetData["matchID"]
if matchID not in glob.matches.matches:
return
chat.partChannel(token=userToken, channel="#multi_{}".format(matchID))
userToken.matchID = 0

View File

@ -0,0 +1,10 @@
from constants import clientPackets
from constants import serverPackets
from objects import glob
def handle(userToken, packetData):
packetData = clientPackets.tournamentMatchInfoRequest(packetData)
matchID = packetData["matchID"]
if matchID not in glob.matches.matches:
return
userToken.enqueue(serverPackets.updateMatch(matchID))

View File

@ -51,6 +51,9 @@ from events import startSpectatingEvent
from events import stopSpectatingEvent from events import stopSpectatingEvent
from events import userPanelRequestEvent from events import userPanelRequestEvent
from events import userStatsRequestEvent from events import userStatsRequestEvent
from events import tournamentMatchInfoRequestEvent
from events import tournamentJoinMatchChannelEvent
from events import tournamentLeaveMatchChannelEvent
from helpers import packetHelper from helpers import packetHelper
from objects import glob from objects import glob
@ -156,6 +159,10 @@ class handler(SentryMixin, requestsManager.asyncRequestHandler):
packetIDs.client_matchFailed: handleEvent(matchFailedEvent), packetIDs.client_matchFailed: handleEvent(matchFailedEvent),
packetIDs.client_matchChangeTeam: handleEvent(matchChangeTeamEvent), packetIDs.client_matchChangeTeam: handleEvent(matchChangeTeamEvent),
packetIDs.client_invite: handleEvent(matchInviteEvent), packetIDs.client_invite: handleEvent(matchInviteEvent),
packetIDs.client_tournamentMatchInfoRequest: handleEvent(tournamentMatchInfoRequestEvent),
packetIDs.client_tournamentJoinMatchChannel: handleEvent(tournamentJoinMatchChannelEvent),
packetIDs.client_tournamentLeaveMatchChannel: handleEvent(tournamentLeaveMatchChannelEvent),
} }
# Packets processed if in restricted mode. # Packets processed if in restricted mode.

View File

@ -177,13 +177,17 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
userID = token.userID userID = token.userID
username = token.username username = token.username
# Make sure this is not a tournament client
if token.tournament:
raise exceptions.userTournamentException()
# Make sure the user is not in restricted mode # Make sure the user is not in restricted mode
if token.restricted: if token.restricted:
raise exceptions.userRestrictedException raise exceptions.userRestrictedException()
# Make sure the user is not silenced # Make sure the user is not silenced
if token.isSilenced(): if token.isSilenced():
raise exceptions.userSilencedException raise exceptions.userSilencedException()
# Determine internal name if needed # Determine internal name if needed
# (toclient is used clientwise for #multiplayer and #spectator channels) # (toclient is used clientwise for #multiplayer and #spectator channels)
@ -242,9 +246,13 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
if recipientToken is None: if recipientToken is None:
raise exceptions.userNotFoundException raise exceptions.userNotFoundException
# Make sure the recipient is not a tournament client
if recipientToken.tournament:
raise exceptions.userTournamentException()
# Make sure the recipient is not restricted or we are FokaBot # Make sure the recipient is not restricted or we are FokaBot
if recipientToken.restricted == True and fro.lower() != "fokabot": if recipientToken.restricted == True and fro.lower() != "fokabot":
raise exceptions.userRestrictedException raise exceptions.userRestrictedException()
# TODO: Make sure the recipient has not disabled PMs for non-friends or he's our friend # TODO: Make sure the recipient has not disabled PMs for non-friends or he's our friend
@ -290,6 +298,9 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
except exceptions.userRestrictedException: except exceptions.userRestrictedException:
log.warning("{} tried to send a message {}, but the recipient is in restricted mode".format(username, to)) log.warning("{} tried to send a message {}, but the recipient is in restricted mode".format(username, to))
return 404 return 404
except exceptions.userTournamentException:
log.warning("{} tried to send a message {}, but the recipient is a tournament client".format(username, to))
return 404
except exceptions.userNotFoundException: except exceptions.userNotFoundException:
log.warning("User not connected to IRC/Bancho") log.warning("User not connected to IRC/Bancho")
return 401 return 401

View File

@ -13,7 +13,7 @@ from objects import glob
class token: class token:
def __init__(self, userID, token_ = None, ip ="", irc = False, timeOffset = 0): def __init__(self, userID, token_ = None, ip ="", irc = False, timeOffset = 0, tournament = False):
""" """
Create a token object and set userID and token Create a token object and set userID and token
@ -36,6 +36,7 @@ class token:
self.timeOffset = timeOffset self.timeOffset = timeOffset
self.lock = threading.Lock() # Sync primitive self.lock = threading.Lock() # Sync primitive
self.streams = [] self.streams = []
self.tournament = tournament
# Default variables # Default variables
self.spectators = [] self.spectators = []

View File

@ -20,7 +20,7 @@ class tokenList:
""" """
self.tokens = {} self.tokens = {}
def addToken(self, userID, ip = "", irc = False, timeOffset=0): def addToken(self, userID, ip = "", irc = False, timeOffset=0, tournament=False):
""" """
Add a token object to tokens list Add a token object to tokens list
@ -28,7 +28,7 @@ class tokenList:
irc -- if True, set this token as IRC client irc -- if True, set this token as IRC client
return -- token object return -- token object
""" """
newToken = osuToken.token(userID, ip=ip, irc=irc, timeOffset=timeOffset) newToken = osuToken.token(userID, ip=ip, irc=irc, timeOffset=timeOffset, tournament=tournament)
self.tokens[newToken.token] = newToken self.tokens[newToken.token] = newToken
return newToken return newToken