Merged with upstream
This commit is contained in:
commit
2cd69a9a63
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,3 +7,4 @@ filters.txt
|
||||||
redistest.py
|
redistest.py
|
||||||
*.c
|
*.c
|
||||||
*.so
|
*.so
|
||||||
|
.pyenv
|
|
@ -40,10 +40,10 @@ def instantRestart(fro, chan, message):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def faq(fro, chan, message):
|
def faq(fro, chan, message):
|
||||||
if message[0] in glob.conf.extra["faq"]:
|
key = message[0].lower()
|
||||||
return glob.conf.extra["faq"][message[0]]
|
if key not in glob.conf.extra["faq"]:
|
||||||
|
return False
|
||||||
return False
|
return glob.conf.extra["faq"][key]
|
||||||
|
|
||||||
def roll(fro, chan, message):
|
def roll(fro, chan, message):
|
||||||
maxPoints = 100
|
maxPoints = 100
|
||||||
|
@ -58,8 +58,8 @@ def roll(fro, chan, message):
|
||||||
# return random.choice(["yes", "no", "maybe"])
|
# return random.choice(["yes", "no", "maybe"])
|
||||||
|
|
||||||
def alert(fro, chan, message):
|
def alert(fro, chan, message):
|
||||||
msg = ' '.join(message[:])
|
msg = ' '.join(message[:]).strip()
|
||||||
if not msg.strip():
|
if not msg:
|
||||||
return False
|
return False
|
||||||
glob.streams.broadcast("main", serverPackets.notification(msg))
|
glob.streams.broadcast("main", serverPackets.notification(msg))
|
||||||
return False
|
return False
|
||||||
|
@ -68,8 +68,8 @@ def alertUser(fro, chan, message):
|
||||||
target = message[0].lower()
|
target = message[0].lower()
|
||||||
targetToken = glob.tokens.getTokenFromUsername(userUtils.safeUsername(target), safe=True)
|
targetToken = glob.tokens.getTokenFromUsername(userUtils.safeUsername(target), safe=True)
|
||||||
if targetToken is not None:
|
if targetToken is not None:
|
||||||
msg = ' '.join(message[1:])
|
msg = ' '.join(message[1:]).strip()
|
||||||
if not msg.strip():
|
if not msg:
|
||||||
return False
|
return False
|
||||||
targetToken.enqueue(serverPackets.notification(msg))
|
targetToken.enqueue(serverPackets.notification(msg))
|
||||||
return False
|
return False
|
||||||
|
@ -137,12 +137,15 @@ def fokabotReconnect(fro, chan, message):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def silence(fro, chan, message):
|
def silence(fro, chan, message):
|
||||||
for i in message:
|
message = [x.lower() for x in message]
|
||||||
i = i.lower()
|
|
||||||
target = message[0]
|
target = message[0]
|
||||||
amount = message[1]
|
amount = message[1]
|
||||||
unit = message[2]
|
unit = message[2]
|
||||||
reason = ' '.join(message[3:])
|
reason = ' '.join(message[3:]).strip()
|
||||||
|
if not reason:
|
||||||
|
return "Please provide a valid reason."
|
||||||
|
if not amount.isdigit():
|
||||||
|
return "The amount must be a number."
|
||||||
|
|
||||||
# Get target user ID
|
# Get target user ID
|
||||||
targetUserID = userUtils.getIDSafe(target)
|
targetUserID = userUtils.getIDSafe(target)
|
||||||
|
@ -758,7 +761,10 @@ def multiplayer(fro, chan, message):
|
||||||
def mpMake():
|
def mpMake():
|
||||||
if len(message) < 2:
|
if len(message) < 2:
|
||||||
raise exceptions.invalidArgumentsException("Wrong syntax: !mp make <name>")
|
raise exceptions.invalidArgumentsException("Wrong syntax: !mp make <name>")
|
||||||
matchID = glob.matches.createMatch(" ".join(message[1:]), generalUtils.stringMd5(generalUtils.randomString(32)), 0, "Tournament", "", 0, -1, isTourney=True)
|
matchName = " ".join(message[1:]).strip()
|
||||||
|
if not matchName:
|
||||||
|
raise exceptions.invalidArgumentsException("Match name must not be empty!")
|
||||||
|
matchID = glob.matches.createMatch(matchName, generalUtils.stringMd5(generalUtils.randomString(32)), 0, "Tournament", "", 0, -1, isTourney=True)
|
||||||
glob.matches.matches[matchID].sendUpdates()
|
glob.matches.matches[matchID].sendUpdates()
|
||||||
return "Tourney match #{} created!".format(matchID)
|
return "Tourney match #{} created!".format(matchID)
|
||||||
|
|
||||||
|
@ -812,7 +818,9 @@ def multiplayer(fro, chan, message):
|
||||||
def mpHost():
|
def mpHost():
|
||||||
if len(message) < 2:
|
if len(message) < 2:
|
||||||
raise exceptions.invalidArgumentsException("Wrong syntax: !mp host <username>")
|
raise exceptions.invalidArgumentsException("Wrong syntax: !mp host <username>")
|
||||||
username = message[1]
|
username = message[1].strip()
|
||||||
|
if not username:
|
||||||
|
raise exceptions.invalidArgumentsException("Please provide a username")
|
||||||
userID = userUtils.getIDSafe(username)
|
userID = userUtils.getIDSafe(username)
|
||||||
if userID is None:
|
if userID is None:
|
||||||
raise exceptions.userNotFoundException("No such user")
|
raise exceptions.userNotFoundException("No such user")
|
||||||
|
@ -877,7 +885,9 @@ def multiplayer(fro, chan, message):
|
||||||
def mpInvite():
|
def mpInvite():
|
||||||
if len(message) < 2:
|
if len(message) < 2:
|
||||||
raise exceptions.invalidArgumentsException("Wrong syntax: !mp invite <username>")
|
raise exceptions.invalidArgumentsException("Wrong syntax: !mp invite <username>")
|
||||||
username = message[1]
|
username = message[1].strip()
|
||||||
|
if not username:
|
||||||
|
raise exceptions.invalidArgumentsException("Please provide a username")
|
||||||
userID = userUtils.getIDSafe(username)
|
userID = userUtils.getIDSafe(username)
|
||||||
if userID is None:
|
if userID is None:
|
||||||
raise exceptions.userNotFoundException("No such user")
|
raise exceptions.userNotFoundException("No such user")
|
||||||
|
@ -944,7 +954,9 @@ def multiplayer(fro, chan, message):
|
||||||
def mpKick():
|
def mpKick():
|
||||||
if len(message) < 2:
|
if len(message) < 2:
|
||||||
raise exceptions.invalidArgumentsException("Wrong syntax: !mp kick <username>")
|
raise exceptions.invalidArgumentsException("Wrong syntax: !mp kick <username>")
|
||||||
username = message[1]
|
username = message[1].strip()
|
||||||
|
if not username:
|
||||||
|
raise exceptions.invalidArgumentsException("Please provide a username")
|
||||||
userID = userUtils.getIDSafe(username)
|
userID = userUtils.getIDSafe(username)
|
||||||
if userID is None:
|
if userID is None:
|
||||||
raise exceptions.userNotFoundException("No such user")
|
raise exceptions.userNotFoundException("No such user")
|
||||||
|
@ -957,7 +969,7 @@ def multiplayer(fro, chan, message):
|
||||||
return "{} has been kicked from the match.".format(username)
|
return "{} has been kicked from the match.".format(username)
|
||||||
|
|
||||||
def mpPassword():
|
def mpPassword():
|
||||||
password = "" if len(message) < 2 else message[1]
|
password = "" if len(message) < 2 or not message[1].strip() else message[1]
|
||||||
_match = glob.matches.matches[getMatchIDFromChannel(chan)]
|
_match = glob.matches.matches[getMatchIDFromChannel(chan)]
|
||||||
_match.changePassword(password)
|
_match.changePassword(password)
|
||||||
return "Match password has been changed!"
|
return "Match password has been changed!"
|
||||||
|
@ -1001,7 +1013,9 @@ def multiplayer(fro, chan, message):
|
||||||
def mpTeam():
|
def mpTeam():
|
||||||
if len(message) < 3:
|
if len(message) < 3:
|
||||||
raise exceptions.invalidArgumentsException("Wrong syntax: !mp team <username> <colour>")
|
raise exceptions.invalidArgumentsException("Wrong syntax: !mp team <username> <colour>")
|
||||||
username = message[1]
|
username = message[1].strip()
|
||||||
|
if not username:
|
||||||
|
raise exceptions.invalidArgumentsException("Please provide a username")
|
||||||
colour = message[2].lower().strip()
|
colour = message[2].lower().strip()
|
||||||
if colour not in ["red", "blue"]:
|
if colour not in ["red", "blue"]:
|
||||||
raise exceptions.invalidArgumentsException("Team colour must be red or blue")
|
raise exceptions.invalidArgumentsException("Team colour must be red or blue")
|
||||||
|
@ -1068,7 +1082,7 @@ def multiplayer(fro, chan, message):
|
||||||
if requestedSubcommand not in subcommands:
|
if requestedSubcommand not in subcommands:
|
||||||
raise exceptions.invalidArgumentsException("Invalid subcommand")
|
raise exceptions.invalidArgumentsException("Invalid subcommand")
|
||||||
return subcommands[requestedSubcommand]()
|
return subcommands[requestedSubcommand]()
|
||||||
except (exceptions.invalidArgumentsException, exceptions.userNotFoundException) as e:
|
except (exceptions.invalidArgumentsException, exceptions.userNotFoundException, exceptions.invalidUserException) as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
except exceptions.wrongChannelException:
|
except exceptions.wrongChannelException:
|
||||||
return "This command only works in multiplayer chat channels"
|
return "This command only works in multiplayer chat channels"
|
||||||
|
@ -1080,7 +1094,9 @@ def multiplayer(fro, chan, message):
|
||||||
def switchServer(fro, chan, message):
|
def switchServer(fro, chan, message):
|
||||||
# Get target user ID
|
# Get target user ID
|
||||||
target = message[0]
|
target = message[0]
|
||||||
newServer = message[1]
|
newServer = message[1].strip()
|
||||||
|
if not newServer:
|
||||||
|
return "Invalid server IP"
|
||||||
targetUserID = userUtils.getIDSafe(target)
|
targetUserID = userUtils.getIDSafe(target)
|
||||||
userID = userUtils.getID(fro)
|
userID = userUtils.getID(fro)
|
||||||
|
|
||||||
|
@ -1098,7 +1114,9 @@ def switchServer(fro, chan, message):
|
||||||
|
|
||||||
def rtx(fro, chan, message):
|
def rtx(fro, chan, message):
|
||||||
target = message[0]
|
target = message[0]
|
||||||
message = " ".join(message[1:])
|
message = " ".join(message[1:]).strip()
|
||||||
|
if not message:
|
||||||
|
return "Invalid message"
|
||||||
targetUserID = userUtils.getIDSafe(target)
|
targetUserID = userUtils.getIDSafe(target)
|
||||||
if not targetUserID:
|
if not targetUserID:
|
||||||
return "{}: user not found".format(target)
|
return "{}: user not found".format(target)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from common.log import logUtils as log
|
from common.log import logUtils as log
|
||||||
from constants import clientPackets
|
from constants import clientPackets, serverPackets
|
||||||
from constants import exceptions
|
from constants import exceptions
|
||||||
from objects import glob
|
from objects import glob
|
||||||
|
|
||||||
|
@ -12,9 +12,14 @@ def handle(userToken, packetData):
|
||||||
# Read packet data
|
# Read packet data
|
||||||
packetData = clientPackets.createMatch(packetData)
|
packetData = clientPackets.createMatch(packetData)
|
||||||
|
|
||||||
|
# Make sure the name is valid
|
||||||
|
matchName = packetData["matchName"].strip()
|
||||||
|
if not matchName:
|
||||||
|
raise exceptions.matchCreateError()
|
||||||
|
|
||||||
# Create a match object
|
# Create a match object
|
||||||
# TODO: Player number check
|
# TODO: Player number check
|
||||||
matchID = glob.matches.createMatch(packetData["matchName"], packetData["matchPassword"], packetData["beatmapID"], packetData["beatmapName"], packetData["beatmapMD5"], packetData["gameMode"], userID)
|
matchID = glob.matches.createMatch(matchName, packetData["matchPassword"].strip(), packetData["beatmapID"], packetData["beatmapName"], packetData["beatmapMD5"], packetData["gameMode"], userID)
|
||||||
|
|
||||||
# Make sure the match has been created
|
# Make sure the match has been created
|
||||||
if matchID not in glob.matches.matches:
|
if matchID not in glob.matches.matches:
|
||||||
|
@ -30,3 +35,4 @@ def handle(userToken, packetData):
|
||||||
match.changePassword(packetData["matchPassword"])
|
match.changePassword(packetData["matchPassword"])
|
||||||
except exceptions.matchCreateError:
|
except exceptions.matchCreateError:
|
||||||
log.error("Error while creating match!")
|
log.error("Error while creating match!")
|
||||||
|
userToken.enqueue(serverPackets.matchJoinFail())
|
||||||
|
|
|
@ -79,7 +79,7 @@ def partChannel(userID = 0, channel = "", token = None, toIRC = True, kick = Fal
|
||||||
token = glob.tokens.getTokenFromUserID(userID)
|
token = glob.tokens.getTokenFromUserID(userID)
|
||||||
# Make sure the token exists
|
# Make sure the token exists
|
||||||
if token is None:
|
if token is None:
|
||||||
raise exceptions.userNotFoundException
|
raise exceptions.userNotFoundException()
|
||||||
else:
|
else:
|
||||||
token = token
|
token = token
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
|
||||||
if token is None:
|
if token is None:
|
||||||
token = glob.tokens.getTokenFromUsername(fro)
|
token = glob.tokens.getTokenFromUsername(fro)
|
||||||
if token is None:
|
if token is None:
|
||||||
raise exceptions.userNotFoundException
|
raise exceptions.userNotFoundException()
|
||||||
else:
|
else:
|
||||||
# token object alredy passed, get its string and its username (fro)
|
# token object alredy passed, get its string and its username (fro)
|
||||||
fro = token.username
|
fro = token.username
|
||||||
|
@ -194,6 +194,11 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
|
||||||
toClient = "#spectator"
|
toClient = "#spectator"
|
||||||
elif to.startswith("#multi_"):
|
elif to.startswith("#multi_"):
|
||||||
toClient = "#multiplayer"
|
toClient = "#multiplayer"
|
||||||
|
|
||||||
|
# Make sure the message is valid
|
||||||
|
if not message.strip():
|
||||||
|
raise exceptions.invalidArgumentsException()
|
||||||
|
|
||||||
# Truncate message if > 2048 characters
|
# Truncate message if > 2048 characters
|
||||||
message = message[:2048]+"..." if len(message) > 2048 else message
|
message = message[:2048]+"..." if len(message) > 2048 else message
|
||||||
|
|
||||||
|
@ -297,6 +302,9 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
|
||||||
except exceptions.userNotFoundException:
|
except exceptions.userNotFoundException:
|
||||||
log.warning("User not connected to IRC/Bancho")
|
log.warning("User not connected to IRC/Bancho")
|
||||||
return 401
|
return 401
|
||||||
|
except exceptions.invalidArgumentsException:
|
||||||
|
log.warning("{} tried to send an invalid message to {}".format(token.username, to))
|
||||||
|
return 404
|
||||||
|
|
||||||
|
|
||||||
""" IRC-Bancho Connect/Disconnect/Join/Part interfaces"""
|
""" IRC-Bancho Connect/Disconnect/Join/Part interfaces"""
|
||||||
|
|
|
@ -28,7 +28,7 @@ def printServerStartHeader(asciiArt=True):
|
||||||
|
|
||||||
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://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,6 +1,9 @@
|
||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
from common.log import logUtils as log
|
from common.log import logUtils as log
|
||||||
from constants import dataTypes
|
from constants import dataTypes
|
||||||
from constants import matchModModes
|
from constants import matchModModes
|
||||||
|
@ -62,6 +65,7 @@ class match:
|
||||||
self.isLocked = False # if True, users can't change slots/teams. Used in tourney matches
|
self.isLocked = False # if True, users can't change slots/teams. Used in tourney matches
|
||||||
self.isStarting = False
|
self.isStarting = False
|
||||||
self._lock = threading.Lock()
|
self._lock = threading.Lock()
|
||||||
|
self.createTime = int(time.time())
|
||||||
|
|
||||||
# Create all slots and reset them
|
# Create all slots and reset them
|
||||||
self.slots = []
|
self.slots = []
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
from objects import match
|
from objects import match
|
||||||
from objects import glob
|
from objects import glob
|
||||||
from constants import serverPackets
|
from constants import serverPackets
|
||||||
|
@ -63,3 +66,31 @@ class matchList:
|
||||||
glob.streams.broadcast("lobby", serverPackets.disposeMatch(matchID))
|
glob.streams.broadcast("lobby", serverPackets.disposeMatch(matchID))
|
||||||
del self.matches[matchID]
|
del self.matches[matchID]
|
||||||
log.info("MPROOM{}: Room disposed manually".format(_match.matchID))
|
log.info("MPROOM{}: Room disposed manually".format(_match.matchID))
|
||||||
|
|
||||||
|
def cleanupLoop(self):
|
||||||
|
"""
|
||||||
|
Start match cleanup loop.
|
||||||
|
Empty matches that have been created more than 60 seconds ago will get deleted.
|
||||||
|
Useful when people create useless lobbies with `!mp make`.
|
||||||
|
The check is done every 30 seconds.
|
||||||
|
This method starts an infinite loop, call it only once!
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
log.debug("Checking empty matches")
|
||||||
|
t = int(time.time())
|
||||||
|
emptyMatches = []
|
||||||
|
|
||||||
|
# Collect all empty matches
|
||||||
|
for key, m in self.matches.items():
|
||||||
|
if [x for x in m.slots if x.user is not None]:
|
||||||
|
continue
|
||||||
|
if t - m.createTime >= 120:
|
||||||
|
log.debug("Match #{} marked for cleanup".format(m.matchID))
|
||||||
|
emptyMatches.append(m.matchID)
|
||||||
|
|
||||||
|
# Dispose all empty matches
|
||||||
|
for matchID in emptyMatches:
|
||||||
|
self.disposeMatch(matchID)
|
||||||
|
|
||||||
|
# Schedule a new check (endless loop)
|
||||||
|
threading.Timer(30, self.cleanupLoop).start()
|
|
@ -171,19 +171,16 @@ class tokenList:
|
||||||
for _, value in self.tokens.items():
|
for _, value in self.tokens.items():
|
||||||
value.enqueue(packet)
|
value.enqueue(packet)
|
||||||
|
|
||||||
def usersTimeoutCheckLoop(self, timeoutTime = 100, checkTime = 100):
|
def usersTimeoutCheckLoop(self):
|
||||||
"""
|
"""
|
||||||
Start timed out users disconnect loop.
|
Start timed out users disconnect loop.
|
||||||
This function will be called every `checkTime` seconds and so on, forever.
|
This function will be called every `checkTime` seconds and so on, forever.
|
||||||
CALL THIS FUNCTION ONLY ONCE!
|
CALL THIS FUNCTION ONLY ONCE!
|
||||||
|
|
||||||
:param timeoutTime: seconds of inactivity required to disconnect someone. Default: 100
|
|
||||||
:param checkTime: seconds between loops. Default: 100
|
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
log.debug("Checking timed out clients")
|
log.debug("Checking timed out clients")
|
||||||
timedOutTokens = [] # timed out users
|
timedOutTokens = [] # timed out users
|
||||||
timeoutLimit = int(time.time())-timeoutTime
|
timeoutLimit = int(time.time()) - 100
|
||||||
for key, value in self.tokens.items():
|
for key, value in self.tokens.items():
|
||||||
# Check timeout (fokabot is ignored)
|
# Check timeout (fokabot is ignored)
|
||||||
if value.pingTime < timeoutLimit and value.userID != 999 and value.irc == False and value.tournament == False:
|
if value.pingTime < timeoutLimit and value.userID != 999 and value.irc == False and value.tournament == False:
|
||||||
|
@ -200,7 +197,7 @@ class tokenList:
|
||||||
del timedOutTokens
|
del timedOutTokens
|
||||||
|
|
||||||
# Schedule a new check (endless loop)
|
# Schedule a new check (endless loop)
|
||||||
threading.Timer(checkTime, self.usersTimeoutCheckLoop, [timeoutTime, checkTime]).start()
|
threading.Timer(100, self.usersTimeoutCheckLoop).start()
|
||||||
|
|
||||||
def spamProtectionResetLoop(self):
|
def spamProtectionResetLoop(self):
|
||||||
"""
|
"""
|
||||||
|
|
5
pep.py
5
pep.py
|
@ -187,6 +187,11 @@ if __name__ == "__main__":
|
||||||
glob.tokens.spamProtectionResetLoop()
|
glob.tokens.spamProtectionResetLoop()
|
||||||
consoleHelper.printDone()
|
consoleHelper.printDone()
|
||||||
|
|
||||||
|
# Initialize multiplayer cleanup loop
|
||||||
|
consoleHelper.printNoNl("> Initializing multiplayer cleanup loop... ")
|
||||||
|
glob.matches.cleanupLoop()
|
||||||
|
consoleHelper.printDone()
|
||||||
|
|
||||||
# Localize warning
|
# Localize warning
|
||||||
glob.localize = generalUtils.stringToBool(glob.conf.config["localize"]["enable"])
|
glob.localize = generalUtils.stringToBool(glob.conf.config["localize"]["enable"])
|
||||||
if not glob.localize:
|
if not glob.localize:
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
requests
|
requests==2.18.1
|
||||||
tornado
|
tornado==4.4.2
|
||||||
mysqlclient
|
mysqlclient==1.3.9
|
||||||
psutil
|
psutil==5.2.2
|
||||||
raven
|
raven==5.32.0
|
||||||
bcrypt>=3.1.1
|
bcrypt==3.1.1
|
||||||
dill
|
dill==0.2.7.1
|
||||||
redis
|
redis==2.10.5
|
||||||
cython
|
cython==0.27.3
|
||||||
datadog
|
datadog==0.14.0
|
Loading…
Reference in New Issue
Block a user