Пример #1
0
    def asyncPost(self):
        statusCode = 400
        data = {"message": "unknown error"}
        try:
            # Check arguments
            if not requestsManager.checkArguments(self.request.arguments,
                                                  ["sid", "refresh"]):
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            # Get beatmap set data from osu api
            beatmapSetID = self.get_argument("sid")
            refresh = int(self.get_argument("refresh"))
            if refresh == 1:
                log.debug("Forced refresh")
            apiResponse = osuapiHelper.osuApiRequest(
                "get_beatmaps", "s={}".format(beatmapSetID), False)
            if len(apiResponse) == 0:
                raise exceptions.invalidBeatmapException

            # Loop through all beatmaps in this set and save them in db
            data["maps"] = []
            for i in apiResponse:
                log.debug("Saving beatmap {} in db".format(i["file_md5"]))
                bmap = beatmap.beatmap(i["file_md5"],
                                       int(i["beatmapset_id"]),
                                       refresh=refresh)
                pp = glob.db.fetch(
                    "SELECT pp_100 FROM beatmaps WHERE beatmap_id = %s LIMIT 1",
                    [bmap.beatmapID])
                if pp is None:
                    pp = 0
                else:
                    pp = pp["pp_100"]
                data["maps"].append({
                    "id": bmap.beatmapID,
                    "name": bmap.songName,
                    "status": bmap.rankedStatus,
                    "frozen": bmap.rankedStatusFrozen,
                    "pp": pp,
                })

            # 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 from osu!api."
        finally:
            # Add status code to data
            data["status"] = statusCode

            # Send response
            self.write(json.dumps(data))
            self.set_header("Content-Type", "application/json")
            #self.add_header("Access-Control-Allow-Origin", "*")
            self.set_status(statusCode)
Пример #2
0
def updateSet(beatmapSetID):
    apiResponse = osuapiHelper.osuApiRequest("get_beatmaps",
                                             "s={}".format(beatmapSetID),
                                             False)
    if len(apiResponse) == 0:
        return
    for i in apiResponse:
        beatmap.beatmap(i["file_md5"], int(i["beatmapset_id"]), refresh=True)
Пример #3
0
	def handle(self, data):
		data = super().parseData(data)
		if data is None:
			return
		if "id" in data:
			beatmapData = osuapiHelper.osuApiRequest("get_beatmaps", "b={}".format(data["id"]))
			if beatmapData is not None and "beatmapset_id" in beatmapData:
				updateSet(beatmapData["beatmapset_id"])
		elif "set_id" in data:
			updateSet(data["set_id"])
Пример #4
0
    def asyncGet(self):
        statusCode = 400
        data = {"message": "unknown error"}
        try:
            # Check arguments
            if not requestsManager.checkArguments(self.request.arguments,
                                                  ["b"]):
                raise exceptions.invalidArgumentsException(self.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(self.MODULE_NAME)

            # Get mods
            if "m" in self.request.arguments:
                modsEnum = self.get_argument("m")
                if not modsEnum.isdigit():
                    raise exceptions.invalidArgumentsException(
                        self.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(
                        self.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(
                        self.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(self.MODULE_NAME)
            beatmapMd5 = osuapiData["file_md5"]
            beatmapSetID = osuapiData["beatmapset_id"]

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

            # Check beatmap length
            # TODO: Why do we do this?
            if bmap.hit_length > 900:
                raise exceptions.beatmapTooLongException(self.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.hit_length,
                "stars": bmap.starsStd
                if bmap.starsStd is not None else bmap.difficultyrating,
                "ar": bmap.diff_approach,
                "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)
Пример #5
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 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 > 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 gameMode in (gameModes.STD, gameModes.TAIKO):
                # Std pp
                if accuracy is None and modsEnum == 0:
                    # Generic acc/nomod
                    # Get cached pp values
                    cachedPP = bmap.getCachedTillerinoPP()
                    if (modsEnum & mods.RELAX):
                        cachedPP = [0, 0, 0, 0]
                    elif (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 = relax2oppai.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))
                    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 = relax2oppai.oppai(bmap,
                                                  mods=modsEnum,
                                                  tillerino=True)
                    else:
                        oppai = rippoppai.oppai(bmap,
                                                mods=modsEnum,
                                                tillerino=True)
                    bmap.starsStd = oppai.stars
                    if accuracy is not None:
                        returnPP = calculatePPFromAcc(oppai, accuracy)
                    else:
                        returnPP = oppai.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,
                "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)
Пример #6
0
    def asyncPost(self):
        statusCode = 400
        data = {"message": "unknown error"}
        try:
            # Check arguments
            if not requestsManager.checkArguments(self.request.arguments,
                                                  ["refresh"]):
                raise exceptions.invalidArgumentsException(MODULE_NAME)

            userID = 0
            gameMode = 0
            outputType = 'dap_rank'
            if 'u' in self.request.arguments:
                userID = int(self.get_argument('u'))
            if 'm' in self.request.arguments:
                gameMode = int(self.get_argument('m'))
            if 'out' in self.request.arguments:
                if self.get_argument('out').lower() in ('page', ):
                    outputType = self.get_argument('out')
            # Get beatmap set data from osu api
            data["maps"] = []
            refresh = int(self.get_argument("refresh"))
            apiResponse = []
            if refresh == 1:
                log.debug("Forced refresh")
            if 'sid' in self.request.arguments:
                beatmapSetID = self.get_argument("sid")
                apiResponse = osuapiHelper.osuApiRequest(
                    "get_beatmaps", "s={}".format(beatmapSetID), False)
            elif 'bid' in self.request.arguments:
                beatmapID = self.get_argument("bid")
                apiResponse = osuapiHelper.osuApiRequest(
                    "get_beatmaps", "b={}".format(beatmapID), False)
            else:
                raise exceptions.invalidArgumentsException(MODULE_NAME)
            if len(apiResponse) == 0:
                raise exceptions.invalidBeatmapException
            forcefulStop = False
            for b in apiResponse:
                bm = glob.db.fetch(
                    'select beatmap_id id, beatmap_md5 md5 from beatmaps where beatmap_id = %s',
                    [b['beatmap_id']])
                if bm is None and not eligible.tryLoadBeatmap(userID):
                    forcefulStop = 'beatmapNotice2'
                if bm is not None and bm['md5'] != b[
                        'file_md5'] and not eligible.tryLoadBeatmap(userID):
                    forcefulStop = 'beatmapNotice3'
                if forcefulStop:
                    break
            if forcefulStop:
                params = {
                    "k": glob.conf.config["server"]["apikey"],
                    "to": userID,
                    "code": forcefulStop,
                    'force': 1
                }
                requests.get("{}/api/v1/specialNotice?{}".format(
                    glob.conf.config["server"]["banchourl"],
                    urlencode(params)))
                raise exceptions.invalidBeatmapException

            def processOutput(t, b, **x):
                if outputType == 'page':
                    if b.creatorSrc == 'datenshi_id':
                        ownerLink = "https://osu.troke.id/u/{}"
                    else:
                        ownerLink = "https://osu.ppy.sh/users/{}"
                    if b.mapperSrc == 'datenshi_id':
                        mapperLink = "https://osu.troke.id/u/{}"
                    else:
                        mapperLink = "https://osu.ppy.sh/users/{}"
                    mapStat = b.stats.get(b.gameMode or gameMode, 0)
                    mapDiff = {
                        'hp': mapStat.hp,
                        'od': mapStat.od,
                        'cs': mapStat.cs,
                        'ar': mapStat.ar,
                        'star': mapStat.rating,
                    }
                    if b.gameMode == 1:
                        del mapDiff['cs'], mapDiff['ar']
                    elif b.gameMode == 2:
                        del mapDiff['cs']
                    elif b.gameMode == 3:
                        del mapDiff['ar']
                    return {
                        'artist':
                        b.artist,
                        'title':
                        b.title,
                        'owner':
                        b.creatorName,
                        'owner_link':
                        ownerLink.format(b.creatorID),
                        'mapper':
                        b.mapperName or b.creatorName,
                        'mapper_link':
                        mapperLink.format(b.mapperID)
                        if b.mapperName else ownerLink.format(b.creatorID),
                        'source':
                        b.source,
                        'version':
                        b.difficultyName,
                        'difficulty':
                        mapDiff,
                        'length': {
                            'drain': mapStat.actual_length_drain,
                            'total': mapStat.actual_length_total,
                        },
                        'bpm':
                        b.bpm,
                    }
                else:
                    return {
                        "id": b.beatmapID,
                        "mode": b.mode,
                        "baseName": "{} - {}".format(b.artist, b.title),
                        "diffName": b.difficultyName,
                        "status": b.rankedStatus,
                        "frozen": b.rankedStatusFrozen,
                        "pp": x['pp'],
                        "request": x['request']
                    }

            # Loop through all beatmaps in this set and save them in db
            for i in apiResponse:
                log.debug("Saving beatmap {} in db".format(i["file_md5"]))
                bmap = beatmap.beatmap(i["file_md5"],
                                       int(i["beatmapset_id"]),
                                       refresh=refresh)
                if outputType == 'out' and bmap.takendown and not bmap.userHaveAccess(
                        userID):
                    continue
                pp = glob.db.fetch(
                    "SELECT pp_100 FROM beatmaps WHERE beatmap_id = %s LIMIT 1",
                    [bmap.beatmapID])
                if pp is None:
                    pp = 0
                else:
                    pp = pp["pp_100"]
                reqData = glob.db.fetch(
                    "SELECT userid as user_id, blacklisted as bad, hidden as done FROM rank_requests WHERE (`type` = 'b' and bid = %s) or (`type` = 's' and bid = %s)",
                    [bmap.beatmapID, bmap.beatmapSetID])
                data["maps"].append(
                    processOutput(outputType, bmap, pp=pp, request=reqData))

            # 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 from osu!api."
        finally:
            # Add status code to data
            data["status"] = statusCode

            # Send response
            self.write(json.dumps(data))
            self.set_header("Content-Type", "application/json")
            #self.add_header("Access-Control-Allow-Origin", "*")
            self.set_status(statusCode)
Пример #7
0
    def autorankCheck(beatmap, recursive=True):
        # No autorank check for frozen maps
        if beatmap.rankedStatusFrozen not in (0, 3):
            return
        # No autorank check for already ranked beatmap
        # Only handle this if the map is ranked by autorank.
        if beatmap.rankedStatusFrozen != 3 and beatmap.rankedStatus >= 2:
            return
        # Only check if the map is autorankable.
        if not autorankFlagOK(beatmap.beatmapID):
            return
        # Check recursiveness
        if recursive:
            beatmap_id_query = glob.db.fetchAll(
                'select beatmap_md5, beatmap_id from beatmaps where beatmapset_id = %s',
                [beatmap.beatmapSetID])
            for beatmap_id_data in beatmap_id_query:
                # Skip self.
                if int(beatmap_id_data['beatmap_id']) == beatmap.beatmapID:
                    continue
                siblingmap = bm.beatmap(None, beatmap.beatmapSetID)
                siblingmap.setData(beatmap_id_data['beatmap_md5'],
                                   beatmap.beatmapSetID, True)
        # Not checking maps with non updated date.
        #if recursive:
        #log.info(f"Checking {beatmap.artist} - {beatmap.title} for autorank eligiblity.")
        # log.info(f"Checking {beatmap.songName} for autorank eligiblity.")
        obtainDateTime = lambda t: datetime.datetime.strptime(
            t, "%Y-%m-%d %H:%M:%S")
        obtainUnixClock = lambda t: int(time.mktime(t.timetuple()))
        if beatmap.updateDate == 0:
            log.info(f"Updating {beatmap.fileMD5} data")
            data = osuapiHelper.osuApiRequest('get_beatmaps',
                                              'h={}'.format(beatmap.fileMD5))
            if not data:
                return
            dateTouch = obtainDateTime(data['last_update'])
            beatmap.updateDate = obtainUnixClock(dateTouch)
        else:
            dateTouch = datetime.datetime.fromtimestamp(beatmap.updateDate)

        dateNow = datetime.datetime.today()
        dateQualify = dateTouch + datetime.timedelta(days=GRAVEYARD_DAYS -
                                                     QUALIFIED_DAYS)
        dateRanked = dateTouch + datetime.timedelta(days=GRAVEYARD_DAYS)
        forLove = autorankFlagForLove(beatmap.beatmapID)
        rankStatus = beatmap.rankedStatus
        needWipe = False
        if dateNow >= dateRanked:
            needWipe = rankStatus == rankedStatuses.QUALIFIED
            if forLove:
                log.debug(f"Considering {beatmap.fileMD5} to be loved")
                beatmap.rankedStatus = rankedStatuses.LOVED
            else:
                log.debug(f"Considering {beatmap.fileMD5} on ranking")
                beatmap.rankedStatus = rankedStatuses.RANKED
            beatmap.rankedStatusFrozen = 3
        elif dateNow >= dateQualify and not forLove:
            log.debug(f"Considering {beatmap.fileMD5} for qualified")
            beatmap.rankedStatus = rankedStatuses.QUALIFIED
            beatmap.rankedStatusFrozen = 3
        else:
            needWipe = rankStatus >= rankedStatuses.RANKED
            beatmap.rankedStatus = rankedStatuses.PENDING
            beatmap.rankedStatusFrozen = 0
        if rankStatus != beatmap.rankedStatus:
            dbBeatmap = glob.db.fetch(
                'select ranked_status_freezed as f from beatmaps where beatmap_md5 = %s',
                [beatmap.fileMD5])
            oldFreeze = 0
            if dbBeatmap is not None:
                oldFreeze = dbBeatmap['f']
            glob.db.execute(
                'update beatmaps set ranked_status_freezed = 0 where beatmap_md5 = %s',
                [beatmap.fileMD5])
            if oldFreeze != beatmap.rankedStatusFrozen and recursive:
                autorankAnnounce(beatmap)
            glob.db.execute(
                'update beatmaps set rankedby = %s where beatmap_md5 = %s',
                [autorankUserID(beatmap.beatmapID), beatmap.fileMD5])
        if needWipe:
            log.info(f"Wiping {beatmap.fileMD5} leaderboard")
            beatmap.clearLeaderboard()
            pass