Add submodules
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -3,3 +3,6 @@ config.ini
 | 
				
			|||||||
filters.txt
 | 
					filters.txt
 | 
				
			||||||
.data
 | 
					.data
 | 
				
			||||||
.idea
 | 
					.idea
 | 
				
			||||||
 | 
					common_funzia
 | 
				
			||||||
 | 
					common_refractor
 | 
				
			||||||
 | 
					common_memato
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					[submodule "common"]
 | 
				
			||||||
 | 
						path = common
 | 
				
			||||||
 | 
						url = git@git.zxq.co:ripple/ripple-python-common.git
 | 
				
			||||||
							
								
								
									
										1
									
								
								common
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								common
									
									
									
									
									
										Submodule
									
								
							 Submodule common added at 1d3a6a0020
									
								
							@@ -1,16 +0,0 @@
 | 
				
			|||||||
"""Contains user actions"""
 | 
					 | 
				
			||||||
IDLE 		= 0
 | 
					 | 
				
			||||||
AFK 		= 1
 | 
					 | 
				
			||||||
PLAYING 	= 2
 | 
					 | 
				
			||||||
EDITING 	= 3
 | 
					 | 
				
			||||||
MODDING 	= 4
 | 
					 | 
				
			||||||
MULTIPLAYER = 5
 | 
					 | 
				
			||||||
WATCHING 	= 6
 | 
					 | 
				
			||||||
UNKNOWN 	= 7
 | 
					 | 
				
			||||||
TESTING 	= 8
 | 
					 | 
				
			||||||
SUBMITTING 	= 9
 | 
					 | 
				
			||||||
PAUSED 		= 10
 | 
					 | 
				
			||||||
LOBBY 		= 11
 | 
					 | 
				
			||||||
MULTIPLAYING= 12
 | 
					 | 
				
			||||||
OSU_DIRECT 	= 13
 | 
					 | 
				
			||||||
NONE		= 14
 | 
					 | 
				
			||||||
@@ -1,9 +0,0 @@
 | 
				
			|||||||
"""Console colors"""
 | 
					 | 
				
			||||||
PINK 		= '\033[95m'
 | 
					 | 
				
			||||||
BLUE 		= '\033[94m'
 | 
					 | 
				
			||||||
GREEN 		= '\033[92m'
 | 
					 | 
				
			||||||
YELLOW 		= '\033[93m'
 | 
					 | 
				
			||||||
RED 		= '\033[91m'
 | 
					 | 
				
			||||||
ENDC 		= '\033[0m'
 | 
					 | 
				
			||||||
BOLD 		= '\033[1m'
 | 
					 | 
				
			||||||
UNDERLINE 	= '\033[4m'
 | 
					 | 
				
			||||||
@@ -1,17 +1,19 @@
 | 
				
			|||||||
from objects import fokabot
 | 
					 | 
				
			||||||
import random
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					 | 
				
			||||||
from helpers import userHelper
 | 
					 | 
				
			||||||
from helpers import systemHelper
 | 
					 | 
				
			||||||
import requests
 | 
					 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
from constants import mods
 | 
					import random
 | 
				
			||||||
from helpers import generalFunctions
 | 
					
 | 
				
			||||||
from helpers import logHelper as log
 | 
					import requests
 | 
				
			||||||
from constants import gameModes
 | 
					
 | 
				
			||||||
from constants import privileges
 | 
					from common import generalUtils
 | 
				
			||||||
 | 
					from common.constants import mods
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from common.ripple import userUtils
 | 
				
			||||||
 | 
					from constants import exceptions
 | 
				
			||||||
 | 
					from common.constants import gameModes
 | 
				
			||||||
 | 
					from common.constants import privileges
 | 
				
			||||||
 | 
					from constants import serverPackets
 | 
				
			||||||
 | 
					from helpers import systemHelper
 | 
				
			||||||
 | 
					from objects import fokabot
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
Commands callbacks
 | 
					Commands callbacks
 | 
				
			||||||
@@ -147,8 +149,8 @@ def silence(fro, chan, message):
 | 
				
			|||||||
	reason = ' '.join(message[3:])
 | 
						reason = ' '.join(message[3:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Get target user ID
 | 
						# Get target user ID
 | 
				
			||||||
	targetUserID = userHelper.getID(target)
 | 
						targetUserID = userUtils.getID(target)
 | 
				
			||||||
	userID = userHelper.getID(fro)
 | 
						userID = userUtils.getID(fro)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Make sure the user exists
 | 
						# Make sure the user exists
 | 
				
			||||||
	if not targetUserID:
 | 
						if not targetUserID:
 | 
				
			||||||
@@ -177,7 +179,7 @@ def silence(fro, chan, message):
 | 
				
			|||||||
		targetToken.silence(silenceTime, reason, userID)
 | 
							targetToken.silence(silenceTime, reason, userID)
 | 
				
			||||||
	else:
 | 
						else:
 | 
				
			||||||
		# User offline, silence user only in db
 | 
							# User offline, silence user only in db
 | 
				
			||||||
		userHelper.silence(targetUserID, silenceTime, reason, userID)
 | 
							userUtils.silence(targetUserID, silenceTime, reason, userID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Log message
 | 
						# Log message
 | 
				
			||||||
	msg = "{} has been silenced for the following reason: {}".format(target, reason)
 | 
						msg = "{} has been silenced for the following reason: {}".format(target, reason)
 | 
				
			||||||
@@ -190,8 +192,8 @@ def removeSilence(fro, chan, message):
 | 
				
			|||||||
	target = message[0].replace("_", " ")
 | 
						target = message[0].replace("_", " ")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Make sure the user exists
 | 
						# Make sure the user exists
 | 
				
			||||||
	targetUserID = userHelper.getID(target)
 | 
						targetUserID = userUtils.getID(target)
 | 
				
			||||||
	userID = userHelper.getID(fro)
 | 
						userID = userUtils.getID(fro)
 | 
				
			||||||
	if not targetUserID:
 | 
						if not targetUserID:
 | 
				
			||||||
		return "{}: user not found".format(target)
 | 
							return "{}: user not found".format(target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -202,7 +204,7 @@ def removeSilence(fro, chan, message):
 | 
				
			|||||||
		targetToken.silence(0, "", userID)
 | 
							targetToken.silence(0, "", userID)
 | 
				
			||||||
	else:
 | 
						else:
 | 
				
			||||||
		# user offline, remove islene ofnlt from db
 | 
							# user offline, remove islene ofnlt from db
 | 
				
			||||||
		userHelper.silence(targetUserID, 0, "", userID)
 | 
							userUtils.silence(targetUserID, 0, "", userID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return "{}'s silence reset".format(target)
 | 
						return "{}'s silence reset".format(target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -213,13 +215,13 @@ def ban(fro, chan, message):
 | 
				
			|||||||
	target = message[0].replace("_", " ")
 | 
						target = message[0].replace("_", " ")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Make sure the user exists
 | 
						# Make sure the user exists
 | 
				
			||||||
	targetUserID = userHelper.getID(target)
 | 
						targetUserID = userUtils.getID(target)
 | 
				
			||||||
	userID = userHelper.getID(fro)
 | 
						userID = userUtils.getID(fro)
 | 
				
			||||||
	if not targetUserID:
 | 
						if not targetUserID:
 | 
				
			||||||
		return "{}: user not found".format(target)
 | 
							return "{}: user not found".format(target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Set allowed to 0
 | 
						# Set allowed to 0
 | 
				
			||||||
	userHelper.ban(targetUserID)
 | 
						userUtils.ban(targetUserID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Send ban packet to the user if he's online
 | 
						# Send ban packet to the user if he's online
 | 
				
			||||||
	targetToken = glob.tokens.getTokenFromUsername(target)
 | 
						targetToken = glob.tokens.getTokenFromUsername(target)
 | 
				
			||||||
@@ -236,13 +238,13 @@ def unban(fro, chan, message):
 | 
				
			|||||||
	target = message[0].replace("_", " ")
 | 
						target = message[0].replace("_", " ")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Make sure the user exists
 | 
						# Make sure the user exists
 | 
				
			||||||
	targetUserID = userHelper.getID(target)
 | 
						targetUserID = userUtils.getID(target)
 | 
				
			||||||
	userID = userHelper.getID(fro)
 | 
						userID = userUtils.getID(fro)
 | 
				
			||||||
	if not targetUserID:
 | 
						if not targetUserID:
 | 
				
			||||||
		return "{}: user not found".format(target)
 | 
							return "{}: user not found".format(target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Set allowed to 1
 | 
						# Set allowed to 1
 | 
				
			||||||
	userHelper.unban(targetUserID)
 | 
						userUtils.unban(targetUserID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.rap(userID, "has unbanned {}".format(target), True)
 | 
						log.rap(userID, "has unbanned {}".format(target), True)
 | 
				
			||||||
	return "Welcome back {}!".format(target)
 | 
						return "Welcome back {}!".format(target)
 | 
				
			||||||
@@ -254,13 +256,13 @@ def restrict(fro, chan, message):
 | 
				
			|||||||
	target = message[0].replace("_", " ")
 | 
						target = message[0].replace("_", " ")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Make sure the user exists
 | 
						# Make sure the user exists
 | 
				
			||||||
	targetUserID = userHelper.getID(target)
 | 
						targetUserID = userUtils.getID(target)
 | 
				
			||||||
	userID = userHelper.getID(fro)
 | 
						userID = userUtils.getID(fro)
 | 
				
			||||||
	if not targetUserID:
 | 
						if not targetUserID:
 | 
				
			||||||
		return "{}: user not found".format(target)
 | 
							return "{}: user not found".format(target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Put this user in restricted mode
 | 
						# Put this user in restricted mode
 | 
				
			||||||
	userHelper.restrict(targetUserID)
 | 
						userUtils.restrict(targetUserID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Send restricted mode packet to this user if he's online
 | 
						# Send restricted mode packet to this user if he's online
 | 
				
			||||||
	targetToken = glob.tokens.getTokenFromUsername(target)
 | 
						targetToken = glob.tokens.getTokenFromUsername(target)
 | 
				
			||||||
@@ -277,13 +279,13 @@ def unrestrict(fro, chan, message):
 | 
				
			|||||||
	target = message[0].replace("_", " ")
 | 
						target = message[0].replace("_", " ")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Make sure the user exists
 | 
						# Make sure the user exists
 | 
				
			||||||
	targetUserID = userHelper.getID(target)
 | 
						targetUserID = userUtils.getID(target)
 | 
				
			||||||
	userID = userHelper.getID(fro)
 | 
						userID = userUtils.getID(fro)
 | 
				
			||||||
	if not targetUserID:
 | 
						if not targetUserID:
 | 
				
			||||||
		return "{}: user not found".format(target)
 | 
							return "{}: user not found".format(target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Set allowed to 1
 | 
						# Set allowed to 1
 | 
				
			||||||
	userHelper.unrestrict(targetUserID)
 | 
						userUtils.unrestrict(targetUserID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.rap(userID, "has removed restricted mode from {}".format(target), True)
 | 
						log.rap(userID, "has removed restricted mode from {}".format(target), True)
 | 
				
			||||||
	return "Welcome back {}!".format(target)
 | 
						return "Welcome back {}!".format(target)
 | 
				
			||||||
@@ -386,7 +388,7 @@ def getPPMessage(userID, just_data = False):
 | 
				
			|||||||
		currentAcc = token.tillerino[2]
 | 
							currentAcc = token.tillerino[2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Send request to LETS api
 | 
							# Send request to LETS api
 | 
				
			||||||
		resp = requests.get("http://127.0.0.1:5002/api/v1/pp?b={}&m={}&a={}".format(currentMap, currentMods, currentAcc), timeout=10).text
 | 
							resp = requests.get("http://127.0.0.1:5002/api/v1/pp?b={}&m={}".format(currentMap, currentMods, currentAcc), timeout=10).text
 | 
				
			||||||
		data = json.loads(resp)
 | 
							data = json.loads(resp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Make sure status is in response data
 | 
							# Make sure status is in response data
 | 
				
			||||||
@@ -405,7 +407,7 @@ def getPPMessage(userID, just_data = False):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		# Return response in chat
 | 
							# Return response in chat
 | 
				
			||||||
		# Song name and mods
 | 
							# Song name and mods
 | 
				
			||||||
		msg = "{song}{plus}{mods}  ".format(song=data["song_name"], plus="+" if currentMods > 0 else "", mods=generalFunctions.readableMods(currentMods))
 | 
							msg = "{song}{plus}{mods}  ".format(song=data["song_name"], plus="+" if currentMods > 0 else "", mods=generalUtils.readableMods(currentMods))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# PP values
 | 
							# PP values
 | 
				
			||||||
		if currentAcc == -1:
 | 
							if currentAcc == -1:
 | 
				
			||||||
@@ -415,9 +417,9 @@ def getPPMessage(userID, just_data = False):
 | 
				
			|||||||
		
 | 
							
 | 
				
			||||||
		originalAR = data["ar"]
 | 
							originalAR = data["ar"]
 | 
				
			||||||
		# calc new AR if HR/EZ is on
 | 
							# calc new AR if HR/EZ is on
 | 
				
			||||||
		if (currentMods & mods.Easy) > 0:
 | 
							if (currentMods & mods.EASY) > 0:
 | 
				
			||||||
			data["ar"] = max(0, data["ar"] / 2)
 | 
								data["ar"] = max(0, data["ar"] / 2)
 | 
				
			||||||
		if (currentMods & mods.HardRock) > 0:
 | 
							if (currentMods & mods.HARDROCK) > 0:
 | 
				
			||||||
			data["ar"] = min(10, data["ar"] * 1.4)
 | 
								data["ar"] = min(10, data["ar"] * 1.4)
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		arstr = " ({})".format(originalAR) if originalAR != data["ar"] else ""
 | 
							arstr = " ({})".format(originalAR) if originalAR != data["ar"] else ""
 | 
				
			||||||
@@ -433,10 +435,10 @@ def getPPMessage(userID, just_data = False):
 | 
				
			|||||||
	except exceptions.apiException:
 | 
						except exceptions.apiException:
 | 
				
			||||||
		# API error
 | 
							# API error
 | 
				
			||||||
		return "Unknown error in LETS API call. Please tell this to a dev."
 | 
							return "Unknown error in LETS API call. Please tell this to a dev."
 | 
				
			||||||
	except:
 | 
						#except:
 | 
				
			||||||
		# Unknown exception
 | 
							# Unknown exception
 | 
				
			||||||
		# TODO: print exception
 | 
							# TODO: print exception
 | 
				
			||||||
		return False
 | 
						#	return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def tillerinoNp(fro, chan, message):
 | 
					def tillerinoNp(fro, chan, message):
 | 
				
			||||||
	try:
 | 
						try:
 | 
				
			||||||
@@ -455,15 +457,15 @@ def tillerinoNp(fro, chan, message):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		modsEnum = 0
 | 
							modsEnum = 0
 | 
				
			||||||
		mapping = {
 | 
							mapping = {
 | 
				
			||||||
			"-Easy": mods.Easy,
 | 
								"-Easy": mods.EASY,
 | 
				
			||||||
			"-NoFail": mods.NoFail,
 | 
								"-NoFail": mods.NOFAIL,
 | 
				
			||||||
			"+Hidden": mods.Hidden,
 | 
								"+Hidden": mods.HIDDEN,
 | 
				
			||||||
			"+HardRock": mods.HardRock,
 | 
								"+HardRock": mods.HARDROCK,
 | 
				
			||||||
			"+Nightcore": mods.Nightcore,
 | 
								"+Nightcore": mods.NIGHTCORE,
 | 
				
			||||||
			"+DoubleTime": mods.DoubleTime,
 | 
								"+DoubleTime": mods.DOUBLETIME,
 | 
				
			||||||
			"-HalfTime": mods.HalfTime,
 | 
								"-HalfTime": mods.HALFTIME,
 | 
				
			||||||
			"+Flashlight": mods.Flashlight,
 | 
								"+Flashlight": mods.FLASHLIGHT,
 | 
				
			||||||
			"-SpunOut": mods.SpunOut
 | 
								"-SpunOut": mods.SPUNOUT
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if playWatch:
 | 
							if playWatch:
 | 
				
			||||||
@@ -513,23 +515,23 @@ def tillerinoMods(fro, chan, message):
 | 
				
			|||||||
				modsEnum = 0
 | 
									modsEnum = 0
 | 
				
			||||||
				break
 | 
									break
 | 
				
			||||||
			elif i == "NF":
 | 
								elif i == "NF":
 | 
				
			||||||
				modsEnum += mods.NoFail
 | 
									modsEnum += mods.NOFAIL
 | 
				
			||||||
			elif i == "EZ":
 | 
								elif i == "EZ":
 | 
				
			||||||
				modsEnum += mods.Easy
 | 
									modsEnum += mods.EASY
 | 
				
			||||||
			elif i == "HD":
 | 
								elif i == "HD":
 | 
				
			||||||
				modsEnum += mods.Hidden
 | 
									modsEnum += mods.HIDDEN
 | 
				
			||||||
			elif i == "HR":
 | 
								elif i == "HR":
 | 
				
			||||||
				modsEnum += mods.HardRock
 | 
									modsEnum += mods.HARDROCK
 | 
				
			||||||
			elif i == "DT":
 | 
								elif i == "DT":
 | 
				
			||||||
				modsEnum += mods.DoubleTime
 | 
									modsEnum += mods.DOUBLETIME
 | 
				
			||||||
			elif i == "HT":
 | 
								elif i == "HT":
 | 
				
			||||||
				modsEnum += mods.HalfTime
 | 
									modsEnum += mods.HALFTIME
 | 
				
			||||||
			elif i == "NC":
 | 
								elif i == "NC":
 | 
				
			||||||
				modsEnum += mods.Nightcore
 | 
									modsEnum += mods.NIGHTCORE
 | 
				
			||||||
			elif i == "FL":
 | 
								elif i == "FL":
 | 
				
			||||||
				modsEnum += mods.Flashlight
 | 
									modsEnum += mods.FLASHLIGHT
 | 
				
			||||||
			elif i == "SO":
 | 
								elif i == "SO":
 | 
				
			||||||
				modsEnum += mods.SpunOut
 | 
									modsEnum += mods.SPUNOUT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Set mods
 | 
							# Set mods
 | 
				
			||||||
		token.tillerino[1] = modsEnum
 | 
							token.tillerino[1] = modsEnum
 | 
				
			||||||
@@ -582,22 +584,22 @@ def tillerinoLast(fro, chan, message):
 | 
				
			|||||||
			return False
 | 
								return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		diffString = "difficulty_{}".format(gameModes.getGameModeForDB(data["play_mode"]))
 | 
							diffString = "difficulty_{}".format(gameModes.getGameModeForDB(data["play_mode"]))
 | 
				
			||||||
		rank = generalFunctions.getRank(data["play_mode"], data["mods"], data["accuracy"],
 | 
							rank = generalUtils.getRank(data["play_mode"], data["mods"], data["accuracy"],
 | 
				
			||||||
										data["300_count"], data["100_count"], data["50_count"], data["misses_count"])
 | 
														data["300_count"], data["100_count"], data["50_count"], data["misses_count"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ifPlayer = "{0} | ".format(fro) if chan != "FokaBot" else ""
 | 
							ifPlayer = "{0} | ".format(fro) if chan != "FokaBot" else ""
 | 
				
			||||||
		ifFc = " (FC)" if data["max_combo"] == data["fc"] else " {0}x/{1}x".format(data["max_combo"], data["fc"])
 | 
							ifFc = " (FC)" if data["max_combo"] == data["fc"] else " {0}x/{1}x".format(data["max_combo"], data["fc"])
 | 
				
			||||||
		beatmapLink = "[http://osu.ppy.sh/b/{1} {0}]".format(data["sn"], data["bid"])
 | 
							beatmapLink = "[http://osu.ppy.sh/b/{1} {0}]".format(data["sn"], data["bid"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		hasPP = data["play_mode"] == gameModes.std or data["play_mode"] == gameModes.mania
 | 
							hasPP = data["play_mode"] == gameModes.STD or data["play_mode"] == gameModes.MANIA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		msg = ifPlayer
 | 
							msg = ifPlayer
 | 
				
			||||||
		msg += beatmapLink
 | 
							msg += beatmapLink
 | 
				
			||||||
		if data["play_mode"] != gameModes.std:
 | 
							if data["play_mode"] != gameModes.STD:
 | 
				
			||||||
			msg += " <{0}>".format(gameModes.getGameModeForPrinting(data["play_mode"]))
 | 
								msg += " <{0}>".format(gameModes.getGameModeForPrinting(data["play_mode"]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if data["mods"]:
 | 
							if data["mods"]:
 | 
				
			||||||
			msg += ' +' + generalFunctions.readableMods(data["mods"])
 | 
								msg += ' +' + generalUtils.readableMods(data["mods"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if not hasPP:
 | 
							if not hasPP:
 | 
				
			||||||
			msg += " | {0:,}".format(data["score"])
 | 
								msg += " | {0:,}".format(data["score"])
 | 
				
			||||||
@@ -657,9 +659,9 @@ def pp(fro, chan, message):
 | 
				
			|||||||
		return False
 | 
							return False
 | 
				
			||||||
	if gameMode is None:
 | 
						if gameMode is None:
 | 
				
			||||||
		gameMode = token.gameMode
 | 
							gameMode = token.gameMode
 | 
				
			||||||
	if gameMode == gameModes.taiko or gameMode == gameModes.ctb:
 | 
						if gameMode == gameModes.TAIKO or gameMode == gameModes.CTB:
 | 
				
			||||||
		return "PP for your current game mode is not supported yet."
 | 
							return "PP for your current game mode is not supported yet."
 | 
				
			||||||
	pp = userHelper.getPP(token.userID, gameMode)
 | 
						pp = userUtils.getPP(token.userID, gameMode)
 | 
				
			||||||
	return "You have {:,} pp".format(pp)
 | 
						return "You have {:,} pp".format(pp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,36 +0,0 @@
 | 
				
			|||||||
std 	= 0
 | 
					 | 
				
			||||||
taiko 	= 1
 | 
					 | 
				
			||||||
ctb 	= 2
 | 
					 | 
				
			||||||
mania 	= 3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getGameModeForDB(gameMode):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Convert a gamemode number to string for database table/column
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	gameMode -- gameMode int or variable (ex: gameMode.std)
 | 
					 | 
				
			||||||
	return -- game mode readable string for db
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	if gameMode == std:
 | 
					 | 
				
			||||||
		return "std"
 | 
					 | 
				
			||||||
	elif gameMode == taiko:
 | 
					 | 
				
			||||||
		return "taiko"
 | 
					 | 
				
			||||||
	elif gameMode == ctb:
 | 
					 | 
				
			||||||
		return "ctb"
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		return "mania"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getGameModeForPrinting(gameMode):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Convert a gamemode number to string for showing to a user (e.g. !last)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	gameMode -- gameMode int or variable (ex: gameMode.std)
 | 
					 | 
				
			||||||
	return -- game mode readable string for a human
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	if gameMode == std:
 | 
					 | 
				
			||||||
		return "osu!"
 | 
					 | 
				
			||||||
	elif gameMode == taiko:
 | 
					 | 
				
			||||||
		return "Taiko"
 | 
					 | 
				
			||||||
	elif gameMode == ctb:
 | 
					 | 
				
			||||||
		return "CatchTheBeat"
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		return "osu!mania"
 | 
					 | 
				
			||||||
@@ -1,30 +0,0 @@
 | 
				
			|||||||
Nomod       = 0
 | 
					 | 
				
			||||||
NoFail      = 1
 | 
					 | 
				
			||||||
Easy        = 2
 | 
					 | 
				
			||||||
NoVideo     = 4
 | 
					 | 
				
			||||||
Hidden      = 8
 | 
					 | 
				
			||||||
HardRock    = 16
 | 
					 | 
				
			||||||
SuddenDeath = 32
 | 
					 | 
				
			||||||
DoubleTime  = 64
 | 
					 | 
				
			||||||
Relax       = 128
 | 
					 | 
				
			||||||
HalfTime    = 256
 | 
					 | 
				
			||||||
Nightcore   = 512
 | 
					 | 
				
			||||||
Flashlight  = 1024
 | 
					 | 
				
			||||||
Autoplay    = 2048
 | 
					 | 
				
			||||||
SpunOut     = 4096
 | 
					 | 
				
			||||||
Relax2      = 8192
 | 
					 | 
				
			||||||
Perfect     = 16384
 | 
					 | 
				
			||||||
Key4        = 32768
 | 
					 | 
				
			||||||
Key5        = 65536
 | 
					 | 
				
			||||||
Key6        = 131072
 | 
					 | 
				
			||||||
Key7        = 262144
 | 
					 | 
				
			||||||
Key8        = 524288
 | 
					 | 
				
			||||||
keyMod      = 1015808
 | 
					 | 
				
			||||||
FadeIn      = 1048576
 | 
					 | 
				
			||||||
Random      = 2097152
 | 
					 | 
				
			||||||
LastMod     = 4194304
 | 
					 | 
				
			||||||
Key9        = 16777216
 | 
					 | 
				
			||||||
Key10       = 33554432
 | 
					 | 
				
			||||||
Key1        = 67108864
 | 
					 | 
				
			||||||
Key3        = 134217728
 | 
					 | 
				
			||||||
Key2        = 268435456
 | 
					 | 
				
			||||||
@@ -1,21 +0,0 @@
 | 
				
			|||||||
USER_PUBLIC = 1
 | 
					 | 
				
			||||||
USER_NORMAL = 2 << 0
 | 
					 | 
				
			||||||
USER_DONOR = 2 << 1
 | 
					 | 
				
			||||||
ADMIN_ACCESS_RAP = 2 << 2
 | 
					 | 
				
			||||||
ADMIN_MANAGE_USERS = 2 << 3
 | 
					 | 
				
			||||||
ADMIN_BAN_USERS = 2 << 4
 | 
					 | 
				
			||||||
ADMIN_SILENCE_USERS = 2 << 5
 | 
					 | 
				
			||||||
ADMIN_WIPE_USERS = 2 << 6
 | 
					 | 
				
			||||||
ADMIN_MANAGE_BEATMAPS = 2 << 7
 | 
					 | 
				
			||||||
ADMIN_MANAGE_SERVERS = 2 << 8
 | 
					 | 
				
			||||||
ADMIN_MANAGE_SETTINGS = 2 << 9
 | 
					 | 
				
			||||||
ADMIN_MANAGE_BETAKEYS = 2 << 10
 | 
					 | 
				
			||||||
ADMIN_MANAGE_REPORTS = 2 << 11
 | 
					 | 
				
			||||||
ADMIN_MANAGE_DOCS = 2 << 12
 | 
					 | 
				
			||||||
ADMIN_MANAGE_BADGES = 2 << 13
 | 
					 | 
				
			||||||
ADMIN_VIEW_RAP_LOGS = 2 << 14
 | 
					 | 
				
			||||||
ADMIN_MANAGE_PRIVILEGES = 2 << 15
 | 
					 | 
				
			||||||
ADMIN_SEND_ALERTS = 2 << 16
 | 
					 | 
				
			||||||
ADMIN_CHAT_MOD = 2 << 17
 | 
					 | 
				
			||||||
ADMIN_KICK_USERS = 2 << 18
 | 
					 | 
				
			||||||
USER_PENDING_VERIFICATION = 2 << 19
 | 
					 | 
				
			||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
""" Contains functions used to write specific server packets to byte streams """
 | 
					""" Contains functions used to write specific server packets to byte streams """
 | 
				
			||||||
from helpers import packetHelper
 | 
					from common.constants import privileges
 | 
				
			||||||
 | 
					from common.ripple import userUtils
 | 
				
			||||||
from constants import dataTypes
 | 
					from constants import dataTypes
 | 
				
			||||||
from helpers import userHelper
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from constants import userRanks
 | 
					 | 
				
			||||||
from constants import packetIDs
 | 
					from constants import packetIDs
 | 
				
			||||||
from constants import privileges
 | 
					from constants import userRanks
 | 
				
			||||||
 | 
					from helpers import packetHelper
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
""" Login errors packets """
 | 
					""" Login errors packets """
 | 
				
			||||||
def loginFailed():
 | 
					def loginFailed():
 | 
				
			||||||
@@ -56,7 +56,7 @@ def userSupporterGMT(supporter, GMT):
 | 
				
			|||||||
	return packetHelper.buildPacket(packetIDs.server_supporterGMT, [[result, dataTypes.UINT32]])
 | 
						return packetHelper.buildPacket(packetIDs.server_supporterGMT, [[result, dataTypes.UINT32]])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def friendList(userID):
 | 
					def friendList(userID):
 | 
				
			||||||
	friends = userHelper.getFriendList(userID)
 | 
						friends = userUtils.getFriendList(userID)
 | 
				
			||||||
	return packetHelper.buildPacket(packetIDs.server_friendsList, [[friends, dataTypes.INT_LIST]])
 | 
						return packetHelper.buildPacket(packetIDs.server_friendsList, [[friends, dataTypes.INT_LIST]])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def onlineUsers():
 | 
					def onlineUsers():
 | 
				
			||||||
@@ -95,9 +95,9 @@ def userPanel(userID, force = False):
 | 
				
			|||||||
	# Only admins and normal users are currently supported
 | 
						# Only admins and normal users are currently supported
 | 
				
			||||||
	if username == "FokaBot":
 | 
						if username == "FokaBot":
 | 
				
			||||||
		userRank = userRanks.MOD
 | 
							userRank = userRanks.MOD
 | 
				
			||||||
	elif userHelper.isInPrivilegeGroup(userID, "community manager"):
 | 
						elif userUtils.isInPrivilegeGroup(userID, "community manager"):
 | 
				
			||||||
		userRank = userRanks.MOD
 | 
							userRank = userRanks.MOD
 | 
				
			||||||
	elif userHelper.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
 | 
				
			||||||
@@ -150,7 +150,7 @@ def sendMessage(fro, to, message):
 | 
				
			|||||||
		[fro, dataTypes.STRING],
 | 
							[fro, dataTypes.STRING],
 | 
				
			||||||
		[message, dataTypes.STRING],
 | 
							[message, dataTypes.STRING],
 | 
				
			||||||
		[to, dataTypes.STRING],
 | 
							[to, dataTypes.STRING],
 | 
				
			||||||
		[userHelper.getID(fro), dataTypes.SINT32]
 | 
							[userUtils.getID(fro), dataTypes.SINT32]
 | 
				
			||||||
	])
 | 
						])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def channelJoinSuccess(userID, chan):
 | 
					def channelJoinSuccess(userID, chan):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,8 @@
 | 
				
			|||||||
from objects import glob
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					from constants import exceptions
 | 
				
			||||||
from helpers import logHelper as log
 | 
					from constants import serverPackets
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, _):
 | 
					def handle(userToken, _):
 | 
				
			||||||
	# get usertoken data
 | 
						# get usertoken data
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,10 @@
 | 
				
			|||||||
from objects import glob
 | 
					from common.constants import actions
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from common.ripple import userUtils
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from constants import serverPackets
 | 
					from constants import serverPackets
 | 
				
			||||||
from helpers import userHelper
 | 
					from objects import glob
 | 
				
			||||||
from helpers import logHelper as log
 | 
					
 | 
				
			||||||
from constants import actions
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	# Get usertoken data
 | 
						# Get usertoken data
 | 
				
			||||||
@@ -11,13 +12,13 @@ def handle(userToken, packetData):
 | 
				
			|||||||
	username = userToken.username
 | 
						username = userToken.username
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Make sure we are not banned
 | 
						# Make sure we are not banned
 | 
				
			||||||
	if userHelper.isBanned(userID):
 | 
						if userUtils.isBanned(userID):
 | 
				
			||||||
		userToken.enqueue(serverPackets.loginBanned())
 | 
							userToken.enqueue(serverPackets.loginBanned())
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Send restricted message if needed
 | 
						# Send restricted message if needed
 | 
				
			||||||
	if not userToken.restricted:
 | 
						if not userToken.restricted:
 | 
				
			||||||
		if userHelper.isRestricted(userID):
 | 
							if userUtils.isRestricted(userID):
 | 
				
			||||||
			userToken.setRestricted()
 | 
								userToken.setRestricted()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Change action packet
 | 
						# Change action packet
 | 
				
			||||||
@@ -34,7 +35,7 @@ if userToken.matchID != -1 and userToken.actionID != actions.MULTIPLAYING and us
 | 
				
			|||||||
		'''
 | 
							'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Update cached stats if our pp changedm if we've just submitted a score or we've changed gameMode
 | 
						# Update cached stats if our pp changedm if we've just submitted a score or we've changed gameMode
 | 
				
			||||||
	if (userToken.actionID == actions.PLAYING or userToken.actionID == actions.MULTIPLAYING) or (userToken.pp != userHelper.getPP(userID, userToken.gameMode)) or (userToken.gameMode != packetData["gameMode"]):
 | 
						if (userToken.actionID == actions.PLAYING or userToken.actionID == actions.MULTIPLAYING) or (userToken.pp != userUtils.getPP(userID, userToken.gameMode)) or (userToken.gameMode != packetData["gameMode"]):
 | 
				
			||||||
		# Always update game mode, or we'll cache stats from the wrong game mode if we've changed it
 | 
							# Always update game mode, or we'll cache stats from the wrong game mode if we've changed it
 | 
				
			||||||
		userToken.gameMode = packetData["gameMode"]
 | 
							userToken.gameMode = packetData["gameMode"]
 | 
				
			||||||
		userToken.updateCachedStats()
 | 
							userToken.updateCachedStats()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,8 @@
 | 
				
			|||||||
from objects import glob
 | 
					from common.constants import mods
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from constants import matchModModes
 | 
					from constants import matchModModes
 | 
				
			||||||
from constants import mods
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	# Get token data
 | 
						# Get token data
 | 
				
			||||||
@@ -22,13 +23,13 @@ def handle(userToken, packetData):
 | 
				
			|||||||
		# Host can set global DT/HT
 | 
							# Host can set global DT/HT
 | 
				
			||||||
		if userID == match.hostUserID:
 | 
							if userID == match.hostUserID:
 | 
				
			||||||
			# If host has selected DT/HT and Freemod is enabled, set DT/HT as match mod
 | 
								# If host has selected DT/HT and Freemod is enabled, set DT/HT as match mod
 | 
				
			||||||
			if (packetData["mods"] & mods.DoubleTime) > 0:
 | 
								if (packetData["mods"] & mods.DOUBLETIME) > 0:
 | 
				
			||||||
				match.changeMatchMods(mods.DoubleTime)
 | 
									match.changeMatchMods(mods.DOUBLETIME)
 | 
				
			||||||
				# Nightcore
 | 
									# Nightcore
 | 
				
			||||||
				if (packetData["mods"] & mods.Nightcore) > 0:
 | 
									if (packetData["mods"] & mods.NIGHTCORE) > 0:
 | 
				
			||||||
					match.changeMatchMods(match.mods+mods.Nightcore)
 | 
										match.changeMatchMods(match.mods + mods.NIGHTCORE)
 | 
				
			||||||
			elif (packetData["mods"] & mods.HalfTime) > 0:
 | 
								elif (packetData["mods"] & mods.HALFTIME) > 0:
 | 
				
			||||||
				match.changeMatchMods(mods.HalfTime)
 | 
									match.changeMatchMods(mods.HALFTIME)
 | 
				
			||||||
			else:
 | 
								else:
 | 
				
			||||||
				# No DT/HT, set global mods to 0 (we are in freemod mode)
 | 
									# No DT/HT, set global mods to 0 (we are in freemod mode)
 | 
				
			||||||
				match.changeMatchMods(0)
 | 
									match.changeMatchMods(0)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
from objects import glob
 | 
					import random
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common import generalUtils
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from constants import matchModModes
 | 
					from constants import matchModModes
 | 
				
			||||||
import random
 | 
					 | 
				
			||||||
from constants import matchTeamTypes
 | 
					from constants import matchTeamTypes
 | 
				
			||||||
from constants import matchTeams
 | 
					from constants import matchTeams
 | 
				
			||||||
from constants import slotStatuses
 | 
					from constants import slotStatuses
 | 
				
			||||||
from helpers import logHelper as log
 | 
					from objects import glob
 | 
				
			||||||
from helpers import generalFunctions
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	# Read new settings
 | 
						# Read new settings
 | 
				
			||||||
@@ -59,7 +61,7 @@ def handle(userToken, packetData):
 | 
				
			|||||||
	# Update match settings
 | 
						# Update match settings
 | 
				
			||||||
	match.inProgress = packetData["inProgress"]
 | 
						match.inProgress = packetData["inProgress"]
 | 
				
			||||||
	if packetData["matchPassword"] != "":
 | 
						if packetData["matchPassword"] != "":
 | 
				
			||||||
		match.matchPassword = generalFunctions.stringMd5(packetData["matchPassword"])
 | 
							match.matchPassword = generalUtils.stringMd5(packetData["matchPassword"])
 | 
				
			||||||
	else:
 | 
						else:
 | 
				
			||||||
		match.matchPassword = ""
 | 
							match.matchPassword = ""
 | 
				
			||||||
	match.beatmapName = packetData["beatmapName"]
 | 
						match.beatmapName = packetData["beatmapName"]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,10 @@
 | 
				
			|||||||
from constants import serverPackets
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from events import joinMatchEvent
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					from constants import exceptions
 | 
				
			||||||
from helpers import logHelper as log
 | 
					from constants import serverPackets
 | 
				
			||||||
 | 
					from events import joinMatchEvent
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	try:
 | 
						try:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,12 @@
 | 
				
			|||||||
from helpers import userHelper
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from common.ripple import userUtils
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from helpers import logHelper as log
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	# Friend add packet
 | 
						# Friend add packet
 | 
				
			||||||
	packetData = clientPackets.addRemoveFriend(packetData)
 | 
						packetData = clientPackets.addRemoveFriend(packetData)
 | 
				
			||||||
	userHelper.addFriend(userToken.userID, packetData["friendID"])
 | 
						userUtils.addFriend(userToken.userID, packetData["friendID"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Console output
 | 
						# Console output
 | 
				
			||||||
	log.info("{} have added {} to their friends".format(userToken.username, str(packetData["friendID"])))
 | 
						log.info("{} have added {} to their friends".format(userToken.username, str(packetData["friendID"])))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,12 @@
 | 
				
			|||||||
from helpers import userHelper
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from common.ripple import userUtils
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from helpers import logHelper as log
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	# Friend remove packet
 | 
						# Friend remove packet
 | 
				
			||||||
	packetData = clientPackets.addRemoveFriend(packetData)
 | 
						packetData = clientPackets.addRemoveFriend(packetData)
 | 
				
			||||||
	userHelper.removeFriend(userToken.userID, packetData["friendID"])
 | 
						userUtils.removeFriend(userToken.userID, packetData["friendID"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Console output
 | 
						# Console output
 | 
				
			||||||
	log.info("{} have removed {} from their friends".format(userToken.username, str(packetData["friendID"])))
 | 
						log.info("{} have removed {} from their friends".format(userToken.username, str(packetData["friendID"])))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from constants import serverPackets
 | 
					from constants import serverPackets
 | 
				
			||||||
from objects import glob
 | 
					from objects import glob
 | 
				
			||||||
from helpers import logHelper as log
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, _):
 | 
					def handle(userToken, _):
 | 
				
			||||||
	# Get userToken data
 | 
						# Get userToken data
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
 | 
					from common import generalUtils
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					from constants import exceptions
 | 
				
			||||||
from helpers import logHelper as log
 | 
					from constants import serverPackets
 | 
				
			||||||
from helpers import chatHelper as chat
 | 
					from helpers import chatHelper as chat
 | 
				
			||||||
from helpers import generalFunctions
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	# read packet data
 | 
						# read packet data
 | 
				
			||||||
@@ -34,7 +35,7 @@ def joinMatch(userToken, matchID, password, isPasswordHashed = False):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		# Hash password if needed
 | 
							# Hash password if needed
 | 
				
			||||||
		if isPasswordHashed == False and password != "":
 | 
							if isPasswordHashed == False and password != "":
 | 
				
			||||||
			password = generalFunctions.stringMd5(password)
 | 
								password = generalUtils.stringMd5(password)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Check password
 | 
							# Check password
 | 
				
			||||||
		# TODO: Admins can enter every match
 | 
							# TODO: Admins can enter every match
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,17 @@
 | 
				
			|||||||
from helpers import userHelper
 | 
					 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from helpers import locationHelper
 | 
					 | 
				
			||||||
from helpers import countryHelper
 | 
					 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import traceback
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
from helpers import chatHelper as chat
 | 
					 | 
				
			||||||
from constants import privileges
 | 
					 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					import traceback
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.constants import privileges
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from common.ripple import userUtils
 | 
				
			||||||
 | 
					from constants import exceptions
 | 
				
			||||||
 | 
					from constants import serverPackets
 | 
				
			||||||
 | 
					from helpers import chatHelper as chat
 | 
				
			||||||
 | 
					from helpers import countryHelper
 | 
				
			||||||
 | 
					from helpers import locationHelper
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(tornadoRequest):
 | 
					def handle(tornadoRequest):
 | 
				
			||||||
	# Data to return
 | 
						# Data to return
 | 
				
			||||||
@@ -51,24 +53,24 @@ def handle(tornadoRequest):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		# Try to get the ID from username
 | 
							# Try to get the ID from username
 | 
				
			||||||
		username = str(loginData[0])
 | 
							username = str(loginData[0])
 | 
				
			||||||
		userID = userHelper.getID(username)
 | 
							userID = userUtils.getID(username)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if not userID:
 | 
							if not userID:
 | 
				
			||||||
			# Invalid username
 | 
								# Invalid username
 | 
				
			||||||
			raise exceptions.loginFailedException()
 | 
								raise exceptions.loginFailedException()
 | 
				
			||||||
		if not userHelper.checkLogin(userID, loginData[1]):
 | 
							if not userUtils.checkLogin(userID, loginData[1]):
 | 
				
			||||||
			# Invalid password
 | 
								# Invalid password
 | 
				
			||||||
			raise exceptions.loginFailedException()
 | 
								raise exceptions.loginFailedException()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Make sure we are not banned or locked
 | 
							# Make sure we are not banned or locked
 | 
				
			||||||
		priv = userHelper.getPrivileges(userID)
 | 
							priv = userUtils.getPrivileges(userID)
 | 
				
			||||||
		if userHelper.isBanned(userID) == True and priv & privileges.USER_PENDING_VERIFICATION == 0:
 | 
							if userUtils.isBanned(userID) == True and priv & privileges.USER_PENDING_VERIFICATION == 0:
 | 
				
			||||||
			raise exceptions.loginBannedException()
 | 
								raise exceptions.loginBannedException()
 | 
				
			||||||
		if userHelper.isLocked(userID) == True and priv & privileges.USER_PENDING_VERIFICATION == 0:
 | 
							if userUtils.isLocked(userID) == True and priv & privileges.USER_PENDING_VERIFICATION == 0:
 | 
				
			||||||
			raise exceptions.loginLockedException()
 | 
								raise exceptions.loginLockedException()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# 2FA check
 | 
							# 2FA check
 | 
				
			||||||
		if userHelper.check2FA(userID, requestIP):
 | 
							if userUtils.check2FA(userID, requestIP):
 | 
				
			||||||
			log.warning("Need 2FA check for user {}".format(loginData[0]))
 | 
								log.warning("Need 2FA check for user {}".format(loginData[0]))
 | 
				
			||||||
			raise exceptions.need2FAException()
 | 
								raise exceptions.need2FAException()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -76,8 +78,8 @@ def handle(tornadoRequest):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		# Verify this user (if pending activation)
 | 
							# Verify this user (if pending activation)
 | 
				
			||||||
		firstLogin = False
 | 
							firstLogin = False
 | 
				
			||||||
		if priv & privileges.USER_PENDING_VERIFICATION > 0 or userHelper.hasVerifiedHardware(userID) == False:
 | 
							if priv & privileges.USER_PENDING_VERIFICATION > 0 or userUtils.hasVerifiedHardware(userID) == False:
 | 
				
			||||||
			if userHelper.verifyUser(userID, clientData):
 | 
								if userUtils.verifyUser(userID, clientData):
 | 
				
			||||||
				# Valid account
 | 
									# Valid account
 | 
				
			||||||
				log.info("Account {} verified successfully!".format(userID))
 | 
									log.info("Account {} verified successfully!".format(userID))
 | 
				
			||||||
				glob.verifiedCache[str(userID)] = 1
 | 
									glob.verifiedCache[str(userID)] = 1
 | 
				
			||||||
@@ -90,7 +92,7 @@ def handle(tornadoRequest):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Save HWID in db for multiaccount detection
 | 
							# Save HWID in db for multiaccount detection
 | 
				
			||||||
		hwAllowed = userHelper.logHardware(userID, clientData, firstLogin)
 | 
							hwAllowed = userUtils.logHardware(userID, clientData, firstLogin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# This is false only if HWID is empty
 | 
							# This is false only if HWID is empty
 | 
				
			||||||
		# if HWID is banned, we get restricted so there's no
 | 
							# if HWID is banned, we get restricted so there's no
 | 
				
			||||||
@@ -99,7 +101,7 @@ def handle(tornadoRequest):
 | 
				
			|||||||
			raise exceptions.haxException()
 | 
								raise exceptions.haxException()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Log user IP
 | 
							# Log user IP
 | 
				
			||||||
		userHelper.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)
 | 
							glob.tokens.deleteOldTokens(userID)
 | 
				
			||||||
@@ -111,7 +113,7 @@ def handle(tornadoRequest):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		# Send message if donor expires soon
 | 
							# Send message if donor expires soon
 | 
				
			||||||
		if responseToken.privileges & privileges.USER_DONOR > 0:
 | 
							if responseToken.privileges & privileges.USER_DONOR > 0:
 | 
				
			||||||
			expireDate = userHelper.getDonorExpire(responseToken.userID)
 | 
								expireDate = userUtils.getDonorExpire(responseToken.userID)
 | 
				
			||||||
			if expireDate-int(time.time()) <= 86400*3:
 | 
								if expireDate-int(time.time()) <= 86400*3:
 | 
				
			||||||
				expireDays = round((expireDate-int(time.time()))/86400)
 | 
									expireDays = round((expireDate-int(time.time()))/86400)
 | 
				
			||||||
				expireIn = "{} days".format(expireDays) if expireDays > 1 else "less than 24 hours"
 | 
									expireIn = "{} days".format(expireDays) if expireDays > 1 else "less than 24 hours"
 | 
				
			||||||
@@ -119,7 +121,7 @@ def handle(tornadoRequest):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Set silence end UNIX time in token
 | 
							# Set silence end UNIX time in token
 | 
				
			||||||
		responseToken.silenceEndTime = userHelper.getSilenceEnd(userID)
 | 
							responseToken.silenceEndTime = userUtils.getSilenceEnd(userID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Get only silence remaining seconds
 | 
							# Get only silence remaining seconds
 | 
				
			||||||
		silenceSeconds = responseToken.getSilenceSecondsLeft()
 | 
							silenceSeconds = responseToken.getSilenceSecondsLeft()
 | 
				
			||||||
@@ -193,15 +195,15 @@ def handle(tornadoRequest):
 | 
				
			|||||||
			log.warning("Location skipped")
 | 
								log.warning("Location skipped")
 | 
				
			||||||
			location = [0,0]
 | 
								location = [0,0]
 | 
				
			||||||
			countryLetters = "XX"
 | 
								countryLetters = "XX"
 | 
				
			||||||
			country = countryHelper.getCountryID(userHelper.getCountry(userID))
 | 
								country = countryHelper.getCountryID(userUtils.getCountry(userID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Set location and country
 | 
							# Set location and country
 | 
				
			||||||
		responseToken.setLocation(location)
 | 
							responseToken.setLocation(location)
 | 
				
			||||||
		responseToken.setCountry(country)
 | 
							responseToken.setCountry(country)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Set country in db if user has no country (first bancho login)
 | 
							# Set country in db if user has no country (first bancho login)
 | 
				
			||||||
		if userHelper.getCountry(userID) == "XX":
 | 
							if userUtils.getCountry(userID) == "XX":
 | 
				
			||||||
			userHelper.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
 | 
				
			||||||
		if not responseToken.restricted:
 | 
							if not responseToken.restricted:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,10 @@
 | 
				
			|||||||
from objects import glob
 | 
					 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
from helpers import logHelper as log
 | 
					
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from constants import serverPackets
 | 
				
			||||||
from helpers import chatHelper as chat
 | 
					from helpers import chatHelper as chat
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, _=None):
 | 
					def handle(userToken, _=None):
 | 
				
			||||||
	# get usertoken data
 | 
						# get usertoken data
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
from objects import glob
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
from helpers import chatHelper as chat
 | 
					from helpers import chatHelper as chat
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, _):
 | 
					def handle(userToken, _):
 | 
				
			||||||
	# Get usertoken data
 | 
						# Get usertoken data
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
from constants import serverPackets
 | 
					from constants import serverPackets
 | 
				
			||||||
from helpers import logHelper as log
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	# Update cache and send new stats
 | 
						# Update cache and send new stats
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from constants import serverPackets
 | 
					from constants import serverPackets
 | 
				
			||||||
from helpers import logHelper as log
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	# get token data
 | 
						# get token data
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from common.ripple import userUtils
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					from constants import exceptions
 | 
				
			||||||
from objects import glob
 | 
					from constants import serverPackets
 | 
				
			||||||
from helpers import userHelper
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
from helpers import chatHelper as chat
 | 
					from helpers import chatHelper as chat
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	try:
 | 
						try:
 | 
				
			||||||
@@ -50,7 +51,7 @@ def handle(userToken, packetData):
 | 
				
			|||||||
				c.enqueue(serverPackets.fellowSpectatorJoined(userID))
 | 
									c.enqueue(serverPackets.fellowSpectatorJoined(userID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Console output
 | 
							# Console output
 | 
				
			||||||
		log.info("{} are spectating {}".format(username, userHelper.getUsername(packetData["userID"])))
 | 
							log.info("{} are spectating {}".format(username, userUtils.getUsername(packetData["userID"])))
 | 
				
			||||||
	except exceptions.tokenNotFoundException:
 | 
						except exceptions.tokenNotFoundException:
 | 
				
			||||||
		# Stop spectating if token not found
 | 
							# Stop spectating if token not found
 | 
				
			||||||
		log.warning("Spectator start: token not found")
 | 
							log.warning("Spectator start: token not found")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from constants import serverPackets
 | 
					from constants import serverPackets
 | 
				
			||||||
from helpers import logHelper as log
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	# Read userIDs list
 | 
						# Read userIDs list
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from constants import clientPackets
 | 
					from constants import clientPackets
 | 
				
			||||||
from constants import serverPackets
 | 
					from constants import serverPackets
 | 
				
			||||||
from helpers import logHelper as log
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def handle(userToken, packetData):
 | 
					def handle(userToken, packetData):
 | 
				
			||||||
	# Read userIDs list
 | 
						# Read userIDs list
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,19 @@
 | 
				
			|||||||
from helpers import requestHelper
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from helpers import chatHelper
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class handler(requestHelper.asyncRequestHandler):
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from common.web import requestsManager
 | 
				
			||||||
 | 
					from constants import exceptions
 | 
				
			||||||
 | 
					from helpers import chatHelper
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class handler(requestsManager.asyncRequestHandler):
 | 
				
			||||||
	def asyncGet(self):
 | 
						def asyncGet(self):
 | 
				
			||||||
		statusCode = 400
 | 
							statusCode = 400
 | 
				
			||||||
		data = {"message": "unknown error"}
 | 
							data = {"message": "unknown error"}
 | 
				
			||||||
		try:
 | 
							try:
 | 
				
			||||||
			# Check arguments
 | 
								# Check arguments
 | 
				
			||||||
			if not requestHelper.checkArguments(self.request.arguments, ["k", "to", "msg"]):
 | 
								if not requestsManager.checkArguments(self.request.arguments, ["k", "to", "msg"]):
 | 
				
			||||||
				raise exceptions.invalidArgumentsException()
 | 
									raise exceptions.invalidArgumentsException()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			# Check ci key
 | 
								# Check ci key
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,11 @@
 | 
				
			|||||||
from helpers import requestHelper
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.web import requestsManager
 | 
				
			||||||
 | 
					from constants import exceptions
 | 
				
			||||||
from objects import glob
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class handler(requestHelper.asyncRequestHandler):
 | 
					
 | 
				
			||||||
 | 
					class handler(requestsManager.asyncRequestHandler):
 | 
				
			||||||
	def asyncGet(self):
 | 
						def asyncGet(self):
 | 
				
			||||||
		statusCode = 400
 | 
							statusCode = 400
 | 
				
			||||||
		data = {"message": "unknown error"}
 | 
							data = {"message": "unknown error"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,10 @@
 | 
				
			|||||||
from helpers import requestHelper
 | 
					 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.web import requestsManager
 | 
				
			||||||
from objects import glob
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class handler(requestHelper.asyncRequestHandler):
 | 
					
 | 
				
			||||||
 | 
					class handler(requestsManager.asyncRequestHandler):
 | 
				
			||||||
	def asyncGet(self):
 | 
						def asyncGet(self):
 | 
				
			||||||
		statusCode = 400
 | 
							statusCode = 400
 | 
				
			||||||
		data = {"message": "unknown error"}
 | 
							data = {"message": "unknown error"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,10 @@
 | 
				
			|||||||
from helpers import requestHelper
 | 
					 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.web import requestsManager
 | 
				
			||||||
from objects import glob
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class handler(requestHelper.asyncRequestHandler):
 | 
					
 | 
				
			||||||
 | 
					class handler(requestsManager.asyncRequestHandler):
 | 
				
			||||||
	def asyncGet(self):
 | 
						def asyncGet(self):
 | 
				
			||||||
		statusCode = 400
 | 
							statusCode = 400
 | 
				
			||||||
		data = {"message": "unknown error"}
 | 
							data = {"message": "unknown error"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,17 @@
 | 
				
			|||||||
from helpers import requestHelper
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class handler(requestHelper.asyncRequestHandler):
 | 
					from common.web import requestsManager
 | 
				
			||||||
 | 
					from constants import exceptions
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class handler(requestsManager.asyncRequestHandler):
 | 
				
			||||||
	def asyncGet(self):
 | 
						def asyncGet(self):
 | 
				
			||||||
		statusCode = 400
 | 
							statusCode = 400
 | 
				
			||||||
		data = {"message": "unknown error"}
 | 
							data = {"message": "unknown error"}
 | 
				
			||||||
		try:
 | 
							try:
 | 
				
			||||||
			# Check arguments
 | 
								# Check arguments
 | 
				
			||||||
			if not requestHelper.checkArguments(self.request.arguments, ["u"]):
 | 
								if not requestsManager.checkArguments(self.request.arguments, ["u"]):
 | 
				
			||||||
				raise exceptions.invalidArgumentsException()
 | 
									raise exceptions.invalidArgumentsException()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			# Get userID and its verified cache thing
 | 
								# Get userID and its verified cache thing
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,19 @@
 | 
				
			|||||||
from helpers import requestHelper
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from helpers import systemHelper
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class handler(requestHelper.asyncRequestHandler):
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from common.web import requestsManager
 | 
				
			||||||
 | 
					from constants import exceptions
 | 
				
			||||||
 | 
					from helpers import systemHelper
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class handler(requestsManager.asyncRequestHandler):
 | 
				
			||||||
	def asyncGet(self):
 | 
						def asyncGet(self):
 | 
				
			||||||
		statusCode = 400
 | 
							statusCode = 400
 | 
				
			||||||
		data = {"message": "unknown error"}
 | 
							data = {"message": "unknown error"}
 | 
				
			||||||
		try:
 | 
							try:
 | 
				
			||||||
			# Check arguments
 | 
								# Check arguments
 | 
				
			||||||
			if not requestHelper.checkArguments(self.request.arguments, ["k"]):
 | 
								if not requestsManager.checkArguments(self.request.arguments, ["k"]):
 | 
				
			||||||
				raise exceptions.invalidArgumentsException()
 | 
									raise exceptions.invalidArgumentsException()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			# Check ci key
 | 
								# Check ci key
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,60 +1,61 @@
 | 
				
			|||||||
import datetime
 | 
					import datetime
 | 
				
			||||||
import gzip
 | 
					import gzip
 | 
				
			||||||
from helpers import requestHelper
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from constants import exceptions
 | 
					 | 
				
			||||||
from constants import packetIDs
 | 
					 | 
				
			||||||
from helpers import packetHelper
 | 
					 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
from events import sendPublicMessageEvent
 | 
					 | 
				
			||||||
from events import sendPrivateMessageEvent
 | 
					 | 
				
			||||||
from events import channelJoinEvent
 | 
					 | 
				
			||||||
from events import channelPartEvent
 | 
					 | 
				
			||||||
from events import changeActionEvent
 | 
					 | 
				
			||||||
from events import cantSpectateEvent
 | 
					 | 
				
			||||||
from events import startSpectatingEvent
 | 
					 | 
				
			||||||
from events import stopSpectatingEvent
 | 
					 | 
				
			||||||
from events import spectateFramesEvent
 | 
					 | 
				
			||||||
from events import friendAddEvent
 | 
					 | 
				
			||||||
from events import friendRemoveEvent
 | 
					 | 
				
			||||||
from events import logoutEvent
 | 
					 | 
				
			||||||
from events import loginEvent
 | 
					 | 
				
			||||||
from events import setAwayMessageEvent
 | 
					 | 
				
			||||||
from events import joinLobbyEvent
 | 
					 | 
				
			||||||
from events import createMatchEvent
 | 
					 | 
				
			||||||
from events import partLobbyEvent
 | 
					 | 
				
			||||||
from events import changeSlotEvent
 | 
					 | 
				
			||||||
from events import joinMatchEvent
 | 
					 | 
				
			||||||
from events import partMatchEvent
 | 
					 | 
				
			||||||
from events import changeMatchSettingsEvent
 | 
					 | 
				
			||||||
from events import changeMatchPasswordEvent
 | 
					 | 
				
			||||||
from events import changeMatchModsEvent
 | 
					 | 
				
			||||||
from events import matchReadyEvent
 | 
					 | 
				
			||||||
from events import matchLockEvent
 | 
					 | 
				
			||||||
from events import matchStartEvent
 | 
					 | 
				
			||||||
from events import matchPlayerLoadEvent
 | 
					 | 
				
			||||||
from events import matchSkipEvent
 | 
					 | 
				
			||||||
from events import matchFramesEvent
 | 
					 | 
				
			||||||
from events import matchCompleteEvent
 | 
					 | 
				
			||||||
from events import matchNoBeatmapEvent
 | 
					 | 
				
			||||||
from events import matchHasBeatmapEvent
 | 
					 | 
				
			||||||
from events import matchTransferHostEvent
 | 
					 | 
				
			||||||
from events import matchFailedEvent
 | 
					 | 
				
			||||||
from events import matchInviteEvent
 | 
					 | 
				
			||||||
from events import matchChangeTeamEvent
 | 
					 | 
				
			||||||
from events import userStatsRequestEvent
 | 
					 | 
				
			||||||
from events import requestStatusUpdateEvent
 | 
					 | 
				
			||||||
from events import userPanelRequestEvent
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Exception tracking
 | 
					 | 
				
			||||||
import tornado.web
 | 
					 | 
				
			||||||
import tornado.gen
 | 
					 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import traceback
 | 
					import traceback
 | 
				
			||||||
from raven.contrib.tornado import SentryMixin
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class handler(SentryMixin, requestHelper.asyncRequestHandler):
 | 
					import tornado.gen
 | 
				
			||||||
 | 
					import tornado.web
 | 
				
			||||||
 | 
					from raven.contrib.tornado import SentryMixin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from common.web import requestsManager
 | 
				
			||||||
 | 
					from constants import exceptions
 | 
				
			||||||
 | 
					from constants import packetIDs
 | 
				
			||||||
 | 
					from constants import serverPackets
 | 
				
			||||||
 | 
					from events import cantSpectateEvent
 | 
				
			||||||
 | 
					from events import changeActionEvent
 | 
				
			||||||
 | 
					from events import changeMatchModsEvent
 | 
				
			||||||
 | 
					from events import changeMatchPasswordEvent
 | 
				
			||||||
 | 
					from events import changeMatchSettingsEvent
 | 
				
			||||||
 | 
					from events import changeSlotEvent
 | 
				
			||||||
 | 
					from events import channelJoinEvent
 | 
				
			||||||
 | 
					from events import channelPartEvent
 | 
				
			||||||
 | 
					from events import createMatchEvent
 | 
				
			||||||
 | 
					from events import friendAddEvent
 | 
				
			||||||
 | 
					from events import friendRemoveEvent
 | 
				
			||||||
 | 
					from events import joinLobbyEvent
 | 
				
			||||||
 | 
					from events import joinMatchEvent
 | 
				
			||||||
 | 
					from events import loginEvent
 | 
				
			||||||
 | 
					from events import logoutEvent
 | 
				
			||||||
 | 
					from events import matchChangeTeamEvent
 | 
				
			||||||
 | 
					from events import matchCompleteEvent
 | 
				
			||||||
 | 
					from events import matchFailedEvent
 | 
				
			||||||
 | 
					from events import matchFramesEvent
 | 
				
			||||||
 | 
					from events import matchHasBeatmapEvent
 | 
				
			||||||
 | 
					from events import matchInviteEvent
 | 
				
			||||||
 | 
					from events import matchLockEvent
 | 
				
			||||||
 | 
					from events import matchNoBeatmapEvent
 | 
				
			||||||
 | 
					from events import matchPlayerLoadEvent
 | 
				
			||||||
 | 
					from events import matchReadyEvent
 | 
				
			||||||
 | 
					from events import matchSkipEvent
 | 
				
			||||||
 | 
					from events import matchStartEvent
 | 
				
			||||||
 | 
					from events import matchTransferHostEvent
 | 
				
			||||||
 | 
					from events import partLobbyEvent
 | 
				
			||||||
 | 
					from events import partMatchEvent
 | 
				
			||||||
 | 
					from events import requestStatusUpdateEvent
 | 
				
			||||||
 | 
					from events import sendPrivateMessageEvent
 | 
				
			||||||
 | 
					from events import sendPublicMessageEvent
 | 
				
			||||||
 | 
					from events import setAwayMessageEvent
 | 
				
			||||||
 | 
					from events import spectateFramesEvent
 | 
				
			||||||
 | 
					from events import startSpectatingEvent
 | 
				
			||||||
 | 
					from events import stopSpectatingEvent
 | 
				
			||||||
 | 
					from events import userPanelRequestEvent
 | 
				
			||||||
 | 
					from events import userStatsRequestEvent
 | 
				
			||||||
 | 
					from helpers import packetHelper
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class handler(SentryMixin, requestsManager.asyncRequestHandler):
 | 
				
			||||||
	@tornado.web.asynchronous
 | 
						@tornado.web.asynchronous
 | 
				
			||||||
	@tornado.gen.engine
 | 
						@tornado.gen.engine
 | 
				
			||||||
	def asyncPost(self):
 | 
						def asyncPost(self):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,12 @@
 | 
				
			|||||||
from objects import glob
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from helpers import logHelper as log
 | 
					from common.ripple import userUtils
 | 
				
			||||||
from constants import exceptions
 | 
					from constants import exceptions
 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
from objects import fokabot
 | 
					 | 
				
			||||||
from helpers import discordBotHelper
 | 
					 | 
				
			||||||
from helpers import userHelper
 | 
					 | 
				
			||||||
from events import logoutEvent
 | 
					 | 
				
			||||||
from constants import messageTemplates
 | 
					from constants import messageTemplates
 | 
				
			||||||
 | 
					from constants import serverPackets
 | 
				
			||||||
 | 
					from events import logoutEvent
 | 
				
			||||||
 | 
					from objects import fokabot
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def joinChannel(userID = 0, channel = "", token = None, toIRC = True):
 | 
					def joinChannel(userID = 0, channel = "", token = None, toIRC = True):
 | 
				
			||||||
	"""
 | 
						"""
 | 
				
			||||||
@@ -272,7 +272,7 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
 | 
				
			|||||||
		# File and discord logs (public chat only)
 | 
							# File and discord logs (public chat only)
 | 
				
			||||||
		if to.startswith("#"):
 | 
							if to.startswith("#"):
 | 
				
			||||||
			log.chat("{fro} @ {to}: {message}".format(fro=username, to=to, message=str(message.encode("utf-8"))))
 | 
								log.chat("{fro} @ {to}: {message}".format(fro=username, to=to, message=str(message.encode("utf-8"))))
 | 
				
			||||||
			discordBotHelper.sendChatlog("**{fro} @ {to}:** {message}".format(fro=username, to=to, message=str(message.encode("utf-8"))[2:-1]))
 | 
								glob.schiavo.sendChatlog("**{fro} @ {to}:** {message}".format(fro=username, to=to, message=str(message.encode("utf-8"))[2:-1]))
 | 
				
			||||||
		return 0
 | 
							return 0
 | 
				
			||||||
	except exceptions.userSilencedException:
 | 
						except exceptions.userSilencedException:
 | 
				
			||||||
		token.enqueue(serverPackets.silenceEndTime(token.getSilenceSecondsLeft()))
 | 
							token.enqueue(serverPackets.silenceEndTime(token.getSilenceSecondsLeft()))
 | 
				
			||||||
@@ -314,7 +314,7 @@ def fixUsernameForIRC(username):
 | 
				
			|||||||
	return username.replace(" ", "_")
 | 
						return username.replace(" ", "_")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def IRCConnect(username):
 | 
					def IRCConnect(username):
 | 
				
			||||||
	userID = userHelper.getID(username)
 | 
						userID = userUtils.getID(username)
 | 
				
			||||||
	if not userID:
 | 
						if not userID:
 | 
				
			||||||
		log.warning("{} doesn't exist".format(username))
 | 
							log.warning("{} doesn't exist".format(username))
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -332,7 +332,7 @@ def IRCDisconnect(username):
 | 
				
			|||||||
	log.info("{} disconnected from IRC".format(username))
 | 
						log.info("{} disconnected from IRC".format(username))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def IRCJoinChannel(username, channel):
 | 
					def IRCJoinChannel(username, channel):
 | 
				
			||||||
	userID = userHelper.getID(username)
 | 
						userID = userUtils.getID(username)
 | 
				
			||||||
	if not userID:
 | 
						if not userID:
 | 
				
			||||||
		log.warning("{} doesn't exist".format(username))
 | 
							log.warning("{} doesn't exist".format(username))
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -342,7 +342,7 @@ def IRCJoinChannel(username, channel):
 | 
				
			|||||||
	return joinChannel(userID, channel)
 | 
						return joinChannel(userID, channel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def IRCPartChannel(username, channel):
 | 
					def IRCPartChannel(username, channel):
 | 
				
			||||||
	userID = userHelper.getID(username)
 | 
						userID = userUtils.getID(username)
 | 
				
			||||||
	if not userID:
 | 
						if not userID:
 | 
				
			||||||
		log.warning("{} doesn't exist".format(username))
 | 
							log.warning("{} doesn't exist".format(username))
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
from constants import bcolors
 | 
					from common.constants import bcolors
 | 
				
			||||||
from objects import glob
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def printServerStartHeader(asciiArt):
 | 
					def printServerStartHeader(asciiArt):
 | 
				
			||||||
@@ -28,7 +28,7 @@ def printServerStartHeader(asciiArt):
 | 
				
			|||||||
	printColored("> Welcome to pep.py osu!bancho server v{}".format(glob.VERSION), bcolors.GREEN)
 | 
						printColored("> Welcome to pep.py osu!bancho server v{}".format(glob.VERSION), bcolors.GREEN)
 | 
				
			||||||
	printColored("> Made by the Ripple team", bcolors.GREEN)
 | 
						printColored("> Made by the Ripple team", bcolors.GREEN)
 | 
				
			||||||
	printColored("> {}https://git.zxq.co/ripple/pep.py".format(bcolors.UNDERLINE), bcolors.GREEN)
 | 
						printColored("> {}https://git.zxq.co/ripple/pep.py".format(bcolors.UNDERLINE), bcolors.GREEN)
 | 
				
			||||||
	printColored("> Press CTRL+C to exit\n",bcolors.GREEN)
 | 
						printColored("> Press CTRL+C to exit\n", bcolors.GREEN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def printNoNl(string):
 | 
					def printNoNl(string):
 | 
				
			||||||
	"""
 | 
						"""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,222 +0,0 @@
 | 
				
			|||||||
import queue
 | 
					 | 
				
			||||||
import MySQLdb
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class worker():
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	A single MySQL worker
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	def __init__(self, connection, temporary=False):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Initialize a MySQL worker
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param connection: database connection object
 | 
					 | 
				
			||||||
		:param temporary: if True, this worker will be flagged as temporary
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		self.connection = connection
 | 
					 | 
				
			||||||
		self.temporary = temporary
 | 
					 | 
				
			||||||
		log.debug("Created MySQL worker. Temporary: {}".format(self.temporary))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def ping(self):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Ping MySQL server using this worker.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:return: True if connected, False if error occured.
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		try:
 | 
					 | 
				
			||||||
			self.connection.cursor(MySQLdb.cursors.DictCursor).execute("SELECT 1+1")
 | 
					 | 
				
			||||||
			return True
 | 
					 | 
				
			||||||
		except:
 | 
					 | 
				
			||||||
			return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def __del__(self):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Close connection to the server
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:return:
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		self.connection.close()
 | 
					 | 
				
			||||||
		log.debug("Destroyed MySQL worker.")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class connectionsPool():
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	A MySQL workers pool
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	def __init__(self, host, username, password, database, initialSize=16):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Initialize a MySQL connections pool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param host: MySQL host
 | 
					 | 
				
			||||||
		:param username: MySQL username
 | 
					 | 
				
			||||||
		:param password: MySQL password
 | 
					 | 
				
			||||||
		:param database: MySQL database name
 | 
					 | 
				
			||||||
		:param initialSize: initial pool size
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		self.config = (host, username, password, database)
 | 
					 | 
				
			||||||
		self.maxSize = initialSize
 | 
					 | 
				
			||||||
		self.pool = queue.Queue(0)
 | 
					 | 
				
			||||||
		self.consecutiveEmptyPool = 0
 | 
					 | 
				
			||||||
		self.fillPool()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def newWorker(self, temporary=False):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Create a new worker.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param temporary: if True, flag the worker as temporary
 | 
					 | 
				
			||||||
		:return: instance of worker class
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		db = MySQLdb.connect(*self.config)
 | 
					 | 
				
			||||||
		db.autocommit(True)
 | 
					 | 
				
			||||||
		conn = worker(db, temporary)
 | 
					 | 
				
			||||||
		return conn
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def expandPool(self, newWorkers=5):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Add some new workers to the pool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param newWorkers: number of new workers
 | 
					 | 
				
			||||||
		:return:
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		self.maxSize += newWorkers
 | 
					 | 
				
			||||||
		self.fillPool()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def fillPool(self):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Fill the queue with workers until its maxSize
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:return:
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		size = self.pool.qsize()
 | 
					 | 
				
			||||||
		if self.maxSize > 0 and size >= self.maxSize:
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		newConnections = self.maxSize-size
 | 
					 | 
				
			||||||
		for _ in range(0, newConnections):
 | 
					 | 
				
			||||||
			self.pool.put_nowait(self.newWorker())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def getWorker(self):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Get a MySQL connection worker from the pool.
 | 
					 | 
				
			||||||
		If the pool is empty, a new temporary worker is created.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:return: instance of worker class
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if self.pool.empty():
 | 
					 | 
				
			||||||
			# The pool is empty. Spawn a new temporary worker
 | 
					 | 
				
			||||||
			log.warning("Using temporary worker")
 | 
					 | 
				
			||||||
			worker = self.newWorker(True)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			# Increment saturation
 | 
					 | 
				
			||||||
			self.consecutiveEmptyPool += 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			# If the pool is usually empty, expand it
 | 
					 | 
				
			||||||
			if self.consecutiveEmptyPool >= 5:
 | 
					 | 
				
			||||||
				log.warning("MySQL connections pool is saturated. Filling connections pool.")
 | 
					 | 
				
			||||||
				self.expandPool()
 | 
					 | 
				
			||||||
		else:
 | 
					 | 
				
			||||||
			# The pool is not empty. Get worker from the pool
 | 
					 | 
				
			||||||
			# and reset saturation counter
 | 
					 | 
				
			||||||
			worker = self.pool.get()
 | 
					 | 
				
			||||||
			self.consecutiveEmptyPool = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Return the connection
 | 
					 | 
				
			||||||
		return worker
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def putWorker(self, worker):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Put the worker back in the pool.
 | 
					 | 
				
			||||||
		If the worker is temporary, close the connection
 | 
					 | 
				
			||||||
		and destroy the object
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param worker: worker object
 | 
					 | 
				
			||||||
		:return:
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		if worker.temporary:
 | 
					 | 
				
			||||||
			del worker
 | 
					 | 
				
			||||||
		else:
 | 
					 | 
				
			||||||
			self.pool.put_nowait(worker)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class db:
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	A MySQL helper with multiple workers
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	def __init__(self, host, username, password, database, initialSize):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Initialize a new MySQL database helper with multiple workers.
 | 
					 | 
				
			||||||
		This class is thread safe.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param host: MySQL host
 | 
					 | 
				
			||||||
		:param username: MySQL username
 | 
					 | 
				
			||||||
		:param password: MySQL password
 | 
					 | 
				
			||||||
		:param database: MySQL database name
 | 
					 | 
				
			||||||
		:param initialSize: initial pool size
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		self.pool = connectionsPool(host, username, password, database, initialSize)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def execute(self, query, params = ()):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Executes a query
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param query: query to execute. You can bind parameters with %s
 | 
					 | 
				
			||||||
		:param params: parameters list. First element replaces first %s and so on
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		cursor = None
 | 
					 | 
				
			||||||
		worker = self.pool.getWorker()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		try:
 | 
					 | 
				
			||||||
			# Create cursor, execute query and commit
 | 
					 | 
				
			||||||
			cursor = worker.connection.cursor(MySQLdb.cursors.DictCursor)
 | 
					 | 
				
			||||||
			cursor.execute(query, params)
 | 
					 | 
				
			||||||
			log.debug(query)
 | 
					 | 
				
			||||||
			return cursor.lastrowid
 | 
					 | 
				
			||||||
		except MySQLdb.OperationalError:
 | 
					 | 
				
			||||||
			del worker
 | 
					 | 
				
			||||||
			worker = None
 | 
					 | 
				
			||||||
			return self.execute(query, params)
 | 
					 | 
				
			||||||
		finally:
 | 
					 | 
				
			||||||
			# Close the cursor and release worker's lock
 | 
					 | 
				
			||||||
			if cursor is not None:
 | 
					 | 
				
			||||||
				cursor.close()
 | 
					 | 
				
			||||||
			if worker is not None:
 | 
					 | 
				
			||||||
				self.pool.putWorker(worker)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def fetch(self, query, params = (), all = False):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Fetch a single value from db that matches given query
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param query: query to execute. You can bind parameters with %s
 | 
					 | 
				
			||||||
		:param params: parameters list. First element replaces first %s and so on
 | 
					 | 
				
			||||||
		:param all: fetch one or all values. Used internally. Use fetchAll if you want to fetch all values
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		cursor = None
 | 
					 | 
				
			||||||
		worker = self.pool.getWorker()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		try:
 | 
					 | 
				
			||||||
			# Create cursor, execute the query and fetch one/all result(s)
 | 
					 | 
				
			||||||
			cursor = worker.connection.cursor(MySQLdb.cursors.DictCursor)
 | 
					 | 
				
			||||||
			cursor.execute(query, params)
 | 
					 | 
				
			||||||
			log.debug(query)
 | 
					 | 
				
			||||||
			if all == True:
 | 
					 | 
				
			||||||
				return cursor.fetchall()
 | 
					 | 
				
			||||||
			else:
 | 
					 | 
				
			||||||
				return cursor.fetchone()
 | 
					 | 
				
			||||||
		except MySQLdb.OperationalError:
 | 
					 | 
				
			||||||
			del worker
 | 
					 | 
				
			||||||
			worker = None
 | 
					 | 
				
			||||||
			return self.fetch(query, params, all)
 | 
					 | 
				
			||||||
		finally:
 | 
					 | 
				
			||||||
			# Close the cursor and release worker's lock
 | 
					 | 
				
			||||||
			if cursor is not None:
 | 
					 | 
				
			||||||
				cursor.close()
 | 
					 | 
				
			||||||
			if worker is not None:
 | 
					 | 
				
			||||||
				self.pool.putWorker(worker)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def fetchAll(self, query, params = ()):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Fetch all values from db that matche given query.
 | 
					 | 
				
			||||||
		Calls self.fetch with all = True.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param query: query to execute. You can bind parameters with %s
 | 
					 | 
				
			||||||
		:param params: parameters list. First element replaces first %s and so on
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		return self.fetch(query, params, True)
 | 
					 | 
				
			||||||
@@ -1,136 +0,0 @@
 | 
				
			|||||||
from constants import mods
 | 
					 | 
				
			||||||
from time import gmtime, strftime
 | 
					 | 
				
			||||||
import hashlib
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def stringMd5(string):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Return string's md5
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	string -- string to hash
 | 
					 | 
				
			||||||
	return -- string's md5 hash
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	d = hashlib.md5()
 | 
					 | 
				
			||||||
	d.update(string.encode("utf-8"))
 | 
					 | 
				
			||||||
	return d.hexdigest()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def stringToBool(s):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Convert a string (True/true/1) to bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	s -- string/int value
 | 
					 | 
				
			||||||
	return -- True/False
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	return s == "True" or s == "true" or s == "1" or s == 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def hexString(s):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Output s' bytes in HEX
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	s -- string
 | 
					 | 
				
			||||||
	return -- string with hex value
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	return ":".join("{:02x}".format(ord(str(c))) for c in s)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def readableMods(__mods):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Return a string with readable std mods.
 | 
					 | 
				
			||||||
	Used to convert a mods number for oppai
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	__mods -- mods bitwise number
 | 
					 | 
				
			||||||
	return -- readable mods string, eg HDDT
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	r = ""
 | 
					 | 
				
			||||||
	if __mods == 0:
 | 
					 | 
				
			||||||
		return r
 | 
					 | 
				
			||||||
	if __mods & mods.NoFail > 0:
 | 
					 | 
				
			||||||
		r += "NF"
 | 
					 | 
				
			||||||
	if __mods & mods.Easy > 0:
 | 
					 | 
				
			||||||
		r += "EZ"
 | 
					 | 
				
			||||||
	if __mods & mods.Hidden > 0:
 | 
					 | 
				
			||||||
		r += "HD"
 | 
					 | 
				
			||||||
	if __mods & mods.HardRock > 0:
 | 
					 | 
				
			||||||
		r += "HR"
 | 
					 | 
				
			||||||
	if __mods & mods.DoubleTime > 0:
 | 
					 | 
				
			||||||
		r += "DT"
 | 
					 | 
				
			||||||
	if __mods & mods.HalfTime > 0:
 | 
					 | 
				
			||||||
		r += "HT"
 | 
					 | 
				
			||||||
	if __mods & mods.Flashlight > 0:
 | 
					 | 
				
			||||||
		r += "FL"
 | 
					 | 
				
			||||||
	if __mods & mods.SpunOut > 0:
 | 
					 | 
				
			||||||
		r += "SO"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return r
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getRank(gameMode, __mods, acc, c300, c100, c50, cmiss):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Return a string with rank/grade for a given score.
 | 
					 | 
				
			||||||
	Used mainly for "tillerino"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	gameMode -- mode (0 = osu!, 1 = Taiko, 2 = CtB, 3 = osu!mania)
 | 
					 | 
				
			||||||
	__mods -- mods bitwise number
 | 
					 | 
				
			||||||
	acc -- accuracy
 | 
					 | 
				
			||||||
	c300 -- 300 hit count
 | 
					 | 
				
			||||||
	c100 -- 100 hit count
 | 
					 | 
				
			||||||
	c50 -- 50 hit count
 | 
					 | 
				
			||||||
	cmiss -- miss count
 | 
					 | 
				
			||||||
	return -- rank/grade string
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	total = c300 + c100 + c50 + cmiss
 | 
					 | 
				
			||||||
	hdfl = (__mods & (mods.Hidden | mods.Flashlight | mods.FadeIn)) > 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ss = "sshd" if hdfl else "ss"
 | 
					 | 
				
			||||||
	s = "shd" if hdfl else "s"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if gameMode == 0 or gameMode == 1:
 | 
					 | 
				
			||||||
		# osu!std / taiko
 | 
					 | 
				
			||||||
		ratio300 = c300 / total
 | 
					 | 
				
			||||||
		ratio50 = c50 / total
 | 
					 | 
				
			||||||
		if ratio300 == 1:
 | 
					 | 
				
			||||||
			return ss
 | 
					 | 
				
			||||||
		if ratio300 > 0.9 and ratio50 <= 0.01 and cmiss == 0:
 | 
					 | 
				
			||||||
			return s
 | 
					 | 
				
			||||||
		if (ratio300 > 0.8 and cmiss == 0) or (ratio300 > 0.9):
 | 
					 | 
				
			||||||
			return "a"
 | 
					 | 
				
			||||||
		if (ratio300 > 0.7 and cmiss == 0) or (ratio300 > 0.8):
 | 
					 | 
				
			||||||
			return "b"
 | 
					 | 
				
			||||||
		if ratio300 > 0.6:
 | 
					 | 
				
			||||||
			return "c"
 | 
					 | 
				
			||||||
		return "d"
 | 
					 | 
				
			||||||
	elif gameMode == 2:
 | 
					 | 
				
			||||||
		# CtB
 | 
					 | 
				
			||||||
		if acc == 100:
 | 
					 | 
				
			||||||
			return ss
 | 
					 | 
				
			||||||
		if acc > 98:
 | 
					 | 
				
			||||||
			return s
 | 
					 | 
				
			||||||
		if acc > 94:
 | 
					 | 
				
			||||||
			return "a"
 | 
					 | 
				
			||||||
		if acc > 90:
 | 
					 | 
				
			||||||
			return "b"
 | 
					 | 
				
			||||||
		if acc > 85:
 | 
					 | 
				
			||||||
			return "c"
 | 
					 | 
				
			||||||
		return "d"
 | 
					 | 
				
			||||||
	elif gameMode == 3:
 | 
					 | 
				
			||||||
		# osu!mania
 | 
					 | 
				
			||||||
		if acc == 100:
 | 
					 | 
				
			||||||
			return ss
 | 
					 | 
				
			||||||
		if acc > 95:
 | 
					 | 
				
			||||||
			return s
 | 
					 | 
				
			||||||
		if acc > 90:
 | 
					 | 
				
			||||||
			return "a"
 | 
					 | 
				
			||||||
		if acc > 80:
 | 
					 | 
				
			||||||
			return "b"
 | 
					 | 
				
			||||||
		if acc > 70:
 | 
					 | 
				
			||||||
			return "c"
 | 
					 | 
				
			||||||
		return "d"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return "a"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def strContains(s, w):
 | 
					 | 
				
			||||||
	return (' ' + w + ' ') in (' ' + s + ' ')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getTimestamp():
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Return current time in YYYY-MM-DD HH:MM:SS format.
 | 
					 | 
				
			||||||
	Used in logs.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	return strftime("%Y-%m-%d %H:%M:%S", gmtime())
 | 
					 | 
				
			||||||
@@ -1,8 +1,9 @@
 | 
				
			|||||||
import urllib.request
 | 
					 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
 | 
					import urllib.request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from objects import glob
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def getCountry(ip):
 | 
					def getCountry(ip):
 | 
				
			||||||
	"""
 | 
						"""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,135 +0,0 @@
 | 
				
			|||||||
from constants import bcolors
 | 
					 | 
				
			||||||
from helpers import discordBotHelper
 | 
					 | 
				
			||||||
from helpers import generalFunctions
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from helpers import userHelper
 | 
					 | 
				
			||||||
import time
 | 
					 | 
				
			||||||
import os
 | 
					 | 
				
			||||||
ENDL = "\n" if os.name == "posix" else "\r\n"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def logMessage(message, alertType = "INFO", messageColor = bcolors.ENDC, discord = None, alertDev = False, of = None, stdout = True):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Logs a message to stdout/discord/file
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message -- message to log
 | 
					 | 
				
			||||||
	alertType -- can be any string. Standard types: INFO, WARNING and ERRORS. Defalt: INFO
 | 
					 | 
				
			||||||
	messageColor -- message color (see constants.bcolors). Default = bcolots.ENDC (no color)
 | 
					 | 
				
			||||||
	discord -- discord channel (bunker/cm/staff/general). Optional. Default = None
 | 
					 | 
				
			||||||
	alertDev -- if True, devs will receive an hl on discord. Default: False
 | 
					 | 
				
			||||||
	of -- if not None but a string, log the message to that file (inside .data folder). Eg: "warnings.txt" Default: None (don't log to file)
 | 
					 | 
				
			||||||
	stdout -- if True, print the message to stdout. Default: True
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	# Get type color from alertType
 | 
					 | 
				
			||||||
	if alertType == "INFO":
 | 
					 | 
				
			||||||
		typeColor = bcolors.GREEN
 | 
					 | 
				
			||||||
	elif alertType == "WARNING":
 | 
					 | 
				
			||||||
		typeColor = bcolors.YELLOW
 | 
					 | 
				
			||||||
	elif alertType == "ERROR":
 | 
					 | 
				
			||||||
		typeColor = bcolors.RED
 | 
					 | 
				
			||||||
	elif alertType == "CHAT":
 | 
					 | 
				
			||||||
		typeColor = bcolors.BLUE
 | 
					 | 
				
			||||||
	elif alertType == "DEBUG":
 | 
					 | 
				
			||||||
		typeColor = bcolors.PINK
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		typeColor = bcolors.ENDC
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Message without colors
 | 
					 | 
				
			||||||
	finalMessage = "[{time}] {type} - {message}".format(time=generalFunctions.getTimestamp(), type=alertType, message=message)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Message with colors
 | 
					 | 
				
			||||||
	finalMessageConsole = "{typeColor}[{time}] {type}{endc} - {messageColor}{message}{endc}".format(
 | 
					 | 
				
			||||||
		time=generalFunctions.getTimestamp(),
 | 
					 | 
				
			||||||
		type=alertType,
 | 
					 | 
				
			||||||
		message=message,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		typeColor=typeColor,
 | 
					 | 
				
			||||||
		messageColor=messageColor,
 | 
					 | 
				
			||||||
		endc=bcolors.ENDC)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Log to console
 | 
					 | 
				
			||||||
	if stdout:
 | 
					 | 
				
			||||||
		print(finalMessageConsole)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Log to discord if needed
 | 
					 | 
				
			||||||
	if discord is not None:
 | 
					 | 
				
			||||||
		if discord == "bunker":
 | 
					 | 
				
			||||||
			discordBotHelper.sendConfidential(message, alertDev)
 | 
					 | 
				
			||||||
		elif discord == "cm":
 | 
					 | 
				
			||||||
			discordBotHelper.sendCM(message)
 | 
					 | 
				
			||||||
		elif discord == "staff":
 | 
					 | 
				
			||||||
			discordBotHelper.sendStaff(message)
 | 
					 | 
				
			||||||
		elif discord == "general":
 | 
					 | 
				
			||||||
			discordBotHelper.sendGeneral(message)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Log to file if needed
 | 
					 | 
				
			||||||
	if of is not None:
 | 
					 | 
				
			||||||
		glob.fileBuffers.write(".data/"+of, finalMessage+ENDL)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def warning(message, discord = None, alertDev = False):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Log a warning to stdout (always) and discord (optional)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message -- warning message
 | 
					 | 
				
			||||||
	discord -- if not None, send message to that discord channel through schiavo. Optional. Default = None
 | 
					 | 
				
			||||||
	alertDev -- if True, send al hl to devs on discord. Optional. Default = False.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	logMessage(message, "WARNING", bcolors.YELLOW, discord, alertDev)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def error(message, discord = None, alertDev = True):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Log an error to stdout (always) and discord (optional)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message -- error message
 | 
					 | 
				
			||||||
	discord -- if not None, send message to that discord channel through schiavo. Optional. Default = None
 | 
					 | 
				
			||||||
	alertDev -- if True, send al hl to devs on discord. Optional. Default = False.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	logMessage(message, "ERROR", bcolors.RED, discord, alertDev)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def info(message, discord = None, alertDev = False):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Log an info message to stdout
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message -- info message
 | 
					 | 
				
			||||||
	discord -- if not None, send message to that discord channel through schiavo. Optional. Default = None
 | 
					 | 
				
			||||||
	alertDev -- if True, send al hl to devs on discord. Optional. Default = False.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	logMessage(message, "INFO", bcolors.ENDC, discord, alertDev)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def debug(message):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Log a debug message to stdout if server is running in debug mode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message -- debug message
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	if glob.debug:
 | 
					 | 
				
			||||||
		logMessage(message, "DEBUG", bcolors.PINK)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def chat(message):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Log public messages to stdout and chatlog_public.txt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message -- chat message
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	logMessage(message, "CHAT", bcolors.BLUE, of="chatlog_public.txt")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def pm(message):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Log private messages to stdout and chatlog_private.txt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	message -- chat message
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	logMessage(message, "CHAT", bcolors.BLUE, of="chatlog_private.txt")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def rap(userID, message, discord=False, through="FokaBot"):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Log a private message to Admin logs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID of who made the action
 | 
					 | 
				
			||||||
	message -- message without subject (eg: "is a meme" becomes "user is a meme")
 | 
					 | 
				
			||||||
	discord -- if True, send message to discord
 | 
					 | 
				
			||||||
	through -- "through" thing string. Optional. Default: "FokaBot"
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	glob.db.execute("INSERT INTO rap_logs (id, userid, text, datetime, through) VALUES (NULL, %s, %s, %s, %s)", [userID, message, int(time.time()), through])
 | 
					 | 
				
			||||||
	if discord:
 | 
					 | 
				
			||||||
		username = userHelper.getUsername(userID)
 | 
					 | 
				
			||||||
		logMessage("{} {}".format(username, message), discord=True)
 | 
					 | 
				
			||||||
@@ -1,35 +0,0 @@
 | 
				
			|||||||
from helpers import cryptHelper
 | 
					 | 
				
			||||||
import base64
 | 
					 | 
				
			||||||
import bcrypt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def checkOldPassword(password, salt, rightPassword):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check if password+salt corresponds to rightPassword
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	password -- input password
 | 
					 | 
				
			||||||
	salt -- password's salt
 | 
					 | 
				
			||||||
	rightPassword -- right password
 | 
					 | 
				
			||||||
	return -- bool
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	return rightPassword == cryptHelper.crypt(password, "$2y$" + str(base64.b64decode(salt)))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def checkNewPassword(password, dbPassword):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check if a password (version 2) is right.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	password -- input password
 | 
					 | 
				
			||||||
	dbPassword -- the password in the database
 | 
					 | 
				
			||||||
	return -- bool
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	password = password.encode("utf8")
 | 
					 | 
				
			||||||
	dbPassword = dbPassword.encode("utf8")
 | 
					 | 
				
			||||||
	return bcrypt.hashpw(password, dbPassword) == dbPassword
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def genBcrypt(password):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Bcrypts a password.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	password -- the password to hash.
 | 
					 | 
				
			||||||
	return -- bytestring
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	return bcrypt.hashpw(password.encode("utf8"), bcrypt.gensalt(10, b'2a'))
 | 
					 | 
				
			||||||
@@ -1,101 +0,0 @@
 | 
				
			|||||||
import tornado
 | 
					 | 
				
			||||||
import tornado.web
 | 
					 | 
				
			||||||
import tornado.gen
 | 
					 | 
				
			||||||
from tornado.ioloop import IOLoop
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
import threading
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class asyncRequestHandler(tornado.web.RequestHandler):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Tornado asynchronous request handler
 | 
					 | 
				
			||||||
	create a class that extends this one (requestHelper.asyncRequestHandler)
 | 
					 | 
				
			||||||
	use asyncGet() and asyncPost() instad of get() and post().
 | 
					 | 
				
			||||||
	Done. I'm not kidding.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	@tornado.web.asynchronous
 | 
					 | 
				
			||||||
	@tornado.gen.engine
 | 
					 | 
				
			||||||
	def get(self, *args, **kwargs):
 | 
					 | 
				
			||||||
		try:
 | 
					 | 
				
			||||||
			yield tornado.gen.Task(runBackground, (self.asyncGet, tuple(args), dict(kwargs)))
 | 
					 | 
				
			||||||
		except Exception as e:
 | 
					 | 
				
			||||||
			yield tornado.gen.Task(self.captureException, exc_info=True)
 | 
					 | 
				
			||||||
		finally:
 | 
					 | 
				
			||||||
			if not self._finished:
 | 
					 | 
				
			||||||
				self.finish()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@tornado.web.asynchronous
 | 
					 | 
				
			||||||
	@tornado.gen.engine
 | 
					 | 
				
			||||||
	def post(self, *args, **kwargs):
 | 
					 | 
				
			||||||
		try:
 | 
					 | 
				
			||||||
			yield tornado.gen.Task(runBackground, (self.asyncPost, tuple(args), dict(kwargs)))
 | 
					 | 
				
			||||||
		except Exception as e:
 | 
					 | 
				
			||||||
			yield tornado.gen.Task(self.captureException, exc_info=True)
 | 
					 | 
				
			||||||
		finally:
 | 
					 | 
				
			||||||
			if not self._finished:
 | 
					 | 
				
			||||||
				self.finish()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def asyncGet(self, *args, **kwargs):
 | 
					 | 
				
			||||||
		self.send_error(405)
 | 
					 | 
				
			||||||
		self.finish()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def asyncPost(self, *args, **kwargs):
 | 
					 | 
				
			||||||
		self.send_error(405)
 | 
					 | 
				
			||||||
		self.finish()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def getRequestIP(self):
 | 
					 | 
				
			||||||
		realIP = self.request.headers.get("X-Forwarded-For") if glob.cloudflare == True else self.request.headers.get("X-Real-IP")
 | 
					 | 
				
			||||||
		if realIP is not None:
 | 
					 | 
				
			||||||
			return realIP
 | 
					 | 
				
			||||||
		return self.request.remote_ip
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def runBackground(data, callback):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Run a function in the background.
 | 
					 | 
				
			||||||
	Used to handle multiple requests at the same time
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	func, args, kwargs = data
 | 
					 | 
				
			||||||
	def _callback(result):
 | 
					 | 
				
			||||||
		#glob.busyThreads -= 1
 | 
					 | 
				
			||||||
		IOLoop.instance().add_callback(lambda: callback(result))
 | 
					 | 
				
			||||||
	glob.pool.apply_async(func, args, kwargs, _callback)
 | 
					 | 
				
			||||||
	#threading.Thread(target=checkPoolSaturation).start()
 | 
					 | 
				
			||||||
	#glob.busyThreads += 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def checkPoolSaturation():
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check the number of busy threads in connections pool.
 | 
					 | 
				
			||||||
	If the pool is 100% busy, log a message to sentry
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	size = int(glob.conf.config["server"]["threads"])
 | 
					 | 
				
			||||||
	if glob.busyThreads >= size:
 | 
					 | 
				
			||||||
		msg = "Connections threads pool is saturated!"
 | 
					 | 
				
			||||||
		log.warning(msg)
 | 
					 | 
				
			||||||
		glob.application.sentry_client.captureMessage(msg, level="warning", extra={
 | 
					 | 
				
			||||||
			"workersBusy": glob.busyThreads,
 | 
					 | 
				
			||||||
			"workersTotal": size
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def checkArguments(arguments, requiredArguments):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check that every requiredArguments elements are in arguments
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	arguments -- full argument list, from tornado
 | 
					 | 
				
			||||||
	requiredArguments -- required arguments list es: ["u", "ha"]
 | 
					 | 
				
			||||||
	handler -- handler string name to print in exception. Optional
 | 
					 | 
				
			||||||
	return -- True if all arguments are passed, none if not
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	for i in requiredArguments:
 | 
					 | 
				
			||||||
		if i not in arguments:
 | 
					 | 
				
			||||||
			return False
 | 
					 | 
				
			||||||
	return True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def printArguments(t):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Print passed arguments, for debug purposes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	t -- tornado object (self)
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	print("ARGS::")
 | 
					 | 
				
			||||||
	for i in t.request.arguments:
 | 
					 | 
				
			||||||
		print ("{}={}".format(i, t.get_argument(i)))
 | 
					 | 
				
			||||||
@@ -1,15 +1,18 @@
 | 
				
			|||||||
from objects import glob
 | 
					import math
 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
from helpers import consoleHelper
 | 
					 | 
				
			||||||
import psutil
 | 
					 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					import signal
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import threading
 | 
					import threading
 | 
				
			||||||
import signal
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
from constants import bcolors
 | 
					 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
import math
 | 
					
 | 
				
			||||||
 | 
					import psutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.constants import bcolors
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from constants import serverPackets
 | 
				
			||||||
 | 
					from helpers import consoleHelper
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def dispose():
 | 
					def dispose():
 | 
				
			||||||
	"""
 | 
						"""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,640 +0,0 @@
 | 
				
			|||||||
from helpers import passwordHelper
 | 
					 | 
				
			||||||
from constants import gameModes
 | 
					 | 
				
			||||||
from constants import privileges
 | 
					 | 
				
			||||||
from helpers import generalFunctions
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
import time
 | 
					 | 
				
			||||||
from constants import privileges
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getID(username):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get username's user ID from userID cache (if cache hit)
 | 
					 | 
				
			||||||
	or from db (and cache it for other requests) if cache miss
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	username -- user
 | 
					 | 
				
			||||||
	return -- user id or 0
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	# Add to cache if needed
 | 
					 | 
				
			||||||
	if username not in glob.userIDCache:
 | 
					 | 
				
			||||||
		userID = glob.db.fetch("SELECT id FROM users WHERE username = %s LIMIT 1", [username])
 | 
					 | 
				
			||||||
		if userID == None:
 | 
					 | 
				
			||||||
			return 0
 | 
					 | 
				
			||||||
		glob.userIDCache[username] = userID["id"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Get userID from cache
 | 
					 | 
				
			||||||
	return glob.userIDCache[username]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def checkLogin(userID, password):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check userID's login with specified password
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	db -- database connection
 | 
					 | 
				
			||||||
	userID -- user id
 | 
					 | 
				
			||||||
	password -- plain md5 password
 | 
					 | 
				
			||||||
	return -- True or False
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	# Get password data
 | 
					 | 
				
			||||||
	passwordData = glob.db.fetch("SELECT password_md5, salt, password_version FROM users WHERE id = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Make sure the query returned something
 | 
					 | 
				
			||||||
	if passwordData is None:
 | 
					 | 
				
			||||||
		return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Return valid/invalid based on the password version.
 | 
					 | 
				
			||||||
	if passwordData["password_version"] == 2:
 | 
					 | 
				
			||||||
		return passwordHelper.checkNewPassword(password, passwordData["password_md5"])
 | 
					 | 
				
			||||||
	if passwordData["password_version"] == 1:
 | 
					 | 
				
			||||||
		ok = passwordHelper.checkOldPassword(password, passwordData["salt"], passwordData["password_md5"])
 | 
					 | 
				
			||||||
		if not ok: return False
 | 
					 | 
				
			||||||
		newpass = passwordHelper.genBcrypt(password)
 | 
					 | 
				
			||||||
		glob.db.execute("UPDATE users SET password_md5=%s, salt='', password_version='2' WHERE id = %s LIMIT 1", [newpass, userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def exists(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check if userID exists
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- user ID to check
 | 
					 | 
				
			||||||
	return -- bool
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	result = glob.db.fetch("SELECT id FROM users WHERE id = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
	if result is None:
 | 
					 | 
				
			||||||
		return False
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		return True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getSilenceEnd(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get userID's **ABSOLUTE** silence end UNIX time
 | 
					 | 
				
			||||||
	Remember to subtract time.time() to get the actual silence time
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID
 | 
					 | 
				
			||||||
	return -- UNIX time
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	return glob.db.fetch("SELECT silence_end FROM users WHERE id = %s LIMIT 1", [userID])["silence_end"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def silence(userID, seconds, silenceReason, author = 999):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Silence someone
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID
 | 
					 | 
				
			||||||
	seconds -- silence length in seconds
 | 
					 | 
				
			||||||
	silenceReason -- Silence reason shown on website
 | 
					 | 
				
			||||||
	author -- userID of who silenced the user. Default: 999
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	# db qurey
 | 
					 | 
				
			||||||
	silenceEndTime = int(time.time())+seconds
 | 
					 | 
				
			||||||
	glob.db.execute("UPDATE users SET silence_end = %s, silence_reason = %s WHERE id = %s LIMIT 1", [silenceEndTime, silenceReason, userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Loh
 | 
					 | 
				
			||||||
	targetUsername = getUsername(userID)
 | 
					 | 
				
			||||||
	# TODO: exists check im drunk rn i need to sleep (stampa piede ubriaco confirmed)
 | 
					 | 
				
			||||||
	if seconds > 0:
 | 
					 | 
				
			||||||
		log.rap(author, "has silenced {} for {} seconds for the following reason: \"{}\"".format(targetUsername, seconds, silenceReason), True)
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		log.rap(author, "has removed {}'s silence".format(targetUsername), True)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getRankedScore(userID, gameMode):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get userID's ranked score relative to gameMode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID
 | 
					 | 
				
			||||||
	gameMode -- int value, see gameModes
 | 
					 | 
				
			||||||
	return -- ranked score
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	modeForDB = gameModes.getGameModeForDB(gameMode)
 | 
					 | 
				
			||||||
	return glob.db.fetch("SELECT ranked_score_"+modeForDB+" FROM users_stats WHERE id = %s LIMIT 1", [userID])["ranked_score_"+modeForDB]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getTotalScore(userID, gameMode):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get userID's total score relative to gameMode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID
 | 
					 | 
				
			||||||
	gameMode -- int value, see gameModes
 | 
					 | 
				
			||||||
	return -- total score
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	modeForDB = gameModes.getGameModeForDB(gameMode)
 | 
					 | 
				
			||||||
	return glob.db.fetch("SELECT total_score_"+modeForDB+" FROM users_stats WHERE id = %s LIMIT 1", [userID])["total_score_"+modeForDB]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getAccuracy(userID, gameMode):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get userID's average accuracy relative to gameMode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID
 | 
					 | 
				
			||||||
	gameMode -- int value, see gameModes
 | 
					 | 
				
			||||||
	return -- accuracy
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	modeForDB = gameModes.getGameModeForDB(gameMode)
 | 
					 | 
				
			||||||
	return glob.db.fetch("SELECT avg_accuracy_"+modeForDB+" FROM users_stats WHERE id = %s LIMIT 1", [userID])["avg_accuracy_"+modeForDB]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getGameRank(userID, gameMode):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get userID's **in-game rank** (eg: #1337) relative to gameMode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID
 | 
					 | 
				
			||||||
	gameMode -- int value, see gameModes
 | 
					 | 
				
			||||||
	return -- game rank
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	modeForDB = gameModes.getGameModeForDB(gameMode)
 | 
					 | 
				
			||||||
	result = glob.db.fetch("SELECT position FROM leaderboard_"+modeForDB+" WHERE user = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
	if result is None:
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		return result["position"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getPlaycount(userID, gameMode):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get userID's playcount relative to gameMode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID
 | 
					 | 
				
			||||||
	gameMode -- int value, see gameModes
 | 
					 | 
				
			||||||
	return -- playcount
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	modeForDB = gameModes.getGameModeForDB(gameMode)
 | 
					 | 
				
			||||||
	return glob.db.fetch("SELECT playcount_"+modeForDB+" FROM users_stats WHERE id = %s LIMIT 1", [userID])["playcount_"+modeForDB]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getUsername(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get userID's username
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID
 | 
					 | 
				
			||||||
	return -- username
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return glob.db.fetch("SELECT username FROM users WHERE id = %s LIMIT 1", [userID])["username"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getFriendList(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get userID's friendlist
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID
 | 
					 | 
				
			||||||
	return -- list with friends userIDs. [0] if no friends.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Get friends from db
 | 
					 | 
				
			||||||
	friends = glob.db.fetchAll("SELECT user2 FROM users_relationships WHERE user1 = %s", [userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if friends is None or len(friends) == 0:
 | 
					 | 
				
			||||||
		# We have no friends, return 0 list
 | 
					 | 
				
			||||||
		return [0]
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		# Get only friends
 | 
					 | 
				
			||||||
		friends = [i["user2"] for i in friends]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Return friend IDs
 | 
					 | 
				
			||||||
		return friends
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def addFriend(userID, friendID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Add friendID to userID's friend list
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- user
 | 
					 | 
				
			||||||
	friendID -- new friend
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Make sure we aren't adding us to our friends
 | 
					 | 
				
			||||||
	if userID == friendID:
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# check user isn't already a friend of ours
 | 
					 | 
				
			||||||
	if glob.db.fetch("SELECT id FROM users_relationships WHERE user1 = %s AND user2 = %s LIMIT 1", [userID, friendID]) is not None:
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Set new value
 | 
					 | 
				
			||||||
	glob.db.execute("INSERT INTO users_relationships (user1, user2) VALUES (%s, %s)", [userID, friendID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def removeFriend(userID, friendID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Remove friendID from userID's friend list
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- user
 | 
					 | 
				
			||||||
	friendID -- old friend
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	# Delete user relationship. We don't need to check if the relationship was there, because who gives a shit,
 | 
					 | 
				
			||||||
	# if they were not friends and they don't want to be anymore, be it. ¯\_(ツ)_/¯
 | 
					 | 
				
			||||||
	glob.db.execute("DELETE FROM users_relationships WHERE user1 = %s AND user2 = %s", [userID, friendID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getCountry(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get userID's country **(two letters)**.
 | 
					 | 
				
			||||||
	Use countryHelper.getCountryID with what that function returns
 | 
					 | 
				
			||||||
	to get osu! country ID relative to that user
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- user
 | 
					 | 
				
			||||||
	return -- country code (two letters)
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	return glob.db.fetch("SELECT country FROM users_stats WHERE id = %s LIMIT 1", [userID])["country"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getPP(userID, gameMode):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get userID's PP relative to gameMode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- user
 | 
					 | 
				
			||||||
	return -- PP
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	modeForDB = gameModes.getGameModeForDB(gameMode)
 | 
					 | 
				
			||||||
	return glob.db.fetch("SELECT pp_{} FROM users_stats WHERE id = %s LIMIT 1".format(modeForDB), [userID])["pp_{}".format(modeForDB)]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def setCountry(userID, country):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Set userID's country (two letters)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- userID
 | 
					 | 
				
			||||||
	country -- country letters
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	glob.db.execute("UPDATE users_stats SET country = %s WHERE id = %s LIMIT 1", [country, userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def logIP(userID, ip):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	User IP log
 | 
					 | 
				
			||||||
	USED FOR MULTIACCOUNT DETECTION
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	glob.db.execute("""INSERT INTO ip_user (userid, ip, occurencies) VALUES (%s, %s, 1)
 | 
					 | 
				
			||||||
						ON DUPLICATE KEY UPDATE occurencies = occurencies + 1""", [userID, ip])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def saveBanchoSession(userID, ip):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Save userid and ip of this token in bancho_sessions table.
 | 
					 | 
				
			||||||
	Used to cache logins on LETS requests
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID --
 | 
					 | 
				
			||||||
	ip -- user's ip address
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	glob.db.execute("INSERT INTO bancho_sessions (id, userid, ip) VALUES (NULL, %s, %s)", [userID, ip])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def deleteBanchoSessions(userID, ip):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Delete this bancho session from DB
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID --
 | 
					 | 
				
			||||||
	ip -- user's IP address
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	try:
 | 
					 | 
				
			||||||
		glob.db.execute("DELETE FROM bancho_sessions WHERE userid = %s AND ip = %s", [userID, ip])
 | 
					 | 
				
			||||||
	except:
 | 
					 | 
				
			||||||
		log.warning("Token for user: {} ip: {} doesn't exist".format(userID, ip))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def is2FAEnabled(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check if 2FA is enabled on an account
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID --
 | 
					 | 
				
			||||||
	return -- True if 2FA is enabled, False if 2FA is disabled
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	result = glob.db.fetch("SELECT id FROM 2fa_telegram WHERE userid = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
	return True if result is not None else False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def check2FA(userID, ip):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check if an ip is trusted
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID --
 | 
					 | 
				
			||||||
	ip -- user's IP address
 | 
					 | 
				
			||||||
	return -- True if the IP is untrusted, False if it's trusted
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	if not is2FAEnabled(userID):
 | 
					 | 
				
			||||||
		return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	result = glob.db.fetch("SELECT id FROM ip_user WHERE userid = %s AND ip = %s", [userID, ip])
 | 
					 | 
				
			||||||
	return True if result is None else False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getUserStats(userID, gameMode):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Get all user stats relative to gameMode with only two queries
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID --
 | 
					 | 
				
			||||||
	gameMode -- gameMode number
 | 
					 | 
				
			||||||
	return -- dictionary with results
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	modeForDB = gameModes.getGameModeForDB(gameMode)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Get stats
 | 
					 | 
				
			||||||
	stats = glob.db.fetch("""SELECT
 | 
					 | 
				
			||||||
						ranked_score_{gm} AS rankedScore,
 | 
					 | 
				
			||||||
						avg_accuracy_{gm} AS accuracy,
 | 
					 | 
				
			||||||
						playcount_{gm} AS playcount,
 | 
					 | 
				
			||||||
						total_score_{gm} AS totalScore,
 | 
					 | 
				
			||||||
						pp_{gm} AS pp
 | 
					 | 
				
			||||||
						FROM users_stats WHERE id = %s LIMIT 1""".format(gm=modeForDB), [userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Get game rank
 | 
					 | 
				
			||||||
	result = glob.db.fetch("SELECT position FROM leaderboard_{} WHERE user = %s LIMIT 1".format(modeForDB), [userID])
 | 
					 | 
				
			||||||
	if result is None:
 | 
					 | 
				
			||||||
		stats["gameRank"] = 0
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		stats["gameRank"] = result["position"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Return stats + game rank
 | 
					 | 
				
			||||||
	return stats
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def isAllowed(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check if userID is not banned or restricted
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of the user
 | 
					 | 
				
			||||||
	return -- True if not banned or restricted, otherwise false.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	result = glob.db.fetch("SELECT privileges FROM users WHERE id = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
	if result is not None:
 | 
					 | 
				
			||||||
		return (result["privileges"] & privileges.USER_NORMAL) and (result["privileges"] & privileges.USER_PUBLIC)
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def isRestricted(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check if userID is restricted
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of the user
 | 
					 | 
				
			||||||
	return -- True if not restricted, otherwise false.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	result = glob.db.fetch("SELECT privileges FROM users WHERE id = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
	if result is not None:
 | 
					 | 
				
			||||||
		return (result["privileges"] & privileges.USER_NORMAL) and not (result["privileges"] & privileges.USER_PUBLIC)
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def isBanned(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check if userID is banned
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of the user
 | 
					 | 
				
			||||||
	return -- True if not banned, otherwise false.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	result = glob.db.fetch("SELECT privileges FROM users WHERE id = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
	if result is not None:
 | 
					 | 
				
			||||||
		return not (result["privileges"] & 3 > 0)
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		return True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def isLocked(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Check if userID is locked
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of the user
 | 
					 | 
				
			||||||
	return -- True if not locked, otherwise false.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	result = glob.db.fetch("SELECT privileges FROM users WHERE id = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
	if result != None:
 | 
					 | 
				
			||||||
		return ((result["privileges"] & privileges.USER_PUBLIC > 0) and (result["privileges"] & privileges.USER_NORMAL == 0))
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		return True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def ban(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Ban userID
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of user
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	banDateTime = int(time.time())
 | 
					 | 
				
			||||||
	glob.db.execute("UPDATE users SET privileges = privileges & %s, ban_datetime = %s WHERE id = %s LIMIT 1", [ ~(privileges.USER_NORMAL | privileges.USER_PUBLIC | privileges.USER_PENDING_VERIFICATION) , banDateTime, userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def unban(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Unban userID
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of user
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	glob.db.execute("UPDATE users SET privileges = privileges | %s, ban_datetime = 0 WHERE id = %s LIMIT 1", [ (privileges.USER_NORMAL | privileges.USER_PUBLIC) , userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def restrict(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Put userID in restricted mode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of user
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	banDateTime = int(time.time())
 | 
					 | 
				
			||||||
	glob.db.execute("UPDATE users SET privileges = privileges & %s, ban_datetime = %s WHERE id = %s LIMIT 1", [~privileges.USER_PUBLIC, banDateTime, userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def unrestrict(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Remove restricted mode from userID.
 | 
					 | 
				
			||||||
	Same as unban().
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of user
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	unban(userID)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getPrivileges(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Return privileges for userID
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of user
 | 
					 | 
				
			||||||
	return -- privileges number
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	result = glob.db.fetch("SELECT privileges FROM users WHERE id = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
	if result is not None:
 | 
					 | 
				
			||||||
		return result["privileges"]
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def setPrivileges(userID, priv):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Set userID's privileges in db
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of user
 | 
					 | 
				
			||||||
	priv -- privileges number
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	glob.db.execute("UPDATE users SET privileges = %s WHERE id = %s LIMIT 1", [priv, userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def isInPrivilegeGroup(userID, groupName):
 | 
					 | 
				
			||||||
	groupPrivileges = glob.db.fetch("SELECT privileges FROM privileges_groups WHERE name = %s LIMIT 1", [groupName])
 | 
					 | 
				
			||||||
	if groupPrivileges is None:
 | 
					 | 
				
			||||||
		return False
 | 
					 | 
				
			||||||
	groupPrivileges = groupPrivileges["privileges"]
 | 
					 | 
				
			||||||
	userToken = glob.tokens.getTokenFromUserID(userID)
 | 
					 | 
				
			||||||
	if userToken is not None:
 | 
					 | 
				
			||||||
		userPrivileges = userToken.privileges
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		userPrivileges = getPrivileges(userID)
 | 
					 | 
				
			||||||
	return (userPrivileges == groupPrivileges) or (userPrivileges == (groupPrivileges | privileges.USER_DONOR))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def appendNotes(userID, notes, addNl = True):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Append "notes" to current userID's "notes for CM"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- id of user
 | 
					 | 
				
			||||||
	notes -- text to append
 | 
					 | 
				
			||||||
	addNl -- if True, prepend \n to notes. Optional. Default: True.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	if addNl:
 | 
					 | 
				
			||||||
		notes = "\n"+notes
 | 
					 | 
				
			||||||
	glob.db.execute("UPDATE users SET notes=CONCAT(COALESCE(notes, ''),%s) WHERE id = %s LIMIT 1", [notes, userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def logHardware(userID, hashes, activation = False):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Hardware log
 | 
					 | 
				
			||||||
	USED FOR MULTIACCOUNT DETECTION
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Peppy's botnet (client data) structure (new line = "|", already split)
 | 
					 | 
				
			||||||
	[0] osu! version
 | 
					 | 
				
			||||||
	[1] plain mac addressed, separated by "."
 | 
					 | 
				
			||||||
	[2] mac addresses hash set
 | 
					 | 
				
			||||||
	[3] unique ID
 | 
					 | 
				
			||||||
	[4] disk ID
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return -- True if hw is not banned, otherwise false
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	# Make sure the strings are not empty
 | 
					 | 
				
			||||||
	for i in hashes[2:5]:
 | 
					 | 
				
			||||||
		if i == "":
 | 
					 | 
				
			||||||
			log.warning("Invalid hash set ({}) for user {} in HWID check".format(hashes, userID), "bunk")
 | 
					 | 
				
			||||||
			return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Run some HWID checks on that user if he is not restricted
 | 
					 | 
				
			||||||
	if not isRestricted(userID):
 | 
					 | 
				
			||||||
		# Get username
 | 
					 | 
				
			||||||
		username = getUsername(userID)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Get the list of banned or restricted users that have logged in from this or similar HWID hash set
 | 
					 | 
				
			||||||
		banned = glob.db.fetchAll("""SELECT users.id as userid, hw_user.occurencies, users.username FROM hw_user
 | 
					 | 
				
			||||||
						LEFT JOIN users ON users.id = hw_user.userid
 | 
					 | 
				
			||||||
						WHERE hw_user.userid != %(userid)s
 | 
					 | 
				
			||||||
						AND (IF(%(mac)s!='b4ec3c4334a0249dae95c284ec5983df', hw_user.mac = %(mac)s, 1) AND hw_user.unique_id = %(uid)s AND hw_user.disk_id = %(diskid)s)
 | 
					 | 
				
			||||||
						AND (users.privileges & 3 != 3)""", {
 | 
					 | 
				
			||||||
							"userid": userID,
 | 
					 | 
				
			||||||
							"mac": hashes[2],
 | 
					 | 
				
			||||||
							"uid": hashes[3],
 | 
					 | 
				
			||||||
							"diskid": hashes[4],
 | 
					 | 
				
			||||||
						})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for i in banned:
 | 
					 | 
				
			||||||
			# Get the total numbers of logins
 | 
					 | 
				
			||||||
			total = glob.db.fetch("SELECT COUNT(*) AS count FROM hw_user WHERE userid = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
			# and make sure it is valid
 | 
					 | 
				
			||||||
			if total is None:
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			total = total["count"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			# Calculate 10% of total
 | 
					 | 
				
			||||||
			perc = (total*10)/100
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if i["occurencies"] >= perc:
 | 
					 | 
				
			||||||
				# If the banned user has logged in more than 10% of the times from this user, restrict this user
 | 
					 | 
				
			||||||
				restrict(userID)
 | 
					 | 
				
			||||||
				appendNotes(userID, "-- Logged in from HWID ({hwid}) used more than 10% from user {banned} ({bannedUserID}), who is banned/restricted.".format(
 | 
					 | 
				
			||||||
					hwid=hashes[2:5],
 | 
					 | 
				
			||||||
					banned=i["username"],
 | 
					 | 
				
			||||||
					bannedUserID=i["userid"]
 | 
					 | 
				
			||||||
				))
 | 
					 | 
				
			||||||
				log.warning("**{user}** ({userID}) has been restricted because he has logged in from HWID _({hwid})_ used more than 10% from banned/restricted user **{banned}** ({bannedUserID}), **possible multiaccount**.".format(
 | 
					 | 
				
			||||||
					user=username,
 | 
					 | 
				
			||||||
					userID=userID,
 | 
					 | 
				
			||||||
					hwid=hashes[2:5],
 | 
					 | 
				
			||||||
					banned=i["username"],
 | 
					 | 
				
			||||||
					bannedUserID=i["userid"]
 | 
					 | 
				
			||||||
				), "cm")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Update hash set occurencies
 | 
					 | 
				
			||||||
	glob.db.execute("""
 | 
					 | 
				
			||||||
				INSERT INTO hw_user (id, userid, mac, unique_id, disk_id, occurencies) VALUES (NULL, %s, %s, %s, %s, 1)
 | 
					 | 
				
			||||||
				ON DUPLICATE KEY UPDATE occurencies = occurencies + 1
 | 
					 | 
				
			||||||
				""", [userID, hashes[2], hashes[3], hashes[4]])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Optionally, set this hash as 'used for activation'
 | 
					 | 
				
			||||||
	if activation:
 | 
					 | 
				
			||||||
		glob.db.execute("UPDATE hw_user SET activated = 1 WHERE userid = %s AND mac = %s AND unique_id = %s AND disk_id = %s", [userID, hashes[2], hashes[3], hashes[4]])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Access granted, abbiamo impiegato 3 giorni
 | 
					 | 
				
			||||||
	# We grant access even in case of login from banned HWID
 | 
					 | 
				
			||||||
	# because we call restrict() above so there's no need to deny the access.
 | 
					 | 
				
			||||||
	return True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def resetPendingFlag(userID, success=True):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Remove pending flag from an user.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	userID -- ID of the user
 | 
					 | 
				
			||||||
	success -- if True, set USER_PUBLIC and USER_NORMAL flags too
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	glob.db.execute("UPDATE users SET privileges = privileges & %s WHERE id = %s LIMIT 1", [~privileges.USER_PENDING_VERIFICATION, userID])
 | 
					 | 
				
			||||||
	if success:
 | 
					 | 
				
			||||||
		glob.db.execute("UPDATE users SET privileges = privileges | %s WHERE id = %s LIMIT 1", [(privileges.USER_PUBLIC | privileges.USER_NORMAL), userID])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def verifyUser(userID, hashes):
 | 
					 | 
				
			||||||
	# Check for valid hash set
 | 
					 | 
				
			||||||
	for i in hashes[2:5]:
 | 
					 | 
				
			||||||
		if i == "":
 | 
					 | 
				
			||||||
			log.warning("Invalid hash set ({}) for user {} while verifying the account".format(str(hashes), userID), "bunk")
 | 
					 | 
				
			||||||
			return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Get username
 | 
					 | 
				
			||||||
	username = getUsername(userID)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	# Make sure there are no other accounts activated with this exact mac/unique id/hwid
 | 
					 | 
				
			||||||
	match = glob.db.fetchAll("SELECT userid FROM hw_user WHERE (IF(%(mac)s != 'b4ec3c4334a0249dae95c284ec5983df', mac = %(mac)s, 1) AND unique_id = %(uid)s AND disk_id = %(diskid)s) AND userid != %(userid)s AND activated = 1 LIMIT 1", {
 | 
					 | 
				
			||||||
		"mac": hashes[2],
 | 
					 | 
				
			||||||
		"uid": hashes[3],
 | 
					 | 
				
			||||||
		"diskid": hashes[4],
 | 
					 | 
				
			||||||
		"userid": userID
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if match:
 | 
					 | 
				
			||||||
		# This is a multiaccount, restrict other account and ban this account
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Get original userID and username (lowest ID)
 | 
					 | 
				
			||||||
		originalUserID = match[0]["userid"]
 | 
					 | 
				
			||||||
		originalUsername = getUsername(originalUserID)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Ban this user and append notes
 | 
					 | 
				
			||||||
		ban(userID)	# this removes the USER_PENDING_VERIFICATION flag too
 | 
					 | 
				
			||||||
		appendNotes(userID, "-- {}'s multiaccount ({}), found HWID match while verifying account ({})".format(originalUsername, originalUserID, hashes[2:5]))
 | 
					 | 
				
			||||||
		appendNotes(originalUserID, "-- Has created multiaccount {} ({})".format(username, userID))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Restrict the original
 | 
					 | 
				
			||||||
		restrict(originalUserID)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Discord message
 | 
					 | 
				
			||||||
		log.warning("User **{originalUsername}** ({originalUserID}) has been restricted because he has created multiaccount **{username}** ({userID}). The multiaccount has been banned.".format(
 | 
					 | 
				
			||||||
			originalUsername=originalUsername,
 | 
					 | 
				
			||||||
			originalUserID=originalUserID,
 | 
					 | 
				
			||||||
			username=username,
 | 
					 | 
				
			||||||
			userID=userID
 | 
					 | 
				
			||||||
		), "cm")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Disallow login
 | 
					 | 
				
			||||||
		return False
 | 
					 | 
				
			||||||
	else:
 | 
					 | 
				
			||||||
		# No matches found, set USER_PUBLIC and USER_NORMAL flags and reset USER_PENDING_VERIFICATION flag
 | 
					 | 
				
			||||||
		resetPendingFlag(userID)
 | 
					 | 
				
			||||||
		log.info("User **{}** ({}) has verified his account with hash set _{}_".format(username, userID, hashes[2:5]), "cm")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		# Allow login
 | 
					 | 
				
			||||||
		return True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def hasVerifiedHardware(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	userID -- id of the user
 | 
					 | 
				
			||||||
	return -- True if hwid activation data is in db, otherwise false
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	data = glob.db.fetch("SELECT id FROM hw_user WHERE userid = %s AND activated = 1 LIMIT 1", [userID])
 | 
					 | 
				
			||||||
	if data is not None:
 | 
					 | 
				
			||||||
		return True
 | 
					 | 
				
			||||||
	return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def cacheUserIDs():
 | 
					 | 
				
			||||||
	"""Cache userIDs in glob.userIDCache, used later with getID()."""
 | 
					 | 
				
			||||||
	data = glob.db.fetchAll("SELECT id, username FROM users WHERE privileges & {} > 0".format(privileges.USER_NORMAL))
 | 
					 | 
				
			||||||
	for i in data:
 | 
					 | 
				
			||||||
		glob.userIDCache[i["username"]] = i["id"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def getDonorExpire(userID):
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	Return userID's donor expiration UNIX timestamp
 | 
					 | 
				
			||||||
	:param userID:
 | 
					 | 
				
			||||||
	:return: donor expiration UNIX timestamp
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	data = glob.db.fetch("SELECT donor_expire FROM users WHERE id = %s LIMIT 1", [userID])
 | 
					 | 
				
			||||||
	if data is not None:
 | 
					 | 
				
			||||||
		return data["donor_expire"]
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
@@ -6,19 +6,21 @@ by Joel Rosdahl, licensed under the GNU GPL 2 License.
 | 
				
			|||||||
Most of the reference code from miniircd was used for the low-level logic.
 | 
					Most of the reference code from miniircd was used for the low-level logic.
 | 
				
			||||||
The high-level code has been rewritten to make it compatible with pep.py.
 | 
					The high-level code has been rewritten to make it compatible with pep.py.
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
import sys
 | 
					 | 
				
			||||||
import traceback
 | 
					 | 
				
			||||||
import socket
 | 
					 | 
				
			||||||
import select
 | 
					 | 
				
			||||||
import time
 | 
					 | 
				
			||||||
import re
 | 
					 | 
				
			||||||
import hashlib
 | 
					import hashlib
 | 
				
			||||||
from helpers import logHelper as log
 | 
					import re
 | 
				
			||||||
 | 
					import select
 | 
				
			||||||
 | 
					import socket
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					import traceback
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from helpers import chatHelper as chat
 | 
					 | 
				
			||||||
import raven
 | 
					import raven
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from helpers import chatHelper as chat
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Client:
 | 
					class Client:
 | 
				
			||||||
	"""
 | 
						"""
 | 
				
			||||||
	IRC Client object
 | 
						IRC Client object
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
# TODO: Rewrite this shit
 | 
					# TODO: Rewrite this shit
 | 
				
			||||||
 | 
					from common import generalUtils
 | 
				
			||||||
from objects import glob
 | 
					from objects import glob
 | 
				
			||||||
from helpers import generalFunctions
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class banchoConfig:
 | 
					class banchoConfig:
 | 
				
			||||||
	"""
 | 
						"""
 | 
				
			||||||
@@ -26,8 +27,8 @@ class banchoConfig:
 | 
				
			|||||||
		"""
 | 
							"""
 | 
				
			||||||
		(re)load bancho_settings from DB and set values in config array
 | 
							(re)load bancho_settings from DB and set values in config array
 | 
				
			||||||
		"""
 | 
							"""
 | 
				
			||||||
		self.config["banchoMaintenance"] = generalFunctions.stringToBool(glob.db.fetch("SELECT value_int FROM bancho_settings WHERE name = 'bancho_maintenance'")["value_int"])
 | 
							self.config["banchoMaintenance"] = generalUtils.stringToBool(glob.db.fetch("SELECT value_int FROM bancho_settings WHERE name = 'bancho_maintenance'")["value_int"])
 | 
				
			||||||
		self.config["freeDirect"] = generalFunctions.stringToBool(glob.db.fetch("SELECT value_int FROM bancho_settings WHERE name = 'free_direct'")["value_int"])
 | 
							self.config["freeDirect"] = generalUtils.stringToBool(glob.db.fetch("SELECT value_int FROM bancho_settings WHERE name = 'free_direct'")["value_int"])
 | 
				
			||||||
		self.config["menuIcon"] = glob.db.fetch("SELECT value_string FROM bancho_settings WHERE name = 'menu_icon'")["value_string"]
 | 
							self.config["menuIcon"] = glob.db.fetch("SELECT value_string FROM bancho_settings WHERE name = 'menu_icon'")["value_string"]
 | 
				
			||||||
		self.config["loginNotification"] = glob.db.fetch("SELECT value_string FROM bancho_settings WHERE name = 'login_notification'")["value_string"]
 | 
							self.config["loginNotification"] = glob.db.fetch("SELECT value_string FROM bancho_settings WHERE name = 'login_notification'")["value_string"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
from objects import glob
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from objects import channel
 | 
					from objects import channel
 | 
				
			||||||
from helpers import logHelper as log
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class channelList:
 | 
					class channelList:
 | 
				
			||||||
	"""
 | 
						"""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,79 +0,0 @@
 | 
				
			|||||||
from objects import glob
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class buffer():
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	A file buffer object.
 | 
					 | 
				
			||||||
	This buffer caches data in memory and when it's full, it writes the content to a file.
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	def __init__(self, fileName, writeType="a", maxLength=512):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		A file buffer object
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param fileName: Path and name of file on disk .
 | 
					 | 
				
			||||||
		:param writeType: File write type. Optional. Default: "a" .
 | 
					 | 
				
			||||||
		:param maxLength: Max length before writing buffer to disk. Optional. Default: 512.
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		self.content = ""
 | 
					 | 
				
			||||||
		self.length = 0
 | 
					 | 
				
			||||||
		self.fileName = fileName
 | 
					 | 
				
			||||||
		self.writeType = writeType
 | 
					 | 
				
			||||||
		self.maxLength = maxLength
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def write(self, newData):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Add data to buffer.
 | 
					 | 
				
			||||||
		If the total length of the data in buffer is greater than or equal to self.maxLength,
 | 
					 | 
				
			||||||
		the content is written on the disk and the buffer resets
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param newData: Data to append to buffer
 | 
					 | 
				
			||||||
		:return:
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		self.content += newData
 | 
					 | 
				
			||||||
		self.length += len(newData)
 | 
					 | 
				
			||||||
		if self.length >= self.maxLength:
 | 
					 | 
				
			||||||
			self.flush()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def flush(self):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Write buffer content to disk and reset its content
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:return:
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		try:
 | 
					 | 
				
			||||||
			glob.fLocks.lockFile(self.fileName)
 | 
					 | 
				
			||||||
			with open(self.fileName, self.writeType) as f:
 | 
					 | 
				
			||||||
				f.write(self.content)
 | 
					 | 
				
			||||||
		finally:
 | 
					 | 
				
			||||||
			glob.fLocks.unlockFile(self.fileName)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		self.content = ""
 | 
					 | 
				
			||||||
		self.length = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class buffersList():
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	A list of buffers
 | 
					 | 
				
			||||||
	"""
 | 
					 | 
				
			||||||
	def __init__(self):
 | 
					 | 
				
			||||||
		self.buffers = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def write(self, fileName, content):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Write some data to an existing buffer in this list (or create a new one if it doesn't exist).
 | 
					 | 
				
			||||||
		If the buffer is full, the data is written to the file and the buffer resets.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:param fileName: Path of file/buffer
 | 
					 | 
				
			||||||
		:param content: New content
 | 
					 | 
				
			||||||
		:return:
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		if fileName not in self.buffers:
 | 
					 | 
				
			||||||
			self.buffers[fileName] = buffer(fileName)
 | 
					 | 
				
			||||||
		self.buffers[fileName].write(content)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def flushAll(self):
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		Write all buffers to file and flush them
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		:return:
 | 
					 | 
				
			||||||
		"""
 | 
					 | 
				
			||||||
		for _, value in self.buffers.items():
 | 
					 | 
				
			||||||
			value.flush()
 | 
					 | 
				
			||||||
@@ -1,20 +0,0 @@
 | 
				
			|||||||
import threading
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class fileLocks:
 | 
					 | 
				
			||||||
	def __init__(self):
 | 
					 | 
				
			||||||
		# Dictionary containing threading.Lock s
 | 
					 | 
				
			||||||
		self.locks = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def lockFile(self, fileName):
 | 
					 | 
				
			||||||
		if fileName in self.locks:
 | 
					 | 
				
			||||||
			# Acquire existing lock
 | 
					 | 
				
			||||||
			self.locks[fileName].acquire()
 | 
					 | 
				
			||||||
		else:
 | 
					 | 
				
			||||||
			# Create new lock and acquire it
 | 
					 | 
				
			||||||
			self.locks[fileName] = threading.Lock()
 | 
					 | 
				
			||||||
			self.locks[fileName].acquire()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	def unlockFile(self, fileName):
 | 
					 | 
				
			||||||
		if fileName in self.locks:
 | 
					 | 
				
			||||||
			# Release lock if it exists
 | 
					 | 
				
			||||||
			self.locks[fileName].release()
 | 
					 | 
				
			||||||
@@ -1,11 +1,12 @@
 | 
				
			|||||||
"""FokaBot related functions"""
 | 
					"""FokaBot related functions"""
 | 
				
			||||||
from helpers import userHelper
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from constants import actions
 | 
					 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
from constants import fokabotCommands
 | 
					 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
from helpers import generalFunctions
 | 
					
 | 
				
			||||||
 | 
					from common import generalUtils
 | 
				
			||||||
 | 
					from common.constants import actions
 | 
				
			||||||
 | 
					from common.ripple import userUtils
 | 
				
			||||||
 | 
					from constants import fokabotCommands
 | 
				
			||||||
 | 
					from constants import serverPackets
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Tillerino np regex, compiled only once to increase performance
 | 
					# Tillerino np regex, compiled only once to increase performance
 | 
				
			||||||
npRegex = re.compile("^https?:\\/\\/osu\\.ppy\\.sh\\/b\\/(\\d*)")
 | 
					npRegex = re.compile("^https?:\\/\\/osu\\.ppy\\.sh\\/b\\/(\\d*)")
 | 
				
			||||||
@@ -34,13 +35,13 @@ def fokabotResponse(fro, chan, message):
 | 
				
			|||||||
	for i in fokabotCommands.commands:
 | 
						for i in fokabotCommands.commands:
 | 
				
			||||||
		# Loop though all commands
 | 
							# Loop though all commands
 | 
				
			||||||
		#if i["trigger"] in message:
 | 
							#if i["trigger"] in message:
 | 
				
			||||||
		if generalFunctions.strContains(message, i["trigger"]):
 | 
							if generalUtils.strContains(message, i["trigger"]):
 | 
				
			||||||
			# message has triggered a command
 | 
								# message has triggered a command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			# Make sure the user has right permissions
 | 
								# Make sure the user has right permissions
 | 
				
			||||||
			if i["privileges"] is not None:
 | 
								if i["privileges"] is not None:
 | 
				
			||||||
				# Rank = x
 | 
									# Rank = x
 | 
				
			||||||
				if userHelper.getPrivileges(userHelper.getID(fro)) & i["privileges"] == 0:
 | 
									if userUtils.getPrivileges(userUtils.getID(fro)) & i["privileges"] == 0:
 | 
				
			||||||
					return False
 | 
										return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			# Check argument number
 | 
								# Check argument number
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
"""Global objects and variables"""
 | 
					"""Global objects and variables"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from objects import tokenList
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.ddog import datadogClient
 | 
				
			||||||
 | 
					from common.files import fileBuffer, fileLocks
 | 
				
			||||||
from objects import channelList
 | 
					from objects import channelList
 | 
				
			||||||
from objects import matchList
 | 
					from objects import matchList
 | 
				
			||||||
from objects import fileLocks
 | 
					 | 
				
			||||||
from objects import fileBuffer
 | 
					 | 
				
			||||||
from objects import streamList
 | 
					from objects import streamList
 | 
				
			||||||
import time
 | 
					from objects import tokenList
 | 
				
			||||||
 | 
					from common.web import schiavo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
	with open("version") as f:
 | 
						with open("version") as f:
 | 
				
			||||||
@@ -16,6 +18,7 @@ try:
 | 
				
			|||||||
except:
 | 
					except:
 | 
				
			||||||
	VERSION = "¯\_(xd)_/¯"
 | 
						VERSION = "¯\_(xd)_/¯"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DATADOG_PREFIX = "peppy"
 | 
				
			||||||
application = None
 | 
					application = None
 | 
				
			||||||
db = None
 | 
					db = None
 | 
				
			||||||
conf = None
 | 
					conf = None
 | 
				
			||||||
@@ -26,6 +29,8 @@ matches = matchList.matchList()
 | 
				
			|||||||
restarting = False
 | 
					restarting = False
 | 
				
			||||||
fLocks = fileLocks.fileLocks()
 | 
					fLocks = fileLocks.fileLocks()
 | 
				
			||||||
fileBuffers = fileBuffer.buffersList()
 | 
					fileBuffers = fileBuffer.buffersList()
 | 
				
			||||||
 | 
					schiavo = schiavo.schiavo()
 | 
				
			||||||
 | 
					dog = datadogClient.datadogClient()
 | 
				
			||||||
verifiedCache = {}
 | 
					verifiedCache = {}
 | 
				
			||||||
cloudflare = False
 | 
					cloudflare = False
 | 
				
			||||||
chatFilters = None
 | 
					chatFilters = None
 | 
				
			||||||
@@ -36,7 +41,6 @@ busyThreads = 0
 | 
				
			|||||||
debug = False
 | 
					debug = False
 | 
				
			||||||
outputRequestTime = False
 | 
					outputRequestTime = False
 | 
				
			||||||
outputPackets = False
 | 
					outputPackets = False
 | 
				
			||||||
discord = False
 | 
					 | 
				
			||||||
gzip = False
 | 
					gzip = False
 | 
				
			||||||
localize = False
 | 
					localize = False
 | 
				
			||||||
sentry = False
 | 
					sentry = False
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,19 @@
 | 
				
			|||||||
# TODO: Enqueue all
 | 
					# TODO: Enqueue all
 | 
				
			||||||
from constants import gameModes
 | 
					import copy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common import generalUtils
 | 
				
			||||||
 | 
					from common.constants import gameModes
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from constants import dataTypes
 | 
				
			||||||
 | 
					from constants import matchModModes
 | 
				
			||||||
from constants import matchScoringTypes
 | 
					from constants import matchScoringTypes
 | 
				
			||||||
from constants import matchTeamTypes
 | 
					from constants import matchTeamTypes
 | 
				
			||||||
from constants import matchModModes
 | 
					 | 
				
			||||||
from constants import slotStatuses
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
from constants import serverPackets
 | 
					 | 
				
			||||||
from constants import dataTypes
 | 
					 | 
				
			||||||
from constants import matchTeams
 | 
					from constants import matchTeams
 | 
				
			||||||
from helpers import logHelper as log
 | 
					from constants import serverPackets
 | 
				
			||||||
 | 
					from constants import slotStatuses
 | 
				
			||||||
from helpers import chatHelper as chat
 | 
					from helpers import chatHelper as chat
 | 
				
			||||||
from helpers import generalFunctions
 | 
					from objects import glob
 | 
				
			||||||
import copy
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class slot:
 | 
					class slot:
 | 
				
			||||||
	def __init__(self):
 | 
						def __init__(self):
 | 
				
			||||||
@@ -35,7 +37,7 @@ class match:
 | 
				
			|||||||
	beatmapMD5 = ""
 | 
						beatmapMD5 = ""
 | 
				
			||||||
	slots = []
 | 
						slots = []
 | 
				
			||||||
	hostUserID = 0
 | 
						hostUserID = 0
 | 
				
			||||||
	gameMode = gameModes.std
 | 
						gameMode = gameModes.STD
 | 
				
			||||||
	matchScoringType = matchScoringTypes.score
 | 
						matchScoringType = matchScoringTypes.score
 | 
				
			||||||
	matchTeamType = matchTeamTypes.headToHead
 | 
						matchTeamType = matchTeamTypes.headToHead
 | 
				
			||||||
	matchModMode = matchModModes.normal
 | 
						matchModMode = matchModModes.normal
 | 
				
			||||||
@@ -59,7 +61,7 @@ class match:
 | 
				
			|||||||
		self.mods = 0
 | 
							self.mods = 0
 | 
				
			||||||
		self.matchName = matchName
 | 
							self.matchName = matchName
 | 
				
			||||||
		if matchPassword != "":
 | 
							if matchPassword != "":
 | 
				
			||||||
			self.matchPassword = generalFunctions.stringMd5(matchPassword)
 | 
								self.matchPassword = generalUtils.stringMd5(matchPassword)
 | 
				
			||||||
		else:
 | 
							else:
 | 
				
			||||||
			self.matchPassword = ""
 | 
								self.matchPassword = ""
 | 
				
			||||||
		self.beatmapID = beatmapID
 | 
							self.beatmapID = beatmapID
 | 
				
			||||||
@@ -487,7 +489,7 @@ class match:
 | 
				
			|||||||
		newPassword -- new password string
 | 
							newPassword -- new password string
 | 
				
			||||||
		"""
 | 
							"""
 | 
				
			||||||
		if newPassword != "":
 | 
							if newPassword != "":
 | 
				
			||||||
			self.matchPassword = generalFunctions.stringMd5(newPassword)
 | 
								self.matchPassword = generalUtils.stringMd5(newPassword)
 | 
				
			||||||
		else:
 | 
							else:
 | 
				
			||||||
			self.matchPassword = ""
 | 
								self.matchPassword = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +1,15 @@
 | 
				
			|||||||
from constants import actions
 | 
					import threading
 | 
				
			||||||
from constants import gameModes
 | 
					import time
 | 
				
			||||||
from helpers import userHelper
 | 
					import uuid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.constants import gameModes, actions
 | 
				
			||||||
 | 
					from common.log import logUtils as log
 | 
				
			||||||
 | 
					from common.ripple import userUtils
 | 
				
			||||||
from constants import serverPackets
 | 
					from constants import serverPackets
 | 
				
			||||||
from events import logoutEvent
 | 
					from events import logoutEvent
 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
import uuid
 | 
					 | 
				
			||||||
import time
 | 
					 | 
				
			||||||
import threading
 | 
					 | 
				
			||||||
from helpers import chatHelper as chat
 | 
					from helpers import chatHelper as chat
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class token:
 | 
					class token:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,11 +26,11 @@ class token:
 | 
				
			|||||||
		"""
 | 
							"""
 | 
				
			||||||
		# Set stuff
 | 
							# Set stuff
 | 
				
			||||||
		self.userID = userID
 | 
							self.userID = userID
 | 
				
			||||||
		self.username = userHelper.getUsername(self.userID)
 | 
							self.username = userUtils.getUsername(self.userID)
 | 
				
			||||||
		self.privileges = userHelper.getPrivileges(self.userID)
 | 
							self.privileges = userUtils.getPrivileges(self.userID)
 | 
				
			||||||
		self.admin = userHelper.isInPrivilegeGroup(self.userID, "developer") or userHelper.isInPrivilegeGroup(self.userID, "community manager")
 | 
							self.admin = userUtils.isInPrivilegeGroup(self.userID, "developer") or userUtils.isInPrivilegeGroup(self.userID, "community manager")
 | 
				
			||||||
		self.irc = irc
 | 
							self.irc = irc
 | 
				
			||||||
		self.restricted = userHelper.isRestricted(self.userID)
 | 
							self.restricted = userUtils.isRestricted(self.userID)
 | 
				
			||||||
		self.loginTime = int(time.time())
 | 
							self.loginTime = int(time.time())
 | 
				
			||||||
		self.pingTime = self.loginTime
 | 
							self.pingTime = self.loginTime
 | 
				
			||||||
		self.timeOffset = timeOffset
 | 
							self.timeOffset = timeOffset
 | 
				
			||||||
@@ -58,7 +59,7 @@ class token:
 | 
				
			|||||||
		self.actionText = ""
 | 
							self.actionText = ""
 | 
				
			||||||
		self.actionMd5 = ""
 | 
							self.actionMd5 = ""
 | 
				
			||||||
		self.actionMods = 0
 | 
							self.actionMods = 0
 | 
				
			||||||
		self.gameMode = gameModes.std
 | 
							self.gameMode = gameModes.STD
 | 
				
			||||||
		self.beatmapID = 0
 | 
							self.beatmapID = 0
 | 
				
			||||||
		self.rankedScore = 0
 | 
							self.rankedScore = 0
 | 
				
			||||||
		self.accuracy = 0.0
 | 
							self.accuracy = 0.0
 | 
				
			||||||
@@ -78,7 +79,7 @@ class token:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		# If we have a valid ip, save bancho session in DB so we can cache LETS logins
 | 
							# If we have a valid ip, save bancho session in DB so we can cache LETS logins
 | 
				
			||||||
		if ip != "":
 | 
							if ip != "":
 | 
				
			||||||
			userHelper.saveBanchoSession(self.userID, self.ip)
 | 
								userUtils.saveBanchoSession(self.userID, self.ip)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Join main stream
 | 
							# Join main stream
 | 
				
			||||||
		self.joinStream("main")
 | 
							self.joinStream("main")
 | 
				
			||||||
@@ -275,7 +276,7 @@ class token:
 | 
				
			|||||||
		"""
 | 
							"""
 | 
				
			||||||
		# Silence in db and token
 | 
							# Silence in db and token
 | 
				
			||||||
		self.silenceEndTime = int(time.time())+seconds
 | 
							self.silenceEndTime = int(time.time())+seconds
 | 
				
			||||||
		userHelper.silence(self.userID, seconds, reason, author)
 | 
							userUtils.silence(self.userID, seconds, reason, author)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Send silence packet to target
 | 
							# Send silence packet to target
 | 
				
			||||||
		self.enqueue(serverPackets.silenceEndTime(seconds))
 | 
							self.enqueue(serverPackets.silenceEndTime(seconds))
 | 
				
			||||||
@@ -316,7 +317,7 @@ class token:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	def updateCachedStats(self):
 | 
						def updateCachedStats(self):
 | 
				
			||||||
		"""Update all cached stats for this token"""
 | 
							"""Update all cached stats for this token"""
 | 
				
			||||||
		stats = userHelper.getUserStats(self.userID, self.gameMode)
 | 
							stats = userUtils.getUserStats(self.userID, self.gameMode)
 | 
				
			||||||
		log.debug(str(stats))
 | 
							log.debug(str(stats))
 | 
				
			||||||
		if stats is None:
 | 
							if stats is None:
 | 
				
			||||||
			log.warning("Stats query returned None")
 | 
								log.warning("Stats query returned None")
 | 
				
			||||||
@@ -336,7 +337,7 @@ class token:
 | 
				
			|||||||
					If false, get the cached one. Optional. Default: False
 | 
										If false, get the cached one. Optional. Default: False
 | 
				
			||||||
		"""
 | 
							"""
 | 
				
			||||||
		if force:
 | 
							if force:
 | 
				
			||||||
			self.restricted = userHelper.isRestricted(self.userID)
 | 
								self.restricted = userUtils.isRestricted(self.userID)
 | 
				
			||||||
		if self.restricted:
 | 
							if self.restricted:
 | 
				
			||||||
			self.setRestricted()
 | 
								self.setRestricted()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,11 @@
 | 
				
			|||||||
from objects import osuToken
 | 
					 | 
				
			||||||
from objects import glob
 | 
					 | 
				
			||||||
import time
 | 
					 | 
				
			||||||
import threading
 | 
					import threading
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from common.ripple import userUtils
 | 
				
			||||||
from events import logoutEvent
 | 
					from events import logoutEvent
 | 
				
			||||||
from helpers import userHelper
 | 
					from objects import glob
 | 
				
			||||||
 | 
					from objects import osuToken
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class tokenList:
 | 
					class tokenList:
 | 
				
			||||||
	"""
 | 
						"""
 | 
				
			||||||
@@ -39,7 +41,7 @@ class tokenList:
 | 
				
			|||||||
		if token in self.tokens:
 | 
							if token in self.tokens:
 | 
				
			||||||
			# Delete session from DB
 | 
								# Delete session from DB
 | 
				
			||||||
			if self.tokens[token].ip != "":
 | 
								if self.tokens[token].ip != "":
 | 
				
			||||||
				userHelper.deleteBanchoSessions(self.tokens[token].userID, self.tokens[token].ip)
 | 
									userUtils.deleteBanchoSessions(self.tokens[token].userID, self.tokens[token].ip)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			# Pop token from list
 | 
								# Pop token from list
 | 
				
			||||||
			self.tokens.pop(token)
 | 
								self.tokens.pop(token)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										64
									
								
								pep.py
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								pep.py
									
									
									
									
									
								
							@@ -2,39 +2,36 @@
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import threading
 | 
					import threading
 | 
				
			||||||
 | 
					from multiprocessing.pool import ThreadPool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import tornado.gen
 | 
					import tornado.gen
 | 
				
			||||||
import tornado.httpserver
 | 
					import tornado.httpserver
 | 
				
			||||||
import tornado.ioloop
 | 
					import tornado.ioloop
 | 
				
			||||||
import tornado.web
 | 
					import tornado.web
 | 
				
			||||||
from multiprocessing.pool import ThreadPool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Raven
 | 
					 | 
				
			||||||
from raven.contrib.tornado import AsyncSentryClient
 | 
					from raven.contrib.tornado import AsyncSentryClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# pep.py files
 | 
					from common import generalUtils
 | 
				
			||||||
from constants import bcolors
 | 
					from common.constants import bcolors
 | 
				
			||||||
from helpers import configHelper
 | 
					from common.db import dbConnector
 | 
				
			||||||
from objects import glob
 | 
					from common.log import logUtils as log
 | 
				
			||||||
from objects import fokabot
 | 
					from common.ripple import userUtils
 | 
				
			||||||
from objects import banchoConfig
 | 
					from common.web import schiavo
 | 
				
			||||||
from objects import chatFilters
 | 
					from handlers import apiFokabotMessageHandler
 | 
				
			||||||
from helpers import consoleHelper
 | 
					 | 
				
			||||||
from helpers import databaseHelperNew
 | 
					 | 
				
			||||||
from helpers import generalFunctions
 | 
					 | 
				
			||||||
from helpers import logHelper as log
 | 
					 | 
				
			||||||
from helpers import userHelper
 | 
					 | 
				
			||||||
from helpers import systemHelper as system
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from handlers import mainHandler
 | 
					 | 
				
			||||||
from handlers import apiIsOnlineHandler
 | 
					from handlers import apiIsOnlineHandler
 | 
				
			||||||
from handlers import apiOnlineUsersHandler
 | 
					from handlers import apiOnlineUsersHandler
 | 
				
			||||||
from handlers import apiServerStatusHandler
 | 
					from handlers import apiServerStatusHandler
 | 
				
			||||||
from handlers import ciTriggerHandler
 | 
					 | 
				
			||||||
from handlers import apiVerifiedStatusHandler
 | 
					from handlers import apiVerifiedStatusHandler
 | 
				
			||||||
from handlers import apiFokabotMessageHandler
 | 
					from handlers import ciTriggerHandler
 | 
				
			||||||
 | 
					from handlers import mainHandler
 | 
				
			||||||
 | 
					from helpers import configHelper
 | 
				
			||||||
 | 
					from helpers import consoleHelper
 | 
				
			||||||
 | 
					from helpers import systemHelper as system
 | 
				
			||||||
from irc import ircserver
 | 
					from irc import ircserver
 | 
				
			||||||
 | 
					from objects import banchoConfig
 | 
				
			||||||
 | 
					from objects import chatFilters
 | 
				
			||||||
 | 
					from objects import fokabot
 | 
				
			||||||
 | 
					from objects import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def make_app():
 | 
					def make_app():
 | 
				
			||||||
	return tornado.web.Application([
 | 
						return tornado.web.Application([
 | 
				
			||||||
@@ -83,7 +80,7 @@ if __name__ == "__main__":
 | 
				
			|||||||
		# Connect to db
 | 
							# Connect to db
 | 
				
			||||||
		try:
 | 
							try:
 | 
				
			||||||
			consoleHelper.printNoNl("> Connecting to MySQL database...")
 | 
								consoleHelper.printNoNl("> Connecting to MySQL database...")
 | 
				
			||||||
			glob.db = databaseHelperNew.db(glob.conf.config["db"]["host"], glob.conf.config["db"]["username"], glob.conf.config["db"]["password"], glob.conf.config["db"]["database"], int(glob.conf.config["db"]["workers"]))
 | 
								glob.db = dbConnector.db(glob.conf.config["db"]["host"], glob.conf.config["db"]["username"], glob.conf.config["db"]["password"], glob.conf.config["db"]["database"], int(glob.conf.config["db"]["workers"]))
 | 
				
			||||||
			consoleHelper.printNoNl(" ")
 | 
								consoleHelper.printNoNl(" ")
 | 
				
			||||||
			consoleHelper.printDone()
 | 
								consoleHelper.printDone()
 | 
				
			||||||
		except:
 | 
							except:
 | 
				
			||||||
@@ -152,29 +149,30 @@ if __name__ == "__main__":
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		# Cache user ids
 | 
							# Cache user ids
 | 
				
			||||||
		consoleHelper.printNoNl("> Caching user IDs... ")
 | 
							consoleHelper.printNoNl("> Caching user IDs... ")
 | 
				
			||||||
		userHelper.cacheUserIDs()
 | 
							userUtils.cacheUserIDs()
 | 
				
			||||||
		consoleHelper.printDone()
 | 
							consoleHelper.printDone()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Localize warning
 | 
							# Localize warning
 | 
				
			||||||
		glob.localize = generalFunctions.stringToBool(glob.conf.config["localize"]["enable"])
 | 
							glob.localize = generalUtils.stringToBool(glob.conf.config["localize"]["enable"])
 | 
				
			||||||
		if not glob.localize:
 | 
							if not glob.localize:
 | 
				
			||||||
			consoleHelper.printColored("[!] Warning! Users localization is disabled!", bcolors.YELLOW)
 | 
								consoleHelper.printColored("[!] Warning! Users localization is disabled!", bcolors.YELLOW)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Discord
 | 
							# Discord
 | 
				
			||||||
		glob.discord = generalFunctions.stringToBool(glob.conf.config["discord"]["enable"])
 | 
							if generalUtils.stringToBool(glob.conf.config["discord"]["enable"]):
 | 
				
			||||||
		if not glob.discord:
 | 
								glob.schiavo = schiavo.schiavo(glob.conf.config["discord"]["boturl"])
 | 
				
			||||||
 | 
							else:
 | 
				
			||||||
			consoleHelper.printColored("[!] Warning! Discord logging is disabled!", bcolors.YELLOW)
 | 
								consoleHelper.printColored("[!] Warning! Discord logging is disabled!", bcolors.YELLOW)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Gzip
 | 
							# Gzip
 | 
				
			||||||
		glob.gzip = generalFunctions.stringToBool(glob.conf.config["server"]["gzip"])
 | 
							glob.gzip = generalUtils.stringToBool(glob.conf.config["server"]["gzip"])
 | 
				
			||||||
		glob.gziplevel = int(glob.conf.config["server"]["gziplevel"])
 | 
							glob.gziplevel = int(glob.conf.config["server"]["gziplevel"])
 | 
				
			||||||
		if not glob.gzip:
 | 
							if not glob.gzip:
 | 
				
			||||||
			consoleHelper.printColored("[!] Warning! Gzip compression is disabled!", bcolors.YELLOW)
 | 
								consoleHelper.printColored("[!] Warning! Gzip compression is disabled!", bcolors.YELLOW)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Debug mode
 | 
							# Debug mode
 | 
				
			||||||
		glob.debug = generalFunctions.stringToBool(glob.conf.config["debug"]["enable"])
 | 
							glob.debug = generalUtils.stringToBool(glob.conf.config["debug"]["enable"])
 | 
				
			||||||
		glob.outputPackets = generalFunctions.stringToBool(glob.conf.config["debug"]["packets"])
 | 
							glob.outputPackets = generalUtils.stringToBool(glob.conf.config["debug"]["packets"])
 | 
				
			||||||
		glob.outputRequestTime = generalFunctions.stringToBool(glob.conf.config["debug"]["time"])
 | 
							glob.outputRequestTime = generalUtils.stringToBool(glob.conf.config["debug"]["time"])
 | 
				
			||||||
		if glob.debug:
 | 
							if glob.debug:
 | 
				
			||||||
			consoleHelper.printColored("[!] Warning! Server running in debug mode!", bcolors.YELLOW)
 | 
								consoleHelper.printColored("[!] Warning! Server running in debug mode!", bcolors.YELLOW)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -183,7 +181,7 @@ if __name__ == "__main__":
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		# Set up sentry
 | 
							# Set up sentry
 | 
				
			||||||
		try:
 | 
							try:
 | 
				
			||||||
			glob.sentry = generalFunctions.stringToBool(glob.conf.config["sentry"]["enable"])
 | 
								glob.sentry = generalUtils.stringToBool(glob.conf.config["sentry"]["enable"])
 | 
				
			||||||
			if glob.sentry:
 | 
								if glob.sentry:
 | 
				
			||||||
				glob.application.sentry_client = AsyncSentryClient(glob.conf.config["sentry"]["banchodns"], release=glob.VERSION)
 | 
									glob.application.sentry_client = AsyncSentryClient(glob.conf.config["sentry"]["banchodns"], release=glob.VERSION)
 | 
				
			||||||
			else:
 | 
								else:
 | 
				
			||||||
@@ -192,10 +190,10 @@ if __name__ == "__main__":
 | 
				
			|||||||
			consoleHelper.printColored("[!] Error while starting sentry client! Please check your config.ini and run the server again", bcolors.RED)
 | 
								consoleHelper.printColored("[!] Error while starting sentry client! Please check your config.ini and run the server again", bcolors.RED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# Cloudflare memes
 | 
							# Cloudflare memes
 | 
				
			||||||
		glob.cloudflare = generalFunctions.stringToBool(glob.conf.config["server"]["cloudflare"])
 | 
							glob.cloudflare = generalUtils.stringToBool(glob.conf.config["server"]["cloudflare"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		# IRC start message and console output
 | 
							# IRC start message and console output
 | 
				
			||||||
		glob.irc = generalFunctions.stringToBool(glob.conf.config["irc"]["enable"])
 | 
							glob.irc = generalUtils.stringToBool(glob.conf.config["irc"]["enable"])
 | 
				
			||||||
		if glob.irc:
 | 
							if glob.irc:
 | 
				
			||||||
			# IRC port
 | 
								# IRC port
 | 
				
			||||||
			try:
 | 
								try:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user