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)
from pyecharts.faker import Collector, Faker from pyecharts.globals import ThemeType from pyecharts.components import Table, Image from pyecharts.options import ComponentTitleOpts from pyecharts.commons.utils import JsCode from osuapi import OsuApi, ReqConnector, OsuMode import requests api = OsuApi("13a36d70fd32e2f87fd2a7a89e4f52d54ab337a1", connector=ReqConnector()) user_name = input('Please enter osu! user name:') ####################### get mapper beatmaps info ####################### try: beatmap_list= api.get_beatmaps(since=None, beatmapset_id=None, beatmap_id=None, username=user_name, mode=None, include_converted=True, beatmap_hash=None, limit=500) df_beatmap = pd.DataFrame() for beatmap in beatmap_list: df_beatmap_1 = pd.DataFrame( dict(beatmap), index=[0]) df_beatmap = df_beatmap.append(df_beatmap_1, ignore_index=True) except: print('No results for user name') sys.exit() if len(beatmap_list)==0: print('Player has no map') sys.exit() ####################### data collation #######################
import requests from osuapi import OsuApi, ReqConnector import json api = OsuApi("f0bfd051b9e0dba2d56b96a71b416061593d7f31", connector=ReqConnector()) user = "******" scoreThreshold = 5000000000 results = api.get_user_recent(user, limit=1) recentScore = results[0] beatmaps = api.get_beatmaps(beatmap_id=recentScore.beatmap_id, limit=1) beatmapData = beatmaps[0] debugMessage = "User {} ({}) got a score of {} and rank {} on beatmap {} (#{}) at {}" print( debugMessage.format(user, recentScore.user_id, recentScore.score, recentScore.rank, beatmapData.title, recentScore.beatmap_id, recentScore.date))
#get map details filename=playername+"_"+str(datetime.date.today()) fw=open("Users\\"+filename+".txt","w") for i in range(100): c.execute("CREATE TABLE IF NOT EXISTS BEATMAPS(BEATMAP_ID INTEGER, TITLE TEXT, LINK TEXT, CREATOR TEXT, BPM REAL, SR REAL, LENGTH INTEGER, DIFFICULTY TEXT)") try: map = dump[i].split(" ") if map[0] in scoreidonly: continue except: pass c.execute("SELECT * FROM BEATMAPS WHERE BEATMAP_ID=?", (int(map[0]),)) data = c.fetchone() if data is None: result = api.get_beatmaps(beatmap_id=int(map[0])) if len(result) == 0: continue link = ("https://osu.ppy.sh/b/"+str(map[0]) + "?m=0") c.execute("INSERT INTO BEATMAPS VALUES(?,?,?,?,?,?,?,?)", (int(map[0]), result[0].title, link,result[0].creator, result[0].bpm, result[0].difficultyrating, result[0].total_length, result[0].version)) c.execute("SELECT * FROM BEATMAPS WHERE BEATMAP_ID=?", (int(map[0]),)) data = c.fetchone() mod = findmaxmod(map[0], modcounter) outstring=data[1] + "\t" + data[7] + "\t" + mod + "\t" + "SR: " + str(data[5])[:3] + " BPM: " + str(data[4]) + " Length: " + str(data[6])+ " " outstring += data[3] + "\t" + data[2] fw.write(outstring) fw.write("\n") #final steps conn.commit() fw.close()
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