Example #1
0
    async def perf(self, ctx, *, args=None):
        """Shows information about pp of a certain map"""

        args = self.bot.osuHelpers.parseArgsV2(args=args,
                                               customArgs=["mods", "beatmap"])
        mode = args["mode"]

        if args["beatmap"]:
            beatmap: osuClasses.Beatmap = await self.bot.osuHelpers.getBeatmapFromText(
                args["beatmap"])
        else:
            beatmap: osuClasses.Beatmap = await self.bot.osuHelpers.getBeatmapFromHistory(
                ctx)

        if beatmap is None:
            await ctx.send("Failed to find any maps")
            return

        if self.bot.config.redis is True:
            redisIO.setValue(ctx.message.channel.id, beatmap.beatmap_id)
            redisIO.setValue(f'{ctx.message.channel.id}.mode', mode.id)

        mods: osuClasses.Mods = osuClasses.Mods(args["mods"])

        perf = await self.bot.ppAPI.calculateBeatmap(beatmap.beatmap_id, mods,
                                                     mode)

        result = OsuPerformanceEmbed(beatmap, perf, self.bot.config.color)
        await ctx.send(embed=result)
Example #2
0
    async def recent(self, ctx, *, args=None):
        """Shows recent osu! plays for a user. Modes can be specified ``eg. recent -m 2``.\n*Valid Arguments:* ```fix\n-l, -m```"""

        user = None
        server = osuClasses.Server.BANCHO
        mode = osuClasses.Mode.STANDARD
        limit = 1

        if args is not None:
            parsedArgs = self.bot.osuHelpers.parseArgs(args=args,
                                                       validArgs=['-l', '-m'])
            user = parsedArgs['user']
            qtype = parsedArgs['qtype']
            server = osuClasses.Server.from_name(parsedArgs['server'])
            mode = osuClasses.Mode.fromId(parsedArgs['mode'])
            limit = 5 if parsedArgs['recentList'] is True else 1

        if not user:
            qtype = "id"
            user, serverID = await self.bot.mongoIO.getOsu(ctx.message.author)
            server = osuClasses.Server.from_id(serverID)

        if user and isinstance(
                user, str) and user.startswith("<@") and user.endswith(">"):
            qtype = "id"
            mentioned_id = int(id_rx.sub(r'', user))
            mentioned = await self.bot.ensure_member(mentioned_id, ctx.guild)
            user, serverID = await self.bot.mongoIO.getOsu(mentioned)
            server = osuClasses.Server.from_id(serverID)

        profile: osuClasses.User = await self.bot.osuAPI.getuser(
            user, qtype, mode, server)
        recent_score: osuClasses.RecentScore = (await
                                                self.bot.osuAPI.getrecent(
                                                    profile, limit))[0]

        if self.bot.config.redis is True:
            redisIO.setValue(ctx.message.channel.id, recent_score.beatmap_id)
            redisIO.setValue(f'{ctx.message.channel.id}.mode', mode.id)

        beatmap: osuClasses.Beatmap = await self.bot.osuAPI.getbmap(
            recent_score.beatmap_id,
            mode=mode,
            server=server,
            mods=recent_score.enabled_mods)

        recent_score.performance = await self.bot.ppAPI.calculateScore(
            recent_score)
        recent_score.performance.pp = recent_score.pp if recent_score.pp != 0 else recent_score.performance.pp
        beatmap.max_combo = beatmap.max_combo if beatmap.max_combo else recent_score.performance.max_combo

        result = OsuRecentEmbed(recent_score, beatmap, self.bot.config.color)

        await ctx.send(
            f"**Most Recent osu! {mode.name_full} Play for {profile.username} on {server.name_full}:**",
            embed=result)
Example #3
0
    async def on_message(self, message):
        beatmap = await self.bot.osuHelpers.getBeatmapFromText(message.content, True)
        if beatmap is None:
            return
        async with aiohttp.ClientSession() as session:
            async with session.get(f"https://b.ppy.sh/preview/{beatmap.beatmapset_id}.mp3") as resp:
                if resp.status==200:
                    f=BytesIO(await resp.read())

        if self.bot.config.redis is True:
            redisIO.setValue(message.channel.id, beatmap.beatmap_id)
            redisIO.setValue(f'{message.channel.id}.mode', beatmap.mode)

        await message.channel.send(embed=BeatmapEmbed(beatmap, self.bot.config.color), file=discord.File(f, filename="Preview.mp3"))
Example #4
0
    async def compare(self, ctx: commands.Context, *, args=None):
        """Shows your best scores on the last linked map."""

        user = None
        beatmap: osuClasses.Beatmap = None
        server = osuClasses.Server.BANCHO
        mode = osuClasses.Mode.STANDARD
        limit = 5

        if args is not None:
            if 'c' == ctx.invoked_with or 'compare' == ctx.invoked_with:
                parsedArgs = self.bot.osuHelpers.parseArgsV2(
                    args=args, customArgs=["user", "beatmap"])
            elif 's' == ctx.invoked_with or 'scores' == ctx.invoked_with:
                parsedArgs = self.bot.osuHelpers.parseArgsV2(
                    args=args, customArgs=["beatmap", "user"])
                if parsedArgs['beatmap']:
                    beatmap = await self.bot.osuHelpers.getBeatmapFromText(
                        parsedArgs['beatmap'])
                    if self.bot.config.redis is True:
                        redisIO.setValue(ctx.message.channel.id,
                                         beatmap.beatmap_id)
                        redisIO.setValue(f'{ctx.message.channel.id}.mode',
                                         mode.id)
            user = parsedArgs['user']
            qtype = parsedArgs['qtype']
            server = parsedArgs['server']

        if not user:
            qtype = "id"
            user, serverID = await self.bot.mongoIO.getOsu(ctx.message.author)
            server = osuClasses.Server.from_id(serverID)

        if user and isinstance(
                user, str) and user.startswith("<@") and user.endswith(">"):
            qtype = "id"
            mentioned_id = int(id_rx.sub(r'', user))
            mentioned = await self.bot.ensure_member(mentioned_id, ctx.guild)
            user, serverID = await self.bot.mongoIO.getOsu(mentioned)
            server = osuClasses.Server.from_id(serverID)

        if 'c' == ctx.invoked_with or 'compare' == ctx.invoked_with and beatmap is None:
            if self.bot.config.redis is True:
                mode = osuClasses.Mode.fromId(
                    redisIO.getValue(f'{ctx.message.channel.id}.mode'))
                beatmap = await self.bot.osuAPI.getbmap(redisIO.getValue(
                    ctx.message.channel.id),
                                                        mode=mode,
                                                        server=server)
            else:
                return ctx.send(
                    "Redis is disabled in the config. Please contact the owner of this instance!"
                )

        if beatmap is None:
            return

        profile: osuClasses.User = await self.bot.osuAPI.getuser(
            user, qtype, mode, server)
        tops: List[
            osuClasses.BeatmapScore] = await self.bot.osuAPI.getusrscores(
                profile, beatmap.beatmap_id, limit)

        top: osuClasses.Score
        for _, top in enumerate(tops):
            top.performance = await self.bot.ppAPI.calculateScore(top)
            top.performance.pp = top.pp if top.pp != 0 else top.performance.pp
            beatmap.max_combo = beatmap.max_combo if beatmap.max_combo != 0 else top.performance.max_combo

        title = f"Top osu! {mode.name_full} for {profile.username} on {beatmap.title}[{beatmap.version}]"
        result = OsuListEmbed(title, self.bot.config.color, tops,
                              [beatmap] * len(tops), profile)

        await ctx.send(embed=result)
Example #5
0
    async def osutop(self, ctx, *, args=None):
        """Shows osu! top plays for a user. Modes can be specified ``eg. maniatop``.\n*Valid Arguments:* ```fix\n-r, -p```"""

        user = None
        server = osuClasses.Server.BANCHO
        limit = 5
        mode = osuClasses.Mode.fromCommand(ctx.invoked_with)
        recent: bool = False
        positions: List[int] = range(1, 101)
        parsedArgs = None

        if args is not None:
            parsedArgs = self.bot.osuHelpers.parseArgsV2(args=args,
                                                         customArgs=['user'])
            user = parsedArgs['user']
            qtype = parsedArgs['qtype']
            server = parsedArgs['server']

            if parsedArgs['recent'] is True:
                limit = 100
            elif parsedArgs['position'] is not None:
                limit = min(parsedArgs['position'], 100)

        if not user:
            qtype = "id"
            user, serverID = await self.bot.mongoIO.getOsu(ctx.message.author)
            server = osuClasses.Server.from_id(serverID)

        if user and isinstance(
                user, str) and user.startswith("<@") and user.endswith(">"):
            qtype = "id"
            mentioned_id = int(id_rx.sub(r'', user))
            mentioned = await self.bot.ensure_member(mentioned_id, ctx.guild)
            user, serverID = await self.bot.mongoIO.getOsu(mentioned)
            server = osuClasses.Server.from_id(serverID)

        profile: osuClasses.User = await self.bot.osuAPI.getuser(
            user, qtype, mode, server)
        tops: List[osuClasses.RecentScore] = await self.bot.osuAPI.getusrtop(
            profile, limit)

        if parsedArgs:
            if parsedArgs['recent']:
                sorted_tops = sorted(tops, key=lambda x: x.date, reverse=True)
                positions = list(
                    map(lambda top: tops.index(top) + 1, sorted_tops))
                tops = sorted_tops

            if parsedArgs['position'] is None:
                tops = tops[:5]
                positions = positions[:5]
            else:
                tops = tops[parsedArgs['position'] - 1:parsedArgs['position']]
                positions = positions[parsedArgs['position'] -
                                      1:parsedArgs['position']]
        else:
            tops = tops[:5]
            positions = positions[:5]

        if self.bot.config.redis is True:
            redisIO.setValue(ctx.message.channel.id, tops[0].beatmap_id)
            redisIO.setValue(f'{ctx.message.channel.id}.mode', mode.id)

        beatmaps = []

        index: int
        top: osuClasses.Score
        for index, top in enumerate(tops):
            beatmap: osuClasses.Beatmap = await self.bot.osuAPI.getbmap(
                top.beatmap_id,
                mode=mode,
                server=server,
                mods=top.enabled_mods)

            top.performance = await self.bot.ppAPI.calculateScore(top, mode)
            top.performance.pp = top.pp if top.pp else top.performance.pp
            beatmap.max_combo = beatmap.max_combo if beatmap.max_combo else top.performance.max_combo

            beatmaps.append(beatmap)

        title = f'Top plays on osu! {profile.mode.name_full} for {profile.username}'
        result = OsuListEmbed(title, self.bot.config.color, tops, beatmaps,
                              profile, positions, 0)
        await ctx.send(embed=result)
Example #6
0
 async def osutop(self, ctx, *, user=None):
     limit = 5
     spec = False
     recentFirst = False
     if user:
         user = user.split(" ")
         if '-p' in user:
             try:
                 limit = int(user[user.index('-p') + 1])
                 user.pop(user.index('-p') + 1)
                 spec = True
             except IndexError:
                 limit = 5
             user.pop(user.index('-p'))
         if '-r' in user:
             recentFirst = True
             user.remove('-r')
         user = ''.join(user)
     if not user:
         user = getOsu(ctx.message.author)
     if user and user.startswith("<@") and user.endswith(">"):
         user = getOsu(ctx.guild.get_member(int(re.sub('[^0-9]', '',
                                                       user))))
     if not user:
         return await ctx.send("Please set your profile!")
     if ctx.invoked_with == "osutop" or ctx.invoked_with == "ot":
         mode = 0
     if ctx.invoked_with == "taikotop" or ctx.invoked_with == "tt":
         mode = 1
     if ctx.invoked_with == "ctbtop" or ctx.invoked_with == "ct":
         mode = 2
     if ctx.invoked_with == "maniatop" or ctx.invoked_with == "mt":
         mode = 3
     if mode == 0:
         mode_icon = "https://i.imgur.com/lT2nqls.png"
         mode_name = "Standard"
     if mode == 1:
         mode_icon = "https://i.imgur.com/G6bzM0X.png"
         mode_name = "Taiko"
     if mode == 2:
         mode_icon = "https://i.imgur.com/EsanYkH.png"
         mode_name = "Catch the Beat"
     if mode == 3:
         mode_icon = "https://i.imgur.com/0uZM1PZ.png"
         mode_name = "Mania"
     if not recentFirst:
         async with aiohttp.ClientSession() as cs:
             async with cs.get(
                     f"https://osu.ppy.sh/api/get_user_best?k={cfg.OSU_API}&m={mode}&limit={limit}&u={user}&type=string"
             ) as r:
                 tops = await r.json()
     else:
         async with aiohttp.ClientSession() as cs:
             async with cs.get(
                     f"https://osu.ppy.sh/api/get_user_best?k={cfg.OSU_API}&m={mode}&limit=100&u={user}&type=string"
             ) as r:
                 tops = await r.json()
     if tops == []:
         return await ctx.send("User has not been found or has no plays!")
     uid = tops[0]["user_id"]
     if spec:
         tops = tops[limit - 1:]
     elif recentFirst:
         tops.sort(key=lambda x: datetime.strptime(x["date"],
                                                   "%Y-%m-%d %H:%M:%S"),
                   reverse=True)
         tops = tops[:5]
     redisIO.setValue(ctx.message.channel.id, tops[0]["beatmap_id"])
     desc = ""
     for index, play in enumerate(tops):
         rank = play["rank"]
         rankemoji = self.ranks[rank]
         pp = float(play["pp"])
         perfect = int(play["perfect"])
         count50 = int(play["count50"])
         count100 = int(play["count100"])
         count300 = int(play["count300"])
         count0 = int(play["countmiss"])
         countgeki = int(play["countgeki"])
         countkatu = int(play["countkatu"])
         beatmap_id = play["beatmap_id"]
         modnum = int(play["enabled_mods"])
         mods = getMods(modnum)
         bestcombo = int(play["maxcombo"])
         date = datetime.strptime(play["date"], "%Y-%m-%d %H:%M:%S")
         async with aiohttp.ClientSession() as cs:
             async with cs.get(f'https://osu.ppy.sh/osu/{beatmap_id}') as r:
                 if r.status == 200:
                     bmap = StringIO(await r.text())
         async with aiohttp.ClientSession() as cs2:
             async with cs2.get(
                     f"https://osu.ppy.sh/api/get_beatmaps?k={cfg.OSU_API}&b={beatmap_id}&limit=1"
             ) as r2:
                 beatmap = await r2.json()
                 beatmap = beatmap[0]
         maxcombo = int(
             beatmap["max_combo"]) if beatmap["max_combo"] else None
         diff = beatmap["version"]
         beatmap_title = f"{beatmap['artist']} - {beatmap['title']} ({beatmap['creator']}) [{diff}]"
         if_fc = ""
         if mode == 0:
             accuracy = acc.stdCalc(count0, count50, count100, count300)
             sr, __, pp_fc = await self.bot.loop.run_in_executor(
                 None, ppc.stdCalc, bmap, count0, count50, count100,
                 count300, bestcombo, modnum, perfect, maxcombo)
             if perfect == 0:
                 accuracy_fc = acc.stdCalc(0, count50, count100,
                                           count300 + count0)
                 if_fc = f" ({pp_fc}PP for {accuracy_fc}% FC)"
             mode_icon = "https://i.imgur.com/lT2nqls.png"
             mode_name = "Standard"
         if mode == 1:
             accuracy = acc.taikoCalc(count0, count100, count300)
             sr, __ = await self.bot.loop.run_in_executor(
                 None, ppc.taikoCalc, bmap, modnum)
             mode_icon = "https://i.imgur.com/G6bzM0X.png"
             mode_name = "Taiko"
         if mode == 2:
             accuracy = acc.ctbCalc(count0, countkatu, count50, count100,
                                    count300)
             sr, __, maxcombo = await self.bot.loop.run_in_executor(
                 None, ppc.ctbCalc, bmap, accuracy / 100, count0, modnum,
                 bestcombo)
             mode_icon = "https://i.imgur.com/EsanYkH.png"
             mode_name = "Catch the Beat"
         if mode == 3:
             accuracy = acc.maniaCalc(count0, count50, count100, countkatu,
                                      count300, countgeki)
             sr, __ = await self.bot.loop.run_in_executor(
                 None, ppc.maniaCalc)
             mode_icon = "https://i.imgur.com/0uZM1PZ.png"
             mode_name = "Mania"
         if spec:
             index = limit - 1
         desc = desc + f"\n{index+1}. [**{beatmap_title}**](https://osu.ppy.sh/b/{beatmap_id}) + **{mods}** [{sr}★]" + '\n' + f"> {rankemoji} > **{pp}pp**{if_fc} > {accuracy}%\n> {bestcombo}x/{maxcombo}x > [{count300}/{count100}/{count50}/{count0}]\n> {date}\n"
     embed = discord.Embed(title=discord.Embed.Empty,
                           color=get_config().COLOR,
                           description=desc)
     embed.set_author(name=f"Top {limit} osu! {mode_name} for {user}",
                      url=f"https://osu.ppy.sh/users/{uid}",
                      icon_url=mode_icon)
     embed.set_thumbnail(url=f"https://a.ppy.sh/{uid}")
     await ctx.send(embed=embed)
Example #7
0
 async def recent(self, ctx, *, optional=None):
     """Shows recent osu! plays for a user. Modes can be specified."""
     if optional is None:
         user = getOsu(ctx.message.author)
         mode = 0
     else:
         optional = optional.split(" ")
         if '-m' not in optional:
             user = ''.join(optional)
             mode = 0
         else:
             try:
                 mode = int(optional[optional.index('-m') + 1])
                 optional.pop(optional.index('-m') + 1)
             except IndexError:
                 mode = 0
             optional.pop(optional.index('-m'))
             user = ''.join(optional)
             if not user:
                 user = getOsu(ctx.message.author)
     if user is not None and user.startswith("<@") and user.endswith(">"):
         user = getOsu(ctx.guild.get_member(int(re.sub('[^0-9]', '',
                                                       user))))
     if not user:
         return await ctx.send("Please set your profile!")
     async with aiohttp.ClientSession() as cs:
         async with cs.get(
                 f"https://osu.ppy.sh/api/get_user_recent?k={cfg.OSU_API}&u={user}&m={mode}&type=string"
         ) as r:
             recentp = await r.json()
     if recentp != []:
         if_fc = ""
         date = datetime.strptime(recentp[0]["date"], "%Y-%m-%d %H:%M:%S")
         redisIO.setValue(ctx.message.channel.id, recentp[0]["beatmap_id"])
         async with aiohttp.ClientSession() as cs:
             async with cs.get(
                     f'https://osu.ppy.sh/osu/{recentp[0]["beatmap_id"]}'
             ) as r:
                 bmap = StringIO(await r.text())
         async with aiohttp.ClientSession() as cs:
             async with cs.get(
                     f"https://osu.ppy.sh/api/get_beatmaps?k={cfg.OSU_API}&b={recentp[0]['beatmap_id']}&limit=1"
             ) as r:
                 beatmap = await r.json()
         beatmapset_id = int(beatmap[0]["beatmapset_id"])
         status = int(beatmap[0]["approved"])
         beatmapDict, playDict = ppc.calculatePlay(
             bmap, mode, int(recentp[0]["countmiss"]),
             int(recentp[0]["count50"]), int(recentp[0]["count100"]),
             int(recentp[0]["count300"]), int(recentp[0]["countgeki"]),
             int(recentp[0]["countkatu"]), int(recentp[0]["maxcombo"]),
             int(recentp[0]["enabled_mods"]), int(recentp[0]["perfect"]))
         status = self.nomstat[status]
         completion = f'\n> **Completion:** {playDict["completion"]}%' if recentp[
             0]["rank"] == 'F' and mode == 0 else ''
         if_fc = '' if int(
             recentp[0]["perfect"]
         ) == 1 else f" ({playDict['pp_fc']} for {playDict['accuracy_fc']}% FC)"
         rankemoji = self.ranks[recentp[0]["rank"]]
         desc = f"> {rankemoji} > **{playDict['pp']}PP{if_fc}** > {playDict['accuracy']}%\n> {recentp[0]['score']} > x{recentp[0]['maxcombo']}/{beatmapDict['maxcombo']} > [{recentp[0]['count300']}/{recentp[0]['count100']}/{recentp[0]['count50']}/{recentp[0]['countmiss']}]{completion}"
         embed = discord.Embed(title=discord.Embed.Empty,
                               color=get_config().COLOR,
                               description=desc,
                               timestamp=date)
         embed.set_author(
             name=
             f"{beatmapDict['title']} [{beatmapDict['version']}] ({beatmapDict['creator']}) +{playDict['modString']} [{playDict['rating']}★]",
             url=f"https://osu.ppy.sh/b/{recentp[0]['beatmap_id']}",
             icon_url=f"https://a.ppy.sh/{recentp[0]['user_id']}")
         embed.set_thumbnail(
             url=f"https://b.ppy.sh/thumb/{beatmapset_id}.jpg")
         embed.set_footer(
             text=f"{status} | osu! {playDict['mode_name']} Play",
             icon_url=playDict['mode_icon'])
         await ctx.send(
             f"**Most Recent osu! {playDict['mode_name']} Play for {user}:**",
             embed=embed)
     else:
         await ctx.send("User has not been found or has no recent plays!")