Exemplo n.º 1
0
class SlashCommands(commands.Cog):
    def __init__(self, client):
        self.client = client

    #on_ready event example
    @commands.Cog.listener()
    async def on_ready(self):
        print('<SlashCommands> Test module loaded!')

    #fill with id's of guilds where you want to use slash commands
    guild_id = [320574287046115328]

    @cog_ext.cog_slash(
        name="test",
        guild_ids=guild_id,
        description="Test command.",
        options=[
            manage_commands.create_option("option1", "Member example.",
                                          discord.Member, True),
            manage_commands.create_option("option2", "Bool example.", bool,
                                          True),
            manage_commands.create_option(
                "option3", "String example.", str,
                False)  #if set to False it't optional
        ])
    @commands.has_permissions(administrator=True
                              )  #right now we have to use discord.ext check
    async def _test(self, ctx, member: discord.Member):
        try:
            await ctx.respond(True)
            #do something
        except Exception as E:
            print(E)

    #error handler
    @commands.Cog.listener()
    async def on_slash_command_error(self, ctx: SlashContext, error):
        try:
            await ctx.respond(True)
            if isinstance(error, MissingPermissions):
                mess = await ctx.send(
                    f":exclamation: Missing permissions: `{','.join(error.missing_perms)}`!"
                )
                await asyncio.sleep(5)
                await mess.delete()
        except Exception as E:
            print(E)
Exemplo n.º 2
0
class Guild(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    # slash commands
    slash_guilds = [773042619734687766]

    @cog_ext.cog_slash(
        name="guild",
        description=
        "Checks if you are in the guild, and gives you the guild member role",
        options=[
            manage_commands.create_option(
                name="username",
                description="Your username on hypixel",
                option_type=3,
                required=True)
        ],
        guild_ids=slash_guilds)
    async def _guild(self, ctx: SlashContext, username):
        req_player = await self.bot.session.get(
            f"https://api.slothpixel.me/api/players/{username}")
        res_player = await req_player.json()
        if "error" in res_player:
            return await ctx.send(
                "An error happened! Please check if the username you provided is correct",
                hidden=True)
        if res_player['links']['DISCORD'] != str(ctx.author):
            return await ctx.send(
                f"Your Minecraft and Discord accounts are not linked! Please update your discord link on hypixel from {res_player['links']['DISCORD']} to {str(ctx.author)}",
                hidden=True)
        req_guild = await self.bot.session.get(
            f"https://api.slothpixel.me/api/guilds/{username}")
        res_guild = await req_guild.json()
        if not res_guild['name'] == "Galaxy Crusaders":
            return await ctx.send(f"You are not in the guild!", hidden=True)
        role = ctx.guild.get_role(828657324877021204)
        await ctx.author.add_roles(role)
        await ctx.send(
            "Welcome to the guild! I have sucessfully added your guild role. Enjoy!",
            hidden=True)

    #normal commands start here

    @commands.command()
    async def scammer(self, ctx, ign: str):
        uuid_data = await self.bot.session.get(
            f"https://api.mojang.com/users/profiles/minecraft/{ign}")
        if uuid_data.status == 204:
            return await ctx.send("Ign Invalid!")
        uuid_json = await uuid_data.json()
        uuid = uuid_json['id']
        scammer_data = await self.bot.session.get(
            "https://raw.githubusercontent.com/skyblockz/pricecheckbot/master/scammer.json"
        )
        scammer_json = json.loads(await scammer_data.text())
        if uuid in scammer_json:
            embed = discord.Embed(
                title="USER IS A SCAMMER!!",
                description=f"This user has been found on the scammers list!")
            embed.add_field(
                name="Details",
                value=f"{scammer_json[uuid]['reason']}\nUser's UUID: {uuid}")
            embed.set_author(
                name=f"JERRY SCAMMER LIST",
                url=
                "https://raw.githubusercontent.com/skyblockz/pricecheckbot/master/scammer.json"
            )
            embed.set_footer(text=scammer_json[uuid]['operated_staff'])
            await ctx.send(embed=embed)
        else:
            embed = discord.Embed(
                title="Not a Scammer",
                description=
                "this user isn't a scammer, however, always be careful trading!"
            )
            await ctx.send(embed=embed)

    @commands.has_any_role(828661477606817824, 828662244652220436)
    @commands.command(name='addguildrole', aliases=['agr', 'add-guild-role'])
    async def add_guild_role(self, ctx, user: discord.Member):
        """Manually adds the guild role to a user"""
        guild_role = ctx.guild.get_role(828657324877021204)
        await user.add_roles(guild_role)
        await ctx.send(f"I have added the guild role to {str(user)}!")

    @commands.command(name='inguild')
    async def inguild(self, ctx, username: str):
        """Checks if the given username is in the guild"""
        resp = await self.bot.session.get(
            f"https://api.mojang.com/users/profiles/minecraft/{username}")
        if resp.status == 204:
            return await ctx.send("Invalid username!")
        uuid_data = await resp.json()
        uuid = uuid_data['id']
        guild_resp = await self.bot.session.get(
            f"https://api.slothpixel.me/api/guilds/{uuid}")
        guild_data = await guild_resp.json()
        if guild_data['name'] == "Galaxy Crusaders":
            await ctx.send(f"{uuid_data['name']} is in the guild!")
        else:
            await ctx.send(f"{uuid_data['name']} is not in the guild :(")

    @commands.has_role(828662244652220436)
    @commands.command(name="gexpcheck", aliases=['gexp-check'])
    async def gexp_check(self, ctx):
        async with ctx.typing():
            req = await self.bot.session.get(
                f"https://api.slothpixel.me/api/guilds/zeromomentum?populatePlayers=true"
            )
            res = await req.json()
            ending_string = ""
            for member in res['members']:
                gexp = calc(member['exp_history'])
                if gexp >= 30000:
                    ending_string += f"+ {member['profile']['username']} has 30k+ gexp ({gexp:,})\n"
        if len(ending_string) >= 2000:
            hb = await self.bot.session.post("https://hst.sh/documents",
                                             data=ending_string.encode('utf8'))
            url = f"https://hst.sh/{(await hb.json())['key']}"
            return await ctx.send(f"Here is the GEXP overview! {url}")
        else:
            return await ctx.send("```diff\n" + ending_string + "```")

    @commands.has_role(828662244652220436)
    @commands.command(name="choppingblock",
                      aliases=['chopping-block', 'no-gexp'])
    async def chopping_block(self, ctx):
        async with ctx.typing():
            req = await self.bot.session.get(
                f"https://api.slothpixel.me/api/guilds/zeromomentum?populatePlayers=true"
            )
            res = await req.json()
            ending_string = ""
            for member in res['members']:
                gexp = calc(member['exp_history'])
                if gexp <= 30000:
                    ending_string += f"- {member['profile']['username']} has less than 30k gexp ({gexp:,})\n"
        if len(ending_string) >= 2000:
            hb = await self.bot.session.post("https://hst.sh/documents",
                                             data=ending_string.encode('utf8'))
            url = f"https://hst.sh/{(await hb.json())['key']}"
            return await ctx.send(f"Here is the GEXP overview! {url}")
        else:
            return await ctx.send("```diff\n" + ending_string + "```")
Exemplo n.º 3
0
class SlashCmds(commands.Cog):
    def __init__(self, bot):
        self.bot: Skybot = bot

    async def shortcut_error(self, ctx):
        embed = await Embed(
            self.bot,
            ctx.author,
            title="Error",
            description=
            "You can only use this shortcut if you link a username to your Discord account."
        ).set_requested_by_footer()
        await ctx.send(embeds=[embed])
        # await ctx.invoke(self.bot.get_command("help show_command"), arg=ctx.command.name)

    async def profile_not_found_error(self, ctx: commands.Context, player):
        embed = await Embed(
            self.bot,
            ctx.author,
            title="Error",
            description=
            "Couldn't find the provided profile in your Skyblock account. Your profiles: "
            + ", ".join(player.profiles.keys())).set_requested_by_footer()
        await ctx.send(embeds=[embed])

    async def get_uname(self, ctx, uname):
        if not uname:
            uname, profile = await get_uuid_profileid(self.bot, ctx.author)
            if uname is None:
                return await self.shortcut_error(ctx)
        return uname

    async def make_player(self, ctx, uname, profile):
        if uname and uname.lower() == "me":
            uname, rest = await get_uuid_profileid(self.bot, ctx.author)

        if not uname and not profile:
            uname, profile = await get_uuid_profileid(self.bot, ctx.author)
            if uname is None:
                await self.shortcut_error(ctx)
                return None

        uname, uuid = await skypy.fetch_uuid_uname(uname)

        if not uname:
            raise exceptions.BadNameError(uname)
        player = await skypy.Player(keys=self.bot.api_keys, uname=uname)

        if not profile:
            await player.set_profile_automatically()
        elif profile and profile.capitalize() in player.profiles.keys():
            await player.set_profile(player.profiles[profile.capitalize()])
        else:
            try:
                await player.set_profile(profile)
            except exceptions.DataError:
                await self.profile_not_found_error(ctx, player)
                return None
        return player

    def format_name(self, name):
        return name + "'s" if name[-1] != "s" else name

    profiles = [
        manage_commands.create_choice("apple", "Apple"),
        manage_commands.create_choice("banana", "Banana"),
        manage_commands.create_choice("blueberry", "Blueberry"),
        manage_commands.create_choice("coconut", "Coconut"),
        manage_commands.create_choice("cucumber", "Cucumber"),
        manage_commands.create_choice("grapes", "Grapes"),
        manage_commands.create_choice("kiwi", "Kiwi"),
        manage_commands.create_choice("lemon", "Lemon"),
        manage_commands.create_choice("lime", "Lime"),
        manage_commands.create_choice("mango", "Mango")
    ]

    @cog_ext.cog_slash(
        name="dungeons",
        description="Shows you Catacomb stats.",
        options=[
            manage_commands.create_option(
                "username", "Minecraft username/Discord user if linked.",
                SlashCommandOptionType.STRING, False),
            manage_commands.create_option(
                "profile",
                "Profile name (There are more profile names then suggested!)",
                SlashCommandOptionType.STRING,
                False,
                choices=profiles)
        ])
    async def dungeons(self, ctx: SlashContext, username=None, profile=None):
        await ctx.defer()
        player = await self.make_player(ctx, username, profile)
        if not player: return
        embeds = await Player.get_dungeon_embeds(self, ctx, player)
        if isinstance(embeds, Embed):
            return await ctx.send(embed=embeds)
        elif len(embeds) == 1:
            return await ctx.send(embed=embeds[0])
        msg = await ctx.send(embed=embeds[0])
        await Paginator(self.bot,
                        msg,
                        embeds=embeds,
                        timeout=60,
                        only=ctx.author).start()

    @cog_ext.cog_slash(
        name="networth",
        description=
        "View a more in-depth breakdown of your estimated networth.",
        options=[
            manage_commands.create_option(
                "username", "Minecraft username/Discord user if linked.",
                SlashCommandOptionType.STRING, False),
            manage_commands.create_option(
                "profile",
                "Profile name (There are more profile names then suggested!)",
                SlashCommandOptionType.STRING,
                False,
                choices=profiles)
        ])
    async def networth(self, ctx: SlashContext, username=None, profile=None):
        await ctx.defer()
        player = await self.make_player(ctx=ctx,
                                        uname=username,
                                        profile=profile)
        if not player: return
        success = await player.skylea_stats(self.bot.stats_api)
        if success:
            embeds = await Player.get_networth_embeds(self,
                                                      ctx=ctx,
                                                      player=player)
            msg = await ctx.send(embed=embeds[0])
            await Expander(self.bot,
                           msg,
                           embeds=embeds,
                           timeout=120,
                           only=ctx.author).start()
        else:
            await ctx.send(
                content=
                f"An error occurred, perhaps this user has not played skyblock."
            )

    @cog_ext.cog_slash(
        name="skills",
        description="Shows you Skyblock skill levels and xp.",
        options=[
            manage_commands.create_option(
                "username", "Minecraft username/Discord user if linked.",
                SlashCommandOptionType.STRING, False),
            manage_commands.create_option(
                "profile",
                "Profile name (There are more profile names then suggested!)",
                SlashCommandOptionType.STRING,
                False,
                choices=profiles)
        ])
    async def skills(self, ctx: SlashContext, username=None, profile=None):
        await ctx.defer()
        player = await self.make_player(ctx=ctx,
                                        uname=username,
                                        profile=profile)
        if not player: return
        embed = await Player.get_skills_embed(self, ctx=ctx, player=player)
        await ctx.send(embeds=[embed])

    @cog_ext.cog_slash(
        name="stats",
        description=
        "Shows you Skyblock profile stats like health, strength and more.",
        options=[
            manage_commands.create_option(
                "username", "Minecraft username/Discord user if linked.",
                SlashCommandOptionType.STRING, False),
            manage_commands.create_option(
                "profile",
                "Profile name (There are more profile names then suggested!)",
                SlashCommandOptionType.STRING,
                False,
                choices=profiles)
        ])
    async def stats(self, ctx: SlashContext, username=None, profile=None):
        await ctx.defer()
        player = await self.make_player(ctx=ctx,
                                        uname=username,
                                        profile=profile)
        if not player: return
        success = await player.skylea_stats(self.bot.stats_api)
        if success:
            embed = await Player.get_stats_embed(self, ctx=ctx, player=player)
            await ctx.send(embeds=[embed])
        else:
            await ctx.send(
                content=
                f"An error occurred, perhaps this user has not played skyblock."
            )

    @cog_ext.cog_slash(
        name="slayer",
        description="Shows you Slayer stats.",
        options=[
            manage_commands.create_option(
                "username", "Minecraft username/Discord user if linked.",
                SlashCommandOptionType.STRING, False),
            manage_commands.create_option(
                "profile",
                "Profile name (There are more profile names then suggested!)",
                SlashCommandOptionType.STRING,
                False,
                choices=profiles)
        ])
    async def slayer(self, ctx: SlashContext, username=None, profile=None):
        await ctx.defer()
        player = await self.make_player(ctx=ctx,
                                        uname=username,
                                        profile=profile)
        if not player: return
        embed = await Player.get_slayer_embed(self, ctx=ctx, player=player)
        await ctx.send(embeds=[embed])

    @cog_ext.cog_slash(
        name="profiles",
        description="Shows you all your available profiles on Skyblock.",
        options=[
            manage_commands.create_option(
                "username", "Minecraft username/Discord user if linked.",
                SlashCommandOptionType.STRING, False)
        ])
    async def profiles(self, ctx: SlashContext, username=None):
        await ctx.defer()
        uname = await self.get_uname(ctx, username)
        if not uname: return
        embed: Embed = await Player.get_profiles_embed(self,
                                                       ctx=ctx,
                                                       uname=uname)
        await ctx.send(embeds=[embed])

    # @cog_ext.cog_slash(name="auctions", description="Shows you Skyblock auctions and information about them.", options=[manage_commands.create_option("username", "Minecraft username/Discord user if linked.", SlashCommandOptionType.STRING, False),
    #                                                                                                                                   manage_commands.create_option("profile", "Profile name (There are more profile names then suggested!)", SlashCommandOptionType.STRING, False, choices=profiles)])
    # async def auctions(self, ctx : SlashContext, username=None, profile=None):
    #     player = await self.make_player(ctx=ctx, uname=username, profile=profile)
    #     if not player: return
    #     embeds = await Player.get_auctions_embeds(self, ctx=ctx, player=player)
    #     if not embeds:
    #             return await ctx.send(content=f"{player.uname} has no auctions running.")
    #     msg = await ctx.send(embeds=[embeds[0]])
    #     if len(embeds) > 1:
    #         pages = Paginator(self.bot, msg, embeds=embeds, only=ctx.author, use_more=True)
    #         await pages.start()

    async def get_help_embed(self, ctx):
        staff = is_staff(ctx)
        list_embed = Embed(title="Categories", bot=self.bot, user=ctx.author)
        # list_embed.set_author(name=f"Use {ctx.prefix}help [Command/Category]")
        await list_embed.set_requested_by_footer()

        for name, cog in self.bot.cogs.items():
            if name == "Admin" or name == "Help": continue
            if not cog.get_commands(): continue

            commands = []
            for command in cog.get_commands():
                if has_is_staff(command) and not staff: continue
                commands.append(f"`{command.name}`")
            list_embed.add_field(name=name,
                                 value=", ".join(commands),
                                 inline=False)

        list_embed.add_field(
            name="Links",
            value=
            "[Contribute](https://discord.gg/zqRsduD2JN) | [Vote](https://top.gg/bot/630106665387032576/vote) | [Invite the Bot to your server](https://discordapp.com/oauth2/authorize?client_id=630106665387032576&scope=bot&permissions=8) | [Support Server](https://discord.gg/7fPv2uY2Tf) | [Todos](https://trello.com/b/2yBAtx82/skybot-rewrite) | [GitHub repo](https://github.com/Skybot-dev/Skybot-rewrite)",
            inline=False)
        return list_embed

    @cog_ext.cog_slash(name="help",
                       description="List commands and command info.",
                       guild_ids=[636937988248436736])
    async def help(self, ctx: SlashContext):
        await ctx.defer()
        embed = await self.get_help_embed(ctx)
        await ctx.send(embeds=[embed])
Exemplo n.º 4
0
class SlashCommands(commands.Cog):
    """Class to use slash commands in guilds."""
    __slots__ = ("bot")

    def __init__(self, bot):
        self.bot = bot

    @cog_ext.cog_slash(
        name="help",
        description="Shows information about Coronavirus bot",
        options=[
            manage_commands.create_option(
                name="help_type",
                description="Options about how to use the bot",
                option_type=3,
                required=False,
                choices=[
                     manage_commands.create_choice(
                         name="📈Statistics",
                         value="stats"
                     ),
                    manage_commands.create_choice(
                         name="⚙️Bot utilities",
                         value="utilities"
                     )
                ]
            )
        ]
    )
    async def _help(self, ctx: SlashContext, help_type=""):
        await help.help_command(self.bot, ctx, help_type)

    @cog_ext.cog_slash(
        name="getprefix",
        description="Shows current guild prefix"
    )
    async def _getg_prefix(self, ctx: SlashContext):
        await help.get_guild_prefix_command(self.bot, ctx)

    @cog_ext.cog_slash(
        name="setprefix",
        description="Set new prefix for your guild",

    )
    async def _set_prefix(self, ctx: SlashContext, new_prefix):
        await help.setprefix_command(self.bot, ctx, new_prefix)

    @cog_ext.cog_slash(
        name="list",
        description="List all the countries that the bot can find"
    )
    async def _list_countries(self, ctx):
        await data.list_countries_command(self.bot, ctx)

    @cog_ext.cog_slash(
        name="info",
        description="Shows some symbolic numbers about the pandemic"
    )
    async def _info(self, ctx):
        await data.info_command(self.bot, ctx)

    @cog_ext.cog_slash(
        name="country",
        description="Shows information about country.ies"
    )
    async def _country(self, ctx, countries):
        countries = countries.split(" ")
        # TODO: adapt the aux func to avoid split usage
        # temporary fix to use slash commands
        await data.country_command(self.bot, ctx, countries)

    @cog_ext.cog_slash(
        name="stats",
        description="Shows statistics about a country"
    )
    async def _stats(self, ctx, country):
        country = country.split(" ")
        await data.stats_command(self.bot, ctx, country)

    @cog_ext.cog_slash(
        name="notification",
        description="Shows statistics about a country",
        options=[
            manage_commands.create_option(
                name="country",
                description="Country to set the notification for",
                option_type=3,
                required=True
            ),
            manage_commands.create_option(
                name="interval",
                description="Interval between each updates",
                option_type=3,
                required=True
            ),
            manage_commands.create_option(
                name="interval_type",
                description="Interval type",
                option_type=3,
                required=True,
                choices=[
                     manage_commands.create_choice(
                         name="Hours",
                         value="hours"
                     ),
                    manage_commands.create_choice(
                         name="Days",
                         value="days"
                     ),
                    manage_commands.create_choice(
                         name="Weeks",
                         value="weeks"
                     )
                ]
            )
        ]
    )
    async def _notification(self, ctx: SlashContext, country, interval, interval_type):
        logger.info(interval_type)
        await data.notification_command(
            self.bot,
            ctx,
            country=country,
            interval=interval,
            interval_type=interval_type
        )

    @cog_ext.cog_slash(
        name="track",
        description="Track a specific country"
    )
    async def _track(self, ctx, country):
        country = country.split(" ")
        await data.track_command(self.bot, ctx, *country)

    @cog_ext.cog_slash(
        name="region",
        description="Get stats about a region"
    )
    async def _region(self, ctx, country):
        country = country.split(" ")
        await data.region_command(self.bot, ctx, country)

    @cog_ext.cog_slash(
        name="daily",
        description="Daily stats"
    )
    async def _daily(self, ctx, country):
        country = country.split(" ")
        await data.daily_command(self.bot, ctx, *country)

    @cog_ext.cog_slash(
        name="news",
        description="Get the latest news about Covid 19"
    )
    async def _news(self, ctx: SlashContext):
        await data.news_command(self.bot, ctx)
Exemplo n.º 5
0
class Slash(commands.Cog):
    def __init__(self, client):
        self.bot = client

    @cog_ext.cog_slash(name="charts",
                       description='Returns PDF chart for given airport ICAO',
                       options=[
                           manage_commands.create_option(
                               name='icao',
                               description='Required airport ICAO code',
                               option_type=3,
                               required=True)
                       ])
    async def _charts(self, ctx: SlashContext, icao: str):

        # prfx = get_prefix(client=self, message=ctx.message)

        prfx = '/'

        print(f"Requested charts for {icao.upper()}")

        if len(icao) != 4:
            await ctx.send("ICAO code must be composed of 4 characters")
            return

        url = f"http://www.uvairlines.com/admin/resources/{icao.upper()}.pdf"

        request = requests.get(url)

        if request.status_code != 200:
            print(
                f'Failed to retrieve charts for {icao.upper()}, error: {request.status_code}'
            )
            await ctx.send(
                f"Error {request.status_code} while retrieving charts for {icao.upper()}, either the website is down or the airport you chose is not available"
            )
        else:

            charts = discord.Embed(
                title=f"Requested charts for {icao.upper()}",
                description=f"Download or view the charts at: [Link]({url})")
            charts.set_footer(
                text=
                "You can also check the METAR for this airport with `{}metar {}`"
                .format(prfx, icao.upper()))
            charts.set_thumbnail(
                url=
                "https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif"
            )
            await ctx.send(embed=charts)

    @cog_ext.cog_slash(name='metar',
                       description='Fetches METAR for given airport ICAO',
                       options=[
                           manage_commands.create_option(
                               name='icao',
                               description='Required airport ICAO code',
                               option_type=3,
                               required=True)
                       ])
    async def metar(self, ctx: SlashContext, icao: str):

        global gustbool
        if len(icao) != 4:
            await ctx.send("ICAO code must be composed of 4 characters")
            return
        try:
            req = requests.get(
                'https://api.checkwx.com/metar/{}/decoded'.format(icao),
                headers=hdr,
                timeout=5)
        except Exception as err:
            await ctx.send(
                "Timeout error while requesting METAR, API servers are probably offline. Please try again later"
            )
            return print(err)

        print(f"Requested METAR for {icao.upper()}")

        if req.status_code != 200:
            print(
                f"Failed to retrieve METAR for {icao.upper()}, error {req.status_code}"
            )
            return await ctx.send(
                f"Error {req.status_code} while retrieving info for {icao.upper()}, either the website is down or the airport you chose is not available"
            )
        else:

            resp = req.json()

            if resp["results"] == 0:
                await ctx.send(
                    "No results, please check for typos or try a different ICAO"
                )
                return

            # with open('./Utils/wx.json', 'w') as f:
            #     json.dump(resp, f, indent=4)

            layerint = len(resp["data"][0]
                           ["clouds"])  # integer for number of cloud layers

            wxint = 0
            if "conditions" in resp["data"][0]:
                wxint = len(
                    resp["data"][0]["conditions"])  # presence of wx conditions

            visbool = "visibility" in resp["data"][0]  # presence of vis data

            if 'wind' in resp['data'][0]:
                gustbool = "gust_kts" in resp["data"][0][
                    "wind"]  # presence of gusts
                wind_bool = True
            else:
                wind_bool = False

            name = resp["data"][0]["station"]["name"]
            if wind_bool:
                degrees = resp["data"][0]["wind"]["degrees"]
                speed = resp["data"][0]["wind"]["speed_kts"]
            temp = resp["data"][0]["temperature"]["celsius"]
            dew = resp["data"][0]["dewpoint"]["celsius"]
            humidity = resp["data"][0]["humidity"]["percent"]
            inhg = resp["data"][0]["barometer"]["hg"]
            hpa = resp["data"][0]["barometer"]["hpa"]
            obs = resp["data"][0]["observed"]
            cond = resp["data"][0]["flight_category"]
            raw = resp["data"][0]["raw_text"]

            points = []

            lat: float = resp["data"][0]["station"]["geometry"]["coordinates"][
                1]
            long: float = resp["data"][0]["station"]["geometry"][
                "coordinates"][0]

            points.append(tuple([lat, long]))

            marker_outline = CircleMarker((long, lat), 'white', 18)
            marker = CircleMarker((long, lat), '#0036FF', 12)
            icon_flag = IconMarker((long + 0.008, lat),
                                   './Utils/icon-flag.png', 12, 32)

            m = StaticMap(700, 300, 10, 10)
            m.add_marker(marker_outline)
            m.add_marker(marker)
            m.add_marker(icon_flag)

            image = m.render(zoom=8)
            image.save('Utils/metar.png')
            file = discord.File('Utils/metar.png')

            metar = discord.Embed(title="Requested METAR for {} - {}".format(
                icao.upper(), name),
                                  description="Raw: {}".format(raw),
                                  colour=discord.Colour.from_rgb(97, 0, 215))
            if wind_bool:
                if not gustbool:
                    metar.add_field(name="Wind:",
                                    value="{}° at {} kts".format(
                                        degrees, speed))
                else:
                    gust = resp["data"][0]["wind"]["gust_kts"]
                    metar.add_field(name="Wind:",
                                    value="{}° at {} kts, gusts {} kts".format(
                                        degrees, speed, gust))
            else:
                metar.add_field(name="Wind:", value="Calm")

            metar.add_field(name="Temp/Dewpoint:",
                            value="{}°C/ {}°C".format(temp, dew))
            metar.add_field(name="Altimeter:",
                            value="{} hPa/ {} inHg".format(hpa, inhg))
            if visbool:
                vismil = resp["data"][0]["visibility"]["miles"]
                vismet = resp["data"][0]["visibility"]["meters"]
                metar.add_field(name="Visibility:",
                                value="{} meters/ {} miles".format(
                                    vismet, vismil))

            metar.add_field(name="Humidity:", value="{}%".format(humidity))
            metar.set_thumbnail(
                url=
                "https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif"
            )
            metar.set_footer(
                text="Observed at {}. Flight category: {}".format(obs, cond))
            if wxint > 0:
                weather = resp["data"][0]["conditions"][0]["text"]
                metar.add_field(name="Weather condition:",
                                value="{}".format(weather))

            if layerint == 1:
                clouds = resp["data"][0]["clouds"][0]["text"]
                if 'feet' in resp["data"][0]["clouds"][0]:
                    clofeet = resp["data"][0]["clouds"][0]["feet"]
                    metar.add_field(name="Cloud condition:",
                                    value="{}ft {}".format(clofeet, clouds))
                else:
                    metar.add_field(name="Cloud condition:",
                                    value="{}".format(clouds))
            elif layerint == 2:
                clouds = resp["data"][0]["clouds"][0]["text"]
                clofeet = resp["data"][0]["clouds"][0]["feet"]
                clouds1 = resp["data"][0]["clouds"][1]["text"]
                clofeet1 = resp["data"][0]["clouds"][1]["feet"]
                metar.add_field(name="Cloud condition:",
                                value="{}ft {}/ {}ft {}".format(
                                    clofeet, clouds, clofeet1, clouds1))
            elif layerint == 3:
                clouds = resp["data"][0]["clouds"][0]["text"]
                clofeet = resp["data"][0]["clouds"][0]["feet"]
                clouds1 = resp["data"][0]["clouds"][1]["text"]
                clofeet1 = resp["data"][0]["clouds"][1]["feet"]
                clouds2 = resp["data"][0]["clouds"][2]["text"]
                clofeet2 = resp["data"][0]["clouds"][2]["feet"]
                metar.add_field(name="Cloud condition:",
                                value="{}ft {}/ {}ft {}/ {}ft {}".format(
                                    clofeet, clouds, clofeet1, clouds1,
                                    clofeet2, clouds2))
            else:
                metar.add_field(name="Cloud condition:",
                                value="Not Specified / Cloud data error")

            metar.set_image(url='attachment://metar.png')

            await ctx.send(embed=metar, file=file)

    @cog_ext.cog_slash(
        name='flightplan',
        description='Calculates a flight plan between two given airports',
        options=[
            manage_commands.create_option(
                name='dep',
                description='Departure airport ICAO code',
                option_type=3,
                required=True),
            manage_commands.create_option(
                name='arr',
                description='Arrival airport ICAO code',
                option_type=3,
                required=True)
        ])
    async def flightplan(self, ctx: SlashContext, dep='lmfao', arr='lmfao'):

        if len(dep) != 4 or len(arr) != 4:
            await ctx.send(
                'You need to specify two valid airport ICAO codes to create a flight plan'
            )
            return

        # loading = discord.Embed(
        #     title='Your flight plan is loading',
        #     description='Creating flight plan...'
        # )

        # loading.set_thumbnail(
        #     url='https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif')
        # loading.set_footer(text='Using data from the Flight Plan Database (https://flightplandatabase.com)')
        # message = await ctx.send(embed=loading)

        headers = {
            'Content-Type': 'application/json',
            'Authorization': 'Basic ' + fpd_api
        }
        data = '{"fromICAO":"immensecock","toICAO":"giganticpenis"}'
        data = data.replace("immensecock", dep)
        data = data.replace("giganticpenis", arr)
        print(
            f'Requested flight plan: {dep.upper()} to {arr.upper()}, generating...'
        )

        response = requests.post(
            'https://api.flightplandatabase.com/auto/generate',
            headers=headers,
            data=data)
        if response.status_code != 201:
            # await message.delete()
            await ctx.send(
                f"Error {response.status_code} while generating the flight plan, try with different ICAO codes```{response.json()['errors'][0]['message']}```"
            )
            return

        plan = (str(response.json()))[7:14]
        print('Requesting...')

        # loading1 = discord.Embed(
        #     title='Your flight plan is loading',
        #     description='Flight plan created successfully, uploading...'
        # )
        # loading1.set_thumbnail(
        #     url='https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif')
        # loading1.set_footer(text='Using data from the Flight Plan Database (https://flightplandatabase.com)')
        # await message.delete()
        # message1 = await ctx.send(embed=loading1)

        retrieve = requests.get(
            f'https://api.flightplandatabase.com/plan/{plan}')
        if retrieve.status_code != 200:
            # await message1.delete()
            await ctx.send(
                f'There was an error while processing the flight plan: **{retrieve.status_code}**, try with different ICAO codes'
            )
            # self.flightplan.reset_cooldown(ctx)
            return
        print('Received flight plan')

        flp = retrieve.json()
        flpid = flp['id']
        dep_icao = flp['fromICAO']
        arr_icao = flp['toICAO']
        dep_name = flp['fromName']
        arr_name = flp['toName']
        dist = int(flp['distance'])
        cr_alt = flp['maxAltitude']
        wpt_num = flp['waypoints']  # important
        link = f'https://flightplandatabase.com/plan/{flpid}'
        airac = flp['cycle']['ident']

        global fltplan_id

        fltplan_id = flpid

        i = 1
        route = f'***{dep_icao}***'
        route += ' ' + '[SID]'

        while i <= wpt_num:

            if flp['route']['nodes'][i]['ident'] != f'{arr_icao}':

                if flp['route']['nodes'][i]['ident'] == flp['route']['nodes'][
                        i + 1]['ident']:
                    i += 1
                    continue
                elif flp['route']['nodes'][i]['via'] is None:
                    del flp['route']['nodes'][i]['via']
                    flp['route']['nodes'][i]['via'] = {}
                    flp['route']['nodes'][i]['via']['ident'] = 'None'
                    if i != 1:
                        if flp['route']['nodes'][i -
                                                 1]['via']['ident'] == 'None':
                            route += ' ' + '**DCT**' + ' ' + flp['route'][
                                'nodes'][i]['ident']
                        else:
                            route += ' ' + flp['route']['nodes'][i - 1]['ident'] + ' ' + '**DCT**' + ' ' + \
                                     flp['route']['nodes'][i]['ident']
                    else:
                        route += ' ' + flp['route']['nodes'][i]['ident']
                    i += 1
                    continue
                elif flp['route']['nodes'][i]['via']['ident'] != flp['route'][
                        'nodes'][i - 1]['via']['ident']:
                    if flp['route']['nodes'][i - 1]['via']['ident'] == 'None':
                        route += ' ' + '**DCT**' + ' ' + flp['route']['nodes'][i]['ident'] + ' ' + '**' + \
                                 flp['route']['nodes'][i]['via']['ident'] + '**'
                    else:
                        route += ' ' + flp['route']['nodes'][i][
                            'ident'] + ' ' + '**' + flp['route']['nodes'][i][
                                'via']['ident'] + '**'
                    i += 1
                    continue
                else:
                    i += 1
            else:
                route += ' ' + flp['route']['nodes'][
                    i - 1]['ident'] + ' ' + '[STAR]' + ' '
                route += f'***{arr_icao}***'
                break

        base_url = 'https://www.flightplandatabase.com/plan/{fltplan_id}/download/'

        flp_embed = discord.Embed(
            title=f"Here's your flight plan: **{dep_icao} → {arr_icao}**",
            description=f"Flight plan: {route}")
        flp_embed.set_thumbnail(
            url=
            'https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif'
        )
        flp_embed.add_field(name='Departure Airport:', value=dep_name)
        flp_embed.add_field(name='Arrival Airport:', value=arr_name)
        flp_embed.add_field(name='Distance / Cruise Altitude:',
                            value=f'{dist}nm/{cr_alt}ft')
        flp_embed.add_field(
            name='Downloads:',
            value=
            f'[X-PLane 11]({base_url}xplane11) | [X-Plane 10/9]({base_url}xplane) | [FSX]({base_url}fsx) | [FS9]({base_url}fs9) | [PMDG]({base_url}pmdg) | [PDF]({base_url}pdf)'
        )
        flp_embed.add_field(name='Link to full flight plan:', value=link)
        flp_embed.set_footer(
            text=
            f'Using data from the Flight Plan Database (https://flightplandatabase.com), AIRAC Cycle: {airac[3:]}'
        )

        print('Success!')
        # await message1.delete()
        await ctx.send(embed=flp_embed)

    @cog_ext.cog_slash(
        name='checklist',
        description='Returns checklist for supported a aircraft',
        options=[
            manage_commands.create_option(
                name='plane',
                description='Required aircraft ICAO code',
                option_type=3,
                required=False)
        ])
    async def checklist(self, ctx: SlashContext, plane='avail'):

        # prfx = get_prefix(client=self, message=ctx.message)
        prfx = '/'

        if plane == 'avail':
            avplanes = ', '.join(avail_checklists)
            await ctx.send(
                f'Checklists are currenly available for these planes: **{avplanes}**'
            )

        elif len(plane) != 4:
            await ctx.send(
                f"You must input a correct 4 character ICAO code for your plane, check available checklists with {prfx}checklist (empty argument)"
            )
        elif plane.upper() in avail_checklists:
            clfile = discord.File(f'./Utils/Checklists/{plane.upper()}.pdf')
            await ctx.send(
                content=
                f"Here's your requested checklist for the {plane.upper()}:",
                files=[clfile])
        else:
            await ctx.send(
                f"Unfortunately the checklist you requested is not available, check a list of available checklists with {prfx}checklist (empty argument)"
            )

    # @cog_ext.cog_slash(name='download',
    #                    description='Downloads a generated FMS plan in a given format, requires a flight plan to be created (/flightplan)',
    #                    options=[manage_commands.create_option(
    #                        name='sim_type',
    #                        description='Required file format for the flight plan, leave blank for a list of options',
    #                        option_type=3,
    #                        required=False)],
    #                    guild_ids=guild_ids)
    # async def download(self, ctx: SlashContext, sim_type='None'):
    #
    #     # prfx = get_prefix(client=self, message=ctx.message)
    #     prfx = '/'
    #
    #     if fltplan_id == 0:
    #         await ctx.send(f'You need to first create a flight plan with {prfx}flightplan')
    #         return
    #     elif sim_type.lower() not in correct_sim_types:
    #         await ctx.send(
    #             'You need to specify a correct file format, supported formats are: xplane11 [X-Plane 11], xplane [X-Plane 10], fsx [FSX], fs9 [FS2004], pmdg [PMDG], pdf [PDF]')
    #         return
    #     else:
    #         download_embed = discord.Embed(
    #             title=f'Requested flight plan for {sim_type.upper()}',
    #             description=f'To download the file click [here](https://www.flightplandatabase.com/plan/{fltplan_id}/download/{sim_type.lower()})'
    #         )
    #         download_embed.set_thumbnail(
    #             url='https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif')
    #         download_embed.set_footer(text=f'Using data from the Flight Plan Database (https://flightplandatabase.com)')
    #         await ctx.send(embed=download_embed)

    @cog_ext.cog_slash(
        name='info',
        description='Fetches information for given airport ICAO',
        options=[
            manage_commands.create_option(
                name='icao',
                description='Required airport ICAO code',
                option_type=3,
                required=True)
        ])
    @commands.command()
    async def info(self, ctx: SlashContext, icao: str = 'NO INPUT'):

        await ctx.defer()

        if len(icao) != 4:
            await ctx.send("Please input a correct ICAO code")
            return

        request = requests.get(
            f'https://api.flightplandatabase.com/nav/airport/{icao.upper()}')

        if request.status_code != 200:
            print(
                f'Failed to fetch info for {icao.upper()}, error {request.status_code}'
            )
            return await ctx.send(
                f"Error {request.status_code} while retrieving info for {icao.upper()}, either the website is down or the airport you chose is not available  ```{request.json()['message']}```"
            )

        else:
            info = request.json()
            # with open('./Utils/info.json', 'w') as f:
            #     json.dump(info, f, indent=4)

            json_icao = info['ICAO']
            iata = info['IATA']
            name = info['name']
            lat: float = info["lat"]
            lon: float = info["lon"]
            runway_int = info['runwayCount']
            elevation = int(info['elevation'])
            mag_var = round(info['magneticVariation'], 2)
            timezone = info['timezone']['name']
            metar = info['weather']['METAR']
            taf = info['weather']['TAF']

            offset = str(info['timezone']['offset'] / 3600)
            offset = offset.replace('.', ':')
            offset += '0'
            if -10 < info['timezone']['offset'] / 3600 < 10:
                if '-' not in offset:
                    offset = '+0' + offset
                else:
                    offset = list(offset)
                    del offset[0]
                    offset = "".join(offset)
                    offset = '-0' + offset
            if '-' not in offset and '+' not in offset:
                offset = '+' + offset
            offset = list(offset)
            if len(offset) == 7:
                del offset[6]
            if offset[4] != 0:
                if offset[4] == '5':
                    offset[4] = '3'
                elif offset[4] == '7':
                    offset[4] = '4'
            offset = "".join(offset)

            epoch = datetime.datetime.now().timestamp()
            local = epoch + info['timezone']['offset']
            utc = datetime.datetime.fromtimestamp(epoch).strftime(
                '%d-%m-%Y %H:%M:%S')
            local = datetime.datetime.fromtimestamp(local).strftime(
                '%d-%m-%Y %H:%M:%S')

            marker_outline = CircleMarker((lon, lat), 'white', 18)
            marker = CircleMarker((lon, lat), '#0036FF', 12)
            m = StaticMap(
                500,
                300,
                10,
                10,
                url_template=
                'https://tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png')
            m.add_marker(marker_outline)
            m.add_marker(marker)

            image = m.render(zoom=13)
            image.save('Utils/info.png')

            info_embed = discord.Embed(title=f'{json_icao} - {iata}',
                                       description=name,
                                       colour=discord.Colour.from_rgb(
                                           97, 0, 215))

            runways = ''

            i = 0
            # j = 0

            if runway_int == 1:
                runways += f"{info['runways'][i]['ends'][0]['ident']} / {info['runways'][i]['ends'][1]['ident']}"
                len_width = f"{int(info['runways'][0]['length'])}ft x {int(info['runways'][0]['width'])}ft"
                hdg = int(info['runways'][0]['bearing'])
                if hdg + 180 > 360:
                    rwy_hdg = f'{hdg} - {hdg - 180}'
                else:
                    rwy_hdg = f'{hdg}°/{hdg + 180}°'
                info_embed.add_field(name='Runways:', value=runways)
                info_embed.add_field(name='Airport Elevation:',
                                     value=f'{str(elevation)}ft')
                info_embed.add_field(name='Magnetic Variation:',
                                     value=f'{str(mag_var)}°')
                info_embed.add_field(name='Timezone:',
                                     value=f'{offset} UTC, {timezone}')
                # for ils in info['runways'][i]['navaids']:
                #     if ils == "LOC-ILS":
                #         print(info['runways'][i]['navaids'][j]['name'])
                #         break
                #     else:
                #         j += 1
                img = Image.open('Utils/info.png')
                draw = ImageDraw.Draw(img)
                font = ImageFont.truetype('./Utils/font.ttf', 25)
                draw.text((0, 275),
                          f'{runways} - {len_width} - {rwy_hdg}',
                          fill=(0, 0, 0),
                          font=font)
                img.save('Utils/info_done.png')
            else:
                img = Image.open('Utils/info.png')
                draw = ImageDraw.Draw(img)
                font = ImageFont.truetype('./Utils/font.ttf', 20)
                while i < runway_int:
                    px = 280 - i * 19
                    curr_rwy = f"{info['runways'][i]['ends'][0]['ident']} / {info['runways'][i]['ends'][1]['ident']}"
                    runways += f"{info['runways'][i]['ends'][0]['ident']} / {info['runways'][i]['ends'][1]['ident']} - "
                    len_width = f"{int(info['runways'][i]['length'])}ft x {int(info['runways'][i]['width'])}ft"

                    draw.text((0, px),
                              f'{curr_rwy} - {len_width}', (0, 0, 0),
                              font=font)
                    i += 1
                info_embed.add_field(name='Runways:', value=runways[:-3])
                info_embed.add_field(name='Airport Elevation:',
                                     value=f'{str(elevation)}ft')
                info_embed.add_field(name='Magnetic Variation:',
                                     value=f'{str(mag_var)}°')
                info_embed.add_field(name='Timezone:',
                                     value=f'{offset} UTC, {timezone}')
                img.save('Utils/info_done.png')

            info_embed.add_field(name='Zulu/Local Time:',
                                 value=f'Zulu: {utc}\nLocal: {local}')
            info_embed.add_field(name='METAR:', value=metar)
            info_embed.add_field(name='TAF:', value=taf)

            info_embed.set_image(url='attachment://info_done.png')
            info_embed.set_footer(
                text=
                f'Using data from the Flight Plan Database (https://flightplandatabase.com), check the full weather for this airport with /metar {icao.upper()}'
            )

            file = discord.File('Utils/info_done.png')

            await ctx.send(embed=info_embed, file=file)

    @cog_ext.cog_slash(name='notam',
                       description='Fetches NOTAMs for given airport ICAO',
                       options=[
                           manage_commands.create_option(
                               name='icao',
                               description='Required airport ICAO code',
                               option_type=3,
                               required=True),
                           manage_commands.create_option(
                               name='page',
                               description='Required airport ICAO code',
                               option_type=4,
                               required=False)
                       ])
    @commands.command()
    async def notam(self, ctx: SlashContext, icao: str = 'NO INPUT', page=1):

        if len(icao) != 4:
            return await ctx.send("Please input a correct ICAO code")

        if not isinstance(page, int):
            return await ctx.send('Please insert a number for the embed page')

        request = requests.get(
            f'https://api.autorouter.aero/v1.0/notam?itemas=["{icao.upper()}"]&offset=0&limit=200'
        )

        if request.status_code != 200:
            print(
                f'Failed to fetch info for {icao.upper()}, error {request.status_code}'
            )
            return await ctx.send(
                f"Error {request.status_code} while retrieving NOTAMs for {icao.upper()}, either the website is down or the airport you chose is not available"
            )

        else:

            notam = request.json()

            notamemb = discord.Embed(
                title=f'NOTAM list for **{icao.upper()}**',
                description=f"Number of active NOTAMs: {notam['total']}",
                colour=discord.Colour.from_rgb(97, 0, 215))

            # with open('./Utils/notam.json', 'w') as f:
            #     json.dump(notam, f, indent=4)

            total = notam['total']

            numb = 0
            page -= 1
            i = page * 5

            for _ in notam['rows']:
                numb += 1

            total_pages = math.ceil(total / 5)

            if total_pages == 0:
                return await ctx.send(
                    f'No NOTAMs were found for {icao.upper()}!')

            if page + 1 > total_pages:
                return await ctx.send(
                    f'Please select a page number between 1 and {total_pages}')

            try:
                while page * 5 <= i < (page * 5) + 5:
                    lon = (notam['rows'][i]['lon'] * 90) / (1 << 30)
                    lat = (notam['rows'][i]['lat'] * 90) / (1 << 30)
                    radius = str(notam['rows'][i]['radius'])
                    lon_str = str(int(abs(lon)))
                    lat_str = str(int(abs(lat)))

                    if len(radius) < 3:
                        radius = '0' + radius
                        if len(radius) < 3:
                            radius = '0' + radius

                    if len(lon_str) == 2:
                        lon_str = '0' + lon_str
                    elif len(lon_str) == 1:
                        lon_str = '00' + lon_str

                    elif len(lat_str) == 1:
                        lat_str = '0' + lat_str

                    if lon < 0:
                        lon = abs(lon)
                        lon_str += str(int(round((lon - int(lon)) * 60, 0)))
                        lon_str += 'W'
                    else:
                        lon_str += str(int(round((lon - int(lon)) * 60, 0)))
                        lon_str += 'E'

                    if lat < 0:
                        lat = abs(lat)
                        lat_str += str(int(round((lat - int(lat)) * 60, 0)))
                        lat_str += 'S'
                    else:
                        lat_str += str(int(round((lat - int(lat)) * 60, 0)))
                        lat_str += 'N'

                    coordinates = lat_str + lon_str + radius

                    first_line = str(notam['rows'][i]['series']) + str(
                        notam['rows'][i]['number']) + '/' + str(
                            notam['rows'][i]['year']) + ' ' + 'NOTAM' + str(
                                notam['rows'][i]['type']) + ' '

                    if notam['rows'][i]['lower'] == 0:
                        notam['rows'][i]['lower'] = '000'

                    line_q = 'Q) ' + notam['rows'][i]['fir'] + '/' + notam['rows'][i]['code23'] + notam['rows'][i][
                        'code45'] + '/' + notam['rows'][i]['traffic'] + '/' + notam['rows'][i]['purpose'] + '/' + \
                             notam['rows'][i]['scope'] + '/' + str(notam['rows'][i]['lower']) + '/' + str(
                        notam['rows'][i]['upper']) + '/' + coordinates

                    if notam['rows'][i]['estimation'] is not None:
                        line_abc = f'A) {icao.upper()}' + '    B) ' + datetime.datetime.fromtimestamp(
                            notam['rows'][i]['startvalidity']).strftime(
                                '%Y-%m-%d %H:%M'
                            ) + '    C) ' + datetime.datetime.fromtimestamp(
                                notam['rows'][i]['endvalidity']).strftime(
                                    '%Y-%m-%d %H:%M'
                                ) + ' ' + notam['rows'][i]['estimation']
                    else:
                        line_abc = f'A) {icao.upper()}' + '    B) ' + datetime.datetime.fromtimestamp(
                            notam['rows'][i]['startvalidity']).strftime(
                                '%Y-%m-%d %H:%M'
                            ) + '    C) ' + datetime.datetime.fromtimestamp(
                                notam['rows'][i]['endvalidity']).strftime(
                                    '%Y-%m-%d %H:%M')

                    if notam['rows'][i]['referredseries'] is not None:
                        first_line += str(
                            notam['rows'][i]['referredseries']) + str(
                                notam['rows'][i]['referrednumber']
                            ) + '/' + str(notam['rows'][i]['referredyear'])

                    notamemb.add_field(
                        name=
                        f"{notam['rows'][i]['id']} | Modified at {datetime.datetime.fromtimestamp(notam['rows'][i]['modified']).strftime('%Y-%m-%d %H:%M')}",
                        value=f'{first_line}\n'
                        f'{line_q}\n'
                        f'{line_abc}\n'
                        f"E) {notam['rows'][i]['iteme']}",
                        inline=False)
                    i += 1

            except IndexError:
                print('index')

            notamemb.set_thumbnail(
                url=
                'https://cdn.discordapp.com/attachments/356779184393158657/729351510974267513/plane-travel-icon-rebound2.gif'
            )
            notamemb.set_footer(
                text=
                f'Page {page + 1} of {total_pages}, use /notam {icao.upper()} [page number] to select different pages'
            )

            try:
                await ctx.send(embed=notamemb)
            except discord.HTTPException:
                await ctx.send(
                    f'Unfortunately this page has more characters than the max allowed limit of 2000, please try with a different ICAO or a different page'
                )

    @cog_ext.cog_slash(
        name='simbrief',
        description='Returns the last flight plan created in SimBrief',
        options=[
            manage_commands.create_option(name='username',
                                          description='Your username',
                                          option_type=3,
                                          required=True)
        ])
    async def simbrief(self, ctx: SlashContext, username: str):

        request = requests.get(
            f'https://www.simbrief.com/api/xml.fetcher.php?username={username}&json=1'
        )
        if request.status_code == 400:
            print(
                f'Failed to fetch latest flight plan for {username}, error {request.status_code}'
            )
            error = request.json()
            return await ctx.send(
                f"Error {request.status_code} while retrieving flight plan for {username}, make sure you entered a correct username  ```{error['fetch']['status']}```"
            )

        else:

            info = request.json()
            # with open('./Utils/simbrief.json', 'w') as f:
            #     json.dump(info, f, indent=4)
            # print(info)

            i = 0
            toc = False

            for _ in info:
                if info['navlog']['fix'][i]['name'] == 'TOP OF CLIMB':
                    toc = True
                    break
                else:
                    i += 1

            desc = f"Generated at: **{datetime.datetime.fromtimestamp(int(info['params']['time_generated'])).strftime('%H:%M %Y-%m-%d')}**  | AIRAC: **{info['params']['airac']}** | Units: **{info['params']['units']}**\n\n" \
                   f"FL STEPS: **{info['general']['stepclimb_string']}**\n\n" \
                   f"ROUTE: **{info['origin']['icao_code']}/{info['origin']['plan_rwy']}** {info['general']['route']} **{info['destination']['icao_code']}/{info['destination']['plan_rwy']}**"

            fuel = f"TRIP           {info['fuel']['enroute_burn']}\n" \
                   f"CONT           {info['fuel']['contingency']}\n" \
                   f"ALTN           {info['fuel']['alternate_burn']}\n" \
                   f"FINRES         {info['fuel']['reserve']}\n" \
                   f"EXTRA          {info['fuel']['extra']}\n" \
                   f"TAXI           {info['fuel']['taxi']}\n" \
                   f"BLOCK FUEL     {info['fuel']['plan_ramp']}\n"

            payload = f"PAX         {info['weights']['pax_count']}\n" \
                      f"CARGO       {round((int(info['weights']['cargo']) / 1000), 1)}\n" \
                      f"PAYLOAD     {round((int(info['weights']['payload']) / 1000), 1)}\n" \
                      f"ZFW         {round((int(info['weights']['est_zfw']) / 1000), 1)}\n" \
                      f"FUEL        {round((int(info['fuel']['plan_ramp']) / 1000), 1)}\n" \
                      f"TOW         {round((int(info['weights']['est_tow']) / 1000), 1)}\n" \
                      f"LAW         {round((int(info['weights']['est_ldw']) / 1000), 1)}\n"
            if toc:
                general = f"Cost Index:         {info['general']['cruise_profile']}\n" \
                          f"Route Distance:     {info['general']['route_distance']}nm\n" \
                          f"Average Wind:       {info['general']['avg_wind_dir']}°/{info['general']['avg_wind_comp']}kt\n" \
                          f"Aircraft:           {info['aircraft']['name']}\n" \
                          f"Est. Time Enroute:  {round((int(info['times']['est_time_enroute']) / 3600), 2)}hrs\n" \
                          f"TOC Conditions:     {info['navlog']['fix'][i]['wind_dir']}°/{info['navlog']['fix'][i]['wind_spd']}kt | OAT: {info['navlog']['fix'][i]['oat']} | ISA DEV: {info['navlog']['fix'][i]['oat_isa_dev']}\n"
            else:
                general = f"Cost Index:         {info['general']['cruise_profile']}\n" \
                          f"Route Distance:     {info['general']['route_distance']}\n" \
                          f"Average Wind:       {info['general']['avg_wind_dir']}°/{info['general']['avg_wind_comp']}kt\n" \
                          f"Aircraft:           {info['aircraft']['name']}\n" \
                          f"Est. Time Enroute:  {info['times']['est_time_enroute']}\n"

            directory = info['files']['directory']
            files = f"[X-Plane 11]({directory}{info['fms_downloads']['xpe']['link']}) | [MSFS 2020]({directory}{info['fms_downloads']['mfs']['link']}) | " \
                    f"[FSX/P3D]({directory}{info['fms_downloads']['fsx']['link']}) | [PMDG]({directory}{info['fms_downloads']['pmr']['link']})"

            sb_embed = discord.Embed(
                title=
                f"Retrieved SimBrief flight plan: **{info['origin']['icao_code']} → {info['destination']['icao_code']}**  ALTN: {info['alternate']['icao_code']}",
                description=desc,
                colour=discord.Colour.from_rgb(97, 0, 215))

            # sb_embed.set_thumbnail(
            #     url="https://cdn.discordapp.com/attachments/651086904925749252/802617703809548298/ezgif.com-gif-maker_3.gif")
            sb_embed.set_footer(
                text=
                'If you prefer to keep your username private, you can use this command in a private chat'
            )
            sb_embed.add_field(name='Fuel:', value=fuel)
            sb_embed.add_field(name='Weights:', value=payload)
            sb_embed.add_field(name='Info:', value=general)
            sb_embed.add_field(name='Departure METAR:',
                               value=info['weather']['orig_metar'],
                               inline=False)
            sb_embed.add_field(name='Destination METAR:',
                               value=info['weather']['dest_metar'],
                               inline=False)
            sb_embed.add_field(name='FMC Files:', value=files, inline=False)
            try:
                sb_embed.set_image(
                    url=
                    f"{info['images']['directory']}{info['images']['map'][0]['link']}"
                )
            except Exception as err:
                print(err)
            await ctx.send(embed=sb_embed)
            return print('Sent SimBrief flight plan')
Exemplo n.º 6
0
class RussianRoulette(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    def players_description(self, players):
        desc = "\n"
        for i, player in enumerate(players, start=1):
            desc += f"{i}. {str(player.member)}\n"
        return desc

    async def handle_reactions(self, ctx: SlashContext, msg: discord.Message,
                               player: discord.Member):
        try:
            reaction, user = await self.bot.wait_for(
                "reaction_add",
                check=lambda react, usr: react.message.id == msg.id and usr ==
                player,
                timeout=30)

            kill_decision = EmojiUtils.get_emoji_value(reaction.emoji)
            return kill_decision
        except asyncio.TimeoutError:
            # Gdy nie zdąży dodać reakcji - 30 sekund
            await ctx.send(embed=discord.Embed(
                title="⏰ Upływ czasu ⏰",
                description=
                f"{player.mention} nie zdążył strzelić!\nZa kare dostał kulkę od barmana",
                color=discord.Color.red()))
            return -1

    @cog_ext.cog_slash(name="rr",
                       description="Rosyjska ruletka",
                       guild_ids=guild_ids,
                       options=[
                           manage_commands.create_option(
                               name="bet",
                               description="Wartość zakładu",
                               option_type=SlashCommandOptionType.INTEGER,
                               required=True)
                       ])
    async def __rr(self, ctx: SlashContext, bet: int):
        if bet <= 0:
            return

        start_embed = discord.Embed(
            title="Rosyjska ruletka",
            description=
            f"Czy podejmiesz się wyzwaniu?\nKliknij 🔫 aby dołączyć\n🏁 aby wystartować\nKoszt wstępu: `{bet}` chillcoinsów",
            color=discord.Color.red())

        start_embed.set_image(url=self.bot.user.avatar_url)
        start_embed.set_footer(
            text=f"Komenda wyłołana przez {ctx.author.name}",
            icon_url=ctx.author.avatar_url)

        start_message: discord.Message = await ctx.send(embed=start_embed)
        await start_message.add_reaction("🔫")
        await start_message.add_reaction("🏁")

        try:
            await self.bot.wait_for(
                "reaction_add",
                check=lambda react, usr: usr == ctx.author and str(react.emoji)
                == "🏁" and react.message.id == start_message.id,
                timeout=120)
        except asyncio.TimeoutError:
            await ctx.send(embed=discord.Embed(
                title="Upływ czasu",
                description=
                f"Upłynął czas na dodanie 🏁 przez {ctx.author.name}",
                color=discord.Color.red()),
                           delete_after=20)
            await start_message.delete()

        start_message: discord.Message = await ctx.fetch_message(
            start_message.id)

        players: List[Player] = [
            Player(player)
            for player in await start_message.reactions[0].users().flatten()
            if player.display_name != self.bot.user.display_name
        ]

        if len(players) <= 1:
            return

        for player in players:
            member: TeinfMember = db_session.query(TeinfMember).filter_by(
                discordId=player.id).first()
            money = member.money
            if money < bet:
                players.remove(player)
                await player.member.send(
                    "Niestety nie możesz zagrać w rosyjską ruletkę - masz za mało pieniędzy! - {}"
                    .format(money))
            else:
                member.money -= bet

        if len(players) <= 1:
            return

        random.shuffle(players)

        start_players_amount = len(players)
        revolver = Gun(ctx)
        while len(players) > 1:
            for player in players:
                embed = discord.Embed(
                    title="🤔 Wybór 🤔",
                    description=
                    f"{player.member.mention}\n1. Strzał w siebie\n2. Strzał w innego",
                    color=discord.Color.purple())

                embed.set_footer(text=f"{str(player.member)}",
                                 icon_url=player.member.avatar_url)

                msg = await ctx.send(embed=embed, delete_after=20)
                await EmojiUtils.add_digits(msg, 2)

                kill_decision = await self.handle_reactions(
                    ctx, msg, player.member)

                if kill_decision == -1:
                    players.remove(player)

                elif kill_decision == 1:
                    # strzelanie w siebie
                    target = player
                    target_killed = await player.shot(ctx,
                                                      target,
                                                      revolver,
                                                      self_shot=True)
                    if target_killed:
                        players.remove(target)

                elif kill_decision == 2:
                    message = await ctx.send(embed=discord.Embed(
                        title="Strzał!",
                        description=
                        f"{player.member.mention} wybierz osobę w którą chcesz strzelić"
                        + self.players_description(players),
                        color=discord.Color.green()))

                    await EmojiUtils.add_digits(message, len(players))
                    response = await self.handle_reactions(
                        ctx, message, player.member)

                    target = players[response - 1]
                    target_killed = await player.shot(ctx, target, revolver)

                    if not target_killed:
                        await ctx.send(embed=discord.Embed(
                            title="Strzał w siebie",
                            description=
                            f"{player.member.mention} niestety teraz musisz strzelać do siebie...",
                            color=discord.Color.red()))

                        target = player
                        target_killed = await player.shot(ctx,
                                                          target,
                                                          revolver,
                                                          self_shot=True)
                        if target_killed:
                            players.remove(target)

                    else:
                        players.remove(target)

        winning_player = players[0]

        embed = discord.Embed(
            title="🏆 Wygrana! 🏆",
            description=f"Gratulacje {winning_player} wygrałeś rozgrywkę!",
            color=discord.Color.green())

        money_gained = start_players_amount * bet
        exp_gained = money_gained // 2
        embed.set_footer(text=f"+{money_gained}cc, +{exp_gained}exp")
        await ctx.send(embed=embed)

        winning_player: TeinfMember = db_session.query(TeinfMember).filter_by(
            discordId=winning_player.id).first()
        winning_player.money += money_gained
        winning_player.exp += exp_gained
Exemplo n.º 7
0
class Music(commands.Cog):
    def __init__(self, bot: commands.Bot):
        global pillow_installed  # aiya
        global eyed3_installed  # aiya x2

        self.bot = bot
        self.log = bot.log
        self.voice_state = VoiceState(self.bot)

        # read configuration
        self.log.debug("Reading music configuration")
        if "music" in bot.config.config:
            conf = bot.config.config["music"]
            self.root_path = conf.get("MusicPath", fallback="/media/Moosic")
            self.show_song_status = conf.getboolean(
                "CurrentSongAsStatus", fallback=False
            )
            ignored_paths = conf.get("IgnoredPaths", fallback="").split(",")
            self.ignored_paths = ignored_paths if ignored_paths[0] != "" else []

            pillow_installed = conf.getboolean("DominantColorEmbed", pillow_installed)
            eyed3_installed = conf.getboolean("Id3Metadata", eyed3_installed)
        else:
            self.root_path = "/media/Moosic"
            self.show_song_status = False

        # process all songs
        self.get_files()

    def get_files(self):
        self.songs = []
        self.log.info(f"Searching for songs from {self.root_path}.")
        ignored: int = 0
        for root, _, files in os.walk(self.root_path):
            for name in files:
                if name.endswith(".mp3"):
                    for query in self.ignored_paths:
                        if query in root:
                            ignored += 1
                            break
                    else:
                        try:
                            self.songs.append(Song(os.path.join(root, name), self.log))
                        except IOError:
                            # expected if file not found
                            pass

        self.log.info(f"Found {len(self.songs)} songs, ignored {ignored}.")

    async def get_voice_state(self, ctx):
        await self.voice_state.connect(ctx)

    def find_songs(self, query) -> list:
        args = query.lower().split()
        sources = []
        for song in self.songs:
            for q in args:
                if not (q in song.path_lower or q in song.get_name().lower()):
                    break
            else:
                sources.append(song)
        return sources

    @cog_ext.cog_slash(
        name="play",
        description="Play a moosic",
        options=[
            manage_commands.create_option(
                name="query",
                description="Tags to search for",
                option_type=3,
                required=False,
            ),
            manage_commands.create_option(
                name="number",
                description="Song number from search, or 0 for all songs that match search",
                option_type=4,
                required=False,
            ),
        ],
        guild_ids=DEBUG_GUILDS,
    )
    @commands.command()
    async def play(
        self,
        ctx,
        query="",
        number: int = 1,
        play_random: bool = False,
        show_lyrics: bool = True,
    ):
        await self._play(ctx, query, number, play_random, show_lyrics)

    async def _play(
        self,
        ctx,
        query="",
        number: int = 1,
        play_random: bool = False,
        show_lyrics: bool = True,
        return_to_function: bool = False,
    ) -> list:
        # treat numbers <= 0 as play all
        play_all = number <= 0
        if query and not play_random:
            # if there is a query
            try:
                sources = self.find_songs(query)
                if not play_all:
                    sources = [sources[number - 1]]
            except IndexError:
                return await ctx.send(
                    f"No songs matching '{query}' were found at the specified index."
                )
        else:
            # if query is empty play a random song
            if play_all:
                sources = self.songs.copy()
            else:
                sources = [random.choice(self.songs)]

        # if there's only one it doesn't matter if more we want to shuffle them
        random.shuffle(sources)

        try:
            await self.get_voice_state(ctx)
        except AttributeError:
            print(traceback.format_exc())
            return await ctx.send("You are not in a voice channel.")

        if return_to_function:
            return sources

        for s in sources:
            await self.voice_state.add(s, lyrics=show_lyrics)

        if len(sources) > 1:
            await ctx.send(f"Added {len(sources)} songs to the queue.")
        else:
            await ctx.send(f"Added **{sources[0].get_name()}** to the queue.")

    @cog_ext.cog_slash(
        name="playnow",
        description="Play a moosic now",
        options=[
            manage_commands.create_option(
                name="query",
                description="Tags to search for",
                option_type=3,
                required=False,
            ),
            manage_commands.create_option(
                name="number",
                description="Song number from search, or 0 for all songs that match search",
                option_type=4,
                required=False,
            ),
        ],
        guild_ids=DEBUG_GUILDS,
    )
    @commands.command(name="playnow")
    async def play_now(
        self,
        ctx,
        query="",
        number: int = 1,
        play_random: bool = False,
        show_lyrics: bool = True,
    ):
        sources = await self._play(
            ctx, query, number, play_random, show_lyrics, return_to_function=True
        )
        for s in sources:
            await self.voice_state.add(s, True, show_lyrics)
        if len(sources) > 1:
            await ctx.send(
                f"Playing **{sources[0].get_name()}**, added {len(sources)-1} songs to the queue."
            )
        else:
            await ctx.send(f"Playing **{sources[0].get_name()}**.")
        await self.voice_state.skip()

    @cog_ext.cog_slash(
        name="playnext",
        description="Play a moosic right after",
        options=[
            manage_commands.create_option(
                name="query",
                description="Tags to search for",
                option_type=3,
                required=False,
            ),
            manage_commands.create_option(
                name="number",
                description="Song number from search, or 0 for all songs that match search",
                option_type=4,
                required=False,
            ),
        ],
        guild_ids=DEBUG_GUILDS,
    )
    async def play_next(
        self,
        ctx,
        query="",
        number: int = 1,
        play_random: bool = False,
        show_lyrics: bool = True,
    ):
        sources = await self._play(
            ctx, query, number, play_random, show_lyrics, return_to_function=True
        )
        for s in sources:
            await self.voice_state.add(s, True, show_lyrics)
        if len(sources) > 1:
            await ctx.send(f"Added {len(sources)} songs to the queue.")
        else:
            await ctx.send(f"Added **{sources[0].get_name()}** to the queue.")

    @cog_ext.cog_slash(
        name="skip",
        description="Skip a number of tracks (default 1)",
        options=[
            manage_commands.create_option(
                name="number",
                description="The number of tracks to skip / the track number to skip to",
                option_type=4,
                required=False,
            )
        ],
        guild_ids=DEBUG_GUILDS,
    )
    async def skip(self, ctx, number: int = 1):
        await self.voice_state.skip(number)
        await ctx.send("Skipped track.")

    @cog_ext.cog_slash(
        name="search",
        description="Searches local files for music",
        options=[
            manage_commands.create_option(
                name="query",
                description="Query to search for in tags",
                option_type=3,
                required=True,
            ),
            manage_commands.create_option(
                name="page",
                description="Page number to show",
                option_type=4,
                required=False,
            ),
        ],
        guild_ids=DEBUG_GUILDS,
    )
    async def search(self, ctx, query, page: int = 1):
        page -= 1
        sources = self.find_songs(query)
        offset = page * ITEMS_PER_PAGE
        if len(sources) < offset:
            return await ctx.send(f"Page not found for query '{query}'.")

        embed = discord.Embed(title=f"Moosic containing '{query}'", description="")
        for i, n in enumerate(sources[offset : offset + ITEMS_PER_PAGE]):
            embed.description += (
                f"{offset+i+1}. {n.get_name()}{' [LRC]' if n.lyrics else ''}\n"
            )
        embed.description += (
            f"\nPage {page+1} of {math.ceil(len(sources) / ITEMS_PER_PAGE)}"
        )
        await ctx.send(embed=embed)

    @cog_ext.cog_slash(
        name="stop",
        description="Stop playback and disconnect",
        options=[],
        guild_ids=DEBUG_GUILDS,
    )
    async def stop(self, ctx):
        await self.voice_state.stop()
        await ctx.send("Goodbye!")

    @cog_ext.cog_slash(
        name="clear", description="Clear the queue", options=[], guild_ids=DEBUG_GUILDS
    )
    async def clear_queue(self, ctx):
        self.voice_state.queue.clear()
        await ctx.send("Cleared the queue!")

    @cog_ext.cog_slash(
        name="queue",
        description="Show the queue",
        options=[
            manage_commands.create_option(
                name="page",
                description="The page number to view",
                option_type=4,
                required=False,
            )
        ],
        guild_ids=DEBUG_GUILDS,
    )
    async def show_queue(self, ctx, page: int = 1):
        page -= 1
        if len(self.voice_state.queue) < 1:
            return await ctx.send("Nothing in the queue on this page.")
        offset = page * ITEMS_PER_PAGE
        embed = discord.Embed(title="Queue", description="")
        for i, s in enumerate(self.voice_state.queue[offset : offset + ITEMS_PER_PAGE]):
            embed.description += (
                f"{offset+i+1}. {s[0].get_name()}{' [LRC]' if s[0].lyrics else ''}\n"
            )
        embed.description += f"\nPage {page+1} of {math.ceil(len(self.voice_state.queue) / ITEMS_PER_PAGE)}"
        await ctx.send(embed=embed)
Exemplo n.º 8
0
class Admin(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command(brief='Turns on/off my Master\'s PC')
    async def power(self, ctx, arg=None):
        await self._power(ctx, arg)

    @cog_ext.cog_slash(
        name="power",
        description='Turns on/off my Master\'s PC',
        #guild_ids=[207481917975560192, 572648167573684234],
        options=[
            manage_commands.create_option(
                name="arg",
                description="\"on\" to switch on, \"off\" to switch off",
                option_type=3,
                required=True,
                choices=[
                    create_choice(name="On", value="on"),
                    create_choice(name="Off", value="off")
                ]),
        ],
    )
    async def powers(self, ctx: SlashContext, arg: str):
        await self._power(ctx, arg)

    async def _power(self, ctx, arg: str):
        logger.debug("PRE: {}".format(ctx))
        try:
            if not arg:
                if isinstance(ctx, discord.ext.commands.context.Context):
                    await ctx.send('```Usage:(ADMIN ONLY)\n'
                                   '{}power on : to switch on PC\n'
                                   '{}power off : to shutdown PC\n```'.format(
                                       COMMAND_PREFIX, COMMAND_PREFIX))

            elif arg.lower() == "on":
                if ctx.author.id == int(ADMIN_ID):
                    ''' api way '''
                    '''
                    session = aiohttp.ClientSession()
                    data = {"action": "on"}
                    api_path = os.path.join(ROOT_DIR, "keys/api")
                    try:
                        
                        # read API endpoint from file
                        # with open(api_path) as f:
                        #    pc_api = f.read().strip()
                        # res = await session.post(pc_api, data=json.dumps(data), headers={'content-type': 'application/json'})
                        # await session.close()
        
                        await ctx.send('```Done```')
                    except Exception as e:
                        logger.exception(e)
                    '''
                    ''' direct call '''
                    master_mac_path = os.path.join(ROOT_DIR, "keys/master_mac")
                    with open(master_mac_path) as f:
                        master_mac = f.read().strip()
                    logger.debug("Powering on PC")
                    os.system("wakeonlan {}".format(master_mac))
                    await ctx.send("```Powering on PC```")
                else:
                    await ctx.send("```Only my master can use this command```")

            elif arg.lower() == "off":
                admin_id_path = os.path.join(ROOT_DIR, "keys/admin_id")
                with open(admin_id_path) as f:
                    admin_id = f.read().strip()
                if ctx.author.id == int(admin_id):
                    master_ip_path = os.path.join(ROOT_DIR, "keys/master_ip")
                    with open(master_ip_path) as f:
                        master_ip = f.read().strip()
                    logger.debug("Shutting down PC")
                    os.system("ssh preetham@{} shutdown /s".format(master_ip))
                    await ctx.send('```Shutting down PC```')
                else:
                    await ctx.send('```Only my master can use this command.```'
                                   )
            else:
                await ctx.send('```Invalid entry```')
                if isinstance(ctx, discord.ext.commands.context.Context):
                    await ctx.send('```Usage:(ADMIN ONLY)\n'
                                   '{}power on : to switch on PC\n'
                                   '{}power off : to shutdown PC\n```'.format(
                                       COMMAND_PREFIX, COMMAND_PREFIX))
        except Exception as e:
            logger.exception(e)
            await ctx.send('```Zzzzz```')

    @commands.command(brief='', hidden=True)
    async def post(self, ctx, *args):
        if args[0] == 'gb':
            channel = self.bot.get_channel(TEST2_CHANNEL_ID)
            message = ' '.join(args[1:])
        elif args[0] == 'test':
            channel = self.bot.get_channel(TEST_CHANNEL_ID)
            message = ' '.join(args[1:])
        else:
            channel = self.bot.get_channel(GENERAL_CHANNEL_ID)
            message = ' '.join(args)
        logger.debug("{} {}".format(len(args), message))
        await channel.send(message)

    @commands.command(brief='Shows my host hardware-software info')
    async def sysinfo(self, ctx):
        await self._sysinfo(ctx)

    @cog_ext.cog_slash(
        name="sysinfo",
        description='Shows my host hardware-software info',
        #guild_ids=[207481917975560192, 572648167573684234],
    )
    async def sysinfos(self, ctx: SlashContext):
        await self._sysinfo(ctx)

    async def _sysinfo(self, ctx):
        try:
            if ctx.author.id == int(ADMIN_ID):
                # wait_message = await ctx.send("Processing... Please wait. This might take sometime")
                # async with ctx.typing():
                embed = discord.Embed(
                    title="System Info",
                    description="Showing my host hardware/software information",
                    colour=discord.Color.gold())
                embed.set_footer(text="Hope that was helpful, bye!")
                embed.set_author(name="Bro Bot",
                                 icon_url=self.bot.user.avatar_url)
                embed.set_thumbnail(url=ctx.guild.icon_url)
                result = subprocess.Popen(['neofetch', '--stdout'],
                                          stdout=subprocess.PIPE)
                for line in result.stdout:
                    line = line.decode('utf-8').strip('\n').split(':')
                    if len(line) == 2:
                        if line[0] == "OS" or line[0] == "Host":
                            embed.add_field(name=line[0],
                                            value=line[1],
                                            inline=False)
                        else:
                            embed.add_field(name=line[0],
                                            value=line[1],
                                            inline=True)

                # Raspberry Pi Only!!!
                if os.uname()[1] == "raspberrypi":
                    temp = subprocess.Popen(
                        ['/opt/vc/bin/vcgencmd', 'measure_temp'],
                        stdout=subprocess.PIPE)
                    for line in temp.stdout:
                        line = line.decode('utf-8').strip('\n').split('=')
                        if len(line) == 2:
                            embed.add_field(name="CPU Temp",
                                            value=line[1],
                                            inline=True)

                    url = await get_public_url()
                    embed.add_field(name="Public URL", value=url, inline=False)

                    # await wait_message.edit(content='', embed=embed)
                    await embed_send(ctx, embed)
            else:
                await ctx.send('```Only my master can use this command.```')
        except Exception as e:
            logger.exception(e)

    @commands.command(brief='', hidden=True)
    async def runcmd(self, ctx, *args):
        logger.debug(args)
        if ctx.message.author.id == int(ADMIN_ID):
            try:
                result = subprocess.Popen(args, stdout=subprocess.PIPE)
                logger.debug(result.stdout)
                out = ""
                for line in result.stdout:
                    out += line.decode('utf-8')
                logger.debug(out)
                await ctx.send("```{}```".format(out))
            except Exception as e:
                logger.exception(e)
        else:
            await ctx.send('```Only my master can use this command.```')