Example #1
0
def getRawReplayS3(scoreID):
    scoreID = int(scoreID)
    if not glob.conf.s3_enabled:
        log.warning("S3 is disabled! Using failed local")
        return _getRawReplayFailedLocal(scoreID)

    fileName = "replay_{}.osr".format(scoreID)
    log.debug("Downloading {} from s3".format(fileName))
    with io.BytesIO() as f:
        bucket = s3.getReadReplayBucketName(scoreID)
        try:
            glob.threadScope.s3.download_fileobj(bucket, fileName, f)
        except ClientError as e:
            # 404 -> no such key
            # 400 -> no such bucket
            code = e.response["Error"]["Code"]
            if code in ("404", "400"):
                log.warning(
                    "S3 replay returned {}, trying to get from failed replays".
                    format(code))
                if code == "400":
                    sentry.captureMessage(
                        "Invalid S3 replays bucket ({})! (got error 400)".
                        format(bucket))
                return _getRawReplayFailedLocal(scoreID)
            raise
        f.seek(0)
        return f.read()
    def asyncGet(self):
        try:
            # Get request ip
            ip = self.getRequestIP()

            # Check arguments
            if not requestsManager.checkArguments(self.request.arguments,
                                                  ["c", "u", "h"]):
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            # Get arguments
            username = self.get_argument("u")
            password = self.get_argument("h")
            replayID = self.get_argument("c")

            # Login check
            userID = userUtils.getID(username)
            if userID == 0:
                raise exceptions.loginFailedException(MODULE_NAME, userID)
            if not userUtils.checkLogin(userID, password, ip):
                raise exceptions.loginFailedException(MODULE_NAME, username)
            if userUtils.check2FA(userID, ip):
                raise exceptions.need2FAException(MODULE_NAME, username, ip)

            # Get user ID
            replayData = glob.db.fetch(
                "SELECT scores.*, users.username AS uname FROM scores LEFT JOIN users ON scores.userid = users.id WHERE scores.id = %s",
                [replayID])
            if replayData == None:
                replayData = glob.db.fetch(
                    "SELECT scores_relax.*, users.username AS uname FROM scores_relax LEFT JOIN users ON scores_relax.userid = users.id WHERE scores_relax.id = %s",
                    [replayID])
                fileName = "{}_relax/replay_{}.osr".format(
                    glob.conf.config["server"]["replayspath"], replayID)
            else:
                fileName = "{}/replay_{}.osr".format(
                    glob.conf.config["server"]["replayspath"], replayID)

            # Increment 'replays watched by others' if needed
            if replayData is not None:
                if username != replayData["uname"]:
                    userUtils.incrementReplaysWatched(replayData["userid"],
                                                      replayData["play_mode"])

            # Serve replay
            log.info("Serving replay_{}.osr".format(replayID))

            if os.path.isfile(fileName):
                with open(fileName, "rb") as f:
                    fileContent = f.read()
                self.write(fileContent)
            else:
                log.warning("Replay {} doesn't exist".format(replayID))
                self.write("")
        except exceptions.invalidArgumentsException:
            pass
        except exceptions.need2FAException:
            pass
        except exceptions.loginFailedException:
            pass
Example #3
0
    def enqueue(self, bytes_):
        """
		Add bytes (packets) to queue

		:param bytes_: (packet) bytes to enqueue
		"""
        try:
            # Acquire the buffer lock
            self._bufferLock.acquire()

            # Never enqueue for IRC clients or Bot
            #if self.irc or self.userID < 999:

            if self.irc or self.userID == 999:
                return

            # Avoid memory leaks
            if len(bytes_) < 10 * 10**6:
                self.queue += bytes_
            else:
                log.warning(
                    "{}'s packets buffer is above 10M!! Lost some data!".
                    format(self.username))
        finally:
            # Release the buffer lock
            self._bufferLock.release()
Example #4
0
    def updateCachedStats(self):
        """
		Update all cached stats for this token

		:return:
		"""
        stats = userUtils.getUserStats(self.userID, self.gameMode)
        stats_relax = userUtils.getUserStatsRx(self.userID, self.gameMode)
        log.debug(str(stats))

        if stats is None:
            log.warning("Stats query returned None")
            return
        if self.relaxing:
            self.gameRank = stats_relax["gameRank"]
            self.pp = stats_relax["pp"]
            self.rankedScore = stats_relax["rankedScore"]
            self.accuracy = stats_relax["accuracy"] / 100
            self.playcount = stats_relax["playcount"]
            self.totalScore = stats_relax["totalScore"]
        else:
            self.gameRank = stats["gameRank"]
            self.pp = stats["pp"]
            self.rankedScore = stats["rankedScore"]
            self.accuracy = stats["accuracy"] / 100
            self.playcount = stats["playcount"]
            self.totalScore = stats["totalScore"]
Example #5
0
    def updateCachedStats(self):
        """
		Update all cached stats for this token

		:return:
		"""
        stats = [
            userUtils.getUserStats(self.userID, self.gameMode),
            userUtils.getUserStatsRelax(self.userID, self.gameMode)
        ]
        if features.RANKING_SCOREV2:
            stats.append(userUtils.getUserStatsAlt(self.userID, self.gameMode))

        if stats is None:
            log.warning("Stats query returned None")
            return

        if self.specialMode in range(len(stats)):
            stats = stats[self.specialMode]
        else:
            stats = stats[0]

        self.gameRank = stats["gameRank"]
        self.pp = stats["pp"]
        self.rankedScore = stats["rankedScore"]
        self.accuracy = stats["accuracy"] / 100.0
        self.playcount = stats["playcount"]
        self.totalScore = stats["totalScore"]
Example #6
0
def osuApiRequest(request, params, getFirst=True):
	"""
	Send a request to osu!api.

	request -- request type, string (es: get_beatmaps)
	params -- GET parameters, without api key or trailing ?/& (es: h=a5b99395a42bd55bc5eb1d2411cbdf8b&limit=10)
	return -- dictionary with json response if success, None if failed or empty response.
	"""
	# Make sure osuapi is enabled
	if not generalUtils.stringToBool(glob.conf.config["osuapi"]["enable"]):
		log.warning("osu!api is disabled")
		return None

	# Api request
	resp = None
	try:
		finalURL = "{}/api/{}?k={}&{}".format(glob.conf.config["osuapi"]["apiurl"], request, glob.conf.config["osuapi"]["apikey"], params)
		log.debug(finalURL)
		resp = requests.get(finalURL, timeout=5).text
		data = json.loads(resp)
		if getFirst:
			if len(data) >= 1:
				resp = data[0]
			else:
				resp = None
		else:
			resp = data
	finally:
		glob.dog.increment(glob.DATADOG_PREFIX+".osu_api.requests")
		log.debug(str(resp).encode("utf-8"))
		return resp
Example #7
0
def handle(userToken, packetData):
    # read packet data
    packetData = clientPackets.joinMatch(packetData)
    matchID = packetData["matchID"]
    password = packetData["password"]

    # Get match from ID
    try:
        # Make sure the match exists
        if matchID not in glob.matches.matches:
            return

        # Hash password if needed
        # if password != "":
        #	password = generalUtils.stringMd5(password)

        # Check password
        with glob.matches.matches[matchID] as match:
            if match.matchPassword != "" and match.matchPassword != password:
                raise exceptions.matchWrongPasswordException()

            # Password is correct, join match
            userToken.joinMatch(matchID)
    except exceptions.matchWrongPasswordException:
        userToken.enqueue(serverPackets.matchJoinFail())
        log.warning(
            "{} has tried to join a mp room, but he typed the wrong password".
            format(userToken.username))
Example #8
0
def report(fro, chan, message):
    msg = ""
    try:
        # TODO: Rate limit
        # Get username, report reason and report info
        target, reason, additionalInfo = message[0], message[1], message[2]
        target = chat.fixUsernameForBancho(target)

        # Make sure the target is not foka
        if target == glob.BOT_NAME:
            raise exceptions.invalidUserException()

        # Make sure the user exists
        targetID = userUtils.getID(target)
        if targetID == 0:
            raise exceptions.userNotFoundException()

        # Make sure that the user has specified additional info if report reason is 'Other'
        if reason.lower() == "other" and not additionalInfo:
            raise exceptions.missingReportInfoException()

        # Get the token if possible
        chatlog = ""
        token = glob.tokens.getTokenFromUsername(userUtils.safeUsername(target), safe=True)
        if token is not None:
            chatlog = token.getMessagesBufferString()

        # Everything is fine, submit report
        glob.db.execute(
            "INSERT INTO reports (id, from_uid, to_uid, reason, chatlog, time, assigned) VALUES (NULL, %s, %s, %s, %s, %s, 0)",
            [userUtils.getID(fro), targetID, "{reason} - ingame {info}".format(reason=reason, info="({})".format(
                additionalInfo) if additionalInfo is not None else ""), chatlog, int(time.time())])
        msg = "You've reported {target} for {reason}{info}. A Community Manager will check your report as soon as possible. Every !report message you may see in chat wasn't sent to anyone, so nobody in chat, but admins, know about your report. Thank you for reporting!".format(
            target=target, reason=reason, info="" if additionalInfo is None else " (" + additionalInfo + ")")
        adminMsg = "{user} has reported {target} for {reason} ({info})".format(user=fro, target=target, reason=reason,
                                                                               info=additionalInfo)

        # Log report in #admin and on discord
        chat.sendMessage(glob.BOT_NAME, "#admin", adminMsg)
        log.warning(adminMsg, discord="cm")
    except exceptions.invalidUserException:
        msg = "Hello, {} here! You can't report me. I won't forget what you've tried to do. Watch out.".format(
            glob.BOT_NAME)
    except exceptions.invalidArgumentsException:
        msg = "Invalid report command syntax. To report an user, click on it and select 'Report user'."
    except exceptions.userNotFoundException:
        msg = "The user you've tried to report doesn't exist."
    except exceptions.missingReportInfoException:
        msg = "Please specify the reason of your report."
    except:
        raise
    finally:
        if msg != "":
            token = glob.tokens.getTokenFromUsername(fro)
            if token is not None:
                if token.irc:
                    chat.sendMessage(glob.BOT_NAME, fro, msg)
                else:
                    token.enqueue(serverPackets.notification(msg))
    return False
Example #9
0
def updateRankGlobally(gameMode):
    gm = gameModes.getGameModeForDB(gameMode)
    users = glob.db.fetchAll("SELECT user_id FROM osu_user_stats{}".format(gm))
    if users is not None:
        for uid in users:
            updateRank(uid["user_id"], gameMode)
    else:
        log.warning("Fetched None users")
Example #10
0
 def __init__(self, who, map, checksum, additional_notification):
     self.who = who
     self.map = map
     self.checksum = checksum
     self.additional_notification = additional_notification
     log.warning(
         f"{who} not passed checksum on {map} with checksum {checksum}: {additional_notification}"
     )
Example #11
0
	def abort(self):
		if not self.inProgress:
			log.warning("MPROOM{}: Match is not in progress!".format(self.matchID))
			return
		self.inProgress = False
		self.isStarting = False
		self.resetSlots()
		self.sendUpdates()
		glob.streams.broadcast(self.playingStreamName, serverPackets.matchAbort())
		glob.streams.dispose(self.playingStreamName)
		glob.streams.remove(self.playingStreamName)
		log.info("MPROOM{}: Match aborted".format(self.matchID))
Example #12
0
def handle(userToken, _):
	try:
		# We don't have the beatmap, we can't spectate
		if userToken.spectating not in glob.tokens.tokens:
			raise exceptions.tokenNotFoundException()

		# Send the packet to host
		glob.tokens.tokens[userToken.spectating].enqueue(serverPackets.noSongSpectator(userToken.userID))
	except exceptions.tokenNotFoundException:
		# Stop spectating if token not found
		log.warning("Spectator can't spectate: token not found")
		userToken.stopSpectating()
Example #13
0
def IRCPartChannel(username, channel):
    """
	Handle IRC channel part bancho-side.

	:param username: username
	:param channel: channel name
	:return: IRC return code
	"""
    userID = userUtils.getID(username)
    if not userID:
        log.warning("{} doesn't exist".format(username))
        return
    return partChannel(userID, channel)
Example #14
0
def handle(userToken, packetData):
    # Read userIDs list
    packetData = clientPackets.userPanelRequest(packetData)

    # Process lists with length <= 32
    if len(packetData) > 256:
        log.warning("Received userPanelRequest with length > 256.")
        return

    for i in packetData["users"]:
        # Enqueue userpanel packets relative to this user
        log.debug("Sending panel for user {}.".format(i))
        userToken.enqueue(serverPackets.userPanel(i))
Example #15
0
    def asyncGet(self) -> None:
        if not requestsManager.checkArguments(self.request.arguments,
                                              ('us', 'ha', 'b')):
            self.write("-3")
            return

        username: Optional[str] = self.get_argument("us", None)
        userID: int = userUtils.getID(username)

        if not userUtils.checkLogin(userID, self.get_argument("ha", None),
                                    self.getRequestIP()):
            self.write("-3")
            return

        # Get beatmap_idâ„¢ argument
        b = self.get_argument("b", None)

        if (b.startswith('a') and not userUtils.isRestricted(userID)):
            flags = int(b[1:]) if b[1:].isdigit() else None
            if not flags:
                self.write("-3")
                return

            readable: list[str] = []
            if flags & 1 << 0: readable.append("[1] osu! run with -ld")
            if flags & 1 << 1: readable.append("[2] osu! has a console open")
            if flags & 1 << 2:
                readable.append("[4] osu! has extra threads running")
            if flags & 1 << 3: readable.append("[8] osu! is hqosu! (check #1)")
            if flags & 1 << 4:
                readable.append("[16] osu! is hqosu! (check #2)")
            if flags & 1 << 5:
                readable.append(
                    "[32] osu! has special launch settings in registry (probably relife)"
                )
            if flags & 1 << 6: readable.append("[64] AQN is loaded (check #1)")
            if flags & 1 << 7:
                readable.append("[128] AQN is loaded (check #2)")
            if flags & 1 << 8:
                readable.append(
                    "[256] notify_1 was run while out of the editor (AQN sound on program open)"
                )

            # Send our webhook to Discord.
            log.warning('\n\n'.join([
                f'[{username}](https://eggradio.tk/u/{userID}) sent flags **{b}**',
                '**Breakdown**\n' + '\n'.join(readable),
            ]),
                        discord='ac')

        self.write("-3")
Example #16
0
def IRCAway(username, message):
    """
	Handle IRC away command bancho-side.

	:param username:
	:param message: away message
	:return: IRC return code
	"""
    userID = userUtils.getID(username)
    if not userID:
        log.warning("{} doesn't exist".format(username))
        return
    glob.tokens.getTokenFromUserID(userID).awayMessage = message
    return 305 if message == "" else 306
Example #17
0
	def asyncGet(self):
		try:
			# Get request ip
			ip = self.getRequestIP()

			# Check arguments
			if not requestsManager.checkArguments(self.request.arguments, ["c", "u", "h"]):
				raise exceptions.invalidArgumentsException(MODULE_NAME)

			# Get arguments
			username = self.get_argument("u")
			password = self.get_argument("h")
			replayID = self.get_argument("c")

			isRelaxing = False
			if int(replayID) < 500000000:
				isRelaxing = True

			# Login check
			userID = userUtils.getID(username)
			if userID == 0:
				raise exceptions.loginFailedException(MODULE_NAME, userID)
			if not userUtils.checkLogin(userID, password, ip):
				raise exceptions.loginFailedException(MODULE_NAME, username)
			if userUtils.check2FA(userID, ip):
				raise exceptions.need2FAException(MODULE_NAME, username, ip)

			replayData = glob.db.fetch("SELECT scores{relax}.*, users.username AS uname FROM scores{relax} LEFT JOIN users ON scores{relax}.userid = users.id WHERE scores{relax}.id = %s".format(relax="_relax" if isRelaxing else ""), [replayID])

			# Increment 'replays watched by others' if needed
			if replayData is not None:
				if username != replayData["uname"]:
					userUtils.incrementReplaysWatched(replayData["userid"], replayData["play_mode"], replayData["mods"])

			log.info("Serving replay_{}.osr".format(replayID))
			fileName = ".data/replays/replay_{}.osr".format(replayID)
			if os.path.isfile(fileName):
				with open(fileName, "rb") as f:
					fileContent = f.read()
				self.write(fileContent)
			else:
				self.write("")
				log.warning("Replay {} doesn't exist.".format(replayID))

		except exceptions.invalidArgumentsException:
			pass
		except exceptions.need2FAException:
			pass
		except exceptions.loginFailedException:
			pass
Example #18
0
def IRCDisconnect(username):
    """
	Handle IRC logout bancho-side.
	Remove token and broadcast logout packet.

	:param username: username
	:return:
	"""
    token = glob.tokens.getTokenFromUsername(username)
    if token is None:
        log.warning("{} doesn't exist".format(username))
        return
    logoutEvent.handle(token)
    log.info("{} disconnected from IRC".format(username))
Example #19
0
def joinChannel(userID=0, channel="", token=None, toIRC=True, force=False):
    """
	Join a channel

	:param userID: user ID of the user that joins the channel. Optional. token can be used instead.
	:param token: user token object of user that joins the channel. Optional. userID can be used instead.
	:param channel: channel name
	:param toIRC: if True, send this channel join event to IRC. Must be true if joining from bancho. Default: True
	:param force: whether to allow game clients to join #spect_ and #multi_ channels
	:return: 0 if joined or other IRC code in case of error. Needed only on IRC-side
	"""
    try:
        # Get token if not defined
        if token is None:
            token = glob.tokens.getTokenFromUserID(userID)
            # Make sure the token exists
            if token is None:
                raise exceptions.userNotFoundException
        else:
            token = token

        # Normal channel, do check stuff
        # Make sure the channel exists
        if channel not in glob.channels.channels:
            raise exceptions.channelUnknownException()

        # Make sure a game client is not trying to join a #multi_ or #spect_ channel manually
        channelObject = glob.channels.channels[channel]
        if channelObject.isSpecial and not token.irc and not force:
            raise exceptions.channelUnknownException()

        # Add the channel to our joined channel
        token.joinChannel(channelObject)

        # Send channel joined (IRC)
        if glob.irc and not toIRC:
            glob.ircServer.banchoJoinChannel(token.username, channel)

        # Console output
        log.info("{} joined channel {}".format(token.username, channel))

        # IRC code return
        return 0
    except exceptions.channelNoPermissionsException:
        log.warning(
            "{} attempted to join channel {}, but they have no read permissions"
            .format(token.username, channel))
        return 403
    except exceptions.channelUnknownException:
        log.warning("{} attempted to join an unknown channel ({})".format(
            token.username, channel))
        return 403
    except exceptions.userAlreadyInChannelException:
        log.warning("User {} already in channel {}".format(
            token.username, channel))
        return 403
    except exceptions.userNotFoundException:
        log.warning("User not connected to IRC/Bancho")
        return 403  # idk
Example #20
0
def updateStatsRx(userID, score_):
	"""
	Update stats (playcount, total score, ranked score, level bla bla)
	with data relative to a score object

	:param userID:
	:param score_: score object
	:param beatmap_: beatmap object. Optional. If not passed, it'll be determined by score_.
	"""

	# Make sure the user exists
	if not exists(userID):
		log.warning("User {} doesn't exist.".format(userID))
		return

	# Get gamemode for db
	mode = scoreUtils.readableGameMode(score_.gameMode)

	# Update total score, playcount and play time
	if score_.playTime is not None:
		realPlayTime = score_.playTime
	else:
		realPlayTime = score_.fullPlayTime

	glob.db.execute(
		"UPDATE rx_stats SET total_score_{m}=total_score_{m}+%s, playcount_{m}=playcount_{m}+1, "
		"playtime_{m} = playtime_{m} + %s "
		"WHERE id = %s LIMIT 1".format(
            m=mode
        ),
        (score_.score, realPlayTime, userID)
    )

	# Calculate new level and update it
	updateLevelRX(userID, score_.gameMode)

	# Update level, accuracy and ranked score only if we have passed the song
	if score_.passed:
		# Update ranked score
		glob.db.execute(
			"UPDATE rx_stats SET ranked_score_{m}=ranked_score_{m}+%s WHERE id = %s LIMIT 1".format(m=mode),
			(score_.rankedScoreIncrease, userID)
		)

		# Update accuracy
		updateAccuracyRX(userID, score_.gameMode)

		# Update pp
		updatePPRelax(userID, score_.gameMode)
Example #21
0
 def handle(self, data):
     data = super().parseData(data)
     if data is None:
         return
     targetTokens = glob.tokens.getTokenFromUserID(data["userID"],
                                                   ignoreIRC=True,
                                                   _all=True)
     if targetTokens:
         if glob.banchoConf.config["menuIcon"] == "":
             log.warning("Tried to test an unknown main menu icon")
             return
         for x in targetTokens:
             x.enqueue(
                 serverPackets.mainMenuIcon(
                     glob.banchoConf.config["menuIcon"]))
Example #22
0
    def getPP(self):
        try:
            # Reset pp
            self.pp = 0

            # Cache map
            mapsHelper.cacheMap(self.mapPath, self.beatmap)

            # Calculate pp
            self.pp = self._runProcess()
        except PianoError:
            log.warning("Invalid beatmap {}".format(self.beatmap.beatmapID))
            self.pp = 0
        finally:
            return self.pp
def updateStats(userID, score_, *, relax=False):
    """
	Update stats (playcount, total score, ranked score, level bla bla)
	with data relative to a score object

	:param userID:
	:param score_: score object
	:param relax: if True, update relax stats, otherwise classic stats
	"""

    # Make sure the user exists
    if not exists(userID):
        log.warning("User {} doesn't exist.".format(userID))
        return

    # Get gamemode for db
    mode = scoreUtils.readableGameMode(score_.gameMode)

    table = "users_stats_relax" if relax else "users_stats"

    # Update total score, playcount and play time
    if score_.playTime is not None:
        realPlayTime = score_.playTime
    else:
        realPlayTime = score_.fullPlayTime

    glob.db.execute(
        "UPDATE {table} SET total_score_{m}=total_score_{m}+%s, "
        "playcount_{m}=playcount_{m}+1, "
        "playtime_{m} = playtime_{m} + %s "
        "WHERE id = %s LIMIT 1".format(table=table, m=mode),
        (score_.score, realPlayTime, userID))

    # Calculate new level and update it
    updateLevel(userID, score_.gameMode, relax=relax)

    # Update level, accuracy and ranked score only if we have passed the song
    if score_.passed:
        # Update ranked score
        glob.db.execute(
            "UPDATE {table} SET ranked_score_{m}=ranked_score_{m}+%s WHERE id = %s LIMIT 1"
            .format(table=table, m=mode), (score_.rankedScoreIncrease, userID))

        # Update accuracy
        updateAccuracy(userID, score_.gameMode, relax=relax)

        # Update pp
        updatePP(userID, score_.gameMode, relax=relax)
Example #24
0
def updateStats(userID, score_, beatmap_=None):
    """
	Update stats (playcount, total score, ranked score, level bla bla)
	with data relative to a score object

	:param userID:
	:param score_: score object
	:param beatmap_: beatmap object. Optional. If not passed, it'll be determined by score_.
	"""

    # Make sure the user exists
    if not exists(userID):
        log.warning("User {} doesn't exist.".format(userID))
        return

    if beatmap_ is None:
        beatmap_ = objects.beatmap.beatmap(score_.fileMd5, 0)

    # Get gamemode for db
    mode = scoreUtils.readableGameMode(score_.gameMode)

    # Update total score, playcount and play time
    realMapLength = beatmap_.hitLength
    if (score_.mods & mods.DOUBLETIME) > 0:
        realMapLength //= 1.5
    elif (score_.mods & mods.HALFTIME) > 0:
        realMapLength //= 0.75
    glob.db.execute(
        "UPDATE users_stats SET total_score_{m}=total_score_{m}+%s, playcount_{m}=playcount_{m}+1, "
        "playtime_{m} = playtime_{m} + %s "
        "WHERE id = %s LIMIT 1".format(m=mode),
        (score_.score, realMapLength, userID))

    # Calculate new level and update it
    updateLevel(userID, score_.gameMode)

    # Update level, accuracy and ranked score only if we have passed the song
    if score_.passed:
        # Update ranked score
        glob.db.execute(
            "UPDATE users_stats SET ranked_score_{m}=ranked_score_{m}+%s WHERE id = %s LIMIT 1"
            .format(m=mode), (score_.rankedScoreIncrease, userID))

        # Update accuracy
        updateAccuracy(userID, score_.gameMode)

        # Update pp
        updatePP(userID, score_.gameMode)
Example #25
0
def IRCJoinChannel(username, channel):
    """
	Handle IRC channel join bancho-side.

	:param username: username
	:param channel: channel name
	:return: IRC return code
	"""
    userID = userUtils.getID(username)
    if not userID:
        log.warning("{} doesn't exist".format(username))
        return
    # NOTE: This should have also `toIRC` = False` tho,
    # since we send JOIN message later on ircserver.py.
    # Will test this later
    return joinChannel(userID, channel)
Example #26
0
def IRCConnect(username):
    """
	Handle IRC login bancho-side.
	Add token and broadcast login packet.

	:param username: username
	:return:
	"""
    userID = userUtils.getID(username)
    if not userID:
        log.warning("{} doesn't exist".format(username))
        return
    glob.tokens.deleteOldTokens(userID)
    glob.tokens.addToken(userID, irc=True)
    glob.streams.broadcast("main", serverPackets.userPanel(userID))
    log.info("{} logged in from IRC".format(username))
Example #27
0
def updateStats(userID, score_, *, relax=False):
    """
	Update stats (playcount, total score, ranked score, level bla bla)
	with data relative to a score object

	:param userID:
	:param score_: score object
	:param relax: if True, update relax stats, otherwise classic stats
	"""

    # Make sure the user exists
    if not exists(userID):
        log.warning("User {} doesn't exist.".format(userID))
        return

    # Get gamemode for db
    mode = scoreUtils.getGameModeForDB(score_.gameMode)

    # Update total score, playcount and play time
    if score_.playTime is not None:
        realPlayTime = score_.playTime
    else:
        realPlayTime = score_.fullPlayTime

    glob.db.execute(
        "UPDATE osu_user_stats{m} SET total_score=total_score+%s, "
        "playcount=playcount+1, "
        "total_seconds_played = total_seconds_played + %s "
        "WHERE user_id = %s LIMIT 1".format(m=mode),
        (score_.score, realPlayTime, userID))

    # Calculate new level and update it
    updateLevel(userID, score_.gameMode, relax=relax)

    # Update level, accuracy and ranked score only if we have passed the song
    if score_.passed:
        # Update ranked score
        glob.db.execute(
            "UPDATE osu_user_stats{m} SET ranked_score=ranked_score+%s WHERE user_id = %s LIMIT 1"
            .format(m=mode), (score_.rankedScoreIncrease, userID))

        # Update accuracy
        updateAccuracy(userID, score_.gameMode, relax=relax)

        # Update pp
        updatePP(userID, score_.gameMode, relax=relax)
        updateRankGlobally(score_.gameMode)
Example #28
0
 def dbClose(self):
     tid = threading.get_ident()
     if self._db is None:
         log.debug(
             "Attempted to close a None db connection for thread {} (this thread has no db conn!)"
             .format(tid))
         return
     try:
         self._db.close()
     except Exception as e:
         log.warning(
             "Error ({}) while closing db connection for thread {}. Failing silently."
             .format(e, tid))
         pass
     log.debug(
         "Closed and destroyed db connection for thread {}".format(tid))
     self._db = None
Example #29
0
 def dbClose(self):
     tid = threading.get_ident()
     if self._db is None:
         log.info(
             "Closing db connection, but thread {} has no db connection.".
             format(tid))
         return
     try:
         self._db.close()
     except Exception as e:
         log.warning(
             "Error ({}) while closing db connection for thread {}. Failing silently."
             .format(e, tid))
         pass
     log.info(
         "Closed and destroyed db connection for thread {}".format(tid))
     self._db = None
def handle(userToken, packetData):
    # Read userIDs list
    packetData = clientPackets.userStatsRequest(packetData)

    # Process lists with length <= 32
    if len(packetData) > 32:
        log.warning("Received userStatsRequest with length > 32.")
        return

    for i in packetData["users"]:
        log.debug("Sending stats for user {}.".format(i))

        # Skip our stats
        if i == userToken.userID:
            continue

        # Enqueue stats packets relative to this user
        userToken.enqueue(serverPackets.userStats(i))