2016-05-18 17:12:46 +00:00
from helpers import passwordHelper
from constants import gameModes
from helpers import generalFunctions
from objects import glob
2016-06-07 21:19:45 +00:00
from helpers import logHelper as log
import time
2016-07-03 18:51:19 +00:00
from constants import privileges
2016-04-19 17:40:59 +00:00
def getID ( username ) :
"""
Get username ' s user ID
db - - database connection
username - - user
return - - user id or False
"""
# Get user ID from db
2016-05-31 20:49:30 +00:00
userID = glob . db . fetch ( " SELECT id FROM users WHERE username = %s " , [ username ] )
2016-04-19 17:40:59 +00:00
# Make sure the query returned something
if userID == None :
return False
# Return user ID
return userID [ " id " ]
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
2016-05-31 20:49:30 +00:00
passwordData = glob . db . fetch ( " SELECT password_md5, salt, password_version FROM users WHERE id = %s " , [ userID ] )
2016-04-19 17:40:59 +00:00
# Make sure the query returned something
if passwordData == 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 )
2016-05-31 20:49:30 +00:00
glob . db . execute ( " UPDATE users SET password_md5= %s , salt= ' ' , password_version= ' 2 ' WHERE id = %s " , [ newpass , userID ] )
2016-04-19 17:40:59 +00:00
def exists ( userID ) :
"""
Check if userID exists
userID - - user ID to check
return - - bool
"""
2016-05-31 20:49:30 +00:00
result = glob . db . fetch ( " SELECT id FROM users WHERE id = %s " , [ userID ] )
2016-04-19 17:40:59 +00:00
if result == 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
"""
2016-05-31 20:49:30 +00:00
return glob . db . fetch ( " SELECT silence_end FROM users WHERE id = %s " , [ userID ] ) [ " silence_end " ]
2016-04-19 17:40:59 +00:00
2016-06-08 09:33:27 +00:00
def silence ( userID , seconds , silenceReason , author = 999 ) :
2016-04-19 17:40:59 +00:00
"""
2016-06-08 09:33:27 +00:00
Silence someone
2016-04-19 17:40:59 +00:00
userID - - userID
2016-06-08 09:33:27 +00:00
seconds - - silence length in seconds
2016-04-19 17:40:59 +00:00
silenceReason - - Silence reason shown on website
2016-06-07 21:19:45 +00:00
author - - userID of who silenced the user . Default : 999
2016-04-19 17:40:59 +00:00
"""
2016-06-07 21:19:45 +00:00
# db qurey
2016-06-08 09:33:27 +00:00
silenceEndTime = int ( time . time ( ) ) + seconds
2016-05-31 20:49:30 +00:00
glob . db . execute ( " UPDATE users SET silence_end = %s , silence_reason = %s WHERE id = %s " , [ silenceEndTime , silenceReason , userID ] )
2016-04-19 17:40:59 +00:00
2016-06-07 21:19:45 +00:00
# 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 )
2016-04-19 17:40:59 +00:00
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 )
2016-05-31 20:49:30 +00:00
return glob . db . fetch ( " SELECT ranked_score_ " + modeForDB + " FROM users_stats WHERE id = %s " , [ userID ] ) [ " ranked_score_ " + modeForDB ]
2016-04-19 17:40:59 +00:00
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 )
2016-05-31 20:49:30 +00:00
return glob . db . fetch ( " SELECT total_score_ " + modeForDB + " FROM users_stats WHERE id = %s " , [ userID ] ) [ " total_score_ " + modeForDB ]
2016-04-19 17:40:59 +00:00
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 )
2016-05-31 20:49:30 +00:00
return glob . db . fetch ( " SELECT avg_accuracy_ " + modeForDB + " FROM users_stats WHERE id = %s " , [ userID ] ) [ " avg_accuracy_ " + modeForDB ]
2016-04-19 17:40:59 +00:00
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 )
2016-05-31 20:49:30 +00:00
result = glob . db . fetch ( " SELECT position FROM leaderboard_ " + modeForDB + " WHERE user = %s " , [ userID ] )
2016-04-19 17:40:59 +00:00
if result == 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 )
2016-05-31 20:49:30 +00:00
return glob . db . fetch ( " SELECT playcount_ " + modeForDB + " FROM users_stats WHERE id = %s " , [ userID ] ) [ " playcount_ " + modeForDB ]
2016-04-19 17:40:59 +00:00
def getUsername ( userID ) :
"""
Get userID ' s username
userID - - userID
return - - username
"""
2016-05-31 20:49:30 +00:00
return glob . db . fetch ( " SELECT username FROM users WHERE id = %s " , [ userID ] ) [ " username " ]
2016-04-19 17:40:59 +00:00
def getFriendList ( userID ) :
"""
Get userID ' s friendlist
userID - - userID
return - - list with friends userIDs . [ 0 ] if no friends .
"""
# Get friends from db
2016-05-31 20:49:30 +00:00
friends = glob . db . fetchAll ( " SELECT user2 FROM users_relationships WHERE user1 = %s " , [ userID ] )
2016-04-19 17:40:59 +00:00
if friends == 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
2016-05-31 20:49:30 +00:00
if glob . db . fetch ( " SELECT id FROM users_relationships WHERE user1 = %s AND user2 = %s " , [ userID , friendID ] ) != None :
2016-04-19 17:40:59 +00:00
return
# Set new value
2016-05-31 20:49:30 +00:00
glob . db . execute ( " INSERT INTO users_relationships (user1, user2) VALUES ( %s , %s ) " , [ userID , friendID ] )
2016-04-19 17:40:59 +00:00
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. ¯\_(ツ)_/¯
2016-05-31 20:49:30 +00:00
glob . db . execute ( " DELETE FROM users_relationships WHERE user1 = %s AND user2 = %s " , [ userID , friendID ] )
2016-04-19 17:40:59 +00:00
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 )
"""
2016-05-31 20:49:30 +00:00
return glob . db . fetch ( " SELECT country FROM users_stats WHERE id = %s " , [ userID ] ) [ " country " ]
2016-04-19 17:40:59 +00:00
def getPP ( userID , gameMode ) :
"""
Get userID ' s PP relative to gameMode
userID - - user
2016-04-24 09:46:33 +00:00
return - - PP
2016-04-19 17:40:59 +00:00
"""
modeForDB = gameModes . getGameModeForDB ( gameMode )
2016-05-31 20:49:30 +00:00
return glob . db . fetch ( " SELECT pp_ {} FROM users_stats WHERE id = %s " . format ( modeForDB ) , [ userID ] ) [ " pp_ {} " . format ( modeForDB ) ]
2016-04-24 09:46:33 +00:00
2016-05-01 16:09:35 +00:00
def setCountry ( userID , country ) :
"""
Set userID ' s country (two letters)
userID - - userID
country - - country letters
"""
2016-05-31 20:49:30 +00:00
glob . db . execute ( " UPDATE users_stats SET country = %s WHERE id = %s " , [ country , userID ] )
2016-05-01 18:39:01 +00:00
def getShowCountry ( userID ) :
"""
Get userID ' s show country status
userID - - userID
return - - True if country is shown , False if it ' s hidden
"""
2016-05-31 20:49:30 +00:00
country = glob . db . fetch ( " SELECT show_country FROM users_stats WHERE id = %s " , [ userID ] )
2016-05-01 18:39:01 +00:00
if country == None :
return False
return generalFunctions . stringToBool ( country )
2016-05-29 11:32:11 +00:00
def IPLog ( userID , ip ) :
"""
Botnet the user
( log his ip for multiaccount detection )
"""
2016-05-31 20:49:30 +00:00
glob . db . execute ( """ INSERT INTO ip_user (userid, ip, occurencies) VALUES ( %s , %s , ' 1 ' )
2016-05-29 11:32:11 +00:00
ON DUPLICATE KEY UPDATE occurencies = occurencies + 1 """ , [userID, ip])
2016-06-10 11:15:42 +00:00
def saveBanchoSession ( userID , ip ) :
"""
Save userid and ip of this token in bancho_sessions table .
Used to cache logins on LETS requests
"""
log . debug ( " Saving bancho session ( {} :: {} ) in db " . format ( userID , ip ) )
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 """
log . debug ( " Deleting bancho session ( {} :: {} ) from db " . format ( userID , ip ) )
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 ) )
2016-06-11 16:43:27 +00:00
def is2FAEnabled ( userID ) :
""" Returns True if 2FA is enable for this account """
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 ) :
""" Returns True if this IP is untrusted """
if is2FAEnabled ( userID ) == False :
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
2016-06-16 11:38:17 +00:00
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 == None :
stats [ " gameRank " ] = 0
else :
stats [ " gameRank " ] = result [ " position " ]
# Return stats + game rank
return stats
2016-07-03 18:51:19 +00:00
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 " , [ userID ] )
if result != 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 " , [ userID ] )
if result != 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 " , [ userID ] )
if result != None :
return not ( result [ " privileges " ] & privileges . USER_NORMAL ) and not ( result [ " privileges " ] & privileges . USER_PUBLIC )
else :
return True
def ban ( userID ) :
"""
Ban userID
userID - - id of user
"""
banDateTime = int ( time . time ( ) )
2016-07-20 09:59:53 +00:00
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 ] )
2016-07-03 18:51:19 +00:00
def unban ( userID ) :
"""
Unban userID
userID - - id of user
"""
glob . db . execute ( " UPDATE users SET privileges = privileges | %s , ban_datetime = 0 WHERE id = %s " , [ ( 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 " , [ ~ 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 " , [ userID ] )
if result != None :
return result [ " privileges " ]
else :
return 0
2016-07-20 09:59:53 +00:00
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 ] )
2016-07-03 18:51:19 +00:00
def isInPrivilegeGroup ( userID , groupName ) :
groupPrivileges = glob . db . fetch ( " SELECT privileges FROM privileges_groups WHERE name = %s " , [ groupName ] )
if groupPrivileges == None :
return False
groupPrivileges = groupPrivileges [ " privileges " ]
userToken = glob . tokens . getTokenFromUserID ( userID )
if userToken != None :
userPrivileges = userToken . privileges
else :
userPrivileges = getPrivileges ( userID )
return ( userPrivileges == groupPrivileges ) or ( userPrivileges == ( groupPrivileges | privileges . USER_DONOR ) )
2016-07-20 09:59:53 +00:00
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 % f rom 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 % f rom 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