.BANCHO. Add support for tournament client
This commit is contained in:
		@@ -143,3 +143,12 @@ def transferHost(stream):
 | 
			
		||||
 | 
			
		||||
def matchInvite(stream):
 | 
			
		||||
	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]])
 | 
			
		||||
@@ -88,4 +88,7 @@ class loginLockedException(Exception):
 | 
			
		||||
	pass
 | 
			
		||||
 | 
			
		||||
class unknownStreamException(Exception):
 | 
			
		||||
	pass
 | 
			
		||||
 | 
			
		||||
class userTournamentException(Exception):
 | 
			
		||||
	pass
 | 
			
		||||
@@ -74,7 +74,9 @@ server_channelInfoEnd = 89
 | 
			
		||||
client_matchChangePassword = 90
 | 
			
		||||
server_matchChangePassword = 91
 | 
			
		||||
server_silenceEnd = 92
 | 
			
		||||
client_specialMatchInfoRequest = 93
 | 
			
		||||
server_userSilenced = 94
 | 
			
		||||
server_userPresenceBundle = 96
 | 
			
		||||
client_userPanelRequest = 97
 | 
			
		||||
client_tournamentMatchInfoRequest = 93
 | 
			
		||||
client_tournamentJoinMatchChannel = 108
 | 
			
		||||
client_tournamentLeaveMatchChannel = 109
 | 
			
		||||
@@ -50,9 +50,10 @@ def mainMenuIcon(icon):
 | 
			
		||||
def userSupporterGMT(supporter, GMT):
 | 
			
		||||
	result = 1
 | 
			
		||||
	if supporter:
 | 
			
		||||
		result += 4
 | 
			
		||||
		result |= userRanks.SUPPORTER
 | 
			
		||||
	if GMT:
 | 
			
		||||
		result += 2
 | 
			
		||||
		result |= userRanks.BAT
 | 
			
		||||
		result |= userRanks.TOURNAMENT_STAFF
 | 
			
		||||
	return packetHelper.buildPacket(packetIDs.server_supporterGMT, [[result, dataTypes.UINT32]])
 | 
			
		||||
 | 
			
		||||
def friendList(userID):
 | 
			
		||||
@@ -78,9 +79,7 @@ def userLogout(userID):
 | 
			
		||||
def userPanel(userID, force = False):
 | 
			
		||||
	# Connected and restricted check
 | 
			
		||||
	userToken = glob.tokens.getTokenFromUserID(userID)
 | 
			
		||||
	if userToken is None:
 | 
			
		||||
		return bytes()
 | 
			
		||||
	if userToken.restricted == True and force == False:
 | 
			
		||||
	if userToken is None or ((userToken.restricted) and not force):
 | 
			
		||||
		return bytes()
 | 
			
		||||
 | 
			
		||||
	# Get user data
 | 
			
		||||
@@ -93,16 +92,17 @@ def userPanel(userID, force = False):
 | 
			
		||||
 | 
			
		||||
	# Get username color according to rank
 | 
			
		||||
	# Only admins and normal users are currently supported
 | 
			
		||||
	userRank = 0
 | 
			
		||||
	if username == "FokaBot":
 | 
			
		||||
		userRank = userRanks.MOD
 | 
			
		||||
		userRank |= userRanks.MOD
 | 
			
		||||
	elif userUtils.isInPrivilegeGroup(userID, "community manager"):
 | 
			
		||||
		userRank = userRanks.MOD
 | 
			
		||||
		userRank |= userRanks.MOD
 | 
			
		||||
	elif userUtils.isInPrivilegeGroup(userID, "developer"):
 | 
			
		||||
		userRank = userRanks.ADMIN
 | 
			
		||||
		userRank |= userRanks.ADMIN
 | 
			
		||||
	elif (userToken.privileges & privileges.USER_DONOR) > 0:
 | 
			
		||||
		userRank = userRanks.SUPPORTER
 | 
			
		||||
		userRank |= userRanks.SUPPORTER
 | 
			
		||||
	else:
 | 
			
		||||
		userRank = userRanks.NORMAL
 | 
			
		||||
		userRank |= userRanks.NORMAL
 | 
			
		||||
 | 
			
		||||
	return packetHelper.buildPacket(packetIDs.server_userPanel,
 | 
			
		||||
	[
 | 
			
		||||
@@ -120,10 +120,7 @@ def userPanel(userID, force = False):
 | 
			
		||||
def userStats(userID, force = False):
 | 
			
		||||
	# Get userID's token from tokens list
 | 
			
		||||
	userToken = glob.tokens.getTokenFromUserID(userID)
 | 
			
		||||
 | 
			
		||||
	if userToken is None:
 | 
			
		||||
		return bytes()
 | 
			
		||||
	if (userToken.restricted == True or userToken.irc == True) and force == False:
 | 
			
		||||
	if userToken is None or ((userToken.restricted or userToken.irc or userToken.tournament) and not force):
 | 
			
		||||
		return bytes()
 | 
			
		||||
 | 
			
		||||
	return packetHelper.buildPacket(packetIDs.server_userStats,
 | 
			
		||||
@@ -204,6 +201,7 @@ def createMatch(matchID):
 | 
			
		||||
	match = glob.matches.matches[matchID]
 | 
			
		||||
	return packetHelper.buildPacket(packetIDs.server_newMatch, match.getMatchData())
 | 
			
		||||
 | 
			
		||||
# TODO: Add match object argument to save some CPU
 | 
			
		||||
def updateMatch(matchID):
 | 
			
		||||
	# Make sure the match exists
 | 
			
		||||
	if matchID not in glob.matches.matches:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
"""Bancho user ranks"""
 | 
			
		||||
NORMAL			= 0
 | 
			
		||||
PLAYER			= 1
 | 
			
		||||
BAT				= 2
 | 
			
		||||
SUPPORTER		= 4
 | 
			
		||||
MOD				= 6
 | 
			
		||||
PEPPY			= 8
 | 
			
		||||
ADMIN			= 16
 | 
			
		||||
TOURNAMENTSTAFF = 32
 | 
			
		||||
TOURNAMENT_STAFF = 32
 | 
			
		||||
 
 | 
			
		||||
@@ -104,8 +104,10 @@ def handle(tornadoRequest):
 | 
			
		||||
		userUtils.logIP(userID, requestIP)
 | 
			
		||||
 | 
			
		||||
		# Delete old tokens for that user and generate a new one
 | 
			
		||||
		glob.tokens.deleteOldTokens(userID)
 | 
			
		||||
		responseToken = glob.tokens.addToken(userID, requestIP, timeOffset=timeOffset)
 | 
			
		||||
		isTournament = "tourney" in osuVersion
 | 
			
		||||
		if not isTournament:
 | 
			
		||||
			glob.tokens.deleteOldTokens(userID)
 | 
			
		||||
		responseToken = glob.tokens.addToken(userID, requestIP, timeOffset=timeOffset, tournament=isTournament)
 | 
			
		||||
		responseTokenString = responseToken.token
 | 
			
		||||
 | 
			
		||||
		# Check restricted mode (and eventually send message)
 | 
			
		||||
@@ -205,7 +207,7 @@ def handle(tornadoRequest):
 | 
			
		||||
		if userUtils.getCountry(userID) == "XX":
 | 
			
		||||
			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:
 | 
			
		||||
			glob.streams.broadcast("main", serverPackets.userPanel(userID))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								events/tournamentJoinMatchChannelEvent.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								events/tournamentJoinMatchChannelEvent.py
									
									
									
									
									
										Normal 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))
 | 
			
		||||
							
								
								
									
										11
									
								
								events/tournamentLeaveMatchChannelEvent.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								events/tournamentLeaveMatchChannelEvent.py
									
									
									
									
									
										Normal 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
 | 
			
		||||
							
								
								
									
										10
									
								
								events/tournamentMatchInfoRequestEvent.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								events/tournamentMatchInfoRequestEvent.py
									
									
									
									
									
										Normal 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))
 | 
			
		||||
@@ -51,6 +51,9 @@ from events import startSpectatingEvent
 | 
			
		||||
from events import stopSpectatingEvent
 | 
			
		||||
from events import userPanelRequestEvent
 | 
			
		||||
from events import userStatsRequestEvent
 | 
			
		||||
from events import tournamentMatchInfoRequestEvent
 | 
			
		||||
from events import tournamentJoinMatchChannelEvent
 | 
			
		||||
from events import tournamentLeaveMatchChannelEvent
 | 
			
		||||
from helpers import packetHelper
 | 
			
		||||
from objects import glob
 | 
			
		||||
 | 
			
		||||
@@ -156,6 +159,10 @@ class handler(SentryMixin, requestsManager.asyncRequestHandler):
 | 
			
		||||
							packetIDs.client_matchFailed: handleEvent(matchFailedEvent),
 | 
			
		||||
							packetIDs.client_matchChangeTeam: handleEvent(matchChangeTeamEvent),
 | 
			
		||||
							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.
 | 
			
		||||
 
 | 
			
		||||
@@ -177,13 +177,17 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
 | 
			
		||||
		userID = token.userID
 | 
			
		||||
		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
 | 
			
		||||
		if token.restricted:
 | 
			
		||||
			raise exceptions.userRestrictedException
 | 
			
		||||
			raise exceptions.userRestrictedException()
 | 
			
		||||
 | 
			
		||||
		# Make sure the user is not silenced
 | 
			
		||||
		if token.isSilenced():
 | 
			
		||||
			raise exceptions.userSilencedException
 | 
			
		||||
			raise exceptions.userSilencedException()
 | 
			
		||||
 | 
			
		||||
		# Determine internal name if needed
 | 
			
		||||
		# (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:
 | 
			
		||||
				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
 | 
			
		||||
			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
 | 
			
		||||
 | 
			
		||||
@@ -290,6 +298,9 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
 | 
			
		||||
	except exceptions.userRestrictedException:
 | 
			
		||||
		log.warning("{} tried to send a message {}, but the recipient is in restricted mode".format(username, to))
 | 
			
		||||
		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:
 | 
			
		||||
		log.warning("User not connected to IRC/Bancho")
 | 
			
		||||
		return 401
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ from objects import glob
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
@@ -36,6 +36,7 @@ class token:
 | 
			
		||||
		self.timeOffset = timeOffset
 | 
			
		||||
		self.lock = threading.Lock()	# Sync primitive
 | 
			
		||||
		self.streams = []
 | 
			
		||||
		self.tournament = tournament
 | 
			
		||||
 | 
			
		||||
		# Default variables
 | 
			
		||||
		self.spectators = []
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ class tokenList:
 | 
			
		||||
		"""
 | 
			
		||||
		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
 | 
			
		||||
 | 
			
		||||
@@ -28,7 +28,7 @@ class tokenList:
 | 
			
		||||
		irc -- if True, set this token as IRC client
 | 
			
		||||
		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
 | 
			
		||||
		return newToken
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user