Merged with upstream

This commit is contained in:
Sunpy 2018-04-08 21:20:26 +02:00
commit 2cd69a9a63
11 changed files with 114 additions and 44 deletions

3
.gitignore vendored
View File

@ -6,4 +6,5 @@ filters.txt
.idea
redistest.py
*.c
*.so
*.so
.pyenv

View File

@ -40,10 +40,10 @@ def instantRestart(fro, chan, message):
return False
def faq(fro, chan, message):
if message[0] in glob.conf.extra["faq"]:
return glob.conf.extra["faq"][message[0]]
return False
key = message[0].lower()
if key not in glob.conf.extra["faq"]:
return False
return glob.conf.extra["faq"][key]
def roll(fro, chan, message):
maxPoints = 100
@ -58,8 +58,8 @@ def roll(fro, chan, message):
# return random.choice(["yes", "no", "maybe"])
def alert(fro, chan, message):
msg = ' '.join(message[:])
if not msg.strip():
msg = ' '.join(message[:]).strip()
if not msg:
return False
glob.streams.broadcast("main", serverPackets.notification(msg))
return False
@ -68,8 +68,8 @@ def alertUser(fro, chan, message):
target = message[0].lower()
targetToken = glob.tokens.getTokenFromUsername(userUtils.safeUsername(target), safe=True)
if targetToken is not None:
msg = ' '.join(message[1:])
if not msg.strip():
msg = ' '.join(message[1:]).strip()
if not msg:
return False
targetToken.enqueue(serverPackets.notification(msg))
return False
@ -137,12 +137,15 @@ def fokabotReconnect(fro, chan, message):
return False
def silence(fro, chan, message):
for i in message:
i = i.lower()
message = [x.lower() for x in message]
target = message[0]
amount = message[1]
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
targetUserID = userUtils.getIDSafe(target)
@ -758,7 +761,10 @@ def multiplayer(fro, chan, message):
def mpMake():
if len(message) < 2:
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()
return "Tourney match #{} created!".format(matchID)
@ -812,7 +818,9 @@ def multiplayer(fro, chan, message):
def mpHost():
if len(message) < 2:
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)
if userID is None:
raise exceptions.userNotFoundException("No such user")
@ -877,7 +885,9 @@ def multiplayer(fro, chan, message):
def mpInvite():
if len(message) < 2:
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)
if userID is None:
raise exceptions.userNotFoundException("No such user")
@ -944,7 +954,9 @@ def multiplayer(fro, chan, message):
def mpKick():
if len(message) < 2:
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)
if userID is None:
raise exceptions.userNotFoundException("No such user")
@ -957,7 +969,7 @@ def multiplayer(fro, chan, message):
return "{} has been kicked from the match.".format(username)
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.changePassword(password)
return "Match password has been changed!"
@ -1001,7 +1013,9 @@ def multiplayer(fro, chan, message):
def mpTeam():
if len(message) < 3:
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()
if colour not in ["red", "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:
raise exceptions.invalidArgumentsException("Invalid subcommand")
return subcommands[requestedSubcommand]()
except (exceptions.invalidArgumentsException, exceptions.userNotFoundException) as e:
except (exceptions.invalidArgumentsException, exceptions.userNotFoundException, exceptions.invalidUserException) as e:
return str(e)
except exceptions.wrongChannelException:
return "This command only works in multiplayer chat channels"
@ -1080,7 +1094,9 @@ def multiplayer(fro, chan, message):
def switchServer(fro, chan, message):
# Get target user ID
target = message[0]
newServer = message[1]
newServer = message[1].strip()
if not newServer:
return "Invalid server IP"
targetUserID = userUtils.getIDSafe(target)
userID = userUtils.getID(fro)
@ -1098,7 +1114,9 @@ def switchServer(fro, chan, message):
def rtx(fro, chan, message):
target = message[0]
message = " ".join(message[1:])
message = " ".join(message[1:]).strip()
if not message:
return "Invalid message"
targetUserID = userUtils.getIDSafe(target)
if not targetUserID:
return "{}: user not found".format(target)

View File

@ -1,5 +1,5 @@
from common.log import logUtils as log
from constants import clientPackets
from constants import clientPackets, serverPackets
from constants import exceptions
from objects import glob
@ -12,9 +12,14 @@ def handle(userToken, packetData):
# Read packet data
packetData = clientPackets.createMatch(packetData)
# Make sure the name is valid
matchName = packetData["matchName"].strip()
if not matchName:
raise exceptions.matchCreateError()
# Create a match object
# 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
if matchID not in glob.matches.matches:
@ -30,3 +35,4 @@ def handle(userToken, packetData):
match.changePassword(packetData["matchPassword"])
except exceptions.matchCreateError:
log.error("Error while creating match!")
userToken.enqueue(serverPackets.matchJoinFail())

View File

@ -79,7 +79,7 @@ def partChannel(userID = 0, channel = "", token = None, toIRC = True, kick = Fal
token = glob.tokens.getTokenFromUserID(userID)
# Make sure the token exists
if token is None:
raise exceptions.userNotFoundException
raise exceptions.userNotFoundException()
else:
token = token
@ -157,7 +157,7 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
if token is None:
token = glob.tokens.getTokenFromUsername(fro)
if token is None:
raise exceptions.userNotFoundException
raise exceptions.userNotFoundException()
else:
# token object alredy passed, get its string and its username (fro)
fro = token.username
@ -194,6 +194,11 @@ def sendMessage(fro = "", to = "", message = "", token = None, toIRC = True):
toClient = "#spectator"
elif to.startswith("#multi_"):
toClient = "#multiplayer"
# Make sure the message is valid
if not message.strip():
raise exceptions.invalidArgumentsException()
# Truncate message if > 2048 characters
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:
log.warning("User not connected to IRC/Bancho")
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"""

View File

@ -28,7 +28,7 @@ def printServerStartHeader(asciiArt=True):
printColored("> Welcome to pep.py osu!bancho server v{}".format(glob.VERSION), 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)
def printNoNl(string):

View File

@ -1,6 +1,9 @@
import copy
import json
import threading
import time
from common.log import logUtils as log
from constants import dataTypes
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.isStarting = False
self._lock = threading.Lock()
self.createTime = int(time.time())
# Create all slots and reset them
self.slots = []

View File

@ -1,3 +1,6 @@
import threading
import time
from objects import match
from objects import glob
from constants import serverPackets
@ -62,4 +65,32 @@ class matchList:
# Send match dispose packet to everyone in lobby
glob.streams.broadcast("lobby", serverPackets.disposeMatch(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()

View File

@ -171,19 +171,16 @@ class tokenList:
for _, value in self.tokens.items():
value.enqueue(packet)
def usersTimeoutCheckLoop(self, timeoutTime = 100, checkTime = 100):
def usersTimeoutCheckLoop(self):
"""
Start timed out users disconnect loop.
This function will be called every `checkTime` seconds and so on, forever.
CALL THIS FUNCTION ONLY ONCE!
:param timeoutTime: seconds of inactivity required to disconnect someone. Default: 100
:param checkTime: seconds between loops. Default: 100
:return:
"""
log.debug("Checking timed out clients")
timedOutTokens = [] # timed out users
timeoutLimit = int(time.time())-timeoutTime
timeoutLimit = int(time.time()) - 100
for key, value in self.tokens.items():
# Check timeout (fokabot is ignored)
if value.pingTime < timeoutLimit and value.userID != 999 and value.irc == False and value.tournament == False:
@ -200,7 +197,7 @@ class tokenList:
del timedOutTokens
# Schedule a new check (endless loop)
threading.Timer(checkTime, self.usersTimeoutCheckLoop, [timeoutTime, checkTime]).start()
threading.Timer(100, self.usersTimeoutCheckLoop).start()
def spamProtectionResetLoop(self):
"""

5
pep.py
View File

@ -187,6 +187,11 @@ if __name__ == "__main__":
glob.tokens.spamProtectionResetLoop()
consoleHelper.printDone()
# Initialize multiplayer cleanup loop
consoleHelper.printNoNl("> Initializing multiplayer cleanup loop... ")
glob.matches.cleanupLoop()
consoleHelper.printDone()
# Localize warning
glob.localize = generalUtils.stringToBool(glob.conf.config["localize"]["enable"])
if not glob.localize:

View File

@ -1,10 +1,10 @@
requests
tornado
mysqlclient
psutil
raven
bcrypt>=3.1.1
dill
redis
cython
datadog
requests==2.18.1
tornado==4.4.2
mysqlclient==1.3.9
psutil==5.2.2
raven==5.32.0
bcrypt==3.1.1
dill==0.2.7.1
redis==2.10.5
cython==0.27.3
datadog==0.14.0

View File

@ -1 +1 @@
1.13.1
1.13.3