async def osu(self, ctx, *user): username = '' i = 0 for word in user: i += 1 if word == user[-1] and len(user) == i: username += str(word) else: username += str(word) + ' ' api = OsuApi(osuapikey, connector=ReqConnector()) results = api.get_user(username) userid = results[0].user_id thumbnail = "https://s.ppy.sh/a/" + str(userid) embed = Embed(title="%s" % (username), description="id:%s" % (userid), color=0xE0FFFF) embed.set_thumbnail(url=thumbnail) await self.bot.send_message(ctx.message.channel, embed=embed) await self.bot.send_message(ctx.message.channel, "https://osu.ppy.sh/users/%d" % userid)
class BaseTwitchPlugin: def __init__(self, bot): self.bot = bot self.bancho_queue = self.bot.config.get('bancho_queue') self.bancho_nick = self.bot.config.get('bancho_nick') self.osu = OsuApi(self.bot.config.get('osu_api_key'), connector=AHConnector()) tillerino_key = self.bot.config.get('tillerino_api_key') if tillerino_key: self.tillerino = TillerinoApi(tillerino_key) else: self.tillerino = None self.twitch_channel = self.bot.config.get('twitch_channel') if not self.twitch_channel.startswith('#'): self.twitch_channel = '#{}'.format(self.twitch_channel) @irc3.event(irc3.rfc.CONNECTED) def connected(self, **kw): self.bot.log.info('[twitch] Connected to twitch as {}'.format( self.bot.nick)) self.join(self.twitch_channel) def join(self, channel): self.bot.log.info('[twitch] Trying to join channel {}'.format(channel)) self.bot.join(channel) def part(self, channel): self.bot.log.info('[twitch] Leaving channel {}'.format(channel)) self.bot.part(channel) @asyncio.coroutine def _get_pp(self, beatmap, mods=OsuMod.NoMod): if self.tillerino: try: with async_timeout.timeout(15): data = yield from self.tillerino.beatmapinfo( beatmap.beatmap_id, mods=mods.value) if data: if 'starDiff' in data: # use Tillerino star rating since it factors in mods beatmap.difficultyrating = data['starDiff'] pp = { float(acc): pp_val for acc, pp_val in data.get('ppForAcc', {}).items() } if pp: beatmap.pp = pp return pp except (HTTPError, asyncio.TimeoutError) as e: self.bot.log.debug('[twitch] {}'.format(e)) beatmap.pp = None return None def validate_beatmaps(self, beatmaps, **kwargs): """Return subset of maps in beatmaps that pass validation criteria Raises: BeatmapValidationError if a map fails validation Override this method in subclasses as needed """ return beatmaps @asyncio.coroutine def _beatmap_msg(self, beatmap, mods=OsuMod.NoMod): if mods == OsuMod.NoMod: mod_string = '' else: mod_string = ' +{:s}'.format(mods) beatmap = self._apply_mods(beatmap, mods) # get pp before generating message since it may update star rating based on yield from self._get_pp(beatmap, mods=mods) msg = '[{}] {} - {} [{}] (by {}){}, ♫ {:g}, ★ {:.2f}'.format( beatmap.approved.name.capitalize(), beatmap.artist, beatmap.title, beatmap.version, beatmap.creator, mod_string, beatmap.bpm, round(beatmap.difficultyrating, 2), ) if beatmap.pp: msg = ' | '.join([ msg, '95%: {}pp'.format(round(beatmap.pp[.95])), '98%: {}pp'.format(round(beatmap.pp[.98])), '100%: {}pp'.format(round(beatmap.pp[1.0])), ]) return msg @asyncio.coroutine def _request_mapset(self, match, mask, target, mods=OsuMod.NoMod, **kwargs): try: with async_timeout.timeout(15): mapset = yield from self.osu.get_beatmaps( beatmapset_id=match.group('mapset_id'), include_converted=0) if not mapset: return (None, None) mapset = sorted(mapset, key=lambda x: x.difficultyrating) except (HTTPError, asyncio.TimeoutError) as e: self.bot.log.debug('[twitch] {}'.format(e)) return (None, None) try: beatmap = self.validate_beatmaps(mapset, **kwargs)[-1] except BeatmapValidationError as e: return (None, e.reason) msg = yield from self._beatmap_msg(beatmap, mods=mods) return (beatmap, msg) @asyncio.coroutine def _request_beatmap(self, match, mask, target, mods=OsuMod.NoMod, **kwargs): try: with async_timeout.timeout(10): beatmaps = yield from self.osu.get_beatmaps( beatmap_id=match.group('beatmap_id'), include_converted=0) if not beatmaps: return (None, None) except (HTTPError, asyncio.TimeoutError) as e: self.bot.log.debug('[twitch] {}'.format(e)) return (None, None) try: beatmap = self.validate_beatmaps(beatmaps, **kwargs)[0] except BeatmapValidationError as e: return (None, e.reason) msg = yield from self._beatmap_msg(beatmap, mods=mods) return (beatmap, msg) def _badge_list(self, badges): """Parse twitch badge ircv3 tags into a list""" b_list = [] for x in badges.split(','): (badge, version) = x.split('/', 1) b_list.append(badge) return b_list def _is_sub(self, privmsg_tags): """Check if twitch irc3 tags include sub (or mod) badge""" badges = self._badge_list(privmsg_tags.get('badges', '')) if any(b in badges for b in ['broadcaster', 'moderator', 'subscriber']): return True elif privmsg_tags.get('mod', 0) == 1: return True elif privmsg_tags.get('subscriber', 0) == 1: return True @asyncio.coroutine def _request_beatmapsets(self, match, mask, target, **kwargs): """Handle "new" osu web style beatmapsets links""" if match.group('beatmap_id'): return self._request_beatmap(match, mask, target, **kwargs) else: return self._request_mapset(match, mask, target, **kwargs) def _bancho_msg(self, mask, beatmap, mods=OsuMod.NoMod): m, s = divmod(beatmap.total_length, 60) if mods == OsuMod.NoMod: mod_string = '' else: mod_string = ' +{:s}'.format(mods) bancho_msg = ' '.join([ '{} >'.format(mask.nick), '[http://osu.ppy.sh/b/{} {} - {} [{}]]{}'.format( beatmap.beatmap_id, beatmap.artist, beatmap.title, beatmap.version, mod_string, ), '{}:{:02d} ★ {:.2f} ♫ {:g} AR{:g} OD{:g}'.format( m, s, round(beatmap.difficultyrating, 2), beatmap.bpm, round(beatmap.diff_approach, 1), round(beatmap.diff_overall, 1), ), ]) if beatmap.pp: bancho_msg = ' | '.join([ bancho_msg, '95%: {}pp'.format(round(beatmap.pp[.95])), '98%: {}pp'.format(round(beatmap.pp[.98])), '100%: {}pp'.format(round(beatmap.pp[1.0])), ]) return bancho_msg def _parse_mods(self, mods): mod_dict = { 'NF': OsuMod.NoFail, 'EZ': OsuMod.Easy, 'HD': OsuMod.Hidden, 'HR': OsuMod.HardRock, 'SD': OsuMod.SuddenDeath, 'DT': OsuMod.DoubleTime, 'RX': OsuMod.Relax, 'HT': OsuMod.HalfTime, 'NC': OsuMod.Nightcore, 'FL': OsuMod.Flashlight, 'SO': OsuMod.SpunOut, 'AP': OsuMod.Autopilot, 'PF': OsuMod.Perfect, } if (len(mods) % 2) != 0: mods = mods[:-1] mod_flags = OsuMod.NoMod for mod in [mods.upper()[i:i + 2] for i in range(0, len(mods), 2)]: mod_flags |= mod_dict.get(mod, OsuMod.NoMod) return mod_flags def _mod_ar(self, ar, ar_mul, speed_mul): ar0_ms = 1800 ar5_ms = 1200 ar10_ms = 450 ar_ms_step1 = (ar0_ms - ar5_ms) / 5.0 ar_ms_step2 = (ar5_ms - ar10_ms) / 5.0 ar_ms = ar5_ms ar *= ar_mul if ar < 5.0: ar_ms = ar0_ms - ar_ms_step1 * ar else: ar_ms = ar5_ms - ar_ms_step2 * (ar - 5.0) # cap between 0-10 before applying HT/DT ar_ms = min(ar0_ms, max(ar10_ms, ar_ms)) ar_ms /= speed_mul if ar_ms > ar5_ms: ar = (ar0_ms - ar_ms) / ar_ms_step1 else: ar = 5.0 + (ar5_ms - ar_ms) / ar_ms_step2 return ar def _mod_od(self, od, od_mul, speed_mul): od0_ms = 79.5 od10_ms = 19.5 od_ms_step = (od0_ms - od10_ms) / 10.0 od *= od_mul od_ms = od0_ms - math.ceil(od_ms_step * od) # cap between 0-10 before applying HT/DT od_ms = min(od0_ms, max(od10_ms, od_ms)) od_ms /= speed_mul od = (od0_ms - od_ms) / od_ms_step return od def _apply_mods(self, beatmap, mods=OsuMod.NoMod): """Return a copy of beatmap with difficulty modifiers applied""" if mods == OsuMod.NoMod: return beatmap modded = beatmap if (OsuMod.DoubleTime | OsuMod.Nightcore) in mods and OsuMod.HalfTime not in mods: speed_mul = 1.5 elif OsuMod.HalfTime in mods and (OsuMod.DoubleTime | OsuMod.Nightcore) not in mods: speed_mul = .75 else: speed_mul = 1.0 modded.bpm *= speed_mul if OsuMod.HardRock in mods and OsuMod.Easy not in mods: od_ar_hp_mul = 1.4 cs_mul = 1.3 elif OsuMod.Easy in mods and OsuMod.HardRock not in mods: od_ar_hp_mul = .5 cs_mul = .5 else: od_ar_hp_mul = 1.0 cs_mul = 1.0 modded.diff_approach = self._mod_ar(beatmap.diff_approach, od_ar_hp_mul, speed_mul) modded.diff_overall = self._mod_ar(beatmap.diff_overall, od_ar_hp_mul, speed_mul) modded.diff_drain = min(10.0, beatmap.diff_drain * od_ar_hp_mul) modded.diff_size = min(10.0, beatmap.diff_size * cs_mul) return modded @irc3.event(irc3.rfc.PRIVMSG) @asyncio.coroutine def request_beatmap(self, tags=None, mask=None, target=None, data=None, bancho_target=None, **kwargs): if not target.is_channel or not data: return patterns = [ (r'https?://osu\.ppy\.sh/b/(?P<beatmap_id>\d+)', self._request_beatmap), (r'https?://osu\.ppy\.sh/s/(?P<mapset_id>\d+)', self._request_mapset), (r'https?://osu\.ppy\.sh/beatmapsets/(?P<mapset_id>\d+)(#(?P<mode>[a-z]+))?(/(?P<beatmap_id>\d+))?', self._request_beatmapsets), ] for pattern, callback in patterns: mod_pattern = r'(/?\s*\+?(?P<mods>[A-Za-z]+))?' m = re.search(''.join([pattern, mod_pattern]), data) if m: if m.group('mods'): mod_flags = self._parse_mods(m.group('mods')) else: mod_flags = OsuMod.NoMod (beatmap, msg) = yield from callback(m, mask, target, mods=mod_flags, **kwargs) if beatmap: bancho_msg = self._bancho_msg(mask, beatmap, mods=mod_flags) if not bancho_target: bancho_target = self.bancho_nick yield from self.bancho_queue.put( (bancho_target, bancho_msg)) if msg: self.bot.privmsg(target, msg) break @command @asyncio.coroutine def stats(self, mask, target, args, default_user=None): """Check stats for an osu! player %%stats [<username>]... """ self.bot.log.debug('[twitch] !stats {}'.format(args)) if target.is_channel: dest = target else: dest = mask osu_username = '******'.join(args.get('<username>')).strip() if not osu_username: if default_user: osu_username = default_user else: osu_username = self.bancho_nick try: with async_timeout.timeout(10): users = yield from self.osu.get_user(osu_username) except (HTTPError, asyncio.TimeoutError) as e: self.bot.log.debug('[twitch] {}'.format(e)) users = [] if not users: self.bot.privmsg( dest, 'Could not find osu! user {}'.format(osu_username)) return user = users[0] msg = ' | '.join([ user.username, 'PP: {:,} (#{:,})'.format(user.pp_raw, user.pp_rank), 'Acc: {:g}%'.format(round(user.accuracy, 2)), 'Score: {:,}'.format(user.total_score), 'Plays: {:,} (lv{})'.format(user.playcount, math.floor(user.level)), 'https://osu.ppy.sh/users/{}'.format(user.user_id), ]) self.bot.privmsg(dest, msg)
sys.exit() if len(beatmap_list)==0: print('Player has no map') sys.exit() ####################### data collation ####################### df_beatmap['mapping_len'] = df_beatmap.last_update - df_beatmap.submit_date df_beatmap['total_length_class'] = df_beatmap['total_length'].apply(lambda x:'< 1:39' if x<99 else('1:39 ~ 3:29' if x>=99 and x<209 else('3:39 ~ 5:00' if x>=209 and x<300 else '> 5:00'))) df_beatmap['star_rating'] = df_beatmap['difficultyrating'].apply(lambda x:'Easy'if x<2 else('Normal' if x>=2 and x<2.7 else('Hard' if x>=2.7 and x<4 else('Insane' if x>=4 and x<5.3 else('Expert' if x>=5.3 and x<6.5 else 'Expert+'))))) df_beatmap['cover_image'] = ['https://assets.ppy.sh/beatmaps/'+str(i)+'/covers/cover.jpg' for i in list(df_beatmap['beatmapset_id'])] df_beatmap['thumbnail'] = ['https://b.ppy.sh/thumb/'+str(i)+'l.jpg' for i in list(df_beatmap['beatmapset_id'])] user_id = dict(api.get_user(user_name)[0]).get('user_id') user_profile_image = 'http://s.ppy.sh/a/'+str(user_id) def parse_date(td): resYear = float(td.days)/364.0 resMonth = int((resYear - int(resYear))*364/30) resYear = int(resYear) resDay = int(td.days-(364*resYear+30*resMonth)) return str(resYear) + ' years ' + str(resMonth) + ' months and ' + str(resDay) + ' days' # mapping age first_map_submit_date = df_beatmap.sort_values(by='submit_date', ascending=True).iloc[0].submit_date last_map_update_date = df_beatmap.sort_values(by='last_update', ascending=False).iloc[0].last_update mapping_age = last_map_update_date-first_map_submit_date mapping_age_str = parse_date(mapping_age)
from osuapi import OsuApi, ReqConnector import requests import json import sqlite3 import datetime with open("apicode.json") as apc: apicode = json.load(apc)[0]["apicode"] api = OsuApi(apicode, connector = ReqConnector()) playername = "potla" user = api.get_user(playername) def compare_maps(a, b): affinity = 0 ID1 = a.split(" ")[0] ID2 = b.split(" ")[0] if ID1 != ID2: return 0 if "NoMod" in a and "NoMod" in b: return 2 if "Hidden" in a and "Hidden" in b: affinity += 1 if "HardRock" in a and "HardRock" in b: affinity += 1 if "DoubleTime" in a or "Nightcore" in a and "DoubleTime" in b or "Nightcore" in b: affinity += 1 return affinity def mod_finder(score, counter): ID = score.split(" ")[0]
class Osu(commands.Cog): def __init__(self, discordClient): with open("config.json") as f: config = json.loads(f.read()) self.bot = discordClient self.osuApi = OsuApi(config["osu_key"], connector=ReqConnector()) self.modeMap = {'standard': enums.OsuMode.osu, 'mania': enums.OsuMode.mania} self.db = 'guild_settings.db' self.table = 'settings' self.settings = {'guild_id': 'guild_id', 'guild_name': 'guild_name', 'commands_disabled': 'commands_disabled', 'roll_channel': 'roll_channel', 'osu_channel': 'osu_channel', 'admin_role': 'admin_role'} def check_correct_channel(self, message): conn = sqlite3.connect(self.db) c = conn.cursor() with conn: c.execute("SELECT {} FROM {} WHERE guild_id=?".format(self.settings['osu_channel'], self.table), (message.guild.id,)) channel = c.fetchone() conn.close() return(not channel[0] == message.channel.name) @commands.group() async def osu(self, ctx): if ctx.invoked_subcommand is None: return(await ctx.send('Invalid subcommand for osu passed...')) @osu.command() async def profile(self, ctx, profile, mode_arg="standard"): if self.check_correct_channel(ctx.message): return(await ctx.send('You cannot use this command in this channel')) if mode_arg not in self.modeMap: return(await ctx.send('Not a valid game mode')) else: result = self.osuApi.get_user(str(profile),mode=self.modeMap[mode_arg], event_days=31) if not result: return(await ctx.send("User doesn't exist")) data = result[0] #get first and only result acc = str(math.ceil(data.accuracy*100)/100) + "%" lvl = str(math.ceil(data.level*100)/100) profile_embed = discord.Embed( url = "https://osu.ppy.sh/users/{}".format(data.user_id), color = 0xea1595 ) profile_embed.add_field( name = "Performance", value = "Global PP Rank: {0}\nPP: {1}\nAccuracy: {2}".format(data.pp_rank, data.pp_raw, acc), inline = True ) profile_embed.add_field( name = "Experience", value = "Playcount: {0}\nLevel: {1}\n".format(data.playcount, lvl), inline = True ) profile_embed.add_field( name = "Country", value = emoji.emojize("Country PP Rank: {0}\n:flag_{1}:" .format(data.pp_country_rank, data.country.lower()) ), inline = True ) profile_embed.set_author( name = data.username, url = "https://osu.ppy.sh/users/{}".format(data.user_id), icon_url = "http://s.ppy.sh/a/{}".format(data.user_id) ) return(await ctx.send(embed=profile_embed)) @osu.command() async def best(self, ctx, username, mode_arg="standard"): if self.check_correct_channel(ctx.message): return(await ctx.send('You cannot use this command in this channel')) if mode_arg not in self.modeMap: return(await ctx.send('Not a valid game mode')) else: result = self.osuApi.get_user_best(username,mode=self.modeMap[mode_arg], limit=1) if not result: return(await ctx.send("User doesn't exist")) data = result[0] #get first and only result best_embed = discord.Embed( url = "https://osu.ppy.sh/users/{}".format(data.user_id), color = 0xea1595 ) best_embed.add_field( name="Score", value="Score: {0}\nMax Combo: {1}\nPerfect: {2}".format(data.score, data.maxcombo, data.perfect), inline = True ) best_embed.add_field( name="Count", value="Count50: {0}\nCount100: {1}\nCount300: {2}\nMisses: {3}".format(data.count50, data.count100, data.count300, data.countmiss), inline=True ) best_embed.set_author( name = username, url = "https://osu.ppy.sh/users/{}".format(data.user_id), icon_url = "http://s.ppy.sh/a/{}".format(data.user_id) ) return(await ctx.send(embed=best_embed)) @best.error @profile.error async def error(self, ctx, error): return(await ctx.send(str(error).capitalize()))
class OsuTracker(commands.Cog): def __init__(self, bot): self.bot = bot self.config = confparser.get("config.json") self.api = OsuApi(key=self.config.osu_token, connector=ReqConnector()) self.last_check_datetime = datetime.datetime.utcnow() self.tracking_channel = None self.tracked_users = self.get_tracked_users() self.tracker_task_loop.start() def cog_unload(self): self.tracker_task_loop.cancel() @tasks.loop(seconds=30) async def tracker_task_loop(self): for user in self.tracked_users: scores = self.api.get_user_best(user['name'], limit=20) for s in [s for s in scores if s.date > self.last_check_datetime]: bmap = self.api.get_beatmaps(beatmap_id=s.beatmap_id)[0] msg = f"{user['nick']} abım {bmap.title} - {bmap.version} mapınde {int(round(s.pp))} pp play yapmıs\n" \ f"helal abım <@{user['discord'].id}>\n".lower().replace('i', 'ı') await self.tracking_channel.send(msg) self.last_check_datetime = datetime.datetime.utcnow() def get_tracked_users(self): with open("tracked_users.json", "r") as f: data = json.load(f) if not json.load(f) == {} else None users = [] if data: for u in data['users']: users.append({ "name": u['name'], "discord": self.bot.get_user(id=u['discord_id']), "nick": u['nick'] }) return users def add_to_tracked_users_file(self, osu_username, discord_id, nick): with open("tracked_users.json", "w") as f: data = json.load(f) if data == {}: data = { "users": [{ "name": osu_username, "discord_id": discord_id, "nick": nick }] } else: data['users'].append({ "name": osu_username, "discord_id": discord_id, "nick": nick }) data.update() print(data) json.dump(data, f) @commands.command() @commands.check(permissions.is_owner) async def osutrack(self, ctx, mem: discord.Member, osu_username, nick): if osu_username not in [u['name'] for u in self.tracked_users]: try: osu_id = self.api.get_user(osu_username)[0].user_id self.tracked_users.append({ "name": osu_username, "nick": nick, "discord": mem }) self.add_to_tracked_users_file(osu_username, discord_id=mem.id, nick=nick) await ctx.send( f"tracking started : {str(mem)}, osu id : {osu_id}") except: await ctx.send(f"couldn't start tracking") else: await ctx.send(f"already tracking : {str(mem)}") @commands.command() @commands.check(permissions.is_owner) async def setch(self, ctx): self.tracking_channel = ctx await ctx.send(f"ok")
class OsuModule: def __init__(self, client): self.client = client self.database = self.client.database self.api = OsuApi(self.database.get_osu_api_key(), connector=ReqConnector()) # Completed with Rich embed. @commands.command(name='osu') async def osu(self, ctx, *params, member: discord.Member = None): if member is None and len(params) == 0: discord_id = ctx.message.author.id self.database.cursor.execute( "SELECT `osu_id` FROM `users` WHERE `discord_id` = ?", (discord_id, )) osu_id = self.database.cursor.fetchone()[0] embed = self.display_profile(osu_id) await ctx.send(embed=embed) elif len(params) > 0: for osu_id in params: embed = self.display_profile(osu_id) await ctx.send(embed=embed) if member is not None: print(member.id) self.database.cursor.execute( "SELECT `osu_id` FROM `users` WHERE `discord_id` = ?", (member.id, )) osu_id = self.database.cursor.fetchone()[0] embed = self.display_profile(osu_id) await ctx.send(embed=embed) @commands.command(name='top') async def top(self, ctx, *params): (user, amt) = self.params_seperator(ctx, *params) embed = self.top_scores(user, amt) await ctx.send(embed=embed) @commands.command(name='recent') # Completed With Rich Embed. async def recent(self, ctx, *params): (user, amt) = self.params_seperator(ctx, *params) embed = self.recent_scores(user, amt) await ctx.send(embed=embed) @commands.command(name='set') async def set(self, ctx, param): discord_id = ctx.message.author.id osu_id = self.api.get_user(param)[0].user_id self.database.cursor.execute( "SELECT `osu_id` FROM `users` WHERE `discord_id` = ?", (discord_id, )) data = self.database.cursor.fetchone() if data is None: self.database.cursor.execute( "INSERT INTO `users`(`discord_id`, `osu_id`, `days`, `total`) VALUES (?, ?, 0, 0)", (discord_id, osu_id)) self.database.db.commit() title = 'Succesfully set {} IGN as {}'.format( ctx.message.author, param) embed = discord.Embed(title=title, colour=0xDEADBF) await ctx.send(embed=embed) else: await ctx.send("Record Already Exists") @commands.command(name='compare') async def compare(self, ctx, user1, user2): embed = self.check(user1, user2) await ctx.send(embed=embed) @commands.command(name='topr') async def topr(self, ctx, *params): (user, amt) = self.params_seperator(ctx, *params) embed = self.recent_top(user, amt) await ctx.send(embed=embed) def display_profile(self, param): # Obtaining Profile from Paramerter. profile = self.api.get_user(param) # Local Stuff title = "osu! Profile for " + profile[0].username thumbnail = "https://a.ppy.sh/" + str(profile[0].user_id) user_url = "https://osu.ppy.sh/users/" + str(profile[0].user_id) # Embed Creation. embed = discord.Embed(title=title, timestamp=datetime.utcnow(), url=user_url, color=0xFF0418, footer="Osu India bot v.1.0") # thumbnails embed.set_thumbnail(url=thumbnail) # PP embed.add_field(name="PP", value=str(profile[0].pp_raw), inline=True) # Rank embed.add_field(name="Rank", value='#' + str(profile[0].pp_rank), inline=True) # Playcount embed.add_field(name="Playcount", value=str(profile[0].playcount), inline=True) # Accuracy embed.add_field(name="Accuracy", value=str(profile[0].accuracy)[:6], inline=True) # Country Indentification. embed.add_field(name="Country", value=str(profile[0].country), inline=True) # Country Rank. embed.add_field(name="Country Rank", value='#' + str(profile[0].pp_country_rank), inline=True) return embed def top_scores(self, user, amt): # Api Call scores = self.api.get_user_best(user, limit=amt) # Local Stuff. title = "Top {} Scores for {}".format(amt, user) count = 1 # Embed embed = discord.Embed(title=title, timestamp=datetime.utcnow(), color=0xFF0418, footer="Osu India bot v.1.0") # Fields. for score in scores: beatmap = self.api.get_beatmaps(beatmap_id=score.beatmap_id) Title = "#{}. {}[{}] +**{}**".format(count, beatmap[0].title, beatmap[0].version, score.enabled_mods) Value = "PP:{}\n Played {}".format( score.pp, self.time_elapsed(str(score.date))) embed.add_field(name=Title, value=Value, inline=False) count += 1 return embed def recent_scores(self, user, amt): scores = self.api.get_user_recent(user, limit=amt) title = "Recent {} scores for {}".format(amt, user) count = 1 # Discord Embed Creation. embed = discord.Embed(title=title, timestamp=datetime.utcnow(), color=0xFF0418, footer="Osu India bot v0.2.0") # Looping over all Scores and adding fields. for score in scores: beatmap = self.api.get_beatmaps(beatmap_id=score.beatmap_id) name = "#{}. {}[{}] +**{}**".format(count, beatmap[0].title, beatmap[0].version, score.enabled_mods) time_delta = str(score.date) value = "*Played {}\n SR: {}".format( self.time_elapsed(time_delta), str(beatmap[0].difficultyrating)[:5]) embed.add_field(name=name, value=value, inline=False) count += 1 return embed # Hacked this together using 3 lists, modifications needed def recent_top(self, user, amt): scores_list = [] scores = self.api.get_user_best(user, limit=100) for i in range(100): scores_list.append((i + 1, scores[i])) # sort according to date scores_sorted = sorted(scores_list, key=lambda score: score[1].date, reverse=True) title = "Recent {} top scores for {}".format(amt, user) count = 1 # Embed embed = discord.Embed(title=title, timestamp=datetime.utcnow(), color=0xFF0418, footer="Osu India bot v0.2.0") # Fields. for score in scores_sorted: if count > amt: break beatmap = self.api.get_beatmaps(beatmap_id=score[1].beatmap_id) name = "#{}. {}[{}] +**{}**".format(score[0], beatmap[0].title, beatmap[0].version, score[1].enabled_mods) value = "PP:{}\n Played {}".format( score[1].pp, self.time_elapsed(str(score[1].date))) embed.add_field(name=name, value=value, inline=False) count += 1 return embed def check(self, user1, user2): # major formatting required # to add avatar pic no clue how to p1 = self.api.get_user(user1) p2 = self.api.get_user(user2) title = "Comparing stats for " + user1 + " and " + user2 desc = "\t\t" + user1 + " | " + user2 + "\t\t\n" # \t or multiple spaces not working desc += "**Rank :**\t " + str(p1[0].pp_rank) + " | " + str( p2[0].pp_rank) + "\n" desc += "**Country Rank :**\t " + str( p1[0].pp_country_rank) + " | " + str( p2[0].pp_country_rank) + "\n" desc += "**PP :**\t " + str(p1[0].pp_raw) + " | " + str( p2[0].pp_raw) + "\n" desc += "**Accuracy :**\t " + str(p1[0].accuracy)[:5] + " | " + str( p2[0].accuracy)[:5] + "\n" score1 = self.api.get_user_best(user1, limit=1) score2 = self.api.get_user_best(user2, limit=1) desc += "**Top Play :**\t " + str(score1[0].pp) + " | " + str( score2[0].pp) + "\n" desc += "**Playcount :**\t " + str(p1[0].playcount) + " | " + str( p2[0].playcount) + "\n" embed = discord.Embed(title=title, description=desc, colour=0xDEADBF) return embed def time_elapsed(self, datestr): parsed_date = datetime.strptime(datestr, "%Y-%m-%d %H:%M:%S") today = datetime.utcnow() time_delta = relativedelta(today, parsed_date) years = abs(time_delta.years) months = abs(time_delta.months) days = abs(time_delta.days) hours = abs(time_delta.hours) minutes = abs(time_delta.minutes) seconds = abs(time_delta.seconds) time_elapsed = "" if (years > 0): time_elapsed += "{} year{}, ".format(years, "s" if years != 1 else "") if (months > 0): time_elapsed += "{} month{}, ".format(months, "s" if months != 1 else "") if (days > 0): time_elapsed += "{} day{}, ".format(days, "s" if days != 1 else "") if (hours > 0): time_elapsed += "{} hour{}, ".format(hours, "s" if hours != 1 else "") if (minutes > 0): time_elapsed += "{} minute{}, ".format(minutes, "s" if minutes != 1 else "") if (seconds > 0): time_elapsed += "{} second{} ago".format( seconds, "s" if seconds != 1 else "") return time_elapsed def params_seperator(self, ctx, *params): # Default user AND default amount if len(params) == 0: self.database.cursor.execute( "SELECT `osu_id` FROM `users` WHERE `discord_id` = ?", (ctx.message.author.id, )) osu_id = self.database.cursor.fetchone()[0] if osu_id is None: return (None, None) user = self.api.get_user(osu_id)[0].username amt = 5 # Only default amount elif len(params) == 1: user = self.tag_to_id(ctx) if user is False: return (None, None) if user is None: user = params[0] amt = 5 # No defaults else: user = self.tag_to_id(ctx) if user is False: return (None, None) if user is None: user = params[0] amt = params[1] return (user, amt) def tag_to_id(self, ctx): user_list = ctx.message.mentions if len(user_list) == 0: return None else: user_id = user_list[0].id self.database.cursor.execute( "SELECT `osu_id` FROM `users` WHERE `discord_id` = ?", (user_id, )) osu_id = self.database.cursor.fetchone()[0] if osu_id is None: return False return self.api.get_user(osu_id)[0].username def new_recent(self, user_id): scores = self.api.get_user_best(user_id, limit=50) new_scores = [] last_checked = datetime.now( ) # need to save the last checked to a file scores_sorted = sorted(scores, key=lambda s: s.date, reverse=True) # sort according to date for score in scores_sorted: if score.date > last_checked: new_scores.append(score) else: break print("New Recent was executed") return new_scores