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)
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)
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"))
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)
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)
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)
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!")