async def root_client(request: Request) -> bytes: start = time.time() headers = ( request.headers ) # request headers, used for things such as user ip and agent if ( "User-Agent" not in headers or headers["User-Agent"] != "osu!" or request.type == "GET" ): # request isn't sent from osu client, return html return root_web() if ( "osu-token" not in headers ): # sometimes a login request will be a re-connect attempt, in which case they will already have a token, if not: login the user data = ( request.body ) # request data, used to get base_info such as username to login the user if ( len(base_info := data.decode().split("\n")[:-1]) != 3 ): # format data so we can use it easier & also ensure it is valid at the same time request.resp_headers[ "cho-token" ] = "no" # client knows there is something up if we set token to 'no' return writer.userID(-2) if ( len(cinfo := base_info[2].split("|")) != 5 ): # format client data (hash, utc etc.) & ensure it is valid request.resp_headers[ "cho-token" ] = "no" # client knows there is something up if we set token to 'no' return writer.userID(-2)
async def avatar(req: Request, uid: str) -> bytes: user = ava_path / f'{uid}' if user.exists(): req.resp_headers['Content-Type'] = 'image/png' return user.read_bytes() else: default = ava_path / 'default.png' req.resp_headers['Content-Type'] = 'image/png' return default.read_bytes()
async def avatar(req: Request, uid: str) -> bytes: user = ava_path / f"{uid}" if user.exists(): req.resp_headers["Content-Type"] = "image/png" return user.read_bytes() else: default = ava_path / "default.png" req.resp_headers["Content-Type"] = "image/png" return default.read_bytes()
async def ingameAchievements(request: Request, medal: str) -> Union[tuple, bytes]: name = medal.split('.')[0] if name not in custom: request.resp_headers[ 'Location'] = f'https://assets.ppy.sh/medals/client/{medal}' # redirect regular achievements return (301, b'') else: request.resp_headers['Content-Type'] = 'image/png' return ( Path.cwd() / f'resources/achievements/{medal.replace("@2x", "")}').read_bytes()
async def root_client(request: Request) -> bytes: start = time.time() headers = request.headers # request headers, used for things such as user ip and agent if 'User-Agent' not in headers or headers['User-Agent'] != 'osu!' or request.type == 'GET': # request isn't sent from osu client, return html return root_web() if 'osu-token' not in headers: # sometimes a login request will be a re-connect attempt, in which case they will already have a token, if not: login the user data = request.body # request data, used to get info such as username to login the user if len(info := data.decode().split('\n')[:-1]) != 3: # format data so we can use it easier & also ensure it is valid at the same time request.resp_headers['cho-token'] = 'no' # client knows there is something up if we set token to 'no' return writer.userID(-2) if len(cinfo := info[2].split('|')) != 5: # format client data (hash, utc etc.) & ensure it is valid request.resp_headers['cho-token'] = 'no' # client knows there is something up if we set token to 'no' return writer.userID(-2)
async def getScreenshot(request: Request, scr: str) -> bytes: ss = ss_path / scr _type = scr.split('.')[1] if ss.exists(): ssb = ss.read_bytes() request.resp_headers['Content-Type'] = f'image/{_type}' return ssb else: return b'could not find screenshot'
async def getScreenshot(request: Request, scr: str) -> bytes: ss = ss_path / scr _type = scr.split(".")[1] if ss.exists(): ssb = ss.read_bytes() request.resp_headers["Content-Type"] = f"image/{_type}" return ssb else: return b"could not find screenshot"
async def default_avatar(req: Request) -> bytes: file = ava_path / 'default.png' req.resp_headers['Content-Type'] = 'image/png' return file.read_bytes()
async def mapDownload(request: Request, mid: str) -> tuple[int, bytes]: request.resp_headers['Location'] = f'{glob.config.map_api}/d/{mid}' return (301, b'') # redirect
async def getReplay(request: Request) -> Union[tuple, bytes]: args = request.args sid = int(args.get("id", 0)) rx = int(args.get("rx", 0)) if not sid: return (400, {"message": "please specify a score id!"}) BASE_DIR = Path.cwd() / "resources" if not 0 <= rx < 3: return (400, {"message": "invalid relax value (must be 0, 1 or 2)"}) if rx == 0: REPLAY_PATH = BASE_DIR / "replays" table = "scores" elif rx == 1: REPLAY_PATH = BASE_DIR / "replays_rx" table = "scores_rx" elif rx == 2: REPLAY_PATH = BASE_DIR / "replays_ap" table = "scores_ap" file = REPLAY_PATH / f"{sid}.osr" if not file.exists(): return ( 400, { "message": "replay couldn't be found. please check the score id and try again!", }, ) raw_replay = file.read_bytes() # get score from sql score = await glob.db.fetchrow( f"SELECT t.*, t.mode m, users.name, maps.* FROM {table} t " "LEFT OUTER JOIN users ON users.id = t.uid LEFT OUTER JOIN maps ON maps.md5 = t.md5 WHERE t.id = %s", [sid], ) # when im not lazy ill use Score.sql to get score object so we can implement rank and shit replay_hash = hashlib.md5( (f'{score["n100"] + score["n300"]}p{score["n50"]}o' f'{score["geki"]}o{score["katu"]}t' f'{score["miss"]}a{score["md5"]}r' f'{score["combo"]}e{score["fc"] == 1}y' f'{score["name"]}o{score["score"]}u' f'0{score["mods"]}True').encode(), ).hexdigest() buffer = bytearray() # headers timeee # not all scores will have osuver so lets just send latest (as of this code) version buffer += struct.pack("<Bi", score["m"], score["osuver"] or 2021_05_20) buffer += writer.write_string(score["md5"]) buffer += writer.write_string(score["name"]) buffer += writer.write_string(replay_hash) buffer += struct.pack( "<hhhhhhihBi", score["n300"], score["n100"], score["n50"], score["geki"], score["katu"], score["miss"], score["score"], score["combo"], score["fc"], score["mods"], ) buffer += b"\x00" # graph probably NEVER buffer += struct.pack("<q", score["time"] * 1_000_000 + DATETIME_OFFSET) buffer += struct.pack("<i", len(raw_replay)) buffer += raw_replay buffer += struct.pack("<q", sid) name = ( f'{score["name"]} ~ {score["artist"]} - {score["title"]} [{score["diff"]}] ' f'+{score["readable_mods"]} ({datetime.fromtimestamp(score["time"]):%Y/%m/%d})' ) request.resp_headers["Content-Type"] = "application/octet-stream" request.resp_headers["Content-Description"] = "File Transfer" request.resp_headers[ "Content-Disposition"] = f"attachment; filename={name}.osr" return bytes(buffer)
async def mapDownload(request: Request, mid: str) -> tuple[int, bytes]: request.resp_headers["Location"] = f"{glob.config.map_api}/d/{mid}" return (301, b"") # redirect
async def default_avatar(req: Request) -> bytes: file = ava_path / "default.png" req.resp_headers["Content-Type"] = "image/png" return file.read_bytes()