Beispiel #1
0
 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)
Beispiel #2
0
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)
Beispiel #4
0
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]
Beispiel #5
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()))
Beispiel #6
0
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")
Beispiel #7
0
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