Edited 'last' command to new beatmaps table structure
This commit is contained in:
parent
94d46cf45f
commit
a6bd08e928
|
@ -80,3 +80,6 @@ class userRestrictedException(Exception):
|
||||||
|
|
||||||
class haxException(Exception):
|
class haxException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class forceUpdateException(Exception):
|
||||||
|
pass
|
||||||
|
|
|
@ -528,7 +528,7 @@ def tillerinoAcc(fro, chan, message):
|
||||||
def tillerinoLast(fro, chan, message):
|
def tillerinoLast(fro, chan, message):
|
||||||
try:
|
try:
|
||||||
data = glob.db.fetch("""SELECT beatmaps.song_name as sn, scores.*,
|
data = glob.db.fetch("""SELECT beatmaps.song_name as sn, scores.*,
|
||||||
beatmaps.beatmap_id as bid, beatmaps.difficulty, beatmaps.max_combo as fc
|
beatmaps.beatmap_id as bid, beatmaps.difficulty_std, beatmaps.difficulty_taiko, beatmaps.difficulty_ctb, beatmaps.difficulty_mania, beatmaps.max_combo as fc
|
||||||
FROM scores
|
FROM scores
|
||||||
LEFT JOIN beatmaps ON beatmaps.beatmap_md5=scores.beatmap_md5
|
LEFT JOIN beatmaps ON beatmaps.beatmap_md5=scores.beatmap_md5
|
||||||
LEFT JOIN users ON users.id = scores.userid
|
LEFT JOIN users ON users.id = scores.userid
|
||||||
|
@ -538,6 +538,7 @@ def tillerinoLast(fro, chan, message):
|
||||||
if data == None:
|
if data == None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
diffString = "difficulty_{}".format(gameModes.getGameModeForDB(data["play_mode"]))
|
||||||
rank = generalFunctions.getRank(data["play_mode"], data["mods"], data["accuracy"],\
|
rank = generalFunctions.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"])
|
||||||
|
|
||||||
|
@ -555,7 +556,7 @@ def tillerinoLast(fro, chan, message):
|
||||||
msg += ifFc
|
msg += ifFc
|
||||||
msg += " | {0:.2f}%, {1}".format(data["accuracy"], rank.upper())
|
msg += " | {0:.2f}%, {1}".format(data["accuracy"], rank.upper())
|
||||||
msg += " {{ {0} / {1} / {2} / {3} }}".format(data["300_count"], data["100_count"], data["50_count"], data["misses_count"])
|
msg += " {{ {0} / {1} / {2} / {3} }}".format(data["300_count"], data["100_count"], data["50_count"], data["misses_count"])
|
||||||
msg += " | {0:.2f} stars".format(data["difficulty"])
|
msg += " | {0:.2f} stars".format(data[diffString])
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
msg = ifPlayer
|
msg = ifPlayer
|
||||||
|
@ -566,8 +567,8 @@ def tillerinoLast(fro, chan, message):
|
||||||
msg += ifFc
|
msg += ifFc
|
||||||
msg += " | {0:.2f}pp".format(data["pp"])
|
msg += " | {0:.2f}pp".format(data["pp"])
|
||||||
|
|
||||||
stars = data["difficulty"]
|
stars = data[diffString]
|
||||||
if data["mods"]:
|
if data["mods"] and data["play_mode"] == gameModes.std:
|
||||||
token = glob.tokens.getTokenFromUsername(fro)
|
token = glob.tokens.getTokenFromUsername(fro)
|
||||||
if token == None:
|
if token == None:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -18,3 +18,4 @@ ADMIN_MANAGE_PRIVILEGES = 2 << 15
|
||||||
ADMIN_SEND_ALERTS = 2 << 16
|
ADMIN_SEND_ALERTS = 2 << 16
|
||||||
ADMIN_CHAT_MOD = 2 << 17
|
ADMIN_CHAT_MOD = 2 << 17
|
||||||
ADMIN_KICK_USERS = 2 << 18
|
ADMIN_KICK_USERS = 2 << 18
|
||||||
|
USER_PENDING_VERIFICATION = 2 << 19
|
||||||
|
|
|
@ -14,6 +14,7 @@ from helpers import requestHelper
|
||||||
from helpers import discordBotHelper
|
from helpers import discordBotHelper
|
||||||
from helpers import logHelper as log
|
from helpers import logHelper as log
|
||||||
from helpers import chatHelper as chat
|
from helpers import chatHelper as chat
|
||||||
|
from constants import privileges
|
||||||
|
|
||||||
def handle(tornadoRequest):
|
def handle(tornadoRequest):
|
||||||
# Data to return
|
# Data to return
|
||||||
|
@ -23,6 +24,10 @@ def handle(tornadoRequest):
|
||||||
# Get IP from tornado request
|
# Get IP from tornado request
|
||||||
requestIP = tornadoRequest.getRequestIP()
|
requestIP = tornadoRequest.getRequestIP()
|
||||||
|
|
||||||
|
# Avoid exceptions
|
||||||
|
clientData = ["unknown", "unknown", "unknown", "unknown", "unknown"]
|
||||||
|
osuVersion = "unknown"
|
||||||
|
|
||||||
# Split POST body so we can get username/password/hardware data
|
# Split POST body so we can get username/password/hardware data
|
||||||
# 2:-3 thing is because requestData has some escape stuff that we don't need
|
# 2:-3 thing is because requestData has some escape stuff that we don't need
|
||||||
loginData = str(tornadoRequest.request.body)[2:-3].split("\\n")
|
loginData = str(tornadoRequest.request.body)[2:-3].split("\\n")
|
||||||
|
@ -34,6 +39,19 @@ def handle(tornadoRequest):
|
||||||
if len(loginData) < 3:
|
if len(loginData) < 3:
|
||||||
raise exceptions.haxException()
|
raise exceptions.haxException()
|
||||||
|
|
||||||
|
# Get HWID, MAC address and more
|
||||||
|
# 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
|
||||||
|
splitData = loginData[2].split("|")
|
||||||
|
osuVersion = splitData[0]
|
||||||
|
clientData = splitData[3].split(":")[:5]
|
||||||
|
if len(clientData) < 4:
|
||||||
|
raise exceptions.forceUpdateException()
|
||||||
|
|
||||||
# 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 = userHelper.getID(username)
|
||||||
|
@ -46,7 +64,8 @@ def handle(tornadoRequest):
|
||||||
raise exceptions.loginFailedException()
|
raise exceptions.loginFailedException()
|
||||||
|
|
||||||
# Make sure we are not banned
|
# Make sure we are not banned
|
||||||
if userHelper.isBanned(userID) == True:
|
priv = userHelper.getPrivileges(userID)
|
||||||
|
if userHelper.isBanned(userID) == True and priv & privileges.USER_PENDING_VERIFICATION == 0:
|
||||||
raise exceptions.loginBannedException()
|
raise exceptions.loginBannedException()
|
||||||
|
|
||||||
# 2FA check
|
# 2FA check
|
||||||
|
@ -55,6 +74,29 @@ def handle(tornadoRequest):
|
||||||
raise exceptions.need2FAException()
|
raise exceptions.need2FAException()
|
||||||
|
|
||||||
# No login errors!
|
# No login errors!
|
||||||
|
|
||||||
|
# Verify this user (if pending activation)
|
||||||
|
firstLogin = False
|
||||||
|
if priv & privileges.USER_PENDING_VERIFICATION > 0 or userHelper.hasVerifiedHardware(userID) == False:
|
||||||
|
if userHelper.verifyUser(userID, clientData) == True:
|
||||||
|
# Valid account
|
||||||
|
log.info("Account {} verified successfully!".format(userID))
|
||||||
|
glob.verifiedCache[str(userID)] = 1
|
||||||
|
firstLogin = True
|
||||||
|
else:
|
||||||
|
# Multiaccount detected
|
||||||
|
log.info("Account {} NOT verified!".format(userID))
|
||||||
|
glob.verifiedCache[str(userID)] = 0
|
||||||
|
raise exceptions.loginBannedException()
|
||||||
|
|
||||||
|
# Save HWID in db
|
||||||
|
hwAllowed = userHelper.logHardware(userID, clientData, firstLogin)
|
||||||
|
# This is false only if HWID is empty
|
||||||
|
# if HWID is banned, we get restricted so there's no
|
||||||
|
# need to deny bancho access
|
||||||
|
if hwAllowed == False:
|
||||||
|
raise exceptions.haxException()
|
||||||
|
|
||||||
# Log user IP
|
# Log user IP
|
||||||
userHelper.IPLog(userID, requestIP)
|
userHelper.IPLog(userID, requestIP)
|
||||||
|
|
||||||
|
@ -185,6 +227,12 @@ def handle(tornadoRequest):
|
||||||
except exceptions.need2FAException:
|
except exceptions.need2FAException:
|
||||||
# User tried to log in from unknown IP
|
# User tried to log in from unknown IP
|
||||||
responseData += serverPackets.needVerification()
|
responseData += serverPackets.needVerification()
|
||||||
|
except exceptions.haxException:
|
||||||
|
# Using oldoldold client, we can't check hw. Force update.
|
||||||
|
# (we don't use enqueue because we don't have a token since login has failed)
|
||||||
|
err = True
|
||||||
|
responseData += serverPackets.forceUpdate()
|
||||||
|
responseData += serverPackets.notification("Hory shitto, your client is TOO old! Nice preistoria! Please turn off the switcher and update it.")
|
||||||
except:
|
except:
|
||||||
log.error("Unknown error!\n```\n{}\n{}```".format(sys.exc_info(), traceback.format_exc()))
|
log.error("Unknown error!\n```\n{}\n{}```".format(sys.exc_info(), traceback.format_exc()))
|
||||||
finally:
|
finally:
|
||||||
|
@ -192,8 +240,8 @@ def handle(tornadoRequest):
|
||||||
if len(loginData) < 3:
|
if len(loginData) < 3:
|
||||||
msg = "Invalid bancho login request from **{}** (insufficient POST data)".format(requestIP)
|
msg = "Invalid bancho login request from **{}** (insufficient POST data)".format(requestIP)
|
||||||
else:
|
else:
|
||||||
msg = "Bancho login request from **{}** for user **{}** ({}) **({})**".format(requestIP, loginData[0], loginData[2], "failed" if err == True else "success")
|
msg = "Bancho login request from **{}** for user **{}** _({})_\n_Version: {}\nosu!.exe hash: {}\nMAC: {}\nUID: {}\nHWID: {}_\n".format(requestIP, loginData[0], "failed" if err == True else "success", osuVersion, clientData[0], clientData[2], clientData[3], clientData[4])
|
||||||
log.info(msg, True)
|
log.info(msg, "bunker")
|
||||||
|
|
||||||
# Return token string and data
|
# Return token string and data
|
||||||
return (responseTokenString, responseData)
|
return (responseTokenString, responseData)
|
||||||
|
|
46
handlers/apiVerifiedStatusHandler.py
Normal file
46
handlers/apiVerifiedStatusHandler.py
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
from helpers import requestHelper
|
||||||
|
from helpers import logHelper as log
|
||||||
|
import json
|
||||||
|
from objects import glob
|
||||||
|
from constants import exceptions
|
||||||
|
|
||||||
|
class handler(requestHelper.asyncRequestHandler):
|
||||||
|
def asyncGet(self):
|
||||||
|
statusCode = 400
|
||||||
|
data = {"message": "unknown error"}
|
||||||
|
try:
|
||||||
|
# Check arguments
|
||||||
|
if requestHelper.checkArguments(self.request.arguments, ["u"]) == False:
|
||||||
|
raise exceptions.invalidArgumentsException()
|
||||||
|
|
||||||
|
# Get userID and its verified cache thing
|
||||||
|
# -1: Not in cache
|
||||||
|
# 0: Not verified (multiacc)
|
||||||
|
# 1: Verified
|
||||||
|
userID = self.get_argument("u")
|
||||||
|
data["result"] = -1 if userID not in glob.verifiedCache else glob.verifiedCache[userID]
|
||||||
|
|
||||||
|
# Status code and message
|
||||||
|
statusCode = 200
|
||||||
|
data["message"] = "ok"
|
||||||
|
except exceptions.invalidArgumentsException:
|
||||||
|
statusCode = 400
|
||||||
|
data["message"] = "missing required arguments"
|
||||||
|
finally:
|
||||||
|
# Add status code to data
|
||||||
|
data["status"] = statusCode
|
||||||
|
|
||||||
|
# Send response
|
||||||
|
self.add_header("Access-Control-Allow-Origin", "*")
|
||||||
|
self.add_header("Content-Type", "application/json")
|
||||||
|
|
||||||
|
# jquery meme
|
||||||
|
output = ""
|
||||||
|
if "callback" in self.request.arguments:
|
||||||
|
output += self.get_argument("callback")+"("
|
||||||
|
output += json.dumps(data)
|
||||||
|
if "callback" in self.request.arguments:
|
||||||
|
output += ")"
|
||||||
|
|
||||||
|
self.write(output)
|
||||||
|
self.set_status(statusCode)
|
|
@ -59,3 +59,11 @@ def sendChatlog(message):
|
||||||
message -- message to send
|
message -- message to send
|
||||||
"""
|
"""
|
||||||
sendDiscordMessage("chatlog", message, prefix="")
|
sendDiscordMessage("chatlog", message, prefix="")
|
||||||
|
|
||||||
|
def sendCM(message):
|
||||||
|
"""
|
||||||
|
Send a message to #communitymanagers
|
||||||
|
|
||||||
|
message -- message to send
|
||||||
|
"""
|
||||||
|
sendDiscordMessage("cm", message)
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
from constants import bcolors
|
from constants import bcolors
|
||||||
from helpers import discordBotHelper
|
from helpers import discordBotHelper
|
||||||
from helpers import generalFunctions
|
from helpers import generalFunctions
|
||||||
from helpers.systemHelper import runningUnderUnix
|
|
||||||
from objects import glob
|
from objects import glob
|
||||||
from helpers import userHelper
|
from helpers import userHelper
|
||||||
import time
|
import time
|
||||||
|
import os
|
||||||
|
ENDL = "\n" if os.name == "posix" else "\r\n"
|
||||||
|
|
||||||
ENDL = "\n" if runningUnderUnix() else "\r\n"
|
def logMessage(message, alertType = "INFO", messageColor = bcolors.ENDC, discord = None, alertDev = False, of = None, stdout = True):
|
||||||
|
|
||||||
def logMessage(message, alertType = "INFO", messageColor = bcolors.ENDC, discord = False, alertDev = False, of = None, stdout = True):
|
|
||||||
"""
|
"""
|
||||||
Logs a message to stdout/discord/file
|
Logs a message to stdout/discord/file
|
||||||
|
|
||||||
message -- message to log
|
message -- message to log
|
||||||
alertType -- can be any string. Standard types: INFO, WARNING and ERRORS. Defalt: INFO
|
alertType -- can be any string. Standard types: INFO, WARNING and ERRORS. Defalt: INFO
|
||||||
messageColor -- message color (see constants.bcolors). Default = bcolots.ENDC (no color)
|
messageColor -- message color (see constants.bcolors). Default = bcolots.ENDC (no color)
|
||||||
discord -- if True, the message will be logged on #bunker channel on discord. Default: False
|
discord -- discord channel (bunker/cm/staff/general). Optional. Default = None
|
||||||
alertDev -- if True, devs will receive an hl on discord. Default: False
|
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)
|
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
|
stdout -- if True, print the message to stdout. Default: True
|
||||||
|
@ -52,8 +51,15 @@ def logMessage(message, alertType = "INFO", messageColor = bcolors.ENDC, discord
|
||||||
print(finalMessageConsole)
|
print(finalMessageConsole)
|
||||||
|
|
||||||
# Log to discord if needed
|
# Log to discord if needed
|
||||||
if discord == True:
|
if discord != None:
|
||||||
|
if discord == "bunker":
|
||||||
discordBotHelper.sendConfidential(message, alertDev)
|
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
|
# Log to file if needed
|
||||||
if of != None:
|
if of != None:
|
||||||
|
@ -64,32 +70,32 @@ def logMessage(message, alertType = "INFO", messageColor = bcolors.ENDC, discord
|
||||||
finally:
|
finally:
|
||||||
glob.fLocks.unlockFile(of)
|
glob.fLocks.unlockFile(of)
|
||||||
|
|
||||||
def warning(message, discord = False, alertDev = False):
|
def warning(message, discord = None, alertDev = False):
|
||||||
"""
|
"""
|
||||||
Log a warning to stdout, warnings.log (always) and discord (optional)
|
Log a warning to stdout, warnings.log (always) and discord (optional)
|
||||||
|
|
||||||
message -- warning message
|
message -- warning message
|
||||||
discord -- if True, send warning to #bunker. Optional. Default = False.
|
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.
|
alertDev -- if True, send al hl to devs on discord. Optional. Default = False.
|
||||||
"""
|
"""
|
||||||
logMessage(message, "WARNING", bcolors.YELLOW, discord, alertDev, "warnings.txt")
|
logMessage(message, "WARNING", bcolors.YELLOW, discord, alertDev, "warnings.txt")
|
||||||
|
|
||||||
def error(message, discord = False, alertDev = True):
|
def error(message, discord = None, alertDev = True):
|
||||||
"""
|
"""
|
||||||
Log an error to stdout, errors.log (always) and discord (optional)
|
Log an error to stdout, errors.log (always) and discord (optional)
|
||||||
|
|
||||||
message -- error message
|
message -- error message
|
||||||
discord -- if True, send error to #bunker. Optional. Default = False.
|
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.
|
alertDev -- if True, send al hl to devs on discord. Optional. Default = False.
|
||||||
"""
|
"""
|
||||||
logMessage(message, "ERROR", bcolors.RED, discord, alertDev, "errors.txt")
|
logMessage(message, "ERROR", bcolors.RED, discord, alertDev, "errors.txt")
|
||||||
|
|
||||||
def info(message, discord = False, alertDev = False):
|
def info(message, discord = None, alertDev = False):
|
||||||
"""
|
"""
|
||||||
Log an error to stdout (and info.log)
|
Log an error to stdout (and info.log)
|
||||||
|
|
||||||
message -- info message
|
message -- info message
|
||||||
discord -- if True, send error to #bunker. Optional. Default = False.
|
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.
|
alertDev -- if True, send al hl to devs on discord. Optional. Default = False.
|
||||||
"""
|
"""
|
||||||
logMessage(message, "INFO", bcolors.ENDC, discord, alertDev, "info.txt")
|
logMessage(message, "INFO", bcolors.ENDC, discord, alertDev, "info.txt")
|
||||||
|
|
|
@ -392,7 +392,7 @@ def ban(userID):
|
||||||
userID -- id of user
|
userID -- id of user
|
||||||
"""
|
"""
|
||||||
banDateTime = int(time.time())
|
banDateTime = int(time.time())
|
||||||
glob.db.execute("UPDATE users SET privileges = privileges & %s, ban_datetime = %s WHERE id = %s", [ ~(privileges.USER_NORMAL | privileges.USER_PUBLIC) , banDateTime, userID])
|
glob.db.execute("UPDATE users SET privileges = privileges & %s, ban_datetime = %s WHERE id = %s", [ ~(privileges.USER_NORMAL | privileges.USER_PUBLIC | privileges.USER_PENDING_VERIFICATION) , banDateTime, userID])
|
||||||
|
|
||||||
def unban(userID):
|
def unban(userID):
|
||||||
"""
|
"""
|
||||||
|
@ -433,6 +433,15 @@ def getPrivileges(userID):
|
||||||
else:
|
else:
|
||||||
return 0
|
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", [priv, userID])
|
||||||
|
|
||||||
def isInPrivilegeGroup(userID, groupName):
|
def isInPrivilegeGroup(userID, groupName):
|
||||||
groupPrivileges = glob.db.fetch("SELECT privileges FROM privileges_groups WHERE name = %s", [groupName])
|
groupPrivileges = glob.db.fetch("SELECT privileges FROM privileges_groups WHERE name = %s", [groupName])
|
||||||
if groupPrivileges == None:
|
if groupPrivileges == None:
|
||||||
|
@ -444,3 +453,168 @@ def isInPrivilegeGroup(userID, groupName):
|
||||||
else:
|
else:
|
||||||
userPrivileges = getPrivileges(userID)
|
userPrivileges = getPrivileges(userID)
|
||||||
return (userPrivileges == groupPrivileges) or (userPrivileges == (groupPrivileges | privileges.USER_DONOR))
|
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 == True:
|
||||||
|
notes = "\n"+notes
|
||||||
|
glob.db.execute("UPDATE users SET notes=CONCAT(COALESCE(notes, ''),%s) WHERE id = %s", [notes, userID])
|
||||||
|
|
||||||
|
|
||||||
|
def logHardware(userID, hashes, activation = False):
|
||||||
|
"""
|
||||||
|
Hardware log
|
||||||
|
|
||||||
|
Peppy's botnet 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:
|
||||||
|
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 isRestricted(userID) == False:
|
||||||
|
# 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, 0) OR hw_user.unique_id = %(uid)s OR 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 == 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 == True:
|
||||||
|
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 == True:
|
||||||
|
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:
|
||||||
|
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, 0) OR unique_id = %(uid)s OR 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 != None:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
|
@ -22,6 +22,7 @@ matches = matchList.matchList()
|
||||||
restarting = False
|
restarting = False
|
||||||
pool = None
|
pool = None
|
||||||
fLocks = fileLocks.fileLocks()
|
fLocks = fileLocks.fileLocks()
|
||||||
|
verifiedCache = {}
|
||||||
cloudflare = False
|
cloudflare = False
|
||||||
|
|
||||||
debug = False
|
debug = False
|
||||||
|
|
2
pep.py
2
pep.py
|
@ -30,6 +30,7 @@ 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 ciTriggerHandler
|
||||||
|
from handlers import apiVerifiedStatusHandler
|
||||||
|
|
||||||
from irc import ircserver
|
from irc import ircserver
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ def make_app():
|
||||||
(r"/api/v1/onlineUsers", apiOnlineUsersHandler.handler),
|
(r"/api/v1/onlineUsers", apiOnlineUsersHandler.handler),
|
||||||
(r"/api/v1/serverStatus", apiServerStatusHandler.handler),
|
(r"/api/v1/serverStatus", apiServerStatusHandler.handler),
|
||||||
(r"/api/v1/ciTrigger", ciTriggerHandler.handler),
|
(r"/api/v1/ciTrigger", ciTriggerHandler.handler),
|
||||||
|
(r"/api/v1/verifiedStatus", apiVerifiedStatusHandler.handler),
|
||||||
])
|
])
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in New Issue
Block a user