Ejemplo n.º 1
0
class Sample(Cog):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.tags = AsyncJSONStorage('tags.json')

    def __unload(self):
        print('Original unload.')

    @command()
    async def sample(self, ctx):
        """ A sample command. """
        await ctx.send('Hello!')

    @Cog.every(10, wait_until_ready=True)
    async def scheduled(self):
        pass

    @group(invoke_without_command=True)
    async def tag(self, ctx, *, key):
        """ Tag management commands. """
        tag = self.tags.get(key)
        if not tag:
            await ctx.send('No such tag.')
        else:
            await ctx.send(tag)

    @tag.command()
    async def list(self, ctx):
        """ Lists all tags. """
        tags = self.tags.all().keys()
        await ctx.send(f'{len(tags)}: {", ".join(tags)}')

    @tag.command(aliases=['create'])
    async def make(self, ctx, key: commands.clean_content, *,
                   value: commands.clean_content):
        """ Creates a tag. """
        if key in self.tags:
            await ctx.send('Tag already exists.')
            return
        await self.tags.put(key, value)
        await ctx.ok()
Ejemplo n.º 2
0
class Osu(Cog):
    wait_interval: int = 10

    def __init__(self, bot):
        super().__init__(bot)
        self.tracking = AsyncJSONStorage('osu.json', loop=bot.loop)
        self.track_task = bot.loop.create_task(self.poll())
        self.session = aiohttp.ClientSession(
            headers={'user-agent': 'bottlecap/0.0.0'})

    def __unload(self):
        self.session.close()
        self.track_task.cancel()

    def endpoint(self, url: str) -> str:
        return f'https://osu.ppy.sh/api{url}'

    async def get_recent_plays(self,
                               user_id: Union[int, str],
                               *,
                               limit: int = 10) -> List[OsuPlay]:
        params = {'k': self.bot.cfg.osu_api_key, 'u': user_id, 'limit': limit}
        async with self.session.get(self.endpoint('/get_user_recent'),
                                    params=params) as resp:
            resp.raise_for_status()
            plays = await resp.json()
            return [OsuPlay(**play) for play in plays]

    async def get_top_plays(self,
                            user_id: Union[int, str],
                            *,
                            limit: int = 10) -> List[OsuPlay]:
        params = {'k': self.bot.cfg.osu_api_key, 'u': user_id, 'limit': limit}
        async with self.session.get(self.endpoint('/get_user_best'),
                                    params=params) as resp:
            plays = await resp.json()
            return [OsuPlay(**play) for play in plays]

    async def get_beatmap(self, beatmap_id: str) -> OsuBeatmap:
        params = {'k': self.bot.cfg.osu_api_key, 'b': beatmap_id}
        async with self.session.get(self.endpoint('/get_beatmaps'),
                                    params=params) as resp:
            resp.raise_for_status()
            beatmaps = await resp.json()
            return OsuBeatmap(**beatmaps[0])

    async def alert_play(self, user_id: int, info: Dict[str, Any],
                         play: OsuPlay):
        log.debug('Attempting to alert %d about recent play: %s.', user_id,
                  play)
        last_tracked = info.get('last_tracked')

        if play.date == last_tracked:
            log.debug('Detected a stale play for %d (%s).', user_id, play.date)
            return

        await self.tracking.put(user_id, {**info, 'last_tracked': play.date})

        if play.rank == 'F':
            log.debug('Detected failed play, not tracking.')
            return

        log.debug('Tracking this play. (%s)', play)

        beatmap = await self.get_beatmap(play.beatmap_id)
        stars = float(beatmap.difficultyrating)
        user = self.bot.get_user(user_id)

        embed = discord.Embed()
        embed.title = f'{beatmap.artist} - {beatmap.title} [{beatmap.version}]'
        embed.url = f'https://osu.ppy.sh/b/{play.beatmap_id}'
        embed.set_author(name=f"{info['osu_username']} ({user})",
                         url=f'https://osu.ppy.sh/u/{play.user_id}')
        embed.description = PLAY_DESCRIPTION.format(play=play,
                                                    player=user_id,
                                                    beatmap=beatmap,
                                                    stars=stars)

        top_plays = await self.get_top_plays(play.user_id)
        log.debug('Top plays for %d: %s', user_id, top_plays)
        as_top_play: Optional[OsuPlay] = discord.utils.get(top_plays,
                                                           date=play.date)
        log.debug('Current play date: %s, detected top play: %s', play.date,
                  as_top_play)

        channel = self.bot.get_channel(info['channel_id'])
        if not channel:
            log.warning('Cannot locate channel %d, not alerting.',
                        info['channel_id'])
            return

        try:
            if as_top_play:
                log.debug('Using top play PP score (%s).', as_top_play.pp)
                content = f'<@{user_id}> **+{as_top_play.pp} PP'
            else:
                content = ''
            log.debug('Alerting %d in %d.', user_id, info['channel_id'])
            await channel.send(embed=embed, content=content)
        except discord.Forbidden:
            pass

    async def poll(self):
        while True:
            for user_id, info in self.tracking.all().items():
                user_id = int(user_id)
                plays = await self.get_recent_plays(info['osu_username'],
                                                    limit=1)
                if not plays:
                    log.warning('Found NO plays for %s.', info['osu_username'])
                    continue
                await self.alert_play(user_id, info, plays[0])
            await asyncio.sleep(self.wait_interval)

    @group(invoke_without_command=True)
    async def track(self, ctx: Context, username):
        """tracks you on osu"""
        log.info('Now tracking %d (%s).', ctx.author.id, username)
        await self.tracking.put(
            ctx.author.id, {
                'channel_id': ctx.channel.id,
                'osu_username': username,
                'created_at': time.time(),
                'guild_id': ctx.guild.id
            })
        await ctx.send('okay, tracking you here')

    @track.command(hidden=True)
    async def reset(self, ctx: Context, who: discord.User = None):
        """resets your tracking status"""
        target = who or ctx.author
        record = self.tracking.get(target.id)

        if not record:
            return

        try:
            del record['last_tracked']
        except KeyError:
            return

        await self.tracking.put(target.id, record)
        await ctx.send(f"ok, reset {target}'s tracking state.")

    @command()
    async def untrack(self, ctx: Context):
        """untracks you on osu"""
        log.info('Untracking %d.', ctx.author.id)
        try:
            await self.tracking.delete(ctx.author.id)
        except KeyError:
            pass
        await ctx.ok()
Ejemplo n.º 3
0
class Sample(lifesaver.Cog):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.tags = AsyncJSONStorage("tags.json")

    def cog_unload(self):
        print("Calling super unload:", super().cog_unload)
        super().cog_unload()
        print("My unload.")

    @lifesaver.command()
    async def long_help(self, ctx: lifesaver.commands.Context):
        """A command with a long help message.

        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin
        ultricies nulla sed sapien varius posuere. Suspendisse volutpat
        lobortis ligula sit amet feugiat. Duis lobortis turpis id diam porta,
        eget egestas dui posuere. Maecenas scelerisque efficitur nunc. Ut ac
        sem placerat, placerat libero sit amet, consectetur tellus. Vivamus
        venenatis efficitur leo, at sollicitudin odio efficitur vel. Orci
        varius natoque penatibus et magnis dis parturient montes, nascetur
        ridiculus mus. Praesent porta elementum dolor et euismod. Etiam et
        ullamcorper elit, quis bibendum tellus. Vivamus mattis ipsum ac gravida
        efficitur. Vestibulum et finibus ipsum. Vestibulum lorem lectus,
        rhoncus ac odio in, maximus iaculis lacus. Ut a volutpat nisl. Integer
        a fringilla arcu. Cras condimentum maximus magna at viverra.
        Pellentesque habitant morbi tristique senectus et netus et malesuada
        fames ac turpis egestas.

        Pellentesque rutrum lectus eget consectetur varius. Suspendisse
        facilisis condimentum nisi sit amet ultrices. Suspendisse non ipsum id
        metus volutpat venenatis id sed odio. Suspendisse eu fringilla ante,
        quis tempus arcu. Vivamus lacus leo, facilisis et viverra et,
        ullamcorper eget dui. Proin eleifend bibendum enim, sit amet congue
        justo molestie eget. Proin in felis quis nisi efficitur lacinia non nec
        enim. Proin vel sapien vel ipsum commodo venenatis. Morbi ornare porta
        dui, eget varius turpis fermentum id. Cras nec nulla elit. Morbi sit
        amet nunc lobortis, porttitor odio nec, malesuada sem. Suspendisse
        efficitur malesuada viverra. Duis eleifend, felis a tristique faucibus,
        neque odio faucibus purus, ac lacinia quam orci quis leo.
        """

    @lifesaver.group()
    async def sample_group(self, ctx: lifesaver.commands.Context):
        """I am a group."""

    @sample_group.command(typing=True)
    async def subcommand_two(self, ctx: lifesaver.commands.Context):
        """I am a second subcommand."""
        await asyncio.sleep(5)
        await ctx.send("yo!")

    @sample_group.command(typing=True)
    async def subcommand(self, ctx: lifesaver.commands.Context):
        """I am a subcommand."""
        await asyncio.sleep(5)
        await ctx.send("yo!")

    @lifesaver.command()
    async def message(self, ctx: lifesaver.commands.Context):
        """Sends the configurable message."""
        await ctx.send(self.config.configurable_message)

    @lifesaver.command()
    async def pages_example(self, ctx: lifesaver.commands.Context):
        """A demonstration of `ctx +=`."""
        from random import random

        for _ in range(150):
            ctx += str(random())
        await ctx.send_pages()

    @lifesaver.command()
    async def sample(self, ctx: lifesaver.commands.Context):
        """A sample command."""
        await ctx.send("Hello!")

    @lifesaver.command()
    async def source(self, ctx: lifesaver.commands.Context, command):
        """View the source of a command."""
        cmd = ctx.bot.get_command(command)
        if not cmd:
            await ctx.send("No such command.")
            return
        from inspect import getsource

        await ctx.send(codeblock(getsource(cmd.callback), lang="py"))

    @lifesaver.Cog.every(10, wait_until_ready=True)
    async def scheduled(self):
        print("Scheduled function.")

    @lifesaver.group(invoke_without_command=True)
    async def tag(self, ctx: lifesaver.commands.Context, *, key):
        """Tag management commands."""
        tag = self.tags.get(key)
        if not tag:
            await ctx.send("No such tag.")
        else:
            await ctx.send(tag)

    @tag.command()
    async def list(self, ctx: lifesaver.commands.Context):
        """Lists all tags."""
        tags = self.tags.all().keys()
        await ctx.send(f'{len(tags)}: {", ".join(tags)}')

    @tag.command(aliases=["create"])
    async def make(
        self,
        ctx: lifesaver.commands.Context,
        key: commands.clean_content,
        *,
        value: commands.clean_content,
    ):
        """Creates a tag."""
        if key in self.tags:
            await ctx.send("Tag already exists.")
            return
        await self.tags.put(key, value)
        await ctx.ok()