Пример #1
0
    async def before(self,
                     ctx: commands.Context,
                     message_id: int,
                     number: int,
                     delete_pinned: bool = False):
        """Deletes X messages before specified message.

        To get a message id, enable developer mode in Discord's
        settings, 'appearance' tab. Then right click a message
        and copy its id.
        """

        channel = ctx.channel
        author = ctx.author

        try:
            before = await channel.get_message(message_id)
        except discord.NotFound:
            return await ctx.send(_("Message not found."))

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            before=before,
            delete_pinned=delete_pinned)
        to_delete.append(ctx.message)

        reason = "{}({}) deleted {} messages in channel {}.".format(
            author.name, author.id, len(to_delete), channel.name)
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #2
0
    async def messages(self, ctx: commands.Context, number: int, delete_pinned: bool = False):
        """Delete the last X messages.

        Example:
            `[p]cleanup messages 26`
        """

        channel = ctx.channel
        author = ctx.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        to_delete = await self.get_messages_for_deletion(
            channel=channel, number=number, before=ctx.message, delete_pinned=delete_pinned
        )
        to_delete.append(ctx.message)

        reason = "{}({}) deleted {} messages in channel {}.".format(
            author.name, author.id, number, channel.name
        )
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #3
0
    async def messages(self,
                       ctx: commands.Context,
                       number: int,
                       delete_pinned: bool = False):
        """Delete the last X messages.

        Example:
            `[p]cleanup messages 26`
        """

        channel = ctx.channel
        author = ctx.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            before=ctx.message,
            delete_pinned=delete_pinned)
        to_delete.append(ctx.message)

        reason = "{}({}) deleted {} messages in channel {}.".format(
            author.name, author.id, number, channel.name)
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #4
0
    async def messages(self,
                       ctx: commands.Context,
                       number: int,
                       delete_pinned: bool = False):
        """Deletes last X messages.

        Example:
        cleanup messages 26"""

        channel = ctx.channel
        if not channel.permissions_for(ctx.guild.me).manage_messages:
            await ctx.send("I need the Manage Messages permission to do this.")
            return
        author = ctx.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            before=ctx.message,
            delete_pinned=delete_pinned)
        to_delete.append(ctx.message)

        reason = "{}({}) deleted {} messages in channel {}.".format(
            author.name, author.id, number, channel.name)
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #5
0
    async def after(self,
                    ctx: commands.Context,
                    message_id: int,
                    delete_pinned: bool = False):
        """Deletes all messages after specified message.

        To get a message id, enable developer mode in Discord's
        settings, 'appearance' tab. Then right click a message
        and copy its id.

        This command only works on bots running as bot accounts.
        """

        channel = ctx.channel
        if not channel.permissions_for(ctx.guild.me).manage_messages:
            await ctx.send("I need the Manage Messages permission to do this.")
            return
        author = ctx.author

        try:
            after = await channel.get_message(message_id)
        except discord.NotFound:
            return await ctx.send(_("Message not found."))

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=None,
            after=after,
            delete_pinned=delete_pinned)

        reason = "{}({}) deleted {} messages in channel {}.".format(
            author.name, author.id, len(to_delete), channel.name)
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #6
0
    async def before(
        self, ctx: commands.Context, message_id: int, number: int, delete_pinned: bool = False
    ):
        """Deletes X messages before specified message.

        To get a message id, enable developer mode in Discord's
        settings, 'appearance' tab. Then right click a message
        and copy its id.
        """

        channel = ctx.channel
        author = ctx.author

        try:
            before = await channel.get_message(message_id)
        except discord.NotFound:
            return await ctx.send(_("Message not found."))

        to_delete = await self.get_messages_for_deletion(
            channel=channel, number=number, before=before, delete_pinned=delete_pinned
        )
        to_delete.append(ctx.message)

        reason = "{}({}) deleted {} messages in channel {}.".format(
            author.name, author.id, len(to_delete), channel.name
        )
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #7
0
    async def cleanup_bot(self,
                          ctx: commands.Context,
                          number: int,
                          delete_pinned: bool = False):
        """Cleans up command messages and messages from the bot."""

        channel = ctx.channel
        if not channel.permissions_for(ctx.guild.me).manage_messages:
            await ctx.send("I need the Manage Messages permission to do this.")
            return
        author = ctx.message.author
        is_bot = self.bot.user.bot

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        prefixes = await self.bot.get_prefix(
            ctx.message)  # This returns all server prefixes
        if isinstance(prefixes, str):
            prefixes = [prefixes]

        # In case some idiot sets a null prefix
        if "" in prefixes:
            prefixes.remove("")

        def check(m):
            if m.author.id == self.bot.user.id:
                return True
            elif m == ctx.message:
                return True
            p = discord.utils.find(m.content.startswith, prefixes)
            if p and len(p) > 0:
                cmd_name = m.content[len(p):].split(" ")[0]
                return bool(self.bot.get_command(cmd_name))
            return False

        to_delete = await self.get_messages_for_deletion(
            ctx,
            channel,
            number,
            check=check,
            limit=1000,
            before=ctx.message,
            delete_pinned=delete_pinned,
        )
        to_delete.append(ctx.message)

        reason = ("{}({}) deleted {} "
                  " command messages in channel {}."
                  "".format(author.name, author.id, len(to_delete),
                            channel.name))
        log.info(reason)

        if is_bot:
            await mass_purge(to_delete, channel)
        else:
            await slow_deletion(to_delete)
Пример #8
0
    async def user(self,
                   ctx: commands.Context,
                   user: str,
                   number: int,
                   delete_pinned: bool = False):
        """Deletes last X messages from specified user.

        Examples:
        cleanup user @\u200bTwentysix 2
        cleanup user Red 6"""
        channel = ctx.channel
        if not channel.permissions_for(ctx.guild.me).manage_messages:
            await ctx.send("I need the Manage Messages permission to do this.")
            return

        member = None
        try:
            member = await commands.converter.MemberConverter().convert(
                ctx, user)
        except commands.BadArgument:
            try:
                _id = int(user)
            except ValueError:
                raise commands.BadArgument()
        else:
            _id = member.id

        author = ctx.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        def check(m):
            if m.author.id == _id:
                return True
            elif m == ctx.message:
                return True
            else:
                return False

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            check=check,
            before=ctx.message,
            delete_pinned=delete_pinned,
        )
        reason = ("{}({}) deleted {} messages "
                  " made by {}({}) in channel {}."
                  "".format(author.name, author.id, len(to_delete), member
                            or "???", _id, channel.name))
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #9
0
    async def after(self,
                    ctx: commands.Context,
                    message_id: int,
                    delete_pinned: bool = False):
        """Deletes all messages after specified message.

        To get a message id, enable developer mode in Discord's
        settings, 'appearance' tab. Then right click a message
        and copy its id.

        This command only works on bots running as bot accounts.
        """

        channel = ctx.channel
        if not channel.permissions_for(ctx.guild.me).manage_messages:
            await ctx.send("I need the Manage Messages permission to do this.")
            return
        author = ctx.author
        is_bot = self.bot.user.bot

        if not is_bot:
            await ctx.send(
                _("This command can only be used on bots with bot accounts."))
            return

        try:
            message = await channel.get_message(message_id)
        except discord.NotFound:
            await ctx.send(_("Message not found."))
            return

        if (ctx.message.created_at - message.created_at).days >= 14:
            await ctx.send(
                "The specified message must be less than 14 days old.")
            return

        if not delete_pinned:
            pinned_msgs = await channel.pins()
            to_exclude = set(m for m in pinned_msgs
                             if m.created_at > message.created_at)
        else:
            to_exclude = None

        if to_exclude:
            to_delete = await channel.history(limit=None,
                                              after=message).flatten()
            to_delete = set(to_delete) - to_exclude
            await channel.delete_messages(to_delete)
            num_deleted = len(to_delete)
        else:
            num_deleted = len(await channel.purge(limit=None, after=message))

        reason = "{}({}) deleted {} messages in channel {}.".format(
            author.name, author.id, num_deleted, channel.name)
        log.info(reason)
Пример #10
0
    async def user(
        self, ctx: commands.Context, user: str, number: int, delete_pinned: bool = False
    ):
        """Delete the last X messages from a specified user.

        Examples:
            `[p]cleanup user @\u200bTwentysix 2`
            `[p]cleanup user Red 6`
        """
        channel = ctx.channel

        member = None
        try:
            member = await commands.MemberConverter().convert(ctx, user)
        except commands.BadArgument:
            try:
                _id = int(user)
            except ValueError:
                raise commands.BadArgument()
        else:
            _id = member.id

        author = ctx.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        def check(m):
            if m.author.id == _id:
                return True
            else:
                return False

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            check=check,
            before=ctx.message,
            delete_pinned=delete_pinned,
        )
        to_delete.append(ctx.message)

        reason = (
            "{}({}) deleted {} messages "
            " made by {}({}) in channel {}."
            "".format(author.name, author.id, len(to_delete), member or "???", _id, channel.name)
        )
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #11
0
    async def text(self,
                   ctx: commands.Context,
                   text: str,
                   number: int,
                   delete_pinned: bool = False):
        """Deletes last X messages matching the specified text.

        Example:
        cleanup text \"test\" 5

        Remember to use double quotes."""

        channel = ctx.channel
        if not channel.permissions_for(ctx.guild.me).manage_messages:
            await ctx.send("I need the Manage Messages permission to do this.")
            return

        author = ctx.author
        is_bot = self.bot.user.bot

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        def check(m):
            if text in m.content:
                return True
            elif m == ctx.message:
                return True
            else:
                return False

        to_delete = await self.get_messages_for_deletion(
            ctx,
            channel,
            number,
            check=check,
            limit=1000,
            before=ctx.message,
            delete_pinned=delete_pinned,
        )

        reason = "{}({}) deleted {} messages containing '{}' in channel {}.".format(
            author.name, author.id, len(to_delete), text, channel.id)
        log.info(reason)

        if is_bot:
            await mass_purge(to_delete, channel)
        else:
            await slow_deletion(to_delete)
Пример #12
0
    async def text(self,
                   ctx: commands.Context,
                   text: str,
                   number: int,
                   delete_pinned: bool = False):
        """Delete the last X messages matching the specified text.

        Example:
            `[p]cleanup text "test" 5`

        Remember to use double quotes.
        """

        channel = ctx.channel

        author = ctx.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        def check(m):
            if text in m.content:
                return True
            else:
                return False

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            check=check,
            before=ctx.message,
            delete_pinned=delete_pinned,
        )
        to_delete.append(ctx.message)

        reason = "{}({}) deleted {} messages containing '{}' in channel {}.".format(
            author.name, author.id, len(to_delete), text, channel.id)
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #13
0
    async def text(
        self, ctx: commands.Context, text: str, number: int, delete_pinned: bool = False
    ):
        """Delete the last X messages matching the specified text.

        Example:
            `[p]cleanup text "test" 5`

        Remember to use double quotes.
        """

        channel = ctx.channel

        author = ctx.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        def check(m):
            if text in m.content:
                return True
            else:
                return False

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            check=check,
            before=ctx.message,
            delete_pinned=delete_pinned,
        )
        to_delete.append(ctx.message)

        reason = "{}({}) deleted {} messages containing '{}' in channel {}.".format(
            author.name, author.id, len(to_delete), text, channel.id
        )
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #14
0
    async def cleanup_self(
        self,
        ctx: commands.Context,
        number: int,
        match_pattern: str = None,
        delete_pinned: bool = False,
    ):
        """Clean up messages owned by the bot.

        By default, all messages are cleaned. If a third argument is specified,
        it is used for pattern matching: If it begins with r( and ends with ),
        then it is interpreted as a regex, and messages that match it are
        deleted. Otherwise, it is used in a simple substring test.

        Some helpful regex flags to include in your pattern:
        Dots match newlines: (?s); Ignore case: (?i); Both: (?si)
        """
        channel = ctx.channel
        author = ctx.message.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        # You can always delete your own messages, this is needed to purge
        can_mass_purge = False
        if type(author) is discord.Member:
            me = ctx.guild.me
            can_mass_purge = channel.permissions_for(me).manage_messages

        use_re = match_pattern and match_pattern.startswith(
            "r(") and match_pattern.endswith(")")

        if use_re:
            match_pattern = match_pattern[1:]  # strip 'r'
            match_re = re.compile(match_pattern)

            def content_match(c):
                return bool(match_re.match(c))

        elif match_pattern:

            def content_match(c):
                return match_pattern in c

        else:

            def content_match(_):
                return True

        def check(m):
            if m.author.id != self.bot.user.id:
                return False
            elif content_match(m.content):
                return True
            return False

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            check=check,
            before=ctx.message,
            delete_pinned=delete_pinned,
        )

        if ctx.guild:
            channel_name = "channel " + channel.name
        else:
            channel_name = str(channel)

        reason = ("{}({}) deleted {} messages "
                  "sent by the bot in {}."
                  "".format(author.name, author.id, len(to_delete),
                            channel_name))
        log.info(reason)

        if can_mass_purge:
            await mass_purge(to_delete, channel)
        else:
            await slow_deletion(to_delete)
Пример #15
0
    async def cleanup_bot(self,
                          ctx: commands.Context,
                          number: int,
                          delete_pinned: bool = False):
        """Clean up command messages and messages from the bot."""

        channel = ctx.channel
        author = ctx.message.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        prefixes = await self.bot.get_prefix(
            ctx.message)  # This returns all server prefixes
        if isinstance(prefixes, str):
            prefixes = [prefixes]

        # In case some idiot sets a null prefix
        if "" in prefixes:
            prefixes.remove("")

        cc_cog = self.bot.get_cog("CustomCommands")
        if cc_cog is not None:
            command_names: Set[str] = await cc_cog.get_command_names(ctx.guild)
            is_cc = lambda name: name in command_names
        else:
            is_cc = lambda name: False
        alias_cog = self.bot.get_cog("Alias")
        if alias_cog is not None:
            alias_names: Set[str] = (
                set((a.name
                     for a in await alias_cog.unloaded_global_aliases()))
                | set(a.name
                      for a in await alias_cog.unloaded_aliases(ctx.guild)))
            is_alias = lambda name: name in alias_names
        else:
            is_alias = lambda name: False

        bot_id = self.bot.user.id

        def check(m):
            if m.author.id == bot_id:
                return True
            elif m == ctx.message:
                return True
            p = discord.utils.find(m.content.startswith, prefixes)
            if p and len(p) > 0:
                cmd_name = m.content[len(p):].split(" ")[0]
                return (bool(self.bot.get_command(cmd_name))
                        or is_alias(cmd_name) or is_cc(cmd_name))
            return False

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            check=check,
            before=ctx.message,
            delete_pinned=delete_pinned,
        )
        to_delete.append(ctx.message)

        reason = ("{}({}) deleted {} "
                  " command messages in channel {}."
                  "".format(author.name, author.id, len(to_delete),
                            channel.name))
        log.info(reason)

        await mass_purge(to_delete, channel)
Пример #16
0
    async def cleanup_self(
        self,
        ctx: commands.Context,
        number: int,
        match_pattern: str = None,
        delete_pinned: bool = False,
    ):
        """Clean up messages owned by the bot.

        By default, all messages are cleaned. If a third argument is specified,
        it is used for pattern matching: If it begins with r( and ends with ),
        then it is interpreted as a regex, and messages that match it are
        deleted. Otherwise, it is used in a simple substring test.

        Some helpful regex flags to include in your pattern:
        Dots match newlines: (?s); Ignore case: (?i); Both: (?si)
        """
        channel = ctx.channel
        author = ctx.message.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        # You can always delete your own messages, this is needed to purge
        can_mass_purge = False
        if type(author) is discord.Member:
            me = ctx.guild.me
            can_mass_purge = channel.permissions_for(me).manage_messages

        use_re = match_pattern and match_pattern.startswith("r(") and match_pattern.endswith(")")

        if use_re:
            match_pattern = match_pattern[1:]  # strip 'r'
            match_re = re.compile(match_pattern)

            def content_match(c):
                return bool(match_re.match(c))

        elif match_pattern:

            def content_match(c):
                return match_pattern in c

        else:

            def content_match(_):
                return True

        def check(m):
            if m.author.id != self.bot.user.id:
                return False
            elif content_match(m.content):
                return True
            return False

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            check=check,
            before=ctx.message,
            delete_pinned=delete_pinned,
        )

        if ctx.guild:
            channel_name = "channel " + channel.name
        else:
            channel_name = str(channel)

        reason = (
            "{}({}) deleted {} messages "
            "sent by the bot in {}."
            "".format(author.name, author.id, len(to_delete), channel_name)
        )
        log.info(reason)

        if can_mass_purge:
            await mass_purge(to_delete, channel)
        else:
            await slow_deletion(to_delete)
Пример #17
0
    async def cleanup_bot(self, ctx: commands.Context, number: int, delete_pinned: bool = False):
        """Clean up command messages and messages from the bot."""

        channel = ctx.channel
        author = ctx.message.author

        if number > 100:
            cont = await self.check_100_plus(ctx, number)
            if not cont:
                return

        prefixes = await self.bot.get_prefix(ctx.message)  # This returns all server prefixes
        if isinstance(prefixes, str):
            prefixes = [prefixes]

        # In case some idiot sets a null prefix
        if "" in prefixes:
            prefixes.remove("")

        cc_cog = self.bot.get_cog("CustomCommands")
        if cc_cog is not None:
            command_names: Set[str] = await cc_cog.get_command_names(ctx.guild)
            is_cc = lambda name: name in command_names
        else:
            is_cc = lambda name: False
        alias_cog = self.bot.get_cog("Alias")
        if alias_cog is not None:
            alias_names: Set[str] = (
                set((a.name for a in await alias_cog.unloaded_global_aliases()))
                | set(a.name for a in await alias_cog.unloaded_aliases(ctx.guild))
            )
            is_alias = lambda name: name in alias_names
        else:
            is_alias = lambda name: False

        bot_id = self.bot.user.id

        def check(m):
            if m.author.id == bot_id:
                return True
            elif m == ctx.message:
                return True
            p = discord.utils.find(m.content.startswith, prefixes)
            if p and len(p) > 0:
                cmd_name = m.content[len(p) :].split(" ")[0]
                return (
                    bool(self.bot.get_command(cmd_name)) or is_alias(cmd_name) or is_cc(cmd_name)
                )
            return False

        to_delete = await self.get_messages_for_deletion(
            channel=channel,
            number=number,
            check=check,
            before=ctx.message,
            delete_pinned=delete_pinned,
        )
        to_delete.append(ctx.message)

        reason = (
            "{}({}) deleted {} "
            " command messages in channel {}."
            "".format(author.name, author.id, len(to_delete), channel.name)
        )
        log.info(reason)

        await mass_purge(to_delete, channel)