async def from_api(cls, md5: str) -> Optional['Beatmap']: api = 'https://old.ppy.sh/api/get_beatmaps' params = {'k': glob.config.api_key, 'h': md5} async with glob.web.get(api, params=params) as resp: if resp.status != 200 or not resp: return # request failed, map prob doesnt exist data = await resp.json() if not data: return bmap = data[0] # i hate this idea but o well self = cls() self.id = int(bmap['beatmap_id']) self.sid = int(bmap['beatmapset_id']) self.md5 = md5 self.bpm = float(bmap['bpm']) self.cs = float(bmap['diff_size']) self.ar = float(bmap['diff_approach']) self.od = float(bmap['diff_overall']) self.hp = float(bmap['diff_drain']) self.sr = float(bmap['difficultyrating']) self.mode = osuModes(int(bmap['mode'])) self.artist = bmap['artist'] self.title = bmap['title'] self.diff = bmap['version'] self.mapper = bmap['creator'] self.status = mapStatuses.from_api(int(bmap['approved'])) self.update = dt.strptime(bmap['last_update'], '%Y-%m-%d %H:%M:%S').timestamp() self.nc = time.time() e = await glob.db.fetchrow('SELECT frozen, status, `update` FROM maps WHERE id = %s', [self.id]) if e: if self.update > e['update']: if e['frozen'] and self.status != e['status']: self.status = e['status'] self.frozen = e['frozen'] == 1 self.lb = None # status has changed, lets reset lb cache in case await self.save() else: pass else: self.frozen = False # don't freeze by default, we can override if someone manually edits the map status await self.save() glob.cache['maps'][md5] = self # cache the map now we have it from api & saved in sql await cls.cache_set(self.sid) log(f'Retrieved Set ID {self.sid} from osu!api', Ansi.LCYAN) return self
async def restrict(self, reason: str, fr: "Player") -> None: if self.restricted: return # ? await self.add_priv(Privileges.Restricted) self.restricted = True if self.token: self.enqueue( writer.restartServer(0)) # force relog if they're online await glob.db.execute( "INSERT INTO punishments (`type`, `reason`, `target`, `from`, `time`) " "VALUES (%s, %s, %s, %s, %s)", ["restrict", reason, self.id, fr.id, time.time()], ) for mode, stat in self.stats.items(): mode_name = osuModes(mode).name await glob.redis.zrem(f"asahi:leaderboard:{mode_name}", self.id) await glob.redis.zrem( f"asahi:leaderboard:{mode_name}:{self.country_iso}", self.id, ) stat.rank = 0 stat.country_rank = 0 if wh_url := glob.config.webhooks["anticheat"]: wh = Webhook(url=wh_url) embed = Embed(title=f"") embed.set_author( url=f"https://{glob.config.domain}/u/{self.id}", icon_url=f"https://a.{glob.config.domain}/{self.id}", name=self.name, ) embed.add_field( name="New restricted user", value= f"{self.name} has been restricted by {fr.name} for {reason}.", inline=True, ) wh.add_embed(embed) await wh.post()
async def ban(self, reason: str, fr: 'Player') -> None: if self.priv & Privileges.Banned: return # ? await self.add_priv(Privileges.Banned) if self.token: self.enqueue(writer.userID(-3)) await glob.db.execute( 'INSERT INTO punishments (`type`, `reason`, `target`, `from`, `time`) ' 'VALUES (%s, %s, %s, %s, %s)', ['ban', reason, self.id, fr.id, time.time()] ) for mode, stat in self.stats.items(): mode_name = osuModes(mode).name await glob.redis.zrem(f'asahi:leaderboard:{mode_name}', self.id) await glob.redis.zrem(f'asahi:leaderboard:{mode_name}:{self.country_iso}', self.id) stat.rank = 0 stat.country_rank = 0 if (wh_url := glob.config.webhooks['anticheat']): wh = Webhook(url=wh_url) embed = Embed(title=f'') embed.set_author( url=f'https://{glob.config.domain}/u/{self.id}', icon_url=f'https://a.{glob.config.domain}/{self.id}', name=self.name ) embed.add_field( name='New banned user', value=f'{self.name} has been banned by {fr.name} for {reason}.', inline=True ) wh.add_embed(embed) await wh.post()
async def cache_from_map(cls, bid: int) -> None: api = "https://old.ppy.sh/api/get_beatmaps" params = {"k": glob.config.api_key, "b": bid} async with glob.web.get(api, params=params) as resp: if resp.status != 200 or not resp: return data = await resp.json() if not data: return for bmap in data: self = cls() self.id = int(bmap["beatmap_id"]) self.sid = int(bmap["beatmapset_id"]) self.md5 = bmap["file_md5"] self.bpm = float(bmap["bpm"]) self.cs = float(bmap["diff_size"]) self.ar = float(bmap["diff_approach"]) self.od = float(bmap["diff_overall"]) self.hp = float(bmap["diff_drain"]) self.sr = float(bmap["difficultyrating"]) self.mode = osuModes(int(bmap["mode"])) self.artist = bmap["artist"] self.title = bmap["title"] self.diff = bmap["version"] self.mapper = bmap["creator"] self.status = mapStatuses.from_api(int(bmap["approved"])) self.update = dt.strptime( bmap["last_update"], "%Y-%m-%d %H:%M:%S", ) self.frozen = True self.nc = time.time() await self.save() glob.cache["maps"][self.md5] = self
async def osuMapInfo(request: Request) -> bytes: args = request.args if not await auth(args["u"], args["h"], request): return b"" data = orjson.loads(request.body) player = request.extras["player"] ret = [] for idx, file in enumerate(data["Filenames"]): if not (info := regexes.map_file.match( unquote_plus(file))): # once again osu why continue _map = await glob.db.fetchrow( "SELECT id, sid, md5, status FROM maps WHERE artist = %s AND title = %s AND diff = %s AND mapper = %s", [info["artist"], info["title"], info["diff"], info["mapper"]], ) if not _map: continue status = mapStatuses(_map["status"]) _map["status"] = status.to_api() grades = ["N", "N", "N", "N"] # 1 per mode, N = no score? mode_table = osuModes( player.mode).table # use grades for their current mode async for s in glob.db.iter( f"SELECT grade, mode FROM {mode_table} WHERE md5 = %s AND uid = %s AND status = 2", [_map["md5"], player.id], ): grades[s["mode"]] = s["grade"] ret.append( f"{idx}|" f'{_map["id"]}|{_map["sid"]}|{_map["md5"]}|' f'{_map["status"]}|{"|".join(grades)}', )
async def cache_from_map(cls, bid: int) -> None: api = 'https://old.ppy.sh/api/get_beatmaps' params = {'k': glob.config.api_key, 'b': bid} async with glob.web.get(api, params=params) as resp: if resp.status != 200 or not resp: return data = await resp.json() if not data: return for bmap in data: self = cls() self.id = int(bmap['beatmap_id']) self.sid = int(bmap['beatmapset_id']) self.md5 = bmap['file_md5'] self.bpm = float(bmap['bpm']) self.cs = float(bmap['diff_size']) self.ar = float(bmap['diff_approach']) self.od = float(bmap['diff_overall']) self.hp = float(bmap['diff_drain']) self.sr = float(bmap['difficultyrating']) self.mode = osuModes(int(bmap['mode'])) self.artist = bmap['artist'] self.title = bmap['title'] self.diff = bmap['version'] self.mapper = bmap['creator'] self.status = mapStatuses.from_api(int(bmap['approved'])) self.update = dt.strptime(bmap['last_update'], '%Y-%m-%d %H:%M:%S').timestamp() self.frozen = True self.nc = time.time() await self.save() glob.cache['maps'][self.md5] = self
async def osuMapInfo(request: Request) -> bytes: args = request.args if not await auth(args['u'], args['h'], request): return b'' data = orjson.loads(request.body) player = request.extras.get('player') ret = [] for idx, file in enumerate(data['Filenames']): if not (info := regexes.map_file.match( unquote(file))): # once again osu why continue _map = await glob.db.fetchrow( 'SELECT id, sid, md5, status FROM maps WHERE artist = %s AND title = %s AND diff = %s AND mapper = %s', [info['artist'], info['title'], info['diff'], info['mapper']]) if not _map: continue status = mapStatuses(_map['status']) _map['status'] = status.to_api() grades = ['N', 'N', 'N', 'N'] # 1 per mode, N = no score? mode_table = osuModes( player.mode).table # use grades for their current mode async for s in glob.db.iter( f'SELECT grade, mode FROM {mode_table} WHERE md5 = %s AND uid = %s AND status = 2', [_map['md5'], player.id]): grades[s['mode']] = s['grade'] ret.append(f'{idx}|' f'{_map["id"]}|{_map["sid"]}|{_map["md5"]}|' f'{_map["status"]}|{"|".join(grades)}')
def __init__(self, **kwargs) -> None: self.md5: str = kwargs.get("md5", "") self.id: int = kwargs.get("id", 0) self.sid: int = kwargs.get("sid", 0) self.bpm: float = kwargs.get("bpm", 0.0) self.cs: float = kwargs.get("cs", 0.0) self.ar: float = kwargs.get("ar", 0.0) self.od: float = kwargs.get("od", 0.0) self.hp: float = kwargs.get("hp", 0.0) self.sr: float = kwargs.get("sr", 0.00) self.mode: osuModes = osuModes(kwargs.get("mode", 0)) self.artist: str = kwargs.get("artist", "") self.title: str = kwargs.get("title", "") self.diff: str = kwargs.get("diff", "") self.mapper: str = kwargs.get("mapper", "") self.status: "mapStatuses" = mapStatuses(kwargs.get("status", 0)) self.frozen: bool = kwargs.get("frozen", 0) == 1 self.update: dt = kwargs.get("update", 0) self.nc: float = kwargs.get("nc", 0) # nc = next check (for status update) self.lb: "Leaderboard" = kwargs.get("lb") self.lb_rx: "Leaderboard" = kwargs.get("lb_rx") self.lb_ap: "Leaderboard" = kwargs.get("lb_ap") self.plays: int = kwargs.get("plays", 0) self.passes: int = kwargs.get("passes", 0)
def __init__(self, **kwargs) -> None: self.md5: str = kwargs.get('md5', '') self.id: int = kwargs.get('id', 0) self.sid: int = kwargs.get('sid', 0) self.bpm: float = kwargs.get('bpm', 0.0) self.cs: float = kwargs.get('cs', 0.0) self.ar: float = kwargs.get('ar', 0.0) self.od: float = kwargs.get('od', 0.0) self.hp: float = kwargs.get('hp', 0.0) self.sr: float = kwargs.get('sr', 0.00) self.mode: int = osuModes(kwargs.get('mode', 0)) self.artist: str = kwargs.get('artist', '') self.title: str = kwargs.get('title', '') self.diff: str = kwargs.get('diff', '') self.mapper: str = kwargs.get('mapper', '') self.status: 'mapStatuses' = mapStatuses(kwargs.get('status', 0)) self.frozen: bool = kwargs.get('frozen', 0) == 1 self.update: int = kwargs.get('update', 0) self.nc: int = kwargs.get('nc', 0) # nc = next check (for status update) self.lb: 'Leaderboard' = kwargs.get('lb') self.lb_rx: 'Leaderboard' = kwargs.get('lb_rx') self.lb_ap: 'Leaderboard' = kwargs.get('lb_ap') self.plays: int = kwargs.get('plays', 0) self.passes: int = kwargs.get('passes', 0)
if not (player := await glob.players.get(id=id)): return {"status": {"online": False}} if player.priv & Privileges.Disallowed: return (400, {"message": "user is restricted/banned!"}) if player.map_md5: bmap = await Beatmap.from_md5(player.map_md5) else: bmap = None status = { "online": True, "action": player.action, "info": player.info, "mode": osuModes(player.mode).name, "mods": repr(player.mods), "map": { "md5": bmap.md5, "id": bmap.id, "set_id": bmap.sid, "artist": bmap.artist, "title": bmap.title, "difficulty": bmap.diff, "mapper": bmap.mapper, "star_rating": bmap.sr, } if bmap else None, } return {"status": status}
if not (player := await glob.players.get(id=id)): return {'status': {'online': False}} if player.priv & Privileges.Disallowed: return (400, {'message': 'user is restricted/banned!'}) if player.map_md5: bmap = await Beatmap.from_md5(player.map_md5) else: bmap = None status = { 'online': True, 'action': player.action, 'info': player.info, 'mode': osuModes(player.mode).name, 'mods': repr(player.mods), 'map': { 'md5': bmap.md5, 'id': bmap.id, 'set_id': bmap.sid, 'artist': bmap.artist, 'title': bmap.title, 'difficulty': bmap.diff, 'mapper': bmap.mapper, 'star_rating': bmap.sr } if bmap else None } return {'status': status}
async def from_api(cls, md5: str) -> Optional["Beatmap"]: api = "https://old.ppy.sh/api/get_beatmaps" params = {"k": glob.config.api_key, "h": md5} async with glob.web.get(api, params=params) as resp: if resp.status != 200 or not resp: return # request failed, map prob doesnt exist data = await resp.json() if not data: return bmap = data[0] # i hate this idea but o well self = cls() self.id = int(bmap["beatmap_id"]) self.sid = int(bmap["beatmapset_id"]) self.md5 = md5 self.bpm = float(bmap["bpm"]) self.cs = float(bmap["diff_size"]) self.ar = float(bmap["diff_approach"]) self.od = float(bmap["diff_overall"]) self.hp = float(bmap["diff_drain"]) self.sr = float(bmap["difficultyrating"]) self.mode = osuModes(int(bmap["mode"])) self.artist = bmap["artist"] self.title = bmap["title"] self.diff = bmap["version"] self.mapper = bmap["creator"] self.status = mapStatuses.from_api(int(bmap["approved"])) self.update = dt.strptime(bmap["last_update"], "%Y-%m-%d %H:%M:%S") self.nc = time.time() e = await glob.db.fetchrow( "SELECT frozen, status, `update` FROM maps WHERE id = %s", [self.id], ) if e: if self.update > e["update"]: if e["frozen"] and self.status != e["status"]: self.status = e["status"] self.frozen = e["frozen"] == 1 self.lb = None # status has changed, lets reset lb cache in case await self.save() else: pass else: self.frozen = False # don't freeze by default, we can override if someone manually edits the map status await self.save() glob.cache["maps"][ md5 ] = self # cache the map now we have it from api & saved in sql await cls.cache_set(self.sid) info(f"Retrieved Set ID {self.sid} from osu!api") return self