Exemple #1
0
    async def plants(self, ctx: utils.Context,
                     user: typing.Optional[discord.User]):
        """
        Shows you all the plants that a given user has.
        """

        # Grab the plant data
        user = user or ctx.author
        async with self.bot.database() as db:
            user_rows = await db(
                "SELECT * FROM plant_levels WHERE user_id=$1 ORDER BY plant_name DESC",
                user.id)

        # See if they have anything available
        plant_data = sorted([
            (i['plant_name'], i['plant_type'], i['plant_nourishment'],
             i['last_water_time'], i['plant_adoption_time']) for i in user_rows
        ])
        if not plant_data:
            embed = utils.Embed(use_random_colour=True,
                                description=f"<@{user.id}> has no plants :c")
            return await ctx.send(embed=embed)

        # Add the plant information
        embed = utils.Embed(use_random_colour=True,
                            description=f"<@{user.id}>'s plants")
        ctx._set_footer(embed)
        for plant_name, plant_type, plant_nourishment, last_water_time, plant_adoption_time in plant_data:
            plant_type_display = plant_type.replace('_', ' ').capitalize()
            plant_death_time = last_water_time + timedelta(
                **self.bot.config.get('plants', {}).get(
                    'death_timeout', {'days': 3}))
            plant_death_humanize_time = utils.TimeValue(
                (plant_death_time - dt.utcnow()).total_seconds()).clean_full
            plant_life_humanize_time = utils.TimeValue(
                (dt.utcnow() - plant_adoption_time).total_seconds()).clean_full
            if plant_nourishment == 0:
                text = f"{plant_type_display}, nourishment level {plant_nourishment}/{self.bot.plants[plant_type].max_nourishment_level}."
            elif plant_nourishment > 0:
                text = (
                    f"**{plant_type_display}**, nourishment level {plant_nourishment}/{self.bot.plants[plant_type].max_nourishment_level}.\n"
                    f"If not watered, this plant will die in **{plant_death_humanize_time}**.\n"
                    f"This plant has been alive for **{plant_life_humanize_time}**.\n"
                )
            else:
                text = f"{plant_type_display}, dead :c"
            embed.add_field(plant_name, text, inline=False)

        # Return to user
        v = await ctx.send(embed=embed)
        try:
            await self.bot.add_delete_button(v, (
                ctx.author,
                user,
            ),
                                             wait=False)
        except discord.HTTPException:
            pass
    async def herbiary(self, ctx:utils.Context, *, plant_name:str=None):
        """
        Get the information for a given plant.
        """

        # See if a name was given
        if plant_name is None:
            plant_list = list()
            for plant in self.bot.plants.values():
                plant_list.append(plant.display_name.capitalize())
            plant_list.sort()
            embed = utils.Embed(use_random_colour=True, description="\n".join(plant_list))
            ctx.bot.set_footer_from_config(embed)
            return await ctx.send(embed=embed)

        # See if the given name is valid
        plant_name = plant_name.replace(' ', '_').lower()
        if plant_name not in self.bot.plants:
            return await ctx.send(f"There's no plant with the name **{plant_name.replace('_', ' ')}** :c", allowed_mentions=discord.AllowedMentions(users=False, roles=False, everyone=False))
        plant = self.bot.plants[plant_name]

        # Work out our artist info to be displayed
        description_list = []
        artist_info = self.artist_info.get(plant.artist, {}).copy()
        discord_id = artist_info.pop('discord', None)
        description_list.append(f"**Artist `{plant.artist}`**")
        if discord_id:
            description_list.append(f"Discord: <@{discord_id}> (`{discord_id}`)")
        for i, o in sorted(artist_info.items()):
            description_list.append(f"{i.capitalize()}: [Link]({o})")
        description_list.append("")

        # Embed the data
        with utils.Embed(use_random_colour=True) as embed:
            embed.title = plant.display_name.capitalize()
            embed.description = '\n'.join(description_list)
            embed.set_image("attachment://plant.gif")
            ctx.bot.set_footer_from_config(embed)
        display_utils = self.bot.get_cog("PlantDisplayUtils")

        # Make a gif of the stages
        pot_hue = random.randint(0, 360)
        display_levels = []
        added_display_stages = []
        for i, o in plant.nourishment_display_levels.items():
            if o not in added_display_stages:
                display_levels.insert(0, int(i))
                added_display_stages.append(o)
        gif_frames = [display_utils.get_plant_image(plant.name, i, "clay", pot_hue) for i in display_levels]
        plant_image_bytes = display_utils.gif_to_bytes(*gif_frames, duration=1_000)
        await ctx.send(embed=embed, file=discord.File(plant_image_bytes, filename=f"plant.gif"))
Exemple #3
0
    async def plants(self,
                     ctx: utils.Context,
                     user: utils.converters.UserID = None):
        """
        Shows you all the plants that a given user has.
        """

        # Grab the plant data
        user = discord.Object(user) if user else ctx.author
        async with self.bot.database() as db:
            user_rows = await db(
                "SELECT * FROM plant_levels WHERE user_id=$1 ORDER BY plant_name DESC",
                user.id)

        # See if they have anything available
        plant_data = sorted([(i['plant_name'], i['plant_type'],
                              i['plant_nourishment'], i['last_water_time'])
                             for i in user_rows])
        if not plant_data:
            embed = utils.Embed(use_random_colour=True,
                                description=f"<@{user.id}> has no plants :c")
            return await ctx.send(embed=embed)

        # Add the plant information
        embed = utils.Embed(use_random_colour=True,
                            description=f"<@{user.id}>'s plants")
        ctx._set_footer(embed)
        for plant_name, plant_type, plant_nourishment, last_water_time in plant_data:
            plant_type_display = plant_type.replace('_', ' ').capitalize()
            # plant_name_display = re.sub(r"([\_*`])", r"\\\1", plant_name)
            plant_death_time = last_water_time + timedelta(
                **self.bot.config.get('plants', {}).get(
                    'death_timeout', {'days': 3}))
            plant_death_humanize_time = arrow.get(plant_death_time).humanize(
                granularity=["day", "hour", "minute"], only_distance=True)
            if plant_nourishment == 0:
                text = f"{plant_type_display}, nourishment level {plant_nourishment}/{self.bot.plants[plant_type].max_nourishment_level}."
            elif plant_nourishment > 0:
                text = (
                    f"{plant_type_display}, nourishment level {plant_nourishment}/{self.bot.plants[plant_type].max_nourishment_level}.\n"
                    f"If not watered, this plant will die in *{plant_death_humanize_time}*."
                )
            else:
                text = f"{plant_type_display}, dead :c"
            embed.add_field(plant_name, text)

        # Return to user
        return await ctx.send(embed=embed)
Exemple #4
0
    async def grandexchange(self, ctx, *, item:str):
        """
        Get the value of an item on the grand exchange (OSRS).
        """

        async with ctx.typing():
            if item.lower() in ['random']:
                item_id = random.choice(list(self.item_ids.values()))
            else:
                item = item.capitalize()
                item_id = self.item_ids.get(item)

            if item_id:
                item_dict = await self.get_item_details_by_id(item_id)
                item_value = await self.parse_item_value(item_dict, return_int=False)

                name = item_dict['name']
                item_page_url = API_BASE_URL + f"a=373/{name.replace(' ', '+')}/viewitem?obj={item_id}"

                with utils.Embed() as embed:
                    embed.set_author(name=name, url=item_page_url, icon_url=item_dict['icon'])
                    embed.set_thumbnail(url=item_dict['icon_large'])
                    embed.add_field('Value', f'{item_value} coins', inline=False)
                    embed.add_field(f'Examine {name}', item_dict['description'], inline=False)
                    embed.add_field('Members', MEMBERS_MAPPING[item_dict['members']], inline=False)

                return await ctx.send(embed=embed)
            else:
                return await ctx.send('Item not found')
Exemple #5
0
    async def roll_dice(self, ctx: utils.Context, dice_limit: int, multiplier: int, bet: localutils.BetAmount):
        """
        Roll the dice on the user's bet.
        """

        # Work out what the user's rolled
        rolled_number = random.randint(1, 100)
        user_won = rolled_number > dice_limit

        # Work out what to say to the user
        embed = utils.Embed(title=f"\N{GAME DIE} {rolled_number}")
        if user_won:
            embed.colour = discord.Colour.green()
            embed.description = "You won! :D"
            if bet.amount:
                embed.description = f"You won! Added **{bet.amount * (multiplier - 1):,}** to your account! :D"
            win_amount = bet.amount * (multiplier - 1)
        else:
            embed.colour = discord.Colour.red()
            embed.description = "You lost :c"
            if bet.amount:
                embed.description = f"You lost, removed **{bet.amount:,}** from your account :c"
            win_amount = -bet.amount

        # Tell the user all is well
        self.bot.dispatch("transaction", ctx.author, bet.currency, win_amount, ctx.command.name.upper(), user_won)
        return await ctx.send(embed=embed)
Exemple #6
0
    async def points_leaderboard(self, ctx: utils.Context):
        """
        Create a points leaderboard.
        """

        # See if they're running a subcommand
        if ctx.invoked_subcommand is not None:
            return

        # Get data
        async with self.bot.database() as db:
            rows = await db(
                "SELECT * FROM user_points WHERE guild_id=$1 AND points > 0 ORDER BY points DESC",
                ctx.guild.id)

        # Format it into an embed
        valid_users = []
        for i in rows:
            member = ctx.guild.get_member(i['user_id'])
            if member is None:
                continue
            valid_users.append(f"{member.mention}: {i['points']:,}")
            if len(valid_users) >= 30:
                break
        with utils.Embed(use_random_colour=True) as embed:
            embed.description = '\n'.join(
                valid_users) or 'Nobody is on here :c'

        # Output
        await ctx.send(embed=embed)
Exemple #7
0
    async def dnd_class(self, ctx: vbu.Context, *, class_name: str):
        """
        Gives you information on a D&D class.
        """

        async with ctx.typing():
            data = await self.send_web_request("classes", class_name)
        if not data:
            return await ctx.send(
                "I couldn't find any information for that class.", wait=False)
        embed = vbu.Embed(
            use_random_colour=True,
            title=data['name'],
        ).add_field(
            "Proficiencies",
            ", ".join([i['name'] for i in data['proficiencies']]),
        ).add_field(
            "Saving Throws",
            ", ".join([i['name'] for i in data['saving_throws']]),
        ).add_field(
            "Starting Equipment",
            "\n".join([
                f"{i['quantity']}x {i['equipment']['name']}"
                for i in data['starting_equipment']
            ]),
        )
        return await ctx.send(embed=embed, wait=False)
Exemple #8
0
    async def wolfram(self, ctx, *, search: str):
        """
        Ping some data to WolframAlpha.
        """

        params = {
            "input": search,
            "appid": self.bot.config['api_keys']['wolfram'],
            "format": "image",
            "output": "json",
        }
        headers = {
            "User-Agent": self.bot.user_agent,
        }
        async with ctx.typing():
            async with self.bot.session.get(
                    "https://api.wolframalpha.com/v2/query",
                    params=params,
                    headers=headers) as r:
                data = json.loads(await r.text())
        try:
            pod = data['queryresult']['pods'][1]
            # await ctx.send(pod['subpods'][0]['img'])
            return await ctx.reply(
                embed=utils.Embed(title=pod['title'], use_random_colour=True
                                  ).set_image(pod['subpods'][0]['img']['src']))
        except (KeyError, IndexError):
            return await ctx.reply("No results for that query!")
Exemple #9
0
    async def httpcat(self, ctx: utils.Context, errorcode: str):
        """
        Gives you a cat based on an HTTP error code.
        """

        standard_errorcodes = [error.value for error in http.HTTPStatus]

        if errorcode in ('random', 'rand', 'r'):
            errorcode = random.choice(standard_errorcodes)
        else:
            try:
                errorcode = int(errorcode)
            except ValueError:
                return ctx.channel.send(
                    'Converting to "int" failed for parameter "errorcode".')

        await ctx.channel.trigger_typing()
        headers = {"User-Agent": self.bot.user_agent}
        async with self.bot.session.get(f"https://http.cat/{errorcode}",
                                        headers=headers) as r:
            if r.status == 404:
                if errorcode not in standard_errorcodes:
                    await ctx.send("That HTTP code doesn't exist.")
                else:
                    await ctx.send('Image for HTTP code not found on provider.'
                                   )
                return
            if r.status != 200:
                await ctx.send(
                    f'Something went wrong, try again later. ({r.status})')
                return
        with utils.Embed(use_random_colour=True) as embed:
            embed.set_image(url=f'https://http.cat/{errorcode}')
        await ctx.send(embed=embed)
Exemple #10
0
    async def rtdm_js(self, ctx, *, obj: str):
        """
        Gives you a documentation link for a Javascript entity.
        """

        url = "https://developer.mozilla.org/api/v1/search"
        params = {
            'q': obj,
            'local': 'en-US',
        }
        headers = {
            'User-Agent': self.bot.user_agent,
        }
        async with self.bot.session.get(url, params=params,
                                        headers=headers) as r:
            data = await r.json()
        if not data['documents']:
            return await ctx.send("I couldn't find anything. Sorry.")
        embed = vbu.Embed(use_random_colour=True, description="")
        for i in data['documents']:
            if 'web/javascript' not in i['slug']:
                continue
            embed.description += f"[`{i['title']}`](https://developer.mozilla.org{i['mdn_url']})\n"
            if embed.description.count("\n") >= 8:
                break
        return await ctx.send(embed=embed)
Exemple #11
0
    async def displayplant(self, ctx: utils.Context,
                           user: typing.Optional[utils.converters.UserID], *,
                           plant_name: str):
        """
        Shows you your plant status.
        """

        # Get data from database
        user = discord.Object(user) if user else ctx.author
        async with self.bot.database() as db:
            plant_rows = await db(
                "SELECT * FROM plant_levels WHERE user_id=$1 AND LOWER(plant_name)=LOWER($2)",
                user.id, plant_name)
            if not plant_rows:
                return await ctx.send(
                    f"You have no plant named **{plant_name.capitalize()}**",
                    allowed_mentions=discord.AllowedMentions(users=False,
                                                             roles=False,
                                                             everyone=False))

        # Filter into variables
        display_utils = self.bot.get_cog("PlantDisplayUtils")
        if plant_rows:
            display_data = display_utils.get_display_data(plant_rows[0],
                                                          user_id=user.id)
        else:
            display_data = display_utils.get_display_data(None,
                                                          user_id=user.id)

        # Generate text
        if display_data['plant_type'] is None:
            if ctx.author.id == user.id:
                text = f"You don't have a plant yet, {ctx.author.mention}! Run `{ctx.prefix}getplant` to get one!"
            else:
                text = f"<@{user.id}> doesn't have a plant yet!"
        else:
            text = f"<@{user.id}>'s {display_data['plant_type'].replace('_', ' ')} - **{plant_rows[0]['plant_name']}**"
            if int(display_data['plant_nourishment']) > 0:
                if ctx.author.id == user.id:
                    text += "!"
            elif int(display_data['plant_nourishment']) < 0:
                if ctx.author.id == user.id:
                    text += f". It's looking a tad... dead. Run `{ctx.prefix}deleteplant {plant_name}` to plant some new seeds."
                else:
                    text += ". It looks a bit... worse for wear, to say the least."
            elif int(display_data['plant_nourishment']) == 0:
                if ctx.author.id == user.id:
                    text += f". There are some seeds there, but you need to `{ctx.prefix}water {plant_rows[0]['plant_name']}` them to get them to grow."
                else:
                    text += ". There are some seeds there I think, but they need to be watered."

        # Send image
        image_data = display_utils.image_to_bytes(
            display_utils.get_plant_image(**display_data))
        file = discord.File(image_data, filename="plant.png")
        embed = utils.Embed(
            use_random_colour=True,
            description=text).set_image("attachment://plant.png")
        ctx._set_footer(embed)
        await ctx.send(embed=embed, file=file)
Exemple #12
0
    async def nuget(self, ctx: vbu.Context, package_name: str):
        """
        Check nuget for a package.
        """

        # Get our data
        async with self.bot.session.get(
            f"https://azuresearch-usnc.nuget.org/query?q={package_name}") as e:
            if e.status != 200:
                await ctx.send("Something went wrong, try again later...")
                return
            data = await e.json()

        # make a lil embed
        with vbu.Embed(use_random_colour=True) as embed:
            if data['data']:
                embed.set_author(
                    name=data['data'][0]['title'],
                    url=
                    f"https://www.nuget.org/packages/{data['data'][0]['id']}")
                embed.description = data['data'][0]['description']
            else:
                await ctx.send(
                    f"I could not find anything for `{package_name}` :c")
                return
        await ctx.send(embed=embed)
    async def showallold(self, ctx: utils.Context, user: typing.Optional[discord.User]):
        """
        Show you all of your plants.
        """

        # Get data from database
        user = user or ctx.author
        async with self.bot.database() as db:
            plant_rows = await db("SELECT * FROM plant_levels WHERE user_id=$1 ORDER BY plant_name DESC", user.id)
            if not plant_rows:
                return await ctx.send(f"<@{user.id}> has no available plants.", allowed_mentions=discord.AllowedMentions(users=[ctx.author]))
        await ctx.trigger_typing()

        # Filter into variables
        display_utils = self.bot.get_cog("PlantDisplayUtils")
        plant_rows = display_utils.sort_plant_rows(plant_rows)
        images = []
        for plant_row in plant_rows:
            if plant_row:
                display_data = display_utils.get_display_data(plant_row, user_id=user.id)
            else:
                display_data = display_utils.get_display_data(None, user_id=user.id)
            images.append(display_utils.get_plant_image(**display_data))

        # Get our images
        image = display_utils.compile_plant_images(*images)
        image_to_send = display_utils.image_to_bytes(image)
        text = f"Here are all of <@{user.id}>'s plants!"
        file = discord.File(image_to_send, filename="plant.png")
        embed = utils.Embed(use_random_colour=True, description=text).set_image("attachment://plant.png")
        ctx.bot.set_footer_from_config(embed)
        await ctx.send(embed=embed, file=file)
Exemple #14
0
    async def wikihow(self, ctx: utils.Context):
        """That classic ol wikihow game"""

        if self.possible_images is None:
            await self.load_images()
        choices = random.choices(self.possible_images, k=4)
        chosen_image = choices[0]
        random.shuffle(choices)
        with utils.Embed(use_random_colour=True) as embed:
            embed.set_image(url=self.IMAGE_DIRECTORY + chosen_image.lower() +
                            '.jpg')
            # await ctx.send(self.IMAGE_DIRECTORY + chosen_image.lower() + '.jpg')
            embed.description = ''.join((
                "1\N{COMBINING ENCLOSING KEYCAP} How to... {0}\n".format(
                    choices[0].lower().replace('-', ' ')),
                "2\N{COMBINING ENCLOSING KEYCAP} How to... {0}\n".format(
                    choices[1].lower().replace('-', ' ')),
                "3\N{COMBINING ENCLOSING KEYCAP} How to... {0}\n".format(
                    choices[2].lower().replace('-', ' ')),
                "4\N{COMBINING ENCLOSING KEYCAP} How to... {0}\n".format(
                    choices[3].lower().replace('-', ' ')),
            ))
        m = await ctx.send(embed=embed)
        for e in [
                "1\N{COMBINING ENCLOSING KEYCAP}",
                "2\N{COMBINING ENCLOSING KEYCAP}",
                "3\N{COMBINING ENCLOSING KEYCAP}",
                "4\N{COMBINING ENCLOSING KEYCAP}"
        ]:
            await m.add_reaction(e)
Exemple #15
0
    async def httpdog(self, ctx: vbu.Context, errorcode: str):
        """
        Gives you a dog based on an HTTP error code.
        """

        standard_errorcodes = [error.value for error in http.HTTPStatus]

        if errorcode in ('random', 'rand', 'r'):
            errorcode = random.choice(standard_errorcodes)
        else:
            try:
                errorcode = int(errorcode)
            except ValueError:
                return ctx.channel.send(
                    'Converting to "int" failed for parameter "errorcode".')

        await ctx.trigger_typing()
        headers = {"User-Agent": self.bot.user_agent}
        async with self.bot.session.get(
                f"https://httpstatusdogs.com/img/{errorcode}.jpg",
                headers=headers,
                allow_redirects=False) as r:
            if str(r.status)[0] != "2":
                if errorcode not in standard_errorcodes:
                    await ctx.send("That HTTP code doesn't exist.", wait=False)
                else:
                    await ctx.send(
                        'Image for HTTP code not found on provider.',
                        wait=False)
                return
        with vbu.Embed(use_random_colour=True) as embed:
            embed.set_image(
                url=f'https://httpstatusdogs.com/img/{errorcode}.jpg')
        await ctx.send(embed=embed, wait=False)
Exemple #16
0
    async def bot(self, ctx: utils.Context, bot: discord.User):
        """
        Gives you information about a bot.
        """

        if bot.bot is False:
            return await ctx.send("That isn't even a bot.")

        bot_info = [
            i for i in self.bot.config['bot_info'] if i['user_id'] == bot.id
        ]
        if not bot_info:
            return await ctx.send(
                f"I don't have any information on record about {bot.mention}.")
        bot_info = bot_info[0]

        with utils.Embed(use_random_colour=True) as embed:
            embed.set_author_to_user(user=bot)
            embed.description = bot_info['description']
            for field in bot_info.get('fields', list()):
                embed.add_field(name=field['name'],
                                value=field['value'],
                                inline=field.get('inline', False))
            embed.set_thumbnail(url=bot.avatar_url)
            if bot_info.get('image'):
                embed.set_image(url=bot_info['image'])
        return await ctx.send(embed=embed)
Exemple #17
0
    async def rtdm_dotnet(self, ctx, *, obj: str):
        """
        Gives you a documentation link for a Javascript entity.
        """

        url = "https://docs.microsoft.com/api/apibrowser/dotnet/search"
        params = {
            'api-version': '0.2',
            'search': obj,
            'locale': 'en-us',
            '$filter': "monikers/any(t: t eq 'net-5.0')",
        }
        headers = {
            'User-Agent': self.bot.user_agent,
        }
        async with self.bot.session.get(url, params=params,
                                        headers=headers) as r:
            data = await r.json()
        if not data['results']:
            return await ctx.send("I couldn't find anything. Sorry.")
        embed = vbu.Embed(use_random_colour=True, description="")
        for i in data['results']:
            embed.description += f"[`{i['displayName']}`]({i['url']})\n"
            if embed.description.count("\n") >= 8:
                break
        return await ctx.send(embed=embed)
    async def list(self, ctx: utils.Context, user: discord.Member = None):
        """List who's simping for you"""

        user = user or ctx.author
        simp_user = localutils.SimpableUser.get_simpable_user(
            user.id, ctx.guild.id)
        simping_for = [
            o for o in
            [ctx.guild.get_member(i.user_id) for i in simp_user.simping_for]
            if o
        ]
        being_simped_by = [
            o for o in [
                ctx.guild.get_member(i.user_id)
                for i in simp_user.being_simped_by
            ] if o
        ]
        mutual_simping = [i for i in simping_for if i in being_simped_by]
        with utils.Embed(use_random_colour=True) as embed:
            embed.set_author_to_user(user)

            # Add simping for
            if [i for i in simping_for if i not in mutual_simping]:
                embed.add_field("Simping For",
                                ", ".join([
                                    i.mention for i in simping_for
                                    if i not in mutual_simping
                                ]),
                                inline=False)
            else:
                if not mutual_simping:
                    embed.add_field("Simping For",
                                    "Nobody... \N{THINKING FACE}")
                else:
                    embed.add_field("Simping For", "Nobody")

            # Add being simped by
            if [i for i in being_simped_by if i not in mutual_simping]:
                embed.add_field("Being Simped By",
                                ", ".join([
                                    i.mention for i in being_simped_by
                                    if i not in mutual_simping
                                ]),
                                inline=False)
            else:
                if not mutual_simping:
                    embed.add_field("Being Simped By",
                                    "Nobody... \N{UNAMUSED FACE}")
                else:
                    embed.add_field("Being Simped By", "Nobody")

            # Add mutuals
            if mutual_simping:
                embed.add_field("Mutual Simping owo",
                                ", ".join([i.mention for i in mutual_simping]),
                                inline=False)

        # And done
        return await ctx.send(embed=embed)
Exemple #19
0
    async def avatar(self, ctx: utils.Context, user: discord.User = None):
        """Shows you the avatar of a given user"""

        if user is None:
            user = ctx.author
        with utils.Embed(use_random_colour=True) as embed:
            embed.set_image(url=user.avatar_url)
        await ctx.send(embed=embed)
Exemple #20
0
    async def update_shop_message(self, guild: discord.Guild):
        """
        Edit the shop message to to be pretty good.
        """

        # Get the shop message
        self.logger.info(f"Shop message update dispatched (G{guild.id})")
        try:
            shop_channel = self.bot.get_channel(
                self.bot.guild_settings[guild.id]['shop_channel_id'])
            shop_message = await shop_channel.fetch_message(
                self.bot.guild_settings[guild.id]['shop_message_id'])
            if shop_message is None:
                self.logger.info(
                    f"Can't update shop message - no message found (G{guild.id})"
                )
                raise AttributeError()
        except (discord.NotFound, AttributeError):
            self.logger.info(
                f"Can't update shop message - no message/channel found (G{guild.id})"
            )
            return

        # Generate embed
        coin_emoji = self.bot.guild_settings[guild.id].get("coin_emoji",
                                                           None) or "coins"
        emojis = []
        with utils.Embed() as embed:
            for emoji, data in self.get_shop_items(guild).items():
                item_price = self.bot.guild_settings[guild.id].get(
                    data['price_key'], data['amount'])
                if item_price <= 0:
                    continue
                embed.add_field(
                    f"{data['name']} ({emoji}) - {item_price} {coin_emoji}",
                    data['description'],
                    inline=False)
                emojis.append(emoji)

        # See if we need to edit the message
        try:
            current_embed = shop_message.embeds[0]
        except IndexError:
            current_embed = None
        if embed == current_embed:
            self.logger.info(
                f"Not updating shop message - no changes presented (G{guild.id})"
            )
            return

        # Edit message
        self.logger.info(f"Updating shop message (G{guild.id})")
        await shop_message.edit(content=None, embed=embed)

        # Add reactions
        await shop_message.clear_reactions()
        for e in emojis:
            await shop_message.add_reaction(e)
Exemple #21
0
    async def coaster_data(self, ctx: utils.Context, coaster_id: int):
        """Get data for a specific coaster"""

        # Grab page data
        async with self.bot.session.get(f"https://rcdb.com/{coaster_id}.htm",
                                        headers=self.HEADERS) as r:
            text = await r.text()

        # Get features
        soup = BeautifulSoup(text, "html.parser")
        data = soup.find(class_="stat-tbl")
        x = data.find("tbody")
        v = []
        while True:
            y = list(x)
            for i in y:
                if isinstance(i, str):
                    v.append(i)
                elif i.name == 'span':
                    v.append(i.text)
            try:
                x = y[-1].children
            except (IndexError, AttributeError):
                break
        b = []
        continue_next = False
        for index, i in enumerate(v):
            if continue_next:
                continue_next = False
                continue
            if i.strip().lower() == 'elements':
                break
            try:
                if v[index +
                     1].strip() in ['ft', 'mph', 'ft tall', 'ft long', '°']:
                    b.append(f"{i}{v[index + 1].strip()}")
                    continue_next = True
                else:
                    b.append(i)
            except IndexError:
                b.append(i)
        features = {}
        for index, i in enumerate(b[::2]):
            try:
                features[i] = b[(index * 2) + 1]
            except IndexError:
                features = {}
                break
        title = soup.title.text
        image = "https://rcdb.com" + soup.find(id="opfAnchor")['data-url']

        # Wew that took a while - let's make that into an embed now
        with utils.Embed(use_random_colour=True) as embed:
            embed.set_author(name=title, url=r.url)
            embed.set_image(image)
            for i, o in features.items():
                embed.add_field(i, o, True)
        await ctx.send(embed=embed)
Exemple #22
0
 def formatter(menu, data):
     return vbu.Embed(
         use_random_colour=True,
         title=data[0][0]
     ).set_image(
         data[0][1]
     ).set_footer(
         f"Page {menu.current_page + 1}/{menu.max_pages}"
     )
Exemple #23
0
    async def movie(self, ctx: utils.Context, *, name: str):
        """Searches for a movie on the OMDB API"""

        # See if we gave a year
        original_name = name
        if name.split(' ')[-1].isdigit() and int(name.split(' ')[-1]) > 1900:
            *name, year = name.split(' ')
            name = ' '.join(name)
        else:
            year = None

        # Build up the params
        params = {
            'apikey': self.bot.config['api_keys']['omdb'],
            't': name,
            'type': 'movie'
        }
        if year:
            params.update({'year': year})

        # Send the request
        async with self.bot.session.get("http://www.omdbapi.com/",
                                        params=params) as r:
            data = await r.json()

        # Build an embed
        if data.get('Title') is None:
            return await ctx.invoke(self.bot.get_command("movie search"),
                                    name=original_name)
        with utils.Embed(use_random_colour=True,
                         title=f"{data['Title']} ({data['Year']})") as embed:
            if data['Plot']:
                embed.description = data['Plot']
            if data['Released']:
                embed.add_field("Release Date", data['Released'])
            if data['Rated']:
                embed.add_field("Age Rating", data['Rated'])
            if data['Runtime']:
                embed.add_field("Runtime", data['Runtime'])
            if data['Genre']:
                embed.add_field("Genre", data['Genre'])
            if data['imdbRating']:
                embed.add_field("IMDB Rating", data['imdbRating'])
            if data['Production']:
                embed.add_field("Production Company", data['Production'])
            if data['Director']:
                embed.add_field("Director", data['Director'])
            if data['Writer']:
                embed.add_field("Writer", data['Writer'], inline=False)
            if data['imdbID']:
                embed.add_field(
                    "IMDB Page",
                    f"[Direct Link](https://www.imdb.com/title/{data['imdbID']}/) - IMDB ID `{data['imdbID']}`",
                    inline=False)
            if data['Poster']:
                embed.set_thumbnail(data['Poster'])
        return await ctx.send(embed=embed)
Exemple #24
0
    async def quote_list(self, ctx: vbu.Context, user: discord.Member=None):
        """
        List the IDs of quotes for a user.
        """

        # Grab data from db
        user = user or ctx.author
        async with self.bot.database() as db:
            rows = await db("SELECT quote_id FROM user_quotes WHERE user_id=$1 AND guild_id=$2", user, ctx.guild.id)
        if not rows:
            embed = vbu.Embed(
                use_random_colour=True, description="This user has no quotes.",
            ).set_author_to_user(user)
            return await ctx.send(embed=embed)
        embed = vbu.Embed(
            use_random_colour=True, description="\n".join([i['quote_id'] for i in rows[:50]]),
        ).set_author_to_user(user)
        return await ctx.send(embed=embed)
Exemple #25
0
    async def inventory(self, ctx: utils.Context,
                        user: typing.Optional[discord.User]):
        """
        Show you the inventory of a user.
        """

        # Get user info
        user = user or ctx.author
        async with self.bot.database() as db:
            user_rows = await db(
                "SELECT * FROM user_settings WHERE user_id=$1", user.id)
            plant_rows = await db(
                "SELECT * FROM plant_levels WHERE user_id=$1", user.id)
            user_inventory_rows = await db(
                "SELECT * FROM user_inventory WHERE user_id=$1 AND amount > 0",
                user.id)

        # Start our embed
        embed = utils.Embed(use_random_colour=True, description="")
        ctx.bot.set_footer_from_config(embed)

        # Format exp into a string
        if user_rows:
            exp_value = user_rows[0]['user_experience']
        else:
            exp_value = 0
        embed.description += f"<@{user.id}> has **{exp_value:,}** experience.\n"

        # Format plant limit into a string
        if user_rows:
            plant_limit = user_rows[0]['plant_limit']
        else:
            plant_limit = 1
        they_you = {True: "you", False: "they"}.get(user.id == ctx.author.id)
        their_your = {
            True: "your",
            False: "their"
        }.get(user.id == ctx.author.id)
        if plant_limit == len(plant_rows):
            embed.description += ((
                f"{they_you.capitalize()} are currently using all of {their_your} "
                f"available {plant_limit} plant pots.\n"))
        else:
            embed.description += ((
                f"{they_you.capitalize()} are currently using {len(plant_rows)} of "
                f"{their_your} available {plant_limit} plant pots.\n"))

        # Format inventory into a string
        if user_inventory_rows:
            inventory_string = "\n".join([
                f"{row['item_name'].replace('_', ' ').capitalize()} x{row['amount']:,}"
                for row in user_inventory_rows
            ])
            embed.add_field("Inventory", inventory_string)

        # Return to user
        return await ctx.send(embed=embed)
Exemple #26
0
    async def commit_poster_loop(self, embed_title: str, api_url: str,
                                 repo_url: str):
        """Grab the data from the Discord datamining repo and post it to the coding channel of VFL"""

        # Grab the data
        self.logger.info(f"Grabbing repo data from {api_url}")
        async with self.bot.session.get(api_url) as r:
            data = await r.json()

        # Let's work out the new data
        new_commits = []
        if self.last_posted_commit[repo_url] is None:
            self.last_posted_commit[repo_url] = data[0]['sha']
            self.logger.info("Setting to last commit - no commits cached")
            return
        for index, i in enumerate(data):
            if i['sha'] == self.last_posted_commit[repo_url]:
                new_commits = data[:index]
                break

        # See if we have anything to talk about
        if not new_commits:
            self.logger.info("No new commits found")
            return
        self.logger.info(f"Logging info of {len(new_commits)} commits")

        # Work out which of our new commits have comments
        comment_urls = [
            i['comments_url'] for i in new_commits
            if i['commit']['comment_count'] > 0
        ]
        comment_text = []
        for url in comment_urls:
            async with self.bot.session.get(url) as r:
                data = await r.json()
            comment_text.extend([(i['commit_id'],
                                  re.sub(r"^## (.+)", r"**\1**", i['body']))
                                 for i in data])
        self.logger.info(f"Logging info of {len(comment_text)} comments")

        # Format it all into an embed
        with utils.Embed(use_random_colour=True) as embed:
            embed.title = embed_title
            embed.description = '\n'.join([
                f"{i['commit']['message']} - [Link]({repo_url}commit/{i['sha']})"
                for i in new_commits
            ])
            for sha, body in comment_text:
                embed.add_field(sha, body, inline=False)

        # And send
        channel = self.bot.get_channel(self.VFL_CODING_CHANNEL_ID)
        m = await channel.send(embed=embed)
        await m.publish()
        self.logger.info("Sent data to channel")
        self.last_posted_commit[repo_url] = new_commits[0]['sha']
    async def daily(self, ctx: utils.Context):
        """
        Get money on the daily.
        """

        async with self.bot.database() as db:

            # See which currencies allow faily command
            all_guild_currencies = await db(
                """SELECT currency_name FROM guild_currencies WHERE guild_id=$1 AND allow_daily_command=true""",
                ctx.guild.id,
            )

            # Check out last run commands
            allowed_daily_currencies = await db(
                """SELECT currency_name, last_daily_command FROM user_money WHERE user_money.guild_id=$1 AND
                user_money.user_id=$2 AND currency_name=ANY($3::TEXT[])""",
                ctx.guild.id, ctx.author.id, [i['currency_name'] for i in all_guild_currencies],
            )

            # Work out when each thing was last run
            allowed_daily_dict = {}
            for row in all_guild_currencies:
                allowed_daily_dict[row['currency_name']] = dt(2000, 1, 1)
            for row in allowed_daily_currencies:
                allowed_daily_dict[row['currency_name']] = row['last_daily_command']
            if not allowed_daily_dict:
                return await ctx.send("There's nothing available for use with the daily command right now.")

            # Work out how much we're adding
            changed_daily = {}
            for currency_name, last_run_time in allowed_daily_dict.items():
                if last_run_time > dt.utcnow() - self.DAILY_COMMAND_TIMEOUT:
                    continue
                amount = random.randint(9_000, 13_000)
                await db(
                    """INSERT INTO user_money (user_id, guild_id, currency_name, money_amount, last_daily_command)
                    VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id, guild_id, currency_name) DO UPDATE SET
                    money_amount=user_money.money_amount+excluded.money_amount, last_daily_command=excluded.last_daily_command""",
                    ctx.author.id, ctx.guild.id, currency_name, amount, ctx.message.created_at,
                )
                self.bot.dispatch("transaction", ctx.author, currency_name, amount, "DAILY_COMMAND")
                changed_daily[row['currency_name']] = amount

        # Make them into an embed
        if not changed_daily:
            soonest_allow_daily = max(allowed_daily_dict.values())
            soonest_tv = utils.TimeValue((soonest_allow_daily - (dt.utcnow() - self.DAILY_COMMAND_TIMEOUT)).total_seconds())
            return await ctx.send(f"You can't get anything with the daily command for another **{soonest_tv.clean_full}**.")
        embed = utils.Embed(use_random_colour=True)
        description_list = []
        for currency, amount in changed_daily.items():
            currency_name = currency.title() if currency.lower() == currency else currency
            description_list.append(f"**{currency_name}** - {amount}")
        embed.description = "\n".join(description_list)
        return await ctx.send(embed=embed)
Exemple #28
0
        def formatter(menu, items):
            # Create the embed
            commands_embed = vbu.Embed(title="Command Data (times run)")
            # Add the total count footer
            commands_embed.set_footer(text=f"Total: {total_count}")
            # Add the command list to the emebd
            commands_embed.description = "\n".join(items)

            # Return the embed
            return commands_embed
Exemple #29
0
    def get_embed_from_cache(self, cache, obj) -> dict:
        """
        Build up some kwargs from the cache and a given input object.
        """

        item_casefold = obj.casefold()
        split = item_casefold.split('.')
        outputs = []

        for key, link in cache.items():

            # Key would be something like 'TextChannel.fetch', now 'textchannel.fetch'
            key_casefold = key.casefold()

            # See if we got an exact match
            if item_casefold in key_casefold:
                if item_casefold == key_casefold:
                    outputs.append((key, link, 20,))
                else:
                    outputs.append((key, link, 15,))

            # See if we're looking for a method
            if len(split) == 1:
                continue

            # Search by method
            if split[1] and split[1] in key_casefold:
                if split[1] == key_casefold:
                    outputs.append((key, link, 12,))
                else:
                    outputs.append((key, link, 10,))

            # Search by class
            if split[0] and split[0] in key_casefold:
                if split[0] == key_casefold:
                    outputs.append((key, link, 7,))
                else:
                    outputs.append((key, link, 5,))

        # Hey maybe they didn't say anything useful
        if len(outputs) == 0:
            return {"content": "I couldn't find anything. Sorry."}

        # Yo there's a result. Let's embed that.
        embed = utils.Embed(use_random_colour=True)
        outputs.sort(key=lambda i: (i[2], i[0]), reverse=True)
        embed.description = ""
        for key, url, weight in outputs:
            v = f"[`{key}`]({url})\n"
            if v in embed.description:
                continue
            embed.description += v
            if embed.description.count("\n") >= 8:
                break
        return {"embed": embed}
Exemple #30
0
    async def panda(self, ctx: utils.Context):
        """Gives you some panda pictures"""

        await ctx.channel.trigger_typing()
        headers = {"User-Agent": "Apple.py/0.0.1 - Discord@Caleb#2831"}
        async with self.bot.session.get("https://some-random-api.ml/img/panda",
                                        headers=headers) as r:
            data = await r.json()
        with utils.Embed(use_random_colour=True) as embed:
            embed.set_image(url=data['link'])
        await ctx.send(embed=embed)