From 6ac3b853f40975e8eef24f8409a30cd27cb688f5 Mon Sep 17 00:00:00 2001 From: Nyo Date: Sun, 3 Jul 2016 20:51:19 +0200 Subject: [PATCH] .BANCHO. New privileges system, add restricted mode --- constants/exceptions.py | 3 + constants/fokabotCommands.py | 104 +++++++++++++++++------- constants/privileges.py | 20 +++++ constants/serverPackets.py | 33 ++++---- events/changeActionEvent.py | 7 +- events/channelJoinEvent.py | 3 +- events/loginEvent.py | 30 +++---- events/sendPrivateMessageEvent.py | 8 +- events/sendPublicMessageEvent.py | 11 ++- handlers/mainHandler.py | 18 +++- helpers/locationHelper.py | 2 +- helpers/packetHelper.py | 8 ++ helpers/userHelper.py | 131 +++++++++++++++++++++++------- objects/fokabot.py | 10 +-- objects/osuToken.py | 17 +++- version | 2 +- 16 files changed, 291 insertions(+), 116 deletions(-) create mode 100644 constants/privileges.py diff --git a/constants/exceptions.py b/constants/exceptions.py index 676cdfd..e9967af 100644 --- a/constants/exceptions.py +++ b/constants/exceptions.py @@ -74,3 +74,6 @@ class userSilencedException(Exception): class need2FAException(Exception): pass + +class userRestrictedException(Exception): + pass diff --git a/constants/fokabotCommands.py b/constants/fokabotCommands.py index d9cd923..398b024 100644 --- a/constants/fokabotCommands.py +++ b/constants/fokabotCommands.py @@ -11,6 +11,7 @@ from constants import mods from helpers import generalFunctions from helpers import logHelper as log from constants import gameModes +from constants import privileges """ Commands callbacks @@ -98,7 +99,7 @@ def kickAll(fro, chan, message): # Kick everyone but mods/admins toKick = [] for key, value in glob.tokens.tokens.items(): - if value.rank < 3: + if value.admin == False: toKick.append(key) # Loop though users to kick (we can't change dictionary size while iterating) @@ -213,7 +214,7 @@ def ban(fro, chan, message): return "{}: user not found".format(target) # Set allowed to 0 - userHelper.setAllowed(targetUserID, 0) + userHelper.ban(targetUserID) # Send ban packet to the user if he's online targetToken = glob.tokens.getTokenFromUsername(target) @@ -236,11 +237,52 @@ def unban(fro, chan, message): return "{}: user not found".format(target) # Set allowed to 1 - userHelper.setAllowed(targetUserID, 1) + userHelper.unban(targetUserID) log.rap(userID, "has unbanned {}".format(target), True) return "Welcome back {}!".format(target) +def restrict(fro, chan, message): + # Get parameters + for i in message: + i = i.lower() + target = message[0].replace("_", " ") + + # Make sure the user exists + targetUserID = userHelper.getID(target) + userID = userHelper.getID(fro) + if targetUserID == False: + return "{}: user not found".format(target) + + # Put this user in restricted mode + userHelper.restrict(targetUserID) + + # Send restricted mode packet to this user if he's online + targetToken = glob.tokens.getTokenFromUsername(target) + if targetToken != None: + targetToken.setRestricted() + + log.rap(userID, "has put {} in restricted mode".format(target), True) + return "Bye bye {}. See you later, maybe.".format(target) + +def unrestrict(fro, chan, message): + # Get parameters + for i in message: + i = i.lower() + target = message[0].replace("_", " ") + + # Make sure the user exists + targetUserID = userHelper.getID(target) + userID = userHelper.getID(fro) + if targetUserID == False: + return "{}: user not found".format(target) + + # Set allowed to 1 + userHelper.unrestrict(targetUserID) + + log.rap(userID, "has removed restricted mode from {}".format(target), True) + return "Welcome back {}!".format(target) + def restartShutdown(restart): """Restart (if restart = True) or shutdown (if restart = False) pep.py safely""" msg = "We are performing some maintenance. Bancho will {} in 5 seconds. Thank you for your patience.".format("restart" if restart else "shutdown") @@ -287,7 +329,7 @@ def systemMaintenance(fro, chan, message): # Disconnect everyone but mod/admins for _, value in glob.tokens.tokens.items(): - if value.rank < 3: + if value.admin == False: who.append(value.userID) glob.tokens.enqueueAll(serverPackets.notification("Our bancho server is in maintenance mode. Please try to login again later.")) @@ -306,7 +348,7 @@ def systemStatus(fro, chan, message): data = systemHelper.getSystemInfo() # Final message - msg = "pep.py bancho server v{}\n".format(glob.VERSION) + msg = "pep.py bancho server v{}".format(glob.VERSION) msg += "made by the Ripple team\n" msg += "\n" msg += "=== BANCHO STATS ===\n" @@ -555,14 +597,7 @@ trigger: message that triggers the command callback: function to call when the command is triggered. Optional. response: text to return when the command is triggered. Optional. syntax: command syntax. Arguments must be separated by spaces (eg: ) -minRank: minimum rank to execute that command. Optional (default = 1) -rank: EXACT rank used to execute that command. Optional. - -RANKS: -1: Normal user -2: Supporter -3: Developer -4: Community manager +privileges: privileges needed to execute the command. Optional. NOTES: - You CAN'T use both rank and minRank at the same time. @@ -593,70 +628,80 @@ commands = [ }, { "trigger": "!alert", "syntax": "", - "minRank": 3, + "privileges": privileges.ADMIN_SEND_ALERTS, "callback": alert }, { "trigger": "!alertuser", "syntax": " ", - "minRank": 3, + "privileges": privileges.ADMIN_SEND_ALERTS, "callback": alertUser, }, { "trigger": "!moderated", - "minRank": 3, + "privileges": privileges.ADMIN_CHAT_MOD, "callback": moderated }, { "trigger": "!kickall", - "rank": 3, + "privileges": privileges.ADMIN_KICK_USERS, "callback": kickAll }, { "trigger": "!kick", "syntax": "", - "minRank": 3, + "privileges": privileges.ADMIN_KICK_USERS, "callback": kick }, { "trigger": "!fokabot reconnect", - "minRank": 3, + "privileges": privileges.ADMIN_MANAGE_SERVERS, "callback": fokabotReconnect }, { "trigger": "!silence", "syntax": " ", - "minRank": 3, + "privileges": privileges.ADMIN_SILENCE_USERS, "callback": silence }, { "trigger": "!removesilence", "syntax": "", - "minRank": 3, + "privileges": privileges.ADMIN_SILENCE_USERS, "callback": removeSilence }, { "trigger": "!system restart", - "rank": 3, + "privileges": privileges.ADMIN_MANAGE_SERVERS, "callback": systemRestart }, { "trigger": "!system shutdown", - "rank": 3, + "privileges": privileges.ADMIN_MANAGE_SERVERS, "callback": systemShutdown }, { "trigger": "!system reload", - "minRank": 3, + "privileges": privileges.ADMIN_MANAGE_SETTINGS, "callback": systemReload }, { "trigger": "!system maintenance", - "rank": 3, + "privileges": privileges.ADMIN_MANAGE_SERVERS, "callback": systemMaintenance }, { "trigger": "!system status", - "rank": 3, + "privileges": privileges.ADMIN_MANAGE_SERVERS, "callback": systemStatus }, { "trigger": "!ban", "syntax": "", - "minRank": 3, + "privileges": privileges.ADMIN_BAN_USERS, "callback": ban }, { "trigger": "!unban", "syntax": "", - "minRank": 3, + "privileges": privileges.ADMIN_BAN_USERS, "callback": unban + }, { + "trigger": "!restrict", + "syntax": "", + "privileges": privileges.ADMIN_BAN_USERS, + "callback": restrict + }, { + "trigger": "!unrestrict", + "syntax": "", + "privileges": privileges.ADMIN_BAN_USERS, + "callback": unrestrict }, { "trigger": "\x01ACTION is listening to", "callback": tillerinoNp @@ -684,7 +729,6 @@ commands = [ # Commands list default values for cmd in commands: cmd.setdefault("syntax", "") - cmd.setdefault("minRank", 1) - cmd.setdefault("rank", None) + cmd.setdefault("privileges", None) cmd.setdefault("callback", None) cmd.setdefault("response", "u w0t m8?") diff --git a/constants/privileges.py b/constants/privileges.py new file mode 100644 index 0000000..165bfc1 --- /dev/null +++ b/constants/privileges.py @@ -0,0 +1,20 @@ +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 diff --git a/constants/serverPackets.py b/constants/serverPackets.py index 831fce3..570dcbe 100644 --- a/constants/serverPackets.py +++ b/constants/serverPackets.py @@ -69,18 +69,15 @@ def friendList(userID): return packetHelper.buildPacket(packetIDs.server_friendsList, friendsData) def onlineUsers(): - onlineUsersData = [] - + userIDs = [] users = glob.tokens.tokens - # Users number - onlineUsersData.append([len(users), dataTypes.uInt16]) + # Create list with all connected (and not restricted) users + for _, value in users.items(): + if value.restricted == False: + userIDs.append(value.userID) - # Add all users user IDs to onlineUsersData - for _,value in users.items(): - onlineUsersData.append([value.userID, dataTypes.sInt32]) - - return packetHelper.buildPacket(packetIDs.server_userPresenceBundle, onlineUsersData) + return packetHelper.buildPacket(packetIDs.server_userPresenceBundle, [[userIDs, dataTypes.intList]]) """ Users packets """ @@ -88,8 +85,14 @@ def userLogout(userID): return packetHelper.buildPacket(packetIDs.server_userLogout, [[userID, dataTypes.sInt32], [0, dataTypes.byte]]) def userPanel(userID): - # Get user data + # Connected and restricted check userToken = glob.tokens.getTokenFromUserID(userID) + if userToken == None: + return bytes() + if userToken.restricted == True: + return bytes() + + # Get user data username = userToken.username timezone = 24 # TODO: Timezone country = userToken.country @@ -99,15 +102,13 @@ def userPanel(userID): # Get username color according to rank # Only admins and normal users are currently supported - #rank = userHelper.getRankPrivileges(userID) - rank = userToken.rank if username == "FokaBot": userRank = userRanks.MOD - elif rank == 4: + elif userHelper.isInPrivilegeGroup(userID, "community manager") == True: userRank = userRanks.MOD - elif rank == 3: + elif userHelper.isInPrivilegeGroup(userID, "developer") == True: userRank = userRanks.ADMIN - elif rank == 2: + elif userHelper.isInPrivilegeGroup(userID, "donator") == True: userRank = userRanks.SUPPORTER else: userRank = userRanks.NORMAL @@ -130,6 +131,8 @@ def userStats(userID): userToken = glob.tokens.getTokenFromUserID(userID) if userToken == None: return bytes() # NOTE: ??? + if userToken.restricted == True: + return bytes() # Stats are cached in token object #rankedScore = userHelper.getRankedScore(userID, userToken.gameMode) #accuracy = userHelper.getAccuracy(userID, userToken.gameMode)/100 diff --git a/events/changeActionEvent.py b/events/changeActionEvent.py index 8a5dd55..bfbdb1b 100644 --- a/events/changeActionEvent.py +++ b/events/changeActionEvent.py @@ -11,10 +11,15 @@ def handle(userToken, packetData): username = userToken.username # Make sure we are not banned - if userHelper.getAllowed(userID) == 0: + if userHelper.isBanned(userID) == True: userToken.enqueue(serverPackets.loginBanned()) return + # Send restricted message if needed + if userToken.restricted == False: + if userHelper.isRestricted(userID) == True: + userToken.setRestricted() + # Change action packet packetData = clientPackets.userActionChange(packetData) diff --git a/events/channelJoinEvent.py b/events/channelJoinEvent.py index cb8afb3..fc14b4c 100644 --- a/events/channelJoinEvent.py +++ b/events/channelJoinEvent.py @@ -26,7 +26,6 @@ def joinChannel(userToken, channelName): # Get usertoken data username = userToken.username userID = userToken.userID - userRank = userToken.rank # Check spectator channel # If it's spectator channel, skip checks and list stuff @@ -37,7 +36,7 @@ def joinChannel(userToken, channelName): raise exceptions.channelUnknownException # Check channel permissions - if glob.channels.channels[channelName].publicRead == False and userRank <= 2: + if glob.channels.channels[channelName].publicRead == False and userToken.admin == False: raise exceptions.channelNoPermissionsException # Add our userID to users in that channel diff --git a/events/loginEvent.py b/events/loginEvent.py index 4ce317e..1ffb579 100644 --- a/events/loginEvent.py +++ b/events/loginEvent.py @@ -31,7 +31,8 @@ def handle(tornadoRequest): err = False # Try to get the ID from username - userID = userHelper.getID(str(loginData[0])) + username = str(loginData[0]) + userID = userHelper.getID(username) if userID == False: # Invalid username @@ -41,9 +42,7 @@ def handle(tornadoRequest): raise exceptions.loginFailedException() # Make sure we are not banned - userAllowed = userHelper.getAllowed(userID) - if userAllowed == 0: - # Banned + if userHelper.isBanned(userID) == True: raise exceptions.loginBannedException() # 2FA check @@ -67,10 +66,9 @@ def handle(tornadoRequest): silenceSeconds = responseToken.getSilenceSecondsLeft() # Get supporter/GMT - userRank = userHelper.getRankPrivileges(userID) userGMT = False userSupporter = True - if userRank >= 3: + if responseToken.admin == True: userGMT = True # Server restarting check @@ -105,9 +103,9 @@ def handle(tornadoRequest): # TODO: Configurable default channels channelJoinEvent.joinChannel(responseToken, "#osu") channelJoinEvent.joinChannel(responseToken, "#announce") - if userRank >= 3: - # Join admin chanenl if we are mod/admin - # TODO: Separate channels for mods and admins + + # Join admin channel if we are an admin + if responseToken.admin == True: channelJoinEvent.joinChannel(responseToken, "#admin") # Output channels info @@ -122,12 +120,6 @@ def handle(tornadoRequest): if glob.banchoConf.config["menuIcon"] != "": responseToken.enqueue(serverPackets.mainMenuIcon(glob.banchoConf.config["menuIcon"])) - # Get everyone else userpanel - # TODO: Better online users handling - #for key, value in glob.tokens.tokens.items(): - # responseToken.enqueue(serverPackets.userPanel(value.userID)) - # responseToken.enqueue(serverPackets.userStats(value.userID)) - # Send online users IDs array responseToken.enqueue(serverPackets.onlineUsers()) @@ -151,10 +143,10 @@ def handle(tornadoRequest): # Set country in db if user has no country (first bancho login) if userHelper.getCountry(userID) == "XX": userHelper.setCountry(userID, countryLetters) - - # Send to everyone our userpanel - glob.tokens.enqueueAll(serverPackets.userPanel(userID)) - #glob.tokens.enqueueAll(serverPackets.userStats(userID)) + + # Send to everyone our userpanel if we are not restricted + if responseToken.restricted == False: + glob.tokens.enqueueAll(serverPackets.userPanel(userID)) # Set reponse data to right value and reset our queue responseData = responseToken.queue diff --git a/events/sendPrivateMessageEvent.py b/events/sendPrivateMessageEvent.py index 88eb6e1..3e34a3e 100644 --- a/events/sendPrivateMessageEvent.py +++ b/events/sendPrivateMessageEvent.py @@ -24,6 +24,10 @@ def handle(userToken, packetData): username = userToken.username userID = userToken.userID + # Make sure the user is not in restricted mode + if userToken.restricted == True: + raise exceptions.userRestrictedException + # Private message packet packetData = clientPackets.sendPrivateMessage(packetData) @@ -47,7 +51,7 @@ def handle(userToken, packetData): raise exceptions.tokenNotFoundException() # Check message templates (mods/admins only) - if packetData["message"] in messageTemplates.templates and userToken.rank >= 3: + if packetData["message"] in messageTemplates.templates and userToken.admin == True: packetData["message"] = messageTemplates.templates[packetData["message"]] # Send message to target @@ -71,3 +75,5 @@ def handle(userToken, packetData): except exceptions.messageTooLongException: # Message > 256 silence userToken.silence(2*3600, "Sending messages longer than 256 characters") + except exceptions.userRestrictedException: + pass diff --git a/events/sendPublicMessageEvent.py b/events/sendPublicMessageEvent.py index 76d2ebc..926c1bd 100644 --- a/events/sendPublicMessageEvent.py +++ b/events/sendPublicMessageEvent.py @@ -20,7 +20,10 @@ def handle(userToken, packetData): # Get userToken data userID = userToken.userID username = userToken.username - userRank = userToken.rank + + # Make sure the user is not in restricted mode + if userToken.restricted == True: + raise exceptions.userRestrictedException # Public chat packet packetData = clientPackets.sendPublicMessage(packetData) @@ -85,11 +88,11 @@ def handle(userToken, packetData): raise exceptions.channelUnknownException # Make sure the channel is not in moderated mode - if glob.channels.channels[packetData["to"]].moderated == True and userRank <= 2: + if glob.channels.channels[packetData["to"]].moderated == True and userToken.admin == False: raise exceptions.channelModeratedException # Make sure we have write permissions - if glob.channels.channels[packetData["to"]].publicWrite == False and userRank <= 2: + if glob.channels.channels[packetData["to"]].publicWrite == False and userToken.admin == False: raise exceptions.channelNoPermissionsException # Send this packet to everyone in that channel except us @@ -128,3 +131,5 @@ def handle(userToken, packetData): except exceptions.messageTooLongException: # Message > 256 silence userToken.silence(2*3600, "Sending messages longer than 256 characters") + except exceptions.userRestrictedException: + pass diff --git a/handlers/mainHandler.py b/handlers/mainHandler.py index 1929bff..f02aa8b 100644 --- a/handlers/mainHandler.py +++ b/handlers/mainHandler.py @@ -156,9 +156,25 @@ class handler(SentryMixin, requestHelper.asyncRequestHandler): packetIDs.client_userPanelRequest: handleEvent(userPanelRequestEvent), } + # Packets processed if in restricted mode. + # All other packets will be ignored if the user is in restricted mode + packetsRestricted = [ + packetIDs.client_logout, + packetIDs.client_userStatsRequest, + packetIDs.client_requestStatusUpdate, + packetIDs.client_userPanelRequest, + packetIDs.client_changeAction, + packetIDs.client_channelJoin, + packetIDs.client_channelPart, + ] + + # Process/ignore packet if packetID != 4: if packetID in eventHandler: - eventHandler[packetID]() + if userToken.restricted == False or (userToken.restricted == True and packetID in packetsRestricted): + eventHandler[packetID]() + else: + log.warning("Ignored packet id from {} ({}) (user is restricted)".format(requestTokenString, packetID)) else: log.warning("Unknown packet id from {} ({})".format(requestTokenString, packetID)) diff --git a/helpers/locationHelper.py b/helpers/locationHelper.py index 250dbec..02d0a3a 100644 --- a/helpers/locationHelper.py +++ b/helpers/locationHelper.py @@ -4,7 +4,7 @@ import json from helpers import logHelper as log # API URL -URL = "http://ip.zxq.co/" +URL = "http://ipinfo.io/" def getCountry(ip): diff --git a/helpers/packetHelper.py b/helpers/packetHelper.py index 84d9687..d701de5 100644 --- a/helpers/packetHelper.py +++ b/helpers/packetHelper.py @@ -100,6 +100,14 @@ def packData(__data, __dataType): # Bytes, do not use pack, do manually pack = False data = __data + elif __dataType == dataTypes.intList: + # Pack manually + pack = False + # Add length + data = packData(len(__data), dataTypes.uInt16) + # Add all elements + for i in __data: + data += packData(i, dataTypes.sInt32) elif __dataType == dataTypes.string: # String, do not use pack, do manually pack = False diff --git a/helpers/userHelper.py b/helpers/userHelper.py index bf92b0e..62dc64a 100644 --- a/helpers/userHelper.py +++ b/helpers/userHelper.py @@ -4,6 +4,7 @@ from helpers import generalFunctions from objects import glob from helpers import logHelper as log import time +from constants import privileges def getID(username): """ @@ -67,27 +68,6 @@ def exists(userID): else: return True -def getAllowed(userID): - """ - Get allowed status for userID - - db -- database connection - userID -- user ID - return -- allowed int - """ - - return glob.db.fetch("SELECT allowed FROM users WHERE id = %s", [userID])["allowed"] - - -def getRankPrivileges(userID): - """ - This returns rank **(PRIVILEGES)**, not game rank (like #1337) - If you want to get that rank, user getUserGameRank instead - """ - - return glob.db.fetch("SELECT rank FROM users WHERE id = %s", [userID])["rank"] - - def getSilenceEnd(userID): """ Get userID's **ABSOLUTE** silence end UNIX time @@ -279,16 +259,6 @@ def getPP(userID, gameMode): modeForDB = gameModes.getGameModeForDB(gameMode) return glob.db.fetch("SELECT pp_{} FROM users_stats WHERE id = %s".format(modeForDB), [userID])["pp_{}".format(modeForDB)] -def setAllowed(userID, allowed): - """ - Set userID's allowed status - - userID -- user - allowed -- allowed status. 1: normal, 0: banned - """ - banDateTime = int(time.time()) if allowed == 0 else 0 - glob.db.execute("UPDATE users SET allowed = %s, ban_datetime = %s WHERE id = %s", [allowed, banDateTime, userID]) - def setCountry(userID, country): """ Set userID's country (two letters) @@ -375,3 +345,102 @@ def getUserStats(userID, gameMode): # 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", [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()) + glob.db.execute("UPDATE users SET privileges = privileges & %s, ban_datetime = %s WHERE id = %s", [ ~(privileges.USER_NORMAL | privileges.USER_PUBLIC) , 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", [ (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 + +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)) diff --git a/objects/fokabot.py b/objects/fokabot.py index 94120a7..2f186fb 100644 --- a/objects/fokabot.py +++ b/objects/fokabot.py @@ -47,16 +47,10 @@ def fokabotResponse(fro, chan, message): # message has triggered a command # Make sure the user has right permissions - if i["rank"] != None: + if i["privileges"] != None: # Rank = x - if userHelper.getRankPrivileges(userHelper.getID(fro)) != i["rank"]: + if userHelper.getPrivileges(userHelper.getID(fro)) & i["privileges"] == 0: return False - else: - # Rank > x - if i["minRank"] > 1: - # Get rank from db only if minrank > 1, so we save some CPU - if userHelper.getRankPrivileges(userHelper.getID(fro)) < i["minRank"]: - return False # Check argument number message = message.split(" ") diff --git a/objects/osuToken.py b/objects/osuToken.py index 672623d..95332e0 100644 --- a/objects/osuToken.py +++ b/objects/osuToken.py @@ -8,6 +8,7 @@ from objects import glob import uuid import time import threading +from helpers import logHelper as log class token: """ @@ -16,7 +17,6 @@ class token: token -- token string userID -- userID associated to that token username -- username relative to userID (cache) - rank -- rank (permissions) relative to userID (cache) actionID -- current user action (see actions.py) actionText -- current user action text actionMd5 -- md5 relative to user action @@ -47,7 +47,11 @@ class token: # Set stuff self.userID = __userID self.username = userHelper.getUsername(self.userID) - self.rank = userHelper.getRankPrivileges(self.userID) + self.privileges = userHelper.getPrivileges(self.userID) + self.admin = userHelper.isInPrivilegeGroup(self.userID, "developer") or userHelper.isInPrivilegeGroup(self.userID, "community manager") + self.restricted = userHelper.isRestricted(self.userID) + if self.restricted == True: + self.setRestricted() self.loginTime = int(time.time()) self.pingTime = self.loginTime self.lock = threading.Lock() # Sync primitive @@ -69,7 +73,6 @@ class token: # Spam protection self.spamRate = 0 - #self.lastMessagetime = 0 # Stats cache self.actionID = actions.idle @@ -295,3 +298,11 @@ class token: self.totalScore = stats["totalScore"] self.gameRank = stats["gameRank"] self.pp = stats["pp"] + + def setRestricted(self): + """ + Set this token as restricted, send FokaBot message to user + and send offline packet to everyone + """ + self.restricted = True + self.enqueue(serverPackets.sendMessage("FokaBot", self.username, "Your account is currently in restricted mode. Please visit ripple's website for more information.")) diff --git a/version b/version index 31e5c84..292b7eb 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.3.3 +1.3.