Ejemplo n.º 1
0
    def asyncGet(self):
        statusCode = 400
        data = {"message": "unknown error"}
        try:
            # Check arguments
            if not requestsManager.checkArguments(self.request.arguments,
                                                  ["b"]):
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            # Get beatmap ID and make sure it's a valid number
            beatmapID = self.get_argument("b")
            if not beatmapID.isdigit():
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            # Get mods
            if "m" in self.request.arguments:
                modsEnum = self.get_argument("m")
                if not modsEnum.isdigit():
                    raise exceptions.invalidArgumentsException(MODULE_NAME)
                modsEnum = int(modsEnum)
            else:
                modsEnum = 0

            # Get game mode
            if "g" in self.request.arguments:
                gameMode = self.get_argument("g")
                if not gameMode.isdigit():
                    raise exceptions.invalidArgumentsException(MODULE_NAME)
                gameMode = int(gameMode)
            else:
                gameMode = 0

            # Get acc
            if "a" in self.request.arguments:
                accuracy = self.get_argument("a")
                try:
                    accuracy = float(accuracy)
                except ValueError:
                    raise exceptions.invalidArgumentsException(MODULE_NAME)
            else:
                accuracy = None

            # Print message
            log.info("Requested pp for beatmap {}".format(beatmapID))

            # Get beatmap md5 from osuapi
            # TODO: Move this to beatmap object
            osuapiData = osuapiHelper.osuApiRequest("get_beatmaps",
                                                    "b={}".format(beatmapID))
            if osuapiData is None or "file_md5" not in osuapiData or "beatmapset_id" not in osuapiData:
                raise exceptions.invalidBeatmapException(MODULE_NAME)
            beatmapMd5 = osuapiData["file_md5"]
            beatmapSetID = osuapiData["beatmapset_id"]

            # Create beatmap object
            bmap = beatmap.beatmap(beatmapMd5, beatmapSetID)

            # Check beatmap length
            if bmap.hitLength > 900:
                raise exceptions.beatmapTooLongException(MODULE_NAME)

            if gameMode == gameModes.STD and bmap.starsStd == 0:
                # Mode Specific beatmap, auto detect game mode
                if bmap.starsTaiko > 0:
                    gameMode = gameModes.TAIKO
                if bmap.starsCtb > 0:
                    gameMode = gameModes.CTB
                if bmap.starsMania > 0:
                    gameMode = gameModes.MANIA

            # Calculate pp
            if gameMode in (gameModes.STD, gameModes.TAIKO):
                # osu!standard and osu!taiko
                oppai = ez.Ez(bmap,
                              mods_=modsEnum,
                              tillerino=accuracy is None,
                              acc=accuracy,
                              gameMode=gameMode)
                bmap.starsStd = oppai.stars
                returnPP = oppai.pp
            elif gameMode == gameModes.CTB:
                # osu!catch
                ciccio = cicciobello.Cicciobello(bmap,
                                                 mods_=modsEnum,
                                                 tillerino=accuracy is None,
                                                 accuracy=accuracy)
                bmap.starsStd = ciccio.stars
                returnPP = ciccio.pp
            else:
                raise exceptions.unsupportedGameModeException()

            # Data to return
            data = {
                "song_name": bmap.songName,
                "pp":
                [x for x in returnPP] if type(returnPP) is list else returnPP,
                "game_mode": gameMode,
                "length": bmap.hitLength,
                "stars": bmap.starsStd,
                "ar": bmap.AR,
                "bpm": bmap.bpm,
            }

            # Set status code and message
            statusCode = 200
            data["message"] = "ok"
        except exceptions.invalidArgumentsException:
            # Set error and message
            statusCode = 400
            data["message"] = "missing required arguments"
        except exceptions.invalidBeatmapException:
            statusCode = 400
            data["message"] = "beatmap not found"
        except exceptions.beatmapTooLongException:
            statusCode = 400
            data["message"] = "requested beatmap is too long"
        except exceptions.unsupportedGameModeException:
            statusCode = 400
            data["message"] = "Unsupported gamemode"
        finally:
            # Add status code to data
            data["status"] = statusCode

            # Debug output
            log.debug(str(data))

            # Send response
            self.write(json.dumps(data))
            self.set_header("Content-Type", "application/json")
            self.set_status(statusCode)
Ejemplo n.º 2
0
    def asyncGet(self):
        output = ""
        try:
            if not requestsManager.checkArguments(self.request.arguments,
                                                  ["u", "h"]):
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            username = self.get_argument("u", "")
            password = self.get_argument("h", "")
            userID = userUtils.getID(username)
            if not userUtils.checkLogin(userID, password):
                self.write("error:pass")
                return
            gameMode = self.get_argument("m", "-1")
            rankedStatus = self.get_argument("r", "-1")
            query = self.get_argument("q", "")
            page = int(self.get_argument("p", "0"))

            glob.db = connectToDB(1)

            query = query.lower()

            whereClause = []

            #stars filter
            regexp = r"stars[<>=]\d+(\*\d*)?"
            for match in re.finditer(regexp, query):
                matchStr = match.group(0)
                query = query.replace(matchStr, "")
                num = float(matchStr[6:])
                whereClause.append("difficulty_std " + matchStr[5] + " " +
                                   str(num))

            #ar filter
            regexp = r"ar[<>=]\d+(\*\d*)?"
            for match in re.finditer(regexp, query):
                matchStr = match.group(0)
                query = query.replace(matchStr, "")
                num = float(matchStr[3:])
                whereClause.append("ar " + matchStr[2] + " " + str(num))

            #cs filter
            regexp = r"cs[<>=]\d+(\*\d*)?"
            for match in re.finditer(regexp, query):
                matchStr = match.group(0)
                query = query.replace(matchStr, "")
                num = float(matchStr[3:])
                whereClause.append("cs " + matchStr[2] + " " + str(num))

            #max_combo
            regexp = r"combo[<>=]\d+"
            for match in re.finditer(regexp, query):
                matchStr = match.group(0)
                query = query.replace(matchStr, "")
                num = int(matchStr[6:])
                whereClause.append("max_combo " + matchStr[5] + " " + str(num))

            #length filter
            regexp = r"length[<>=]\d+"
            for match in re.finditer(regexp, query):
                matchStr = match.group(0)
                query = query.replace(matchStr, "")
                num = int(matchStr[7:])
                whereClause.append("hit_length " + matchStr[6] + " " +
                                   str(num))

            #bpm filter
            regexp = r"bpm[<>=]\d+"
            for match in re.finditer(regexp, query):
                matchStr = match.group(0)
                query = query.replace(matchStr, "")
                num = int(matchStr[4:])
                whereClause.append("bpm " + matchStr[3] + " " + str(num))

            if query.lower() in ["newest", "top rated", "most played"]:
                query = ""

            #get response from API
            response = requests.get(
                "https://osu.gatari.pw/api/v1/beatmaps/search?r={0}&q={1}&m={2}&p={3}"
                .format(rankedStatus, query, gameMode, page))

            if len(whereClause
                   ) > 0 and userUtils.getPrivileges(userID) & 4 > 0:
                #join with Database
                bs_ids = parseBeatmapsetIdsFromDirect(response.text)

                if len(bs_ids) == 0:
                    return

                whereClause.append("beatmapset_id IN (" + ",".join(bs_ids) +
                                   ")")

                pandasResult = pandasQuery(
                    "select DISTINCT beatmapset_id from beatmaps WHERE " +
                    " AND ".join(whereClause))

                if len(pandasResult) == 0:
                    return

                filtered_bs_ids = np.array(pandasResult["beatmapset_id"])
                response_rows = response.text.split("\n")[1:-1]
                new_rows = [
                    row for row in response_rows
                    if row.split('|')[7] in list(map(str, filtered_bs_ids))
                ]
                result = str(len(new_rows)) + "\n" + "\n".join(new_rows) + "\n"
                output += result
            else:
                output += response.text

        finally:
            self.write(output)
Ejemplo n.º 3
0
	def asyncGet(self):
		statusCode = 400
		data = {"message": "unknown error"}
		try:
			# Check arguments
			if not requestsManager.checkArguments(self.request.arguments, ["b"]):
				raise exceptions.invalidArgumentsException(MODULE_NAME)

			# Get beatmap ID and make sure it's a valid number
			beatmapID = self.get_argument("b")
			if not beatmapID.isdigit():
				raise exceptions.invalidArgumentsException(MODULE_NAME)

			# Get mods
			if "m" in self.request.arguments:
				modsEnum = self.get_argument("m")
				if not modsEnum.isdigit():
					raise exceptions.invalidArgumentsException(MODULE_NAME)
				modsEnum = int(modsEnum)
			else:
				modsEnum = 0

			# Get game mode
			if "g" in self.request.arguments:
				gameMode = self.get_argument("g")
				if not gameMode.isdigit():
					raise exceptions.invalidArgumentsException(MODULE_NAME)
				gameMode = int(gameMode)
			else:
				gameMode = 0

			# Get acc
			if "a" in self.request.arguments:
				accuracy = self.get_argument("a")
				try:
					accuracy = float(accuracy)
				except ValueError:
					raise exceptions.invalidArgumentsException(MODULE_NAME)
			else:
				accuracy = -1.0

			# Print message
			log.info("Requested pp for beatmap {}".format(beatmapID))

			""" Peppy >:(
			# Get beatmap md5 from osuapi
			# TODO: Move this to beatmap object
			osuapiData = osuapiHelper.osuApiRequest("get_beatmaps", "b={}".format(beatmapID))
			if osuapiData is None or "file_md5" not in osuapiData or "beatmapset_id" not in osuapiData:
				raise exceptions.invalidBeatmapException(MODULE_NAME)

			beatmapMd5 = osuapiData["file_md5"]
			beatmapSetID = osuapiData["beatmapset_id"]
			"""
			dbData = glob.db.fetch("SELECT beatmap_md5, beatmapset_id FROM beatmaps WHERE beatmap_id = {}".format(beatmapID))
			if dbData is None:
				raise exceptions.invalidBeatmapException(MODULE_NAME)

			beatmapMd5 = dbData["beatmap_md5"]
			beatmapSetID = dbData["beatmapset_id"]

			# Create beatmap object
			bmap = beatmap.beatmap(beatmapMd5, beatmapSetID)

			# Check beatmap length
			if bmap.hitLength > 900:
				raise exceptions.beatmapTooLongException(MODULE_NAME)

			returnPP = []
			if gameMode == gameModes.STD and bmap.starsStd == 0:
				# Mode Specific beatmap, auto detect game mode
				if bmap.starsTaiko > 0:
					gameMode = gameModes.TAIKO
				if bmap.starsCtb > 0:
					gameMode = gameModes.CTB
				if bmap.starsMania > 0:
					gameMode = gameModes.MANIA

			# Calculate pp
			if accuracy < 0 and modsEnum == 0:
				# Generic acc
				# Get cached pp values
				cachedPP = bmap.getCachedTillerinoPP()
				if (modsEnum&mods.RELAX or modsEnum&mods.RELAX2):
					cachedPP = [0,0,0,0]

				if cachedPP != [0,0,0,0]:
					log.debug("Got cached pp.")
					returnPP = cachedPP
				else:
					log.debug("Cached pp not found. Calculating pp with oppai...")
					# Cached pp not found, calculate them
					peace = ez_peace.EzPeace(bmap, mods_=modsEnum, tillerino=True)

					returnPP = peace.pp
					bmap.starsStd = peace.stars

					if not (modsEnum&mods.RELAX or modsEnum&mods.RELAX2):
						# Cache values in DB
						log.debug("Saving cached pp...")
						if type(returnPP) == list and len(returnPP) == 4:
							bmap.saveCachedTillerinoPP(returnPP)
			else:
				# Specific accuracy, calculate
				# Create peace instance
				log.debug("Specific request ({}%/{}). Calculating pp with peace...".format(accuracy, modsEnum))
				peace = ez_peace.EzPeace(bmap, mods_=modsEnum, tillerino=True)
				bmap.starsStd = peace.stars
				if accuracy > 0:
					returnPP.append(calculatePPFromAcc(peace, accuracy))
				else:
					returnPP = peace.pp

			# Data to return
			data = {
				"song_name": bmap.songName,
				"pp": [round(x, 2) for x in returnPP] if type(returnPP) == list else round(returnPP, 2),
				"length": bmap.hitLength,
				"stars": bmap.starsStd,
				"ar": bmap.AR,
				"bpm": bmap.bpm,
			}

			# Set status code and message
			statusCode = 200
			data["message"] = "ok"
		except exceptions.invalidArgumentsException:
			# Set error and message
			statusCode = 400
			data["message"] = "missing required arguments"
		except exceptions.invalidBeatmapException:
			statusCode = 400
			data["message"] = "beatmap not found"
		except exceptions.beatmapTooLongException:
			statusCode = 400
			data["message"] = "requested beatmap is too long"
		except exceptions.unsupportedGameModeException:
			statusCode = 400
			data["message"] = "Unsupported gamemode"
		finally:
			# Add status code to data
			data["status"] = statusCode

			# Debug output
			log.debug(str(data))

			# Send response
			#self.clear()
			self.write(json.dumps(data))
			self.set_header("Content-Type", "application/json")
			self.set_status(statusCode)
Ejemplo n.º 4
0
    def asyncGet(self):
        try:
            # Get request ip
            ip = self.getRequestIP()

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

            # Get user ID
            username = self.get_argument("u")
            userID = userUtils.getID(username)
            if userID is None:
                self.write("error: pass\n")
                return

            # Check login
            log.info("{} ({}) wants to connect".format(username, userID))
            if not userUtils.checkLogin(userID, self.get_argument("h"), ip):
                self.write("error: pass\n")
                return

            # Ban check
            if userUtils.isBanned(userID):
                return

            # Lock check
            if userUtils.isLocked(userID):
                return
            # 2FA check
            if userUtils.check2FA(userID, ip):
                self.write("error: verify\n")

            # Update latest activity
            userUtils.updateLatestActivity(userID)

            if "x" in self.request.arguments:
                if len(self.get_argument("x")) > 4:
                    '''
					When "x" is found in the arguments, it means two things,
					1. "Monitor" has just been triggered (desktop screenshot """"""anticheat"""""")
					2. Files named "LL" (used by *a certain cheat website* for login data) have been found on the users computer.
					This should *NEVER* happen, but just incase it does, i'll send a notification to the discord.
					'''
                    webhook = Webhook(
                        glob.conf.config["discord"]
                        ["ahook"],  #send shit to discord hq
                        color=0xc32c74,
                        footer="stupid anticheat")
                    if glob.conf.config["discord"]["enable"]:
                        webhook.set_title(
                            title=f"Catched some cheater {username} ({userID})"
                        )
                        webhook.set_desc(
                            f'They just tried to send bancho_monitor and they have LL files!'
                        )
                        webhook.set_footer(text="peppycode anticheat")
                        webhook.post()

            # Get country and output it
            country = glob.db.fetch(
                "SELECT country FROM users_stats WHERE id = %s",
                [userID])["country"]
            self.write(country)
        except exceptions.invalidArgumentsException:
            pass
        except exceptions.loginFailedException:
            self.write("error: pass\n")
        except exceptions.userBannedException:
            pass
        except exceptions.userLockedException:
            pass
        except exceptions.need2FAException:
            self.write("error: verify\n")
Ejemplo n.º 5
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(self.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(self.MODULE_NAME, userID)
            if not userUtils.checkLogin(userID, password, ip):
                raise exceptions.loginFailedException(self.MODULE_NAME,
                                                      username)
            if userUtils.check2FA(userID, ip):
                raise exceptions.need2FAException(self.MODULE_NAME, username,
                                                  ip)

            # Get user ID
            replayData = glob.db.fetch(
                "SELECT osu_scores.*, phpbb_users.username AS uname FROM osu_scores LEFT JOIN phpbb_users ON osu_scores.user_id = phpbb_users.user_id WHERE osu_scores.score_id = %s",
                [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))
            r = ""
            replayID = int(replayID)
            try:
                r = replayHelper.getRawReplayS3(replayID)
            except timeout_decorator.TimeoutError:
                log.warning("S3 timed out")
                sentry.captureMessage("S3 timeout while fetching replay.")
                glob.stats["replay_download_failures"].labels(
                    type="raw_s3_timeout").inc()
            except FileNotFoundError:
                log.warning("Replay {} doesn't exist".format(replayID))
            except:
                glob.stats["replay_download_failures"].labels(
                    type="raw_other").inc()
                raise
            finally:
                self.write(r)
        except exceptions.invalidArgumentsException:
            pass
        except exceptions.need2FAException:
            pass
        except exceptions.loginFailedException:
            pass
Ejemplo n.º 6
0
    def asyncGet(self):
        try:
            # OOF
            UsingRelax = False
            UsingAuto = False

            # 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
            current_gamemode_redis = "lets:user_current_gamemode:{}".format(
                userID)
            cgamemode = int(glob.redis.get(current_gamemode_redis))
            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 cgamemode == 3:
                log.debug("autopilot")
                UsingRelax = False
                usingAuto = True
                fileName = "{}_ap/replay_{}.osr".format(
                    glob.conf.config["server"]["replayspath"], replayID)
            if cgamemode == 2:
                log.debug("relax")
                fileName = "{}_relax/replay_{}.osr".format(
                    glob.conf.config["server"]["replayspath"], replayID)
                UsingRelax = True
                UsingAuto = False
            if cgamemode == 1:
                log.debug("std")
                UsingRelax = False
                UsingAuto = False
                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"])

            Play = "VANILLA"
            if UsingRelax:
                Play = "RELAX"
            if UsingAuto:
                Play = "AUTOPILOT"
            # Serve replay
            log.info("[{}] Serving replay_{}.osr".format(Play, replayID))

            if os.path.isfile(fileName):
                with open(fileName, "rb") as f:
                    fileContent = f.read()
                self.write(fileContent)
            else:
                log.info("Replay {} doesn't exist".format(replayID))
                self.write("")
        except exceptions.invalidArgumentsException:
            pass
        except exceptions.need2FAException:
            pass
        except exceptions.loginFailedException:
            pass
Ejemplo n.º 7
0
    def asyncPost(self):
        try:
            if glob.debug:
                requestsManager.printArguments(self)

            # Make sure screenshot file was passed
            if "ss" not in self.request.files:
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            # Check user auth because of sneaky people
            if not requestsManager.checkArguments(self.request.arguments,
                                                  ["u", "p"]):
                raise exceptions.invalidArgumentsException(MODULE_NAME)
            username = self.get_argument("u")
            password = self.get_argument("p")
            ip = self.getRequestIP()
            userID = userUtils.getID(username)
            if not userUtils.checkLogin(userID, password):
                raise exceptions.loginFailedException(MODULE_NAME, username)
            if userUtils.check2FA(userID, ip):
                raise exceptions.need2FAException(MODULE_NAME, username, ip)

            # Rate limit
            if glob.redis.get("lets:screenshot:{}".format(userID)) is not None:
                self.write("no")
                return
            glob.redis.set("lets:screenshot:{}".format(userID), 1, 60)

            #check if user folder exist
            screenshotID = generalUtils.randomString(8)
            if not os.path.isdir("{}/{}/".format(
                    glob.conf.config["server"]["storagepath"], userID)):
                os.mkdir("{}/{}/".format(
                    glob.conf.config["server"]["storagepath"], userID))

            # Get a random screenshot id
            found = False
            screenshotID = ""
            while not found:
                screenshotID = generalUtils.randomString(8)
                if not os.path.isfile("{}/{}/{}.jpg".format(
                        glob.conf.config["server"]["storagepath"], userID,
                        screenshotID)):
                    found = True

            # Write screenshot file to screenshots folder
            with open(
                    "{}/{}/{}.jpg".format(
                        glob.conf.config["server"]["storagepath"], userID,
                        screenshotID), "wb") as f:
                f.write(self.request.files["ss"][0]["body"])

            # Output
            log.info("New screenshot ({})".format(screenshotID))

            # Return screenshot link
            self.write("https://storage.aeris-dev.pw/get/{}/{}.jpg".format(
                userID, screenshotID))
        except exceptions.need2FAException:
            pass
        except exceptions.invalidArgumentsException:
            pass
        except exceptions.loginFailedException:
            pass
Ejemplo n.º 8
0
    def asyncGet(self):
        output = ""

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

            ip = self.getRequestIP()
            username = self.get_argument("u").strip()
            password = self.get_argument("p").strip()
            user_id = userUtils.getID(username)
            checksum = self.get_argument("c").strip()
            if not user_id:
                raise exceptions.loginFailedException(MODULE_NAME, user_id)
            if not userUtils.checkLogin(user_id, password, ip):
                raise exceptions.loginFailedException(MODULE_NAME, username)
            if userUtils.check2FA(user_id, ip):
                raise exceptions.need2FAException(MODULE_NAME, user_id, ip)

            ranked = glob.db.fetch(
                "SELECT ranked FROM beatmaps WHERE beatmap_md5 = %s LIMIT 1",
                (checksum, ))
            if ranked is None:
                output = "no exist"
                return
            if ranked["ranked"] < rankedStatuses.RANKED:
                output = "not ranked"
                return

            rating = glob.db.fetch(
                "SELECT rating FROM beatmaps WHERE beatmap_md5 = %s LIMIT 1",
                (checksum, ))
            has_voted = glob.db.fetch(
                "SELECT id FROM beatmaps_rating WHERE user_id = %s AND beatmap_md5 = %s LIMIT 1",
                (user_id, checksum))
            if has_voted != None:
                output = f"alreadyvoted\n{rating['rating']:.2f}"
                return
            vote = self.get_argument("v", default=None)
            if vote is None:
                output = "ok"
                return
            try:
                vote = int(vote)
            except ValueError:
                raise exceptions.invalidArgumentsException(MODULE_NAME)
            if vote < 0 or vote > 10:
                output = "out of range"
                return
            glob.db.execute(
                "REPLACE INTO beatmaps_rating (beatmap_md5, user_id, rating) VALUES (%s, %s, %s)",
                (checksum, user_id, vote))
            glob.db.execute(
                "UPDATE beatmaps SET rating = (SELECT SUM(rating)/COUNT(rating) FROM beatmaps_rating "
                "WHERE beatmap_md5 = %(md5)s) WHERE beatmap_md5 = %(md5)s LIMIT 1",
                {"md5": checksum})
            rating = glob.db.fetch(
                "SELECT rating FROM beatmaps WHERE beatmap_md5 = %s LIMIT 1",
                (checksum, ))
            output = f"{rating['rating']:.2f}"
        except exceptions.loginFailedException:
            output = "auth failed"
        except exceptions.invalidArgumentsException:
            output = "no"
        finally:
            self.write(output)
Ejemplo n.º 9
0
    def asyncPost(self):
        try:
            if glob.conf["DEBUG"]:
                requestsManager.printArguments(self)

            # Make sure screenshot file was passed
            if "ss" not in self.request.files:
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            # Check user auth because of sneaky people
            if not requestsManager.checkArguments(self.request.arguments,
                                                  ["u", "p"]):
                raise exceptions.invalidArgumentsException(MODULE_NAME)
            username = self.get_argument("u")
            password = self.get_argument("p")
            ip = self.getRequestIP()
            userID = userUtils.getID(username)
            if not userUtils.checkLogin(userID, password):
                raise exceptions.loginFailedException(MODULE_NAME, username)
            if userUtils.check2FA(userID, ip):
                raise exceptions.need2FAException(MODULE_NAME, username, ip)

            # Rate limit
            if glob.redis.get("lets:screenshot:{}".format(userID)) is not None:
                self.write("no")
                return
            glob.redis.set("lets:screenshot:{}".format(userID), 1, 60)

            # Get a random screenshot id
            hasS3 = bool(glob.conf["S3_SCREENSHOTS_BUCKET"]) \
             and bool(glob.conf["S3_SCREENSHOTS_REGION"]) \
             and bool(glob.conf["S3_SCREENSHOTS_ENDPOINT_URL"])
            found = False
            screenshotID = ""
            while not found:
                screenshotID = generalUtils.randomString(8)
                if hasS3:
                    try:
                        glob.threadScope.s3Screenshots.head_object(
                            Bucket=glob.conf["S3_SCREENSHOTS_BUCKET"],
                            Key=f"{screenshotID}.jpg")
                        found = False
                    except botocore.errorfactory.ClientError:
                        found = True
                else:
                    found = not os.path.isfile("{}/{}.jpg".format(
                        glob.conf["SCREENSHOTS_FOLDER"], screenshotID))

            # Output
            log.info("New screenshot ({})".format(screenshotID))

            # Write screenshot file to .data folder
            if hasS3:
                with io.BytesIO(self.request.files["ss"][0]["body"]) as f:
                    glob.threadScope.s3Screenshots.upload_fileobj(
                        f,
                        glob.conf["S3_SCREENSHOTS_BUCKET"],
                        f"{screenshotID}.jpg",
                        ExtraArgs={"ACL": "public-read"})
            else:
                with open(
                        "{}/{}.jpg".format(glob.conf["SCREENSHOTS_FOLDER"],
                                           screenshotID), "wb") as f:
                    f.write(self.request.files["ss"][0]["body"])

            # Return screenshot link
            self.write("{}/ss/{}.jpg".format(glob.conf["SERVER_URL"],
                                             screenshotID))
        except exceptions.need2FAException:
            pass
        except exceptions.invalidArgumentsException:
            pass
        except exceptions.loginFailedException:
            pass
Ejemplo n.º 10
0
 def asyncPost(self):
     try:
         if not requestsManager.checkArguments(self.request.arguments, [
                 "user[username]", "user[user_email]", "user[password]",
                 "check"
         ]):
             return self.write("what are you doing here?")
         username = self.get_argument("user[username]")
         email = self.get_argument("user[user_email]")
         password = self.get_argument("user[password]")  # Raw password
         accountCreated = self.get_argument("check")
         if accountCreated == "1":
             return self.write(
                 '{"form_error":{"user":{"check":["Account already created."]}}}'
             )
         emailCheck = glob.db.fetch("SELECT 1 FROM users WHERE email = %s",
                                    [email])
         usernameCheck = glob.db.fetch(
             "SELECT 1 FROM users WHERE username = %s", [username])
         if emailCheck != None:
             return self.write(
                 '{"form_error":{"user":{"user_email":["Email address already used."]}}}'
             )
         if usernameCheck != None or username.lower() in [
                 "peppy", "rrtyui", "cookiezi", "azer", "loctav",
                 "banchobot", "happystick", "doomsday", "sharingan33",
                 "andrea", "cptnxn", "reimu-desu", "hvick225", "_index",
                 "my aim sucks", "kynan", "rafis", "sayonara-bye",
                 "thelewa", "wubwoofwolf", "millhioref", "tom94",
                 "tillerino", "clsw", "spectator", "exgon", "axarious",
                 "angelsim", "recia", "nara", "emperorpenguin83", "bikko",
                 "xilver", "vettel", "kuu01", "_yu68", "tasuke912", "dusk",
                 "ttobas", "velperk", "jakads", "jhlee0133", "abcdullah",
                 "yuko-", "entozer", "hdhr", "ekoro", "snowwhite",
                 "osuplayer111", "musty", "nero", "elysion", "ztrot",
                 "koreapenguin", "fort", "asphyxia", "niko", "shigetora"
         ]:
             return self.write(
                 '{"form_error":{"user":{"username":["Username already used or it is forbidden."]}}}'
             )
         if len(password) < 8 or len(password) > 32:
             return self.write(
                 '{"form_error":{"user":{"password":["Password too short or long! (Password length must be more than 8 and less than 32)"]}}}'
             )
         if "_" in username and " " in username:
             self.write(
                 '{"form_error":{"user":{"username":["An username can not contain both underscores and spaces."]}}}'
             )
         userID = int(
             glob.db.execute(
                 "INSERT INTO users(username, username_safe, password_md5, salt, email, register_datetime, privileges, password_version) VALUES (%s,       %s,            %s,            '',  %s,     %s,                 1048576,          2)",
                 [
                     username,
                     userUtils.safeUsername(username),
                     passwordUtils.genBcrypt(
                         hashlib.md5(password.encode('utf-8')).hexdigest()),
                     email,
                     int(time.time())
                 ]))
         glob.db.execute(
             "INSERT INTO users_stats(id, username, user_color, user_style, ranked_score_std, playcount_std, total_score_std, ranked_score_taiko, playcount_taiko, total_score_taiko, ranked_score_ctb, playcount_ctb, total_score_ctb, ranked_score_mania, playcount_mania, total_score_mania) VALUES (%s, %s, 'black', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)",
             [userID, username])
         glob.db.execute(
             "INSERT INTO rx_stats(id, username, user_color, user_style, ranked_score_std, playcount_std, total_score_std, ranked_score_taiko, playcount_taiko, total_score_taiko, ranked_score_ctb, playcount_ctb, total_score_ctb, ranked_score_mania, playcount_mania, total_score_mania) VALUES (%s, %s, 'black', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)",
             [userID, username])
         log.info(
             "{} created their account using ingame registration.".format(
                 username))
     except Exception as e:
         log.error(e)
Ejemplo n.º 11
0
    def asyncGet(self):
        statusCode = 400
        response = {"message": "unknow error"}
        try:
            # Check args
            if not requestsManager.checkArguments(self.request.arguments, ['k', 'command', 'matchID']):
                response['message'] = 'missing params'
                raise exceptions.invalidArgumentsException()
            
            # Check secret key
            key = self.get_argument('k')
            if key is None or key != glob.conf.config['server']['cikey']:
                response['message'] = 'bad secret key. you are not allowed to access to this api'
                raise exceptions.invalidArgumentsException()
            
            command = self.get_argument('command')
            matchID = self.get_argument('matchID')
            channel = '%23multi_{}'.format(matchID)
            available_commands = {
                'invite': '!mp invite ',
                'move': '!mp move ',
                'lock': '!mp lock',
                'unlock': '!mp unlock',
                'map': '!mp map ',
                'mods': '!mp mods ',
                'scorev': '!mp scorev ',
                'set': '!mp set ',
                'team': '!mp team ',
                'kick': '!mp kick ',
                'start': '!mp start',
                'abort': '!mp abort',
                'close': '!mp close'
            }

            # Main msg for Fokabot
            msg = available_commands.get(command, None)
            
            # LOL
            if msg is None:
                response['message'] = 'Bad command'
                raise exceptions.invalidArgumentsException()
            elif command == 'invite':
                user = self.get_argument('user')
                if user is None:
                    response['message'] = 'Missing username'
                    raise exceptions.invalidArgumentsException()
                else:
                    msg = msg + user
            elif command == 'move':
                user = self.get_argument('user')
                slot = self.get_argument('slot')
                if user is None:
                    response['message'] = 'Missing username'
                    raise exceptions.invalidArgumentsException()
                elif slot is None:
                    response['message'] = 'Missing slot position'
                    raise exceptions.invalidArgumentsException()
                else:
                    msg = msg + user + ' ' + slot
            elif command == 'map':
                beatmapID = self.get_argument('beatmapID')
                if beatmapID is None:
                    response['message'] = 'Missing beatmapID'
                    raise exceptions.invalidArgumentsException()
                else:
                    msg = msg + beatmapID
            elif command == 'mods':
                mods = self.get_arguments('mod')
                if mods is None:
                    response['message'] = 'Missing mod'
                    raise exceptions.invalidArgumentsException()
                else:
                    for mod in mods:
                        msg = msg + mod + ' '
            elif command == 'scorev':
                scorev = self.get_argument('scorev')
                if scorev is None:
                    response['message'] = 'Missing score version (scorev)'
                    raise exceptions.invalidArgumentsException()
                else:
                    msg = msg + scorev
            elif command == 'set':
                gameMode = self.get_argument('mode')
                if gameMode is None:
                    response['message'] = 'Missing game type. Only support h2h and teamvs'
                    raise exceptions.invalidArgumentsException()
                elif gameMode == 'h2h':
                    msg = msg + '0'
                elif gameMode == 'teamvs':
                    msg = msg + '2'
                else:
                    response['message'] = 'Not supported game type'
                    raise exceptions.invalidArgumentsException()
            elif command == 'team':
                user = self.get_argument('user')
                teamColor = self.get_argument('teamColor')
                if user is None:
                    response['message'] = 'Missing username'
                    raise exceptions.invalidArgumentsException()
                elif teamColor is None:
                    response['message'] = 'Missing team color'
                    raise exceptions.invalidArgumentsException()
                elif teamColor == 'red':
                    msg = msg + user + ' red'
                elif teamColor == 'blue':
                    msg = msg + user + ' blue'
                else:
                    response['message'] = 'Bad team color. Only support red and blue'
                    raise exceptions.invalidArgumentsException()
            elif command == 'kick':
                user = self.get_argument('user')
                if user is None:
                    response['message'] = 'Missing username'
                    raise exceptions.invalidArgumentsException()
            
            with urlopen('http://localhost:5001/api/v1/fokabotMessage?k={}&to=%23multi_{}&msg={}'.format(glob.conf.config['server']['cikey'], matchID, msg.replace('!', '%21').replace(' ', '%20'))) as req:
                req = req.read()
            #chatHelper.sendMessage(glob.BOT_NAME, channel.encode().decode("ASCII", "ignore"), msg.encode().decode("ASCII", "ignore"))
            statusCode = 200
            response = req.decode('ASCII')

        except exceptions.invalidArgumentsException:
            statusCode = 400
        finally:
            self.write(json.dumps(response))
            self.set_status(statusCode)
Ejemplo n.º 12
0
    def asyncGet(self):
        statusCode = 400
        data = {"message": "unknown error"}
        try:
            # Check arguments
            if not requestsManager.checkArguments(self.request.arguments,
                                                  ["b"]):
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            # Get beatmap ID and make sure it's a valid number
            beatmapID = self.get_argument("b")
            if not beatmapID.isdigit():
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            # Get mods
            if "m" in self.request.arguments:
                modsEnum = self.get_argument("m")
                if not modsEnum.isdigit():
                    raise exceptions.invalidArgumentsException(MODULE_NAME)
                modsEnum = int(modsEnum)
            else:
                modsEnum = 0

            # Get game mode
            if "g" in self.request.arguments:
                gameMode = self.get_argument("g")
                if not gameMode.isdigit():
                    raise exceptions.invalidArgumentsException(MODULE_NAME)
                gameMode = int(gameMode)
            else:
                gameMode = 0

            # Get acc
            if "a" in self.request.arguments:
                accuracy = self.get_argument("a")
                try:
                    accuracy = float(accuracy)
                except ValueError:
                    raise exceptions.invalidArgumentsException(MODULE_NAME)
            else:
                accuracy = None

            # Max combo
            if "max_combo" in self.request.arguments:
                try:
                    max_combo = int(self.get_argument("max_combo"))
                except ValueError:
                    raise exceptions.invalidArgumentsException(MODULE_NAME)
            else:
                max_combo = -1

            # Print message
            log.info("Requested pp for beatmap {}".format(beatmapID))

            # Get beatmap md5 from osuapi
            # TODO: Move this to beatmap object
            osuapiData = osuapiHelper.osuApiRequest("get_beatmaps",
                                                    "b={}".format(beatmapID))
            if int(beatmapID) > 100000000:
                raise exceptions.ppCustomBeatmap(MODULE_NAME)
            if osuapiData is None or "file_md5" not in osuapiData or "beatmapset_id" not in osuapiData:
                raise exceptions.invalidBeatmapException(MODULE_NAME)
            beatmapMd5 = osuapiData["file_md5"]
            beatmapSetID = osuapiData["beatmapset_id"]

            # Create beatmap object
            bmap = beatmap.beatmap(beatmapMd5, beatmapSetID)

            # Check beatmap length
            if bmap.hitLength > 1500:
                raise exceptions.beatmapTooLongException(MODULE_NAME)

            returnPP = []
            if gameMode == gameModes.STD and bmap.starsStd == 0:
                # Mode Specific beatmap, auto detect game mode
                if bmap.starsTaiko > 0:
                    gameMode = gameModes.TAIKO
                if bmap.starsCtb > 0:
                    gameMode = gameModes.CTB
                if bmap.starsMania > 0:
                    gameMode = gameModes.MANIA

            # Calculate pp
            if gameMode in (gameModes.STD, gameModes.TAIKO):
                # Std pp
                if accuracy is None and max_combo == -1 and modsEnum == 0:
                    # Generic acc/nomod
                    # Get cached pp values
                    cachedPP = bmap.getCachedTillerinoPP()
                    if (modsEnum & mods.RELAX):
                        cachedPP = [0, 0, 0, 0]
                    if (modsEnum & mods.RELAX2):
                        cachedPP = [0, 0, 0, 0]

                    if cachedPP != [0, 0, 0, 0]:
                        log.debug("Got cached pp.")
                        returnPP = cachedPP
                    else:
                        log.debug(
                            "Cached pp not found. Calculating pp with oppai..."
                        )
                        # Cached pp not found, calculate them
                        if gameMode == gameModes.STD and (modsEnum
                                                          & mods.RELAX):
                            oppai = relaxoppai.oppai(bmap,
                                                     mods=modsEnum,
                                                     tillerino=True)
                        elif gameMode == gameModes.STD and (modsEnum
                                                            & mods.RELAX2):
                            oppai = autoppai.oppai(bmap,
                                                   mods=modsEnum,
                                                   tillerino=True)
                        else:
                            oppai = rippoppai.oppai(bmap,
                                                    mods=modsEnum,
                                                    tillerino=True)
                        returnPP = oppai.pp
                        bmap.starsStd = oppai.stars

                        if not (modsEnum & mods.RELAX) or (modsEnum
                                                           & mods.RELAX2):
                            # Cache values in DB
                            log.debug("Saving cached pp...")
                            if type(returnPP) == list and len(returnPP) == 4:
                                bmap.saveCachedTillerinoPP(returnPP)
                else:
                    # Specific accuracy/mods, calculate pp
                    # Create oppai instance
                    log.debug(
                        "Specific request ({}%/{}). Calculating pp with oppai..."
                        .format(accuracy, modsEnum))
                    til_enable = accuracy is None
                    if gameMode == gameModes.STD and (modsEnum & mods.RELAX):
                        oppai = relaxoppai.oppai(bmap,
                                                 mods=modsEnum,
                                                 tillerino=til_enable,
                                                 combo=max_combo)
                    elif gameMode == gameModes.STD and (modsEnum
                                                        & mods.RELAX2):
                        oppai = autoppai.oppai(bmap,
                                               mods=modsEnum,
                                               tillerino=til_enable,
                                               combo=max_combo)
                    else:
                        oppai = rippoppai.oppai(bmap,
                                                mods=modsEnum,
                                                tillerino=til_enable,
                                                combo=max_combo)
                    bmap.starsStd = oppai.stars
                    if not til_enable:
                        returnPP = [calculatePPFromAcc(oppai, accuracy)]
                    else:
                        returnPP = oppai.pp
            else:
                raise exceptions.unsupportedGameModeException()

            # Data to return
            data = {
                "song_name": bmap.songName,
                "pp": returnPP,
                "length": bmap.hitLength,
                "stars": bmap.starsStd,
                "ar": bmap.AR,
                "bpm": bmap.bpm,
            }

            # Set status code and message
            statusCode = 200
            data["message"] = "ok"
        except exceptions.invalidArgumentsException:
            # Set error and message
            statusCode = 400
            data["message"] = "missing required arguments"
        except exceptions.ppCustomBeatmap:
            statusCode = 400
            data[
                "message"] = "Custom map does not supported pp calculating yet"
        except exceptions.invalidBeatmapException:
            statusCode = 400
            data["message"] = "beatmap not found"
        except exceptions.beatmapTooLongException:
            statusCode = 400
            data["message"] = "requested beatmap is too long"
        except exceptions.unsupportedGameModeException:
            statusCode = 400
            data["message"] = "Unsupported gamemode"
        finally:
            # Add status code to data
            data["status"] = statusCode

            # Debug output
            log.debug(str(data))

            # Send response
            #self.clear()
            self.write(json.dumps(data))
            self.set_header("Content-Type", "application/json")
            self.set_status(statusCode)
Ejemplo n.º 13
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")
            s = rxscore.score()
            # 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
            if bool(s.mods & 128):  # Relax
                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])
                # Increment 'replays watched by others' if needed
                if replayData is not None:
                    if username != replayData["uname"]:
                        userUtils.incrementReplaysWatched(
                            replayData["userid"], replayData["play_mode"],
                            s.mods)
            else:
                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])
                # Increment 'replays watched by others' if needed
                if replayData is not None:
                    if username != replayData["uname"]:
                        userUtils.incrementReplaysWatched(
                            replayData["userid"], replayData["play_mode"],
                            s.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
Ejemplo n.º 14
0
    def asyncPost(self):
        try:
            if glob.debug:
                requestsManager.printArguments(self)

            # Make sure screenshot file was passed
            if "ss" not in self.request.files:
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            # Check user auth because of sneaky people
            if not requestsManager.checkArguments(self.request.arguments,
                                                  ["u", "p"]):
                raise exceptions.invalidArgumentsException(MODULE_NAME)
            username = self.get_argument("u")
            password = self.get_argument("p")
            ip = self.getRequestIP()
            userID = userUtils.getID(username)
            if not userUtils.checkLogin(userID, password):
                raise exceptions.loginFailedException(MODULE_NAME, username)
            if userUtils.check2FA(userID, ip):
                raise exceptions.need2FAException(MODULE_NAME, username, ip)

            # Rate limit
            if glob.redis.get("lets:screenshot:{}".format(userID)) is not None:
                self.write("no")
                return
            glob.redis.set("lets:screenshot:{}".format(userID), 1, 60)

            # Get a random screenshot id
            found = False
            screenshotID = ""
            while not found:
                screenshotID = generalUtils.randomString(8)
                if not os.path.isfile("/home/ss/{}.png".format(screenshotID)):
                    found = True

            # Write screenshot file to .data folder
            with open("/home/ss/{}.png".format(screenshotID), "wb") as f:
                f.write(self.request.files["ss"][0]["body"])

            # Add Akatsuki's watermark
            base_screenshot = Image.open(
                '/home/ss/{}.png'.format(screenshotID))
            watermark = Image.open('constants/watermark.png')
            width, height = base_screenshot.size

            position = (width - 330, height - 200)

            transparent = Image.new('RGBA', (width, height), (0, 0, 0, 0))
            transparent.paste(base_screenshot, (0, 0))
            transparent.paste(watermark, position, mask=watermark)
            transparent.show()
            transparent.save('/home/ss/{}.png'.format(screenshotID))

            # Output
            log.info("New screenshot ({})".format(screenshotID))

            # Return screenshot link
            self.write("{}/ss/{}.png".format(
                glob.conf.config["server"]["servername"], screenshotID))
        except exceptions.need2FAException:
            pass
        except exceptions.invalidArgumentsException:
            pass
        except exceptions.loginFailedException:
            pass