예제 #1
0
 async def cyrm(self, ctx):
     """Runs through a series of checks to ensure the bot can access the invoked channel."""
     """
     Check 1: Can the bot see the command?
     True: If this command is invoked, then the bot can see the command. Continue to Check 2.
     """
     """
     Check 2: Check if the bot can write messages to the channel.
     True: Report success status in channel. End command.
     False: Report failure status to author. Continue to Check 3.
     """
     try:
         em = Embed(color=message_color)
         em.set_footer(text=generate_footer(ctx))
         em.add_field(
             name="Loud and Clear!",
             value="I can see and respond to commands in this channel.")
         await ctx.send(embed=em)
     except Forbidden:
         # Unable to send message to channel.
         pass
     else:
         # Able to send message to channel.
         return
     """
     Check 3: Check if the bot can write messages to author.
     True: Report failure status to author. End command.
     False: Attempt to report error with reactions. Continue to Check 4.
     """
     try:
         em = Embed(color=error_color)
         em.set_footer(text=generate_footer(ctx))
         em.add_field(
             name="I can't send messages!",
             value=
             "I do not have permission to send messages in the invoked channel. "
             "Check permissions or contact your server administrator!")
         await ctx.author.send(embed=em)
     except Forbidden:
         # Unable to send error to message author.
         pass
     else:
         # Able to send error to message author.
         return
     """
     Check 4: Check if the bot can react to invoked message.
     True: React with :fox: :sos:. End command.
     False: Impossible to report error. Command fail.
     """
     try:
         await ctx.message.add_reaction("🦊")
         await ctx.message.add_reaction("🆘")
     except Forbidden:
         # No action possible.
         return
     else:
         # Error reaction success.
         return
예제 #2
0
    async def stats(self, ctx):
        logging.info("Hello!")
        """Posts a full application statistics page"""

        em = Embed(title="Application Statistics", color=message_color)

        # Collect system uptime
        ut = time() - boot_time()

        # Collect memory statistics
        memory = virtual_memory()

        em.add_field(
            name=":desktop: System Information",
            value=f"`Uptime` {str(timedelta(seconds=int(ut)))}\n"
            f"`Memory` {round(memory.used / 1000000000, 1)}/{round(memory.total / 1000000000, 1)} GB "
            f"({round((memory.used / memory.total) * 100)}%)\n"
            f"`Load (1/5/15)` {'/'.join([str(round(x / cpu_count() * 100, 2)) for x in getloadavg()])}",
            inline=False)

        em.add_field(
            name=":globe_with_meridians: API Information",
            value=f"`WebSocket Latency` {round(self.client.latency * 1000)}ms\n"
            f"`Client ID` {self.client.user.id}\n"
            f"`Shards` {len(self.client.shards)}\n"
            f"`Users` {len(self.client.users):,}\n"
            f"`Guilds` {len(self.client.guilds):,}",
            inline=False)

        em.set_footer(text=generate_footer(ctx))

        await ctx.send(embed=em)
예제 #3
0
    async def privacy_information(self, ctx):
        """Sends information on what data this bot collects and how we use it."""
        em = Embed(
            title="Privacy Information",
            description="Privacy is important to everyone, so this is a quick overview of the data we have stored.",
            color=message_color
        )
        em.set_footer(text=generate_footer(ctx))

        # Command
        em.add_field(
            name="Error Logging",
            value="If a command returns an error, the contents of the command will be logged for debugging purposes. "
                  "Neither the name of the sender nor the name of the server will be logged."
        )

        em.add_field(
            name="Data Persistence",
            value="Snipe tool data: the contents of your last mention is stored in "
                  "memory, meaning it is wiped as soon as the bot stops running.\n"
                  "User preferences: the user ID and guild ID (where applicable) is stored in a local database."
        )

        em.add_field(
            name="Misuse Policy",
            value="We do not, nor will we ever use the bot to access information not specified by this privacy notice."
        )

        em.add_field(
            name="Questions?",
            value="Feel free to ask questions in the Development Server!"
        )

        await ctx.author.send(embed=em)
예제 #4
0
async def on_command_error(ctx, error):
    """Error handler, parses how message author should be notified about an error."""
    # If CommandNotFound, fail silently
    if isinstance(error, discord.ext.commands.CommandNotFound):
        return

    # error.__cause__ finds cause of CommandInvokeError, useful if exception thrown from inside command.
    if isinstance(error.__cause__, UserWarning):
        title = "There was a user warning while running the command!"
        # Generate formatted string
        exc = f"{type(error.__cause__).__name__}: {error.__cause__}"
    else:
        title = "There was an error while running the command!"
        # Generate formatted string
        exc = f"{type(error).__name__}: {error}"

    em = discord.Embed(title=title, description=f"`{exc}`", color=error_color)
    em.set_footer(text=generate_footer(ctx))
    try:
        await ctx.send(embed=em)
    except discord.Forbidden:
        # Was unable to send exception message, ignore.
        pass
    except discord.HTTPException as http_exception:
        # Was unable to send message due to HTTP error.
        logging.warning(
            f"{type(http_exception)} when sending an exception message. "
            f"{http_exception.status}: {http_exception.text}")
        pass
예제 #5
0
    async def report_bug(self, ctx):
        """Gives the user information on how to report bugs they find."""
        em = Embed(
            title="Found a bug? :bee:",
            description="You can report bugs on the "
            "[Fox Utilities issues](https://github.com/FevenKitsune/Fox-Utilities/issues) page on GitHub!",
            color=message_color)
        em.set_footer(text=generate_footer(ctx))

        await ctx.send(embed=em)
예제 #6
0
    async def pull(self, ctx):
        """Pulls the latest version of the bot from Git"""
        # Find Git repository the bot is stored in
        repo = Repo(getcwd(), search_parent_directories=True)

        # Run git pull and post results into embed.
        em = Embed(title="Fox Utilities GitHub",
                   description=f"```smalltalk\n{str(repo.git.pull())}\n```",
                   color=message_color)
        em.set_footer(text=generate_footer(ctx))
        await ctx.send(embed=em)
예제 #7
0
    async def tags(self, ctx):
        """Gives the user information on permission tags, which allow non-admins to access admin commands."""
        em = Embed(
            title="Fox Utilities Permission Tags",
            description="Create a server role with the syntax `fox:name_of_command`. Assign any user to this role to "
                        "give them access to the named command. This will work with any command that requires "
                        "administrator permissions to access.",
            color=message_color)
        em.set_footer(text=generate_footer(ctx))

        await ctx.send(embed=em)
예제 #8
0
    async def prefix(self, ctx):
        """Gives the user information on prefix tags. This allows per-guild prefix settings."""
        em = Embed(
            title="Fox Utilities Prefix Tags",
            description=
            "Create a server role with the syntax `fox_prefix:desired_prefix`. Assign this role to the "
            "Fox Utilities bot to give it a new prefix.",
            color=message_color)
        em.set_footer(text=generate_footer(ctx))

        await ctx.send(embed=em)
예제 #9
0
    async def invite_bot(self, ctx):
        """Sends information on the development server, the GitHub, and the invite link."""
        em = Embed(
            title="Invite me!",
            description=f"[Invite link!]({bot_invite})\n"
                        f"[Development server!]({bot_development_server})\n"
                        f"[GitHub!]({bot_source})\n"
                        f"[Wiki!]({bot_wiki})",
            color=message_color
        )
        em.set_footer(text=generate_footer(ctx))

        await ctx.send(embed=em)
예제 #10
0
    async def reload(self, ctx, *args):
        """Unload all discord.py cogs and load them back. Easier than a full reboot."""
        em = Embed(title="System Reload", color=message_color)
        em.set_footer(text=generate_footer(ctx))

        # Stores which cogs passed and which cogs failed.
        success = []
        failed = []

        # Check for extensions first.
        if len(extensions) == 0:
            em.add_field(
                name="Oh well.",
                value="Doesn't look like there are any extensions defined.")
            await ctx.send(embed=em)
            return
        for extension in extensions:
            try:
                # Unload extension
                self.client.unload_extension(extension)
            # Continue if unload failed.
            except Exception as e:
                pass
        for extension in extensions:
            try:
                # Load extension
                self.client.load_extension(extension)
            except Exception as e:
                # Post error to embed if load failed.
                expt = f"{type(e).__name__}: {e}"
                failed.append([extension, expt])
            else:
                # Post to embed if load succeeded.
                success.append(extension)

        em.add_field(
            name=":white_check_mark: Load Passed:",
            value='\n'.join([f"`{i}` PASS"
                             for i in success]) if success else "`None`")

        em.add_field(
            name=":warning: Load Failed:",
            value='\n'.join([f"`{i[0]}` {i[1]}"
                             for i in failed]) if failed else "`None`")
        await ctx.send(embed=em)
예제 #11
0
    async def reboot(self, ctx):
        """Restart the bot on the system level."""
        em = Embed(title="Rebooting the bot!",
                   description="Please wait while the bot reboots...",
                   color=message_color)
        em.set_footer(text=generate_footer(ctx))
        await ctx.send(embed=em)

        # Get bot process
        p = Process(getpid())
        for handler in p.open_files() + p.connections():
            # Close all active connections and processes
            close(handler.fd)

        # Get python exec
        python = executable
        # Start python process
        execl(python, python, *argv)
예제 #12
0
    async def help(self, ctx, *args):
        """Help menu. Processes the list of available commands into a readable menu."""
        em = Embed(
            title="Fox Utilities Help Guide",
            description=bot_description,
            color=message_color
        )
        em.set_footer(text=generate_footer(ctx))

        if args and (search := args[0]):
            # If there is an args list, assign variable search with the first value.
            # User is requesting information about a specific command.
            if found_command := self.client.get_command(search):
                # Search client for given command. Assign found_command with found value.
                # found_command will be None if no command is found.
                em.add_field(
                    name=f"{'#' if found_command.hidden else ''}`{found_command.cog_name}`"
                         f"\n{found_command.name} {found_command.usage}",
                    value=f"{found_command.help}\n\n**Aliases**\n{found_command.aliases}"
                )
예제 #13
0
    async def invites(self, ctx):
        """Get a list of invite codes and the number of uses for a given user."""
        # If no one was mentioned, assume author is target.
        if ctx.message.mentions:
            user = ctx.message.mentions[0]
        else:
            user = ctx.message.author

        em = Embed(title=f"{user.name}'s Invites", color=message_color)
        em.set_footer(text=generate_footer(ctx))

        # Iterate through the guild invites and parse invites by the targeted user.
        for inv in await ctx.message.guild.invites():
            if inv.inviter == user:
                time_formatter = "%b %-d, %Y at %-l:%M%p"
                em.add_field(
                    name=f"Invite code: ####{str(inv.code)[4:]}",
                    value=f"`Uses` {inv.uses}\n"
                    f"`Created at` {inv.created_at.strftime(time_formatter)}")

        await ctx.send(embed=em)