Ejemplo n.º 1
0
    async def chat_purgeuser(self, ctx, user: discord.Member, count: int):
        await ctx.message.delete()

        if not perms.check_command_priv("purgeuser", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **purgeuser** command."
            ))
            return

        if count > 100:
            await ctx.send(embed=interface.error_message(
                "Error",
                f"The **purgeuser** command can only delete up to 100 messages at a time. "
                "Messages older than 14 days cannot be deleted.",
            ))

            return

        msg_queue = list()

        async for msg in ctx.message.channel.history():
            if msg.author == user:
                msg_queue.append(msg)

            if len(msg_queue) == count or len(msg_queue) == 100:
                break

        await ctx.message.channel.delete_messages(msg_queue)

        await ctx.send(embed=interface.success_message(
            "Purge",
            f"Purged {user}'s last {len(msg_queue)} message(s) from {ctx.message.channel}."
        ))
Ejemplo n.º 2
0
    async def mod_warn(self, ctx, user: discord.Member, *, reason: str):
        """
        Warn a user and record the warning in the log.

        <user> must be a Discord tag, ID number, or mention.
        <message> can be anything.
        """
        await ctx.message.delete()

        if not perms.check_command_priv("warn", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **warn** command."
            ))
            return

        try:
            db.log_staff_action(utils.get_timestamp(), ctx.message.author,
                                user, "warn", reason)
        except:
            raise
            await ctx.author.send(embed=interface.error_message(
                f"{ctx.message.guild} - Error",
                "There was an error processing the warning you just attempted to issue.",
            ))
        else:
            await ctx.send(embed=interface.error_message(
                "Warning",
                f"{user.mention} has received a warning:\n\n**{reason}**",
                f"User ID: {user.id}"))

            await user.send(embed=interface.error_message(
                f"{ctx.message.guild} - Warning",
                f"You have received a warning:\n\n**{reason}**"))
Ejemplo n.º 3
0
    async def roles_add_grant(self, ctx, granter: discord.Role,
                              granted: discord.Role):
        """
        Grant a role the ability to add a user to a different role.

        This allows anyone with the <granter> role to give the <granted> role to someone else.

        Specify each role by name (case-sensitive) or ID number. If specifying by name, and the name contains a space, enclose that role in quotation marks.
        """
        await ctx.message.delete()

        if not perms.check_command_priv("addgrant", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **addgrant** command."
            ))
            return

        if db.add_role_granter(granter, granted):
            await ctx.send(embed=interface.success_message(
                "Role Grant Addition",
                f"**{granter}** may now grant the **{granted}** role."))
        else:
            await ctx.send(embed=interface.error_message(
                "Error", "There was an error adding the grant permission."))
Ejemplo n.º 4
0
    async def mod_unban(self, ctx, user: discord.User, *, reason: str = None):
        await ctx.message.delete()

        if not perms.check_command_priv("unban", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **unban** command."
            ))
            return

        if reason:
            chanmsg = f"{user.mention} has been unbanned from the server.\n\nReason: **{reason}**"
        else:
            chanmsg = f"{user.mention} has been unbanned from the server."

        try:
            await ctx.send(embed=interface.success_message(
                "Unban", chanmsg, f"User ID: {user.id}"))
            db.log_staff_action(utils.get_timestamp(), ctx.message.author,
                                user, "unban", reason)
            await ctx.author.guild.unban(user, reason=reason)
        except:
            raise
            await ctx.author.send(embed=interface.error_message(
                f"{ctx.message.guild} - Error",
                "There was an error processing the unban you just attempted to issue.",
            ))
Ejemplo n.º 5
0
    async def admin_staff_demote(self, ctx, user: discord.Member):
        """
        Demote a user to the next-lowest staff rank.
        If the user is already at the lowest staff rank, remove them from staff.

        <user> must be a Discord tag, ID number, or mention.
        """
        await ctx.message.delete()

        if not perms.check_command_priv("demote", ctx.message.author.roles):
            await ctx.send(
                embed=interface.error_message(
                    "Access Denied", f"**{ctx.message.author}** does not have access to the **demote** command."
                )
            )
            return

        cur_level = perms.get_staff_rank(user)

        staff_roles_list = [ctx.guild.get_role(r) for r in defs.staff_role_ids]
        new_roles_list = [ctx.guild.get_role(r) for r in defs.staff_role_ids[0 : cur_level - 1]]

        if len(staff_roles_list) == len(new_roles_list) + 1 and not await self.bot.is_owner(ctx.author):
            await ctx.send(embed=interface.error_message("Error", "Only the owner can demote from that rank."))
            return

        msg = await ctx.send(embed=interface.working_message("Staff Demotion", f"Demoting **{user}**..."))

        if cur_level == 1:
            try:
                await user.remove_roles(*staff_roles_list, atomic=True)
            except Exception as e:
                await msg.edit(embed=interface.error_message("Error", f"Error: {e}"))
            else:
                await msg.edit(
                    embed=interface.success_message(
                        "Staff Removal", f"{user.mention} has been removed from staff.", f"User ID: {user.id}"
                    )
                )
        else:
            try:
                await user.remove_roles(*staff_roles_list, atomic=True)
                await user.add_roles(*new_roles_list, atomic=True)
            except Exception as e:
                await msg.edit(embed=interface.error_message("Error", f"Error: {e}"))
            else:
                await msg.edit(
                    embed=interface.success_message(
                        "Staff Demotion",
                        "{} has been demoted to **{}**.".format(user.mention, new_roles_list[len(new_roles_list) - 1]),
                        f"User ID: {user.id}",
                    )
                )
Ejemplo n.º 6
0
    async def mod_unmute(self,
                         ctx,
                         user: discord.Member,
                         *,
                         reason: str = None):
        await ctx.message.delete()

        if not perms.check_command_priv("unmute", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **unmute** command."
            ))
            return

        if user.id == ctx.message.author.id:
            await ctx.send(embed=interface.error_message(
                "Error", f"You can't unmute yourself."))
            return

        if perms.get_staff_rank(
                ctx.message.author) <= perms.get_staff_rank(user):
            await ctx.send(embed=interface.error_message(
                "Error",
                f"You can't unmute someone of the same staff rank or higher."))
            return

        if defs.mute_role_id not in [r.id for r in user.roles]:
            await ctx.send(embed=interface.error_message(
                "Error", f"{user} is not muted.", f"User ID: {user.id}"))
            return

        if reason:
            chanmsg = f"{user.mention} has been unmuted.\n\nReason: **{reason}**"
        else:
            chanmsg = f"{user.mention} has been unmuted."

        try:
            db.log_staff_action(utils.get_timestamp(), ctx.message.author,
                                user, "unmute", reason)
            await self.do_unmute(db.get_mute_record(user))
        except:
            raise
            await ctx.author.send(embed=interface.error_message(
                f"{ctx.message.guild} - Error",
                "There was an error processing the unmute you just attempted.")
                                  )
        else:
            await ctx.send(embed=interface.success_message(
                "Unmute", chanmsg, f"User ID: {user.id}"))
Ejemplo n.º 7
0
    async def chat_unlock(self, ctx):
        await ctx.message.delete()

        if not perms.check_command_priv("unlock", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **unlock** command."
            ))
            return

        if ctx.message.channel.id not in self.lockdowns:
            await ctx.send(embed=interface.error_message(
                "Error", f"This channel is already unlocked."))
            return

        await ctx.send(embed=interface.success_message(
            "Channel Locked", f"This channel is now unlocked."))

        self.lockdowns.remove(ctx.message.channel.id)
Ejemplo n.º 8
0
    async def chat_lock(self, ctx):
        await ctx.message.delete()

        if not perms.check_command_priv("lock", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **lock** command."
            ))
            return

        if ctx.message.channel.id in self.lockdowns:
            await ctx.send(embed=interface.error_message(
                "Error", f"This channel is already locked."))
            return

        await ctx.send(embed=interface.error_message(
            "Channel Locked",
            f"This channel is now locked for non-staff members."))

        self.lockdowns.append(ctx.message.channel.id)
Ejemplo n.º 9
0
    async def roles_list_role_grants(self, ctx, user: discord.Member = None):
        await ctx.message.delete()

        if user is None:
            user = ctx.message.author
        else:
            my_staff_rank = perms.get_staff_rank(ctx.message.author)
            their_staff_rank = perms.get_staff_rank(user)

            if their_staff_rank > my_staff_rank:
                await ctx.send(embed=interface.error_message(
                    "Access Denied",
                    "You cannot check the access of someone of a higher staff rank."
                ))
                return

        giveable_role_ids = dict()

        for role in user.roles:
            role_ids = db.get_grantable_roles(role)
            if role_ids:
                giveable_role_ids[role.name] = role_ids

        if giveable_role_ids:
            giveable_roles = OrderedDict()

            for rname, rids in giveable_role_ids.items():
                giveable_roles[rname] = list(
                    set([ctx.author.guild.get_role(rid).name for rid in rids]))
                giveable_roles[rname].sort()

            rolelist = ""

            for granter, granted in reversed(giveable_roles.items()):
                rolelist += f"{granter} grants:\n"

                for rname in granted:
                    rolelist += f":white_small_square: {rname}\n"

                rolelist += "\n"

            rolelist = rolelist.strip()

            await ctx.send(embed=interface.normal_message(
                "Role Grant List",
                f"**{user}** can give or take the following roles:\n\n{rolelist}",
                f"User ID: {user.id}",
            ))
        else:
            await ctx.send(embed=interface.normal_message(
                "Role Grant List",
                f"**{user}** cannot give or take any roles.",
                f"User ID: {user.id}"))
Ejemplo n.º 10
0
async def command_error(bot, ctx, error):
    if type(error) is commands.errors.MissingRequiredArgument:
        cmd = bot.get_command(ctx.message.content.split(" ")[0][1:])

        await ctx.send(embed=interface.error_message(
            "Error",
            "You left out something that's required for the **{}** command."
            "\n\n{}\n\n{}".format(
                cmd.name, defs.cprefix + cmd.name + " " +
                cmd.signature, cmd.help),
        ))
    else:
        raise Exception(error)
Ejemplo n.º 11
0
    async def cms_unload(self, ctx, cog: str):
        if cog == "cms":
            await ctx.send(
                embed=interface.error_message("Cog Management System", "I can't unload the cog management system.")
            )
            return

        msg = await ctx.send(
            embed=interface.working_message("Cog Management System", f"Trying to unload the **{cog}** cog...")
        )

        try:
            self.bot.unload_extension(f"cogs.{cog}")
        except Exception as e:
            await msg.edit(
                embed=interface.error_message("Cog Management System", f"Unable to unload **{cog}** cog.\nError: {e}")
            )
            print(f"Error while unloading {cog} cog: {e}")
        else:
            await msg.edit(embed=interface.success_message("Cog Management System", f"**{cog.title()}** cog unloaded."))
        finally:
            await ctx.message.delete()
Ejemplo n.º 12
0
    async def mod_jail(self, ctx, user: discord.Member, *, reason: str = None):
        await ctx.message.delete()

        if not perms.check_command_priv("jail", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **jail** command."
            ))
            return

        if user.id == ctx.message.author.id:
            await ctx.send(embed=interface.error_message(
                "Error", f"You can't jail yourself."))
            return

        if perms.get_staff_rank(
                ctx.message.author) <= perms.get_staff_rank(user):
            await ctx.send(embed=interface.error_message(
                "Error",
                f"You can't jail someone of the same staff rank or higher."))
            return

        if defs.jail_role_id in [r.id for r in user.roles]:
            await ctx.send(embed=interface.error_message(
                "Error", f"{user} is already jailed.", f"User ID: {user.id}"))
            return

        if reason:
            chanmsg = f"{user.mention} has been placed in jail.\n\nReason: **{reason}**"
            dmmsg = f"You have been placed in jail.\n\nReason: **{reason}**"
        else:
            chanmsg = f"{user.mention} has been placed in jail."
            dmmsg = f"You have been placed in jail."

        try:
            db.log_staff_action(utils.get_timestamp(), ctx.message.author,
                                user, "jail", reason)
            db.add_jail(ctx.message.author, user, reason)
            await user.remove_roles(*user.roles[1:], atomic=True)
            await user.add_roles(user.guild.get_role(defs.jail_role_id),
                                 atomic=True)
        except:
            raise
            await ctx.author.send(embed=interface.error_message(
                f"{ctx.message.guild} - Error",
                "There was an error processing the jail you just attempted to issue.",
            ))
        else:
            await ctx.send(embed=interface.error_message(
                "Jail", chanmsg, f"User ID: {user.id}"))

            await user.send(embed=interface.error_message(
                f"{ctx.message.guild} - Jail", dmmsg))
Ejemplo n.º 13
0
    async def roles_take(self, ctx, user: discord.Member, role: discord.Role):
        await ctx.message.delete()

        if not perms.check_give_role(
                ctx.author, role) and not await self.bot.is_owner(ctx.author):
            await ctx.send(embed=interface.error_message(
                "Access Denied", f"You cannot take the **{role}** role."))
            return

        if role in [r.name for r in user.roles]:
            await ctx.send(embed=interface.error_message(
                "Error", f"**{user}** does not have that role."))
            return

        try:
            await user.remove_roles(role, atomic=True)
        except:
            await ctx.send(embed=interface.error_message(
                "Error", f"Unable to take **{role}** from **{user}**."))
        else:
            await ctx.send(embed=interface.success_message(
                "Role Removal", f"Removed **{role}** from **{user.mention}**.",
                f"User ID: {user.id}"))
Ejemplo n.º 14
0
    async def admin_give_command(self, ctx, role: discord.Role, cmd: str):
        """
        Give a role permission to use a command.
        """
        await ctx.message.delete()

        cmd = cmd.lower()

        if db.add_command_priv_role(role, cmd):
            await ctx.send(
                embed=interface.success_message(
                    "Grant Command Access", f"**{role}** now has access to the **{cmd}** command."
                )
            )
        else:
            await ctx.send(embed=interface.error_message("Error", "There was an error adding the permission."))
Ejemplo n.º 15
0
    async def chat_purge(self, ctx, count: int):
        await ctx.message.delete()

        if not perms.check_command_priv("purge", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **purge** command."
            ))
            return

        del_msgs = await ctx.message.channel.purge(limit=count, bulk=True)

        await ctx.send(embed=interface.success_message(
            "Purge",
            f"Purged last {len(del_msgs)} message(s) from {ctx.message.channel}."
        ))
Ejemplo n.º 16
0
    async def mod_softban(self,
                          ctx,
                          user: discord.Member,
                          *,
                          reason: str = None):
        await ctx.message.delete()

        if not perms.check_command_priv("softban", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **softban** command."
            ))
            return

        if user.id == ctx.message.author.id:
            await ctx.send(embed=interface.error_message(
                "Error", f"You can't softban yourself."))
            return

        if ctx.author.guild.get_member(user.id):
            if perms.get_staff_rank(
                    ctx.message.author) <= perms.get_staff_rank(user):
                await ctx.send(embed=interface.error_message(
                    "Error",
                    f"You can't softban someone of the same staff rank or higher."
                ))
                return

        if reason:
            chanmsg = f"{user.mention} has been softbanned.\n\nReason: **{reason}**"
            dmmsg = f"You have been softbanned.\n\nReason: **{reason}**"
        else:
            chanmsg = f"{user.mention} has been softbanned."
            dmmsg = f"You have been softbanned."

        try:
            await ctx.send(embed=interface.error_message(
                "Soft Ban", chanmsg, f"User ID: {user.id}"))

            if ctx.author.guild.get_member(user.id):
                await user.send(embed=interface.error_message(
                    f"{ctx.message.guild} - Soft Ban", dmmsg))

            db.log_staff_action(utils.get_timestamp(), ctx.message.author,
                                user, "softban", reason)
            await ctx.author.guild.ban(user,
                                       reason=reason,
                                       delete_message_days=7)
            await ctx.author.guild.unban(user, reason=reason)
        except:
            raise
            await ctx.author.send(embed=interface.error_message(
                f"{ctx.message.guild} - Error",
                "There was an error processing the ban you just attempted to issue.",
            ))
Ejemplo n.º 17
0
    async def admin_take_command(self, ctx, role: discord.Role, cmd: str):
        """
        Revoke a role's ability to use a command.
        """
        await ctx.message.delete()

        cmd = cmd.lower()

        if db.del_command_priv_role(role, cmd):
            await ctx.send(
                embed=interface.success_message(
                    "Remove Command Access", f"**{role}** no longer has access to the **{cmd}** command."
                )
            )
        else:
            await ctx.send(
                embed=interface.error_message("Error", "There was an error removing the command from that role.")
            )
Ejemplo n.º 18
0
    async def cms_reload_all(self, ctx):
        msg = await ctx.send(embed=interface.working_message("Cog Management System", f"Trying to reload all cogs..."))

        loaded_extensions = self.bot.extensions

        try:
            for extension in loaded_extensions:
                self.bot.reload_extension(extension)
        except Exception as e:
            await msg.edit(
                embed=interface.error_message(
                    "Cog Management System", f"An error occurred while reloading cogs.\nError: {e}"
                )
            )
            print(f"Error while reloading all cogs: {e}")
        else:
            await msg.edit(embed=interface.success_message("Cog Management System", f"All cogs reloaded."))
        finally:
            await ctx.message.delete()
Ejemplo n.º 19
0
    async def admin_list_commands(self, ctx, user: discord.Member = None):
        """
        List the commands that you have access to.

        Alternatively, list the commands that someone else has access to.
        """
        await ctx.message.delete()

        if user is None:
            user = ctx.message.author
        else:
            my_staff_rank = perms.get_staff_rank(ctx.message.author)
            their_staff_rank = perms.get_staff_rank(user)

            if their_staff_rank > my_staff_rank:
                await ctx.send(
                    embed=interface.error_message(
                        "Error", "You cannot check the access of someone of a higher staff rank."
                    )
                )
                return

        granted_cmds = OrderedDict()

        for role in user.roles:
            role_cmds = db.get_command_priv_cmds(role)

            if not role_cmds:
                continue

            granted_cmds[role.name] = role_cmds
            granted_cmds[role.name].sort()

        if not granted_cmds:
            await ctx.send(
                embed=interface.normal_message(
                    "Command Access", f"**{user}** cannot use any commands.", f"User ID: {user.id}"
                )
            )

            return

        cmdlist = ""

        for rname, cmds in reversed(granted_cmds.items()):
            cmdlist += f"{rname} grants:\n"
            
            for cmd in cmds:
                cmdlist += f":white_small_square: {cmd}   "

            cmdlist += "\n"

        cmdlist = cmdlist.strip()
    
        await ctx.send(
            embed=interface.normal_message(
                "Command Access",
                f"**{user}** can use the following commands:\n\n{cmdlist}",
                f"User ID: {user.id}",
            )
        )        
Ejemplo n.º 20
0
    async def mod_mute(self,
                       ctx,
                       user: discord.Member,
                       duration: str,
                       *,
                       reason: str = None):
        await ctx.message.delete()

        if not perms.check_command_priv("mute", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **mute** command."
            ))
            return

        if user.id == ctx.message.author.id:
            await ctx.send(embed=interface.error_message(
                "Error", f"You can't mute yourself."))
            return

        if perms.get_staff_rank(
                ctx.message.author) <= perms.get_staff_rank(user):
            await ctx.send(embed=interface.error_message(
                "Error",
                f"You can't mute someone of the same staff rank or higher."))
            return

        if defs.mute_role_id in [r.id for r in user.roles]:
            await ctx.send(embed=interface.error_message(
                "Error", f"{user} is already muted.", f"User ID: {user.id}"))
            return

        dur_num = 0

        num = int(duration[:-1])
        if duration.endswith("s"):
            dur_num = num
        elif duration.endswith("m"):
            dur_num = num * 60
        elif duration.endswith("h"):
            dur_num = num * 3600
        elif duration.endswith("d"):
            dur_num = num * 86400

        exp_time = utils.get_timestamp() + dur_num

        if reason:
            chanmsg = f"{user.mention} has been muted for {utils.get_durationstr(dur_num)}.\n\nReason: **{reason}**"
            dmmsg = f"You have been muted for {utils.get_durationstr(dur_num)}.\n\nReason: **{reason}**"
        else:
            chanmsg = f"{user.mention} has been muted for {utils.get_durationstr(dur_num)}."
            dmmsg = f"You have been muted for {utils.get_durationstr(dur_num)}."

        try:
            db.log_staff_action(utils.get_timestamp(), ctx.message.author,
                                user, f"mute ({duration})", reason)
            db.add_mute(ctx.message.author, user, exp_time, reason)
            await user.remove_roles(*user.roles[1:], atomic=True)
            await user.add_roles(user.guild.get_role(defs.mute_role_id),
                                 atomic=True)
        except:
            raise
            await ctx.author.send(embed=interface.error_message(
                f"{ctx.message.guild} - Error",
                "There was an error processing the mute you just attempted to issue.",
            ))
        else:
            await ctx.send(embed=interface.error_message(
                "Mute", chanmsg, f"User ID: {user.id}"))

            await user.send(embed=interface.error_message(
                f"{ctx.message.guild} - Mute", dmmsg))
Ejemplo n.º 21
0
    async def mod_unjail(self,
                         ctx,
                         user: discord.Member,
                         *,
                         reason: str = None):
        await ctx.message.delete()

        if not perms.check_command_priv("unjail", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **unjail** command."
            ))
            return

        if user.id == ctx.message.author.id:
            await ctx.send(embed=interface.error_message(
                "Error", f"You can't unjail yourself."))
            return

        if perms.get_staff_rank(
                ctx.message.author) <= perms.get_staff_rank(user):
            await ctx.send(embed=interface.error_message(
                "Error",
                f"You can't unjail someone of the same staff rank or higher."))
            return

        if defs.jail_role_id not in [r.id for r in user.roles]:
            await ctx.send(embed=interface.error_message(
                "Error", f"{user} is not jailed.", f"User ID: {user.id}"))
            return

        if reason:
            chanmsg = f"{user.mention} has been released from jail.\n\nReason: **{reason}**"
            dmmsg = f"You have been released from jail.\n\nReason: **{reason}**"
        else:
            chanmsg = f"{user.mention} has been released from jail."
            dmmsg = f"You have been released from jail."

        try:
            db.log_staff_action(utils.get_timestamp(), ctx.message.author,
                                user, "unjail", reason)

            jail = db.get_jail_record(user)

            roles = [user.guild.get_role(rid) for rid in jail["roles"]]
            roles = [
                r for r in roles if r is not None and r.name != "@everyone"
            ]

            db.remove_jail(user)
            await user.remove_roles(user.guild.get_role(defs.jail_role_id),
                                    atomic=True)
            await user.add_roles(*roles, atomic=True)
        except:
            raise
            await ctx.author.send(embed=interface.error_message(
                f"{ctx.message.guild} - Error",
                "There was an error processing the unjail you just attempted to issue.",
            ))
        else:
            await ctx.send(embed=interface.success_message(
                "Unjail", chanmsg, f"User ID: {user.id}"))

            await user.send(embed=interface.success_message(
                f"{ctx.message.guild} - Unjail", dmmsg))
Ejemplo n.º 22
0
    async def mod_history(self, ctx, user: discord.Member):
        """
        List the moderation history of a user.

        <user> must be a Discord tag, ID number, or mention.
        """
        await ctx.message.delete()

        if not perms.check_command_priv("history", ctx.message.author.roles):
            await ctx.send(embed=interface.error_message(
                "Access Denied",
                f"**{ctx.message.author}** does not have access to the **history** command."
            ))
            return

        logs = None

        msg = await ctx.send(embed=interface.working_message(
            "Moderation History", f"Retrieving history for **{user}**..."))

        try:
            logs = db.get_action_history(user)
        except:
            raise
            await ctx.send(embed=interface.error_message(
                "Error",
                f"There was an error retrieving history for **{user}**."))

        if not logs:
            await msg.edit(embed=interface.success_message(
                f"Moderation History for {user}",
                f"**{user}** has no moderation history.",
                f"User ID: {user.id}"))
        else:
            log_dict = defaultdict(list)

            for log in logs:
                actor = ctx.message.guild.get_member(log["actor"])
                action = log["action"]
                reason = log["reason"]

                edate = datetime.fromtimestamp(log["tval"],
                                               tz=timezone.utc).date()
                etime = datetime.fromtimestamp(log["tval"],
                                               tz=timezone.utc).timetz()

                if reason:
                    log_dict[edate].append((
                        etime,
                        f"**{action}** by **{actor}** with reason: **{reason}**"
                    ))
                else:
                    log_dict[edate].append(
                        (etime, f"**{action}** by **{actor}**"))

            logstring = ""

            for date, events in log_dict.items():
                logstring += date.strftime("%A, %b %d %Y\n")
                for time, event in sorted(events,
                                          key=lambda x: x[0],
                                          reverse=True):
                    logstring += "  {} - {}\n".format(
                        time.strftime("%I:%M %p"), event)
                logstring += "\n"
            await msg.edit(embed=interface.success_message(
                f"Moderation History for {user}", logstring.strip(),
                f"User ID: {user.id}"))