Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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()
Ejemplo n.º 3
0
    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()
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
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)}', )
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
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)}')
Ejemplo n.º 8
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: 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)
Ejemplo n.º 9
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)
Ejemplo n.º 10
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}
Ejemplo n.º 11
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}
Ejemplo n.º 12
0
    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