Beispiel #1
0
def test_positive_action_warn():
    """This test also covers Note, Mute, and Ban"""
    discord_id, warn_text = randint(10, 10000), "this is a test warning"
    logged_action = models.Action(mod=BASE_USER, server=BASE_SERVER)
    new_warn = models.Warn(
        text=warn_text,
        user=models.User(discord_id=discord_id),
        server=BASE_SERVER,
        action=logged_action,
    )
    SESSION.add(new_warn)
    SESSION.commit()
    user = SESSION.query(
        models.User).filter(models.User.discord_id == discord_id).one()
    assert new_warn in user.warn
    warn = SESSION.query(models.Warn).filter(models.Warn.user == user).first()
    assert warn.text == warn_text
    assert warn.action == logged_action
Beispiel #2
0
    async def add(self, ctx, user_id: str, *, note_text: str):
        """Adds a note to a users record.

        Example:

        note add userID this is a test note
        note add @wumpus#0000 this is a test note

        Requires Permission: Manage Messages

        Parameters
        -----------
        ctx: context
            The context message involved.
        user_id: str
            The user/member the notes are related to. Can be an ID or a mention
        note_text: str
            The note text you are adding to the record.
        """

        session = self.bot.helpers.get_db_session()
        try:
            self.bot.log.info(
                f"CMD {ctx.command} called by {ctx.message.author} ({ctx.message.author.id})"
            )
            user = await self.bot.helpers.get_member_or_user(
                user_id, ctx.message.guild)
            if not user:
                return await ctx.send(
                    f"Unable to find the requested user. Please make sure the user ID or @ mention is valid."
                )

            # Get mod's DB profile
            db_mod = await self.bot.helpers.db_get_user(
                session, ctx.message.author.id)
            # Get the DB profile for the guild
            db_guild = await self.bot.helpers.db_get_guild(
                session, ctx.message.guild.id)
            # Get the DB profile for the user
            db_user = await self.bot.helpers.db_get_user(session, user.id)

            logged_action = models.Action(mod=db_mod, server=db_guild)
            new_note = models.Note(text=note_text,
                                   user=db_user,
                                   server=db_guild,
                                   action=logged_action)
            session.add(new_note)
            session.commit()

            await ctx.send(
                f"Successfully stored note #{new_note.id} for: {user} ({user.id})"
            )
        except discord.HTTPException as err:
            self.bot.log.error(
                f"Discord HTTP Error responding to {ctx.command} request via Msg ID {ctx.message.id}. {sys.exc_info()[0].__name__}: {err}"
            )
            await ctx.send(
                f"Error processing {ctx.command}. Error has already been reported to my developers."
            )
        except DBAPIError as err:
            self.bot.log.exception(
                f"Error logging note to database. {sys.exc_info()[0].__name__}: {err}"
            )
            await ctx.send(
                f"Unable to log note due to database error for: ({user_id}). Error has already been reported to my developers."
            )
            session.rollback()
        except Exception as err:
            self.bot.log.exception(
                f"Error responding to {ctx.command} via Msg ID {ctx.message.id}. {sys.exc_info()[0].__name__}: {err}"
            )
            await ctx.send(
                f"Error processing {ctx.command}. Error has already been reported to my developers."
            )
        finally:
            session.close()
Beispiel #3
0
    async def edit(self, ctx, user_id: str, note_id: str, *, note_text: str):
        """Edits a note on a users record.

        Example:

        note edit userID noteID new note message
        note add @wumpus#0000 new note message

        Requires Permission: Manage Messages

        Parameters
        -----------
        ctx: context
            The context message involved.
        user_id: str
            The user/member the note is related to.
        note_id: str
            The note id to edit.
        note_text: str
            The note text you are updating on the record.
        """

        session = self.bot.helpers.get_db_session()
        try:
            user = await self.bot.helpers.get_member_or_user(
                user_id, ctx.message.guild)
            if not user:
                return await ctx.send(
                    f"Unable to find the requested user. Please make sure the user ID or @ mention is valid."
                )

            # Clean the Note ID since some people put the #numb when it should just be int
            try:
                note_id = int(note_id.replace("#", ""))
            except ValueError:
                return await ctx.send(
                    f"You must provide the Note ID that you want to edit.")

            # Get mod's DB profile
            db_mod = await self.bot.helpers.db_get_user(
                session, ctx.message.author.id)
            # Get the DB profile for the guild
            db_guild = await self.bot.helpers.db_get_guild(
                session, ctx.message.guild.id)
            # Get the DB profile for the user
            db_user = await self.bot.helpers.db_get_user(session, user.id)

            # Get the note by the ID
            logged_note = session.query(models.Note).get(note_id)
            # Now let's make sure the user isn't trying to update a note they aren't authorized for
            if logged_note and (logged_note.server_id == db_guild.id
                                and logged_note.user_id == db_user.id):
                new_action = models.Action(mod=db_mod, server=db_guild)
                session.add(new_action)
                session.commit()

                logged_note.text = note_text
                logged_note.action_id = new_action.id
                session.add(logged_note)
                session.commit()

                await ctx.send(
                    f"Successfully updated note #{logged_note.id} for: {user} ({user.id})"
                )
            else:
                await ctx.send(
                    f"Unable to update that note. Please make sure you are providing a valid note ID and user ID."
                )
        except discord.HTTPException as err:
            self.bot.log.error(
                f"Discord HTTP Error responding to {ctx.command} request via Msg ID {ctx.message.id}. {sys.exc_info()[0].__name__}: {err}"
            )
            await ctx.send(
                f"Error processing {ctx.command}. Error has already been reported to my developers."
            )
        except DBAPIError as err:
            self.bot.log.exception(
                f"Error saving edited note for: ({user_id}). {sys.exc_info()[0].__name__}: {err}"
            )
            await ctx.send(
                f"Error processing {ctx.command}. Error has already been reported to my developers."
            )
            session.rollback()
        except Exception as err:
            self.bot.log.exception(
                f"Error responding to {ctx.command} via Msg ID {ctx.message.id}. {sys.exc_info()[0].__name__}: {err}"
            )
            await ctx.send(
                f"Error processing {ctx.command}. Error has already been reported to my developers."
            )
        finally:
            session.close()
Beispiel #4
0
    async def mute(
        self,
        ctx,
        user_id: str,
        mute_time: time.UserFriendlyTime(commands.clean_content,
                                         default="\u2026"),
        *,
        reason: str,
    ):
        """Mute a user.

        If no time or note specified default values will be used. Time can be a human readable string, many formats are understood.

        To unmute someone see unmute

        Requires Permission: Manage Messages

        Parameters
        -----------
        ctx: context
            The context message involved.
        user_id: str
            The Discord ID or user mention the command is being run on.
        mute_time: time
            How long the mute will be for.
        reason: str
            The reason for the mute. This will be sent to the user and added to the logs.
        """

        self.bot.log.info(
            f"CMD {ctx.command} called by {ctx.message.author} ({ctx.message.author.id})"
        )

        # If we were provided an ID, let's try and use it
        if user_id:
            member = await self.bot.helpers.get_member_or_user(
                user_id, ctx.message.guild)
            if not member:
                return await ctx.send(
                    f"Unable to find the requested user. Please make sure the user ID or @ mention is valid."
                )
            elif isinstance(member, discord.User):
                await ctx.send(
                    f"The user specified does not appear to be in the server. Proceeding with mute in case they return."
                )
        else:
            return await ctx.send(
                f"A user ID or Mention must be provided for who to mute.")
        if mute_time == "20m":
            mute_time = datetime.datetime.now(
                datetime.timezone.utc) + datetime.timedelta(minutes=20)
        elif isinstance(mute_time, datetime.datetime):
            mute_time = mute_time
        else:
            mute_time = mute_time.dt

        mute_length_human = time.human_timedelta(mute_time)

        settings = self.bot.guild_settings.get(ctx.message.guild.id)
        has_modmail_server = settings.modmail_server_id
        muted_role_id = settings.muted_role
        mod_channel = discord.utils.get(ctx.message.guild.text_channels,
                                        id=settings.mod_channel)
        if not mod_channel:
            await ctx.send(
                "Please set a mod channel using `config modchannel #channel`")
        # delete the message we used to invoke it
        if mod_channel and ctx.message.channel.id != mod_channel.id:
            try:
                await ctx.message.delete()
            except discord.HTTPException as err:
                self.bot.log.warning(
                    f"Couldn't delete command message for {ctx.command}: {err}"
                )

        log_channel = discord.utils.get(ctx.message.guild.text_channels,
                                        name="bot-logs")
        if not log_channel:
            # If there is no normal logs channel, try the sweeper (legacy) logs channel
            log_channel = discord.utils.get(ctx.message.guild.text_channels,
                                            name="sweeper-logs")
            if not log_channel:
                return await ctx.send(
                    f"No log channel setup. Please create a channel called #bot-logs"
                )

        muted_role = ctx.message.guild.get_role(muted_role_id)
        if not muted_role:
            return await ctx.send(
                "Mute role is not yet configured. Unable to proceed.")

        footer_text = (self.bot.constants.footer_with_modmail.format(
            guild=ctx.message.guild) if has_modmail_server else
                       self.bot.constants.footer_no_modmail.format(
                           guild=ctx.message.guild))

        sweeper_emoji = self.bot.get_emoji(
            self.bot.constants.reactions["animated_sweeperbot"])

        session = self.bot.helpers.get_db_session()
        try:
            old_mute_len = None
            old_mute_dt = None
            if not isinstance(member, discord.User):
                if muted_role in member.roles:
                    if (ctx.message.guild.id in self.current_mutes
                            and member.id
                            in self.current_mutes[ctx.message.guild.id]):
                        old_mute_len = self.current_mutes[
                            ctx.message.guild.id][member.id].human_delta
                        old_mute_dt = self.current_mutes[ctx.message.guild.id][
                            member.id].expires
                        self.current_mutes[ctx.message.guild.id][
                            member.id].stop()
                        del self.current_mutes[ctx.message.guild.id][member.id]

                if (member is ctx.message.guild.owner or member.bot
                        or member is ctx.message.author):
                    return await ctx.send(
                        "You may not use this command on that user.")

                if member.top_role > ctx.me.top_role:
                    return await ctx.send(
                        "The user has higher permissions than the bot, can't use this command on that user."
                    )

            actionMsg = await ctx.send("Initiating action. Please wait.")
            self.bot.log.info(
                f"Initiating mute for user: {member} ({member.id}) in guild {ctx.message.guild} ({ctx.message.guild.id})"
            )

            old_roles = []
            old_roles_snow = []
            if not isinstance(member, discord.User):
                for role in member.roles:
                    if role.managed or role.name == "@everyone":
                        continue
                    else:
                        old_roles_snow.append(role)
                        old_roles.append(role.id)

                # Remove all non-managed roles
                await member.remove_roles(
                    *old_roles_snow,
                    reason=
                    f"Muted by request of {ctx.message.author} ({ctx.message.author.id})",
                    atomic=True,
                )
                # Assign mute role
                await member.add_roles(
                    muted_role,
                    reason=
                    f"Muted by request of {ctx.message.author} ({ctx.message.author.id})",
                    atomic=True,
                )
                # If in voice, kick
                try:
                    if member.voice and member.voice.channel:
                        await member.move_to(
                            channel=None,
                            reason=
                            f"Muted by request of {ctx.message.author.mention}",
                        )
                except discord.errors.Forbidden:
                    await ctx.send(
                        f"Missing permissions to drop user from voice channel."
                    )

            self.bot.log.info(
                f"Muted user: {member} ({member.id}) in guild {ctx.message.guild} ({ctx.message.guild.id}) for {mute_length_human}"
            )
            informed_user = False
            try:
                # Format the message
                text = self.bot.constants.infraction_header.format(
                    action_type="mute", guild=ctx.message.guild)

                # Reduces the text to 1,800 characters to leave enough buffer for header and footer text
                text += f"This mute is for **{mute_length_human}** with the reason:\n\n"
                text += reason[:1800]
                text += footer_text
                await member.send(text)
                self.bot.log.info(
                    f"Informed user of their mute: {member} ({member.id}) in guild {ctx.message.guild}"
                )
                informed_user = True
                if mod_channel and actionMsg.channel.id == mod_channel.id:
                    await actionMsg.edit(
                        content=
                        f"Mute successful for {member.mention}. **Time:** *{mute_length_human}*. {sweeper_emoji}"
                    )
                    if old_mute_len:
                        await ctx.send(
                            f"**Note**: This user was previously muted until {old_mute_len}."
                        )
                else:
                    await actionMsg.edit(
                        content=f"That action was successful. {sweeper_emoji}")
            except Exception as e:
                if mod_channel:
                    await mod_channel.send(
                        f"Mute successful for {member.mention}. **Time:** *{mute_length_human}*. {sweeper_emoji}\n"
                        f"However, user couldn't be informed: {e}")
                if not (type(e) == discord.errors.Forbidden
                        and e.code == 50007):
                    self.bot.log.exception(
                        f"There was an error while informing {member} ({member.id}) about their mute"
                    )

            if informed_user:
                reason += "| **Msg Delivered: Yes**"
            else:
                reason += "| **Msg Delivered: No**"

            # Log action
            await log.user_action(
                self.bot,
                log_channel.name,
                member,
                "Mute",
                f"**Length:** {mute_length_human}\n"
                f"**Reason:** {reason}",
                ctx.message.author,
                ctx.message.guild,
            )

            # Get the DB profile for the guild
            db_guild = await self.bot.helpers.db_get_guild(
                session, ctx.message.guild.id)
            # Get the DB profile for the user
            db_user = await self.bot.helpers.db_get_user(session, member.id)
            # Get mod's DB profile
            db_mod = await self.bot.helpers.db_get_user(
                session, ctx.message.author.id)
            db_action = models.Action(mod=db_mod, server=db_guild)

            db_mute = None
            if old_mute_len:
                db_mute = (session.query(
                    models.Mute).filter(models.Mute.server == db_guild).filter(
                        models.Mute.user == db_user).filter(
                            models.Mute.expires == old_mute_dt).one_or_none())
            if db_mute:
                session.add(db_action)
                session.commit()

                db_mute.action_id = db_action.id
                db_mute.text = reason
                db_mute.expires = mute_time
                db_mute.updated = datetime.datetime.now(datetime.timezone.utc)
            else:
                db_mute = models.Mute(
                    text=reason,
                    user=db_user,
                    server=db_guild,
                    action=db_action,
                    expires=mute_time,
                    old_roles=old_roles,
                )
            session.add(db_mute)
            session.commit()

            # Add timer to remove mute
            timer = Timer.temporary(
                ctx.message.guild.id,
                member.id,
                old_roles,
                event=self._unmute,
                expires=mute_time,
                created=datetime.datetime.now(datetime.timezone.utc),
            )
            timer.start(self.bot.loop)
            if ctx.message.guild.id not in self.current_mutes:
                self.current_mutes[ctx.message.guild.id] = {}
            self.current_mutes[ctx.message.guild.id][member.id] = timer

        except Exception as e:
            set_sentry_scope(ctx)
            if mod_channel:
                await mod_channel.send(
                    f"There was an error while creating mute for {member.mention}\n"
                    f"**Error**: {e}")
            self.bot.log.exception(
                f"There was an error while creating mute for {member} ({member.id})"
            )
        finally:
            session.close()
Beispiel #5
0
    async def unmute(self, ctx, member: discord.Member):
        """Removes a mute for specified user.

        To Mute someone see mute
        """

        self.bot.log.info(
            f"CMD {ctx.command} called by {ctx.message.author} ({ctx.message.author.id})"
        )

        settings = self.bot.guild_settings.get(ctx.message.guild.id)
        muted_role_id = settings.muted_role
        muted_role = member.guild.get_role(muted_role_id)
        mod_channel = discord.utils.get(ctx.message.guild.text_channels,
                                        id=settings.mod_channel)
        if not mod_channel:
            await ctx.send(
                "Please set a mod channel using `config modchannel #channel`")
        # delete the message we used to invoke it
        if mod_channel and ctx.message.channel.id != mod_channel.id:
            try:
                await ctx.message.delete()
            except discord.HTTPException as err:
                self.bot.log.warning(
                    f"Couldn't delete command message for {ctx.command}: {err}"
                )

        session = self.bot.helpers.get_db_session()
        try:
            if muted_role is None:
                return await ctx.send("Mute role is not yet configured.")

            if muted_role not in member.roles:
                return await ctx.send("User is not muted")

            if (member is member.guild.owner or member.bot
                    or member is ctx.message.author):
                return await ctx.send(
                    "You may not use this command on that user.")

            old_mute_dt = None
            old_roles = []
            if (member.guild.id in self.current_mutes
                    and member.id in self.current_mutes[member.guild.id]):
                old_mute_dt = self.current_mutes[member.guild.id][
                    member.id].expires
                query = (session.query(models.Mute.old_roles).filter(
                    models.Mute.expires == old_mute_dt).first())
                if query:
                    old_roles = query.old_roles

            if self._unmute(member.guild.id, member.id, old_roles,
                            ctx.message.author):
                if ctx.message.channel.id == mod_channel.id:
                    await ctx.send(f"Successfully unmuted {member.mention}.")
                else:
                    await ctx.send(f"That action was successful.")
            else:
                await mod_channel.send(
                    f"Successfully unmuted {member.mention}. However, user could not be informed."
                )

            if old_mute_dt:
                # Get the DB profile for the guild
                db_guild = await self.bot.helpers.db_get_guild(
                    session, ctx.message.guild.id)
                # Get the DB profile for the user
                db_user = await self.bot.helpers.db_get_user(
                    session, member.id)
                # Get mod's DB profile
                db_mod = await self.bot.helpers.db_get_user(
                    session, ctx.message.author.id)
                db_action = models.Action(mod=db_mod, server=db_guild)

                db_mute = (session.query(
                    models.Mute).filter(models.Mute.server == db_guild).filter(
                        models.Mute.user == db_user).filter(
                            models.Mute.expires == old_mute_dt).one_or_none())
                if db_mute:
                    session.add(db_action)
                    session.commit()

                    db_mute.action_id = db_action.id
                    db_mute.expires = datetime.datetime.now(
                        datetime.timezone.utc)
                    db_mute.updated = datetime.datetime.now(
                        datetime.timezone.utc)
                    session.add(db_mute)
                    session.commit()
                else:
                    self.bot.log.warning(
                        f"Couldn't find mute for {member} ({member.id}) in database"
                    )
            else:
                self.bot.log.warning(
                    f"Couldn't find mute for {member} ({member.id}) in currently active mutes"
                )

        except Exception as e:
            set_sentry_scope(ctx)
            self.bot.log.exception(
                f"There was an error while unmuting {member} ({member.id})")
            await mod_channel.send(
                f"There was an error while unmuting {member.mention}\n"
                f"**Error**: {e}")
        finally:
            session.close()
Beispiel #6
0
    async def process_unban(self,
                            session,
                            member,
                            mod,
                            guild,
                            action_timestamp,
                            action_text="None"):
        db_logged = False
        chan_logged = False
        try:
            # Try and log to the database
            new_note = None
            try:
                # Get mod's DB profile
                db_mod = await self.bot.helpers.db_get_user(session, mod.id)
                # Get the DB profile for the guild
                db_guild = await self.bot.helpers.db_get_guild(
                    session, guild.id)
                # Get the DB profile for the user
                db_user = await self.bot.helpers.db_get_user(
                    session, member.id)

                logged_action = models.Action(mod=db_mod, server=db_guild)
                new_note = models.Note(
                    text=f"(Unban) {action_text}",
                    user=db_user,
                    server=db_guild,
                    action=logged_action,
                )
                session.add(new_note)
                session.commit()
                db_logged = True
            except DBAPIError as err:
                self.bot.log.exception(
                    f"Error logging unban to database for: ({member}). {sys.exc_info()[0].__name__}: {err}"
                )
                session.rollback()
                db_logged = False

            # Create the embed of info
            description = (f"**Member:** {member} ({member.id})\n"
                           f"**Moderator:** {mod} ({mod.id})\n"
                           f"**Reason:** {action_text[:1900]}")

            embed = discord.Embed(
                color=0xBDBDBD,
                timestamp=action_timestamp,
                title=
                f"A users ban was removed | *#{new_note.id if new_note else 'n/a'}*",
                description=description,
            )
            embed.set_author(name=f"{member} ({member.id})",
                             icon_url=member.avatar_url)
            # Try and get the logs channel
            logs = discord.utils.get(guild.text_channels, name="bot-logs")

            if not logs:
                # If there is no normal logs channel, try the sweeper (legacy) logs channel
                logs = discord.utils.get(guild.text_channels,
                                         name="sweeper-logs")

            if logs:
                # Checks if the bot can even send messages in that channel
                if (logs.permissions_for(logs.guild.me).send_messages
                        and logs.permissions_for(logs.guild.me).embed_links):
                    await logs.send(embed=embed)
                    chan_logged = True

        except Exception as err:
            self.bot.log.exception(
                f"Error processing ban for user: '******' in Guild: '{guild.id}'. {sys.exc_info()[0].__name__}: {err}"
            )
            raise
        finally:
            return db_logged, chan_logged
Beispiel #7
0
    async def kick(self, ctx, user_id: str, *, action_text: str):
        """Adds a database record for the user, attempts to message the user about the kick, then kicks from the guild.

        Example:

        kick userID this is a test message
        kick @wumpus#0000 this is a test message
        k @wumpus#0000 this is a test message

        Requires Permission: Manage Messages

        Parameters
        -----------
        ctx: context
            The context message involved.
        user_id: str
            The user/member the action is related to. Can be an ID or a mention
        action_text: str
            The action text you are adding to the record.
        """

        session = self.bot.helpers.get_db_session()
        try:
            self.bot.log.info(
                f"CMD {ctx.command} called by {ctx.message.author} ({ctx.message.author.id})"
            )
            # Get the user profile
            user = await self.bot.helpers.get_member_or_user(
                user_id, ctx.message.guild)
            if not user:
                return await ctx.send(
                    f"Unable to find the requested user. Please make sure the user ID or @ mention is valid."
                )
            # Don't allow you to kick yourself or the guild owner, or itself or other bots.
            if (user.id in [
                    ctx.message.author.id, ctx.message.guild.owner.id,
                    self.bot.user.id
            ] or user.bot):
                return await ctx.send(
                    f"Sorry, but you are not allowed to do that action to that user."
                )

            # Set some meta data
            action_type = "Kick"
            guild = ctx.message.guild
            settings = self.bot.guild_settings.get(guild.id)
            modmail_enabled = settings.modmail_server_id

            # Confirm the action
            confirm = await self.bot.prompt.send(
                ctx, f"Are you sure you want to kick {user} ({user.id})?")
            if confirm is False or None:
                return await ctx.send("Aborting kicking that user.")
            elif confirm:
                # Try to message the user
                try:
                    # Format the message
                    message = self.bot.constants.infraction_header.format(
                        action_type=action_type, guild=guild)

                    # Reduces the text to 1,800 characters to leave enough buffer for header and footer text
                    message += f"'{action_text[:1800]}'"
                    # Set footer based on if the server has modmail or not
                    if modmail_enabled:
                        message += self.bot.constants.footer_with_modmail.format(
                            guild=guild)
                    else:
                        message += self.bot.constants.footer_no_modmail.format(
                            guild=guild)
                    await user.send(message)
                    user_informed = (
                        f"User was successfully informed of their {action_type}."
                    )
                    msg_success = True
                except discord.errors.Forbidden as err:
                    self.bot.log.warning(
                        f"Error sending {action_type} to user. Bot is either blocked by user or doesn't share a server. Error: {sys.exc_info()[0].__name__}: {err}"
                    )
                    user_informed = f"User was unable to be informed of their {action_type}. They might not share a server with the bot, their DM's might not allow messages, or they blocked the bot."
                    msg_success = False

                # Try and log to the database
                new_kick = None
                try:
                    # Get mod's DB profile
                    db_mod = await self.bot.helpers.db_get_user(
                        session, ctx.message.author.id)
                    # Get the DB profile for the guild
                    db_guild = await self.bot.helpers.db_get_guild(
                        session, guild.id)
                    # Get the DB profile for the user
                    db_user = await self.bot.helpers.db_get_user(
                        session, user.id)

                    # Log the action to the database
                    # Edit the action_text to indicate success or failure on informing the user.
                    if msg_success:
                        action_text += " | **Msg Delivered: Yes**"
                    else:
                        action_text += " | **Msg Delivered: No**"
                    logged_action = models.Action(mod=db_mod, server=db_guild)
                    new_kick = models.Kick(
                        text=action_text,
                        user=db_user,
                        server=db_guild,
                        action=logged_action,
                    )
                    session.add(new_kick)
                    session.commit()
                    db_logged = True
                except Exception as err:
                    self.bot.log.exception(
                        f"Error logging {action_type} to database.")
                    db_logged = False

                # Create the embed of info
                description = (
                    f"**Member:** {user} ({user.id})\n"
                    f"**Moderator:** {ctx.message.author} ({ctx.message.author.id})\n"
                    f"**Reason:** {action_text[:1900]}")

                embed = discord.Embed(
                    color=0x0083FF,
                    timestamp=datetime.utcnow(),
                    title=f"A user was kicked | *#{new_kick.id}*",
                    description=description,
                )
                embed.set_author(name=f"{user} ({user.id})",
                                 icon_url=user.avatar_url)
                # Try and get the logs channel
                logs = discord.utils.get(guild.text_channels, name="bot-logs")

                if not logs:
                    # If there is no normal logs channel, try the sweeper (legacy) logs channel
                    logs = discord.utils.get(guild.text_channels,
                                             name="sweeper-logs")

                if logs:
                    # Checks if the bot can even send messages in that channel
                    if (logs.permissions_for(logs.guild.me).send_messages and
                            logs.permissions_for(logs.guild.me).embed_links):
                        await logs.send(embed=embed)

                # Now that we've handled messaging the user, let's kick them
                try:
                    if isinstance(user, discord.member.Member):
                        reason_text = f"Mod: {ctx.message.author} ({ctx.message.author.id}) | Reason: {action_text[:400]}"
                        await guild.kick(user, reason=reason_text)
                        if db_logged:
                            response = f"A {action_type} was successfully logged and actioned for: {user} ({user.id}).\n\n{user_informed}"
                        else:
                            response = f"A {action_type} was unable to be logged, however it was successfully actioned for: {user} ({user.id}).\n\n{user_informed}"
                        await ctx.send(response)
                    else:
                        raise Exception(
                            "User is not in the guild, unable to kick them.")
                except Exception as err:
                    self.bot.log.warning(
                        f"Failed to kick user. Error: {sys.exc_info()[0].__name__}: {err}"
                    )
                    await ctx.send(
                        f"Successfully logged a {action_type} for: {user} ({user.id}), however **unable to kick them.** This could mean they weren't in the server.\n\n{user_informed}"
                    )

        except discord.HTTPException as err:
            self.bot.log.error(
                f"Discord HTTP Error responding to {ctx.command} request via Msg ID {ctx.message.id}. {sys.exc_info()[0].__name__}: {err}"
            )
            await ctx.send(
                f"Error processing {ctx.command}. Error has already been reported to my developers."
            )
        except DBAPIError as err:
            self.bot.log.exception(
                f"Error with database calls in CMD {ctx.command} for: ({user_id}). {sys.exc_info()[0].__name__}: {err}"
            )
            await ctx.send(
                f"Error processing {ctx.command}. Error has already been reported to my developers."
            )
            session.rollback()
        except Exception as err:
            self.bot.log.exception(
                f"Error responding to {ctx.command} via Msg ID {ctx.message.id}. {sys.exc_info()[0].__name__}: {err}"
            )
            await ctx.send(
                f"Error processing {ctx.command}. Error has already been reported to my developers."
            )
        finally:
            session.close()