<commit_before>"""
Contains commands that relate to server moderation and management.
"""

import logging

import discord
import emoji
from discord.ext import commands

from dog import Cog
from dog.core import checks, converters
from dog.core.converters import DeleteDays
from dog.core.utils.formatting import describe

logger = logging.getLogger(__name__)


class Mod(Cog):
    async def __global_check(self, ctx: commands.Context):
        # do not handle guild-specific command disables in dms
        if not isinstance(ctx.channel, discord.abc.GuildChannel):
            return True

        # role names that cannot use dog
        banned_names = (
            'Can\'t Use Dog', 'can\'t use dog', 'Dog Plonk', 'dog plonk', 'Banned from Dog', 'banned from dog'
        )

        if any(discord.utils.get(ctx.author.roles, name=name) for name in banned_names):
            return False

        return not await self.bot.command_is_disabled(ctx.guild, ctx.command.name)

    async def on_message(self, message: discord.Message):
        # do not handle invisibility in dms
        if isinstance(message.channel, discord.abc.PrivateChannel):
            return

        if await self.bot.config_is_set(message.guild, 'invisible_nag'):
            if message.author.status is discord.Status.offline:
                reply = 'Hey {0.mention}! You\'re invisible. Stop being invisible, please. Thanks.'
                await message.channel.send(reply.format(message.author))

    async def base_purge(self, ctx: commands.Context, limit: int, check=None, **kwargs):
        # check if it's too much
        if limit > 5000:
            await ctx.send('Too many messages to purge. 5,000 is the maximum.')
            return

        # purge the actual command message too
        limit += 1

        try:
            msgs = await ctx.channel.purge(limit=limit, check=check, **kwargs)
            await ctx.send(f'Purge complete. Removed {len(msgs)} message(s).', delete_after=2.5)
        except discord.NotFound:
            pass  # ignore not found errors

    @commands.group(invoke_without_command=True)
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge(self, ctx, amount: int):
        """
        Purges messages the last <n> messages.

        This includes the purge command message. The bot will send a message
        upon completion, but will automatically be deleted.

        Note: The <n> that you specify will be the amount of messages checked,
              not deleted. This only applies to purge subcommands.
        """
        await self.base_purge(ctx, amount)

    @purge.command(name='by', aliases=['from'])
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge_by(self, ctx, target: discord.Member, amount: int = 5):
        """ Purges <n> messages from someone. """
        await self.base_purge(ctx, amount, lambda m: m.author == target)

    @purge.command(name='embeds', aliases=['e'])
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge_embeds(self, ctx, amount: int = 5):
        """ Purges <n> messages containing embeds. """
        await self.base_purge(ctx, amount, lambda m: len(m.embeds) != 0)

    @purge.command(name='attachments', aliases=['images', 'uploads', 'i'])
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge_attachments(self, ctx, amount: int = 5):
        """ Purges <n> messages containing attachments. """
        await self.base_purge(ctx, amount, lambda m: len(m.attachments) != 0)

    @purge.command(name='bot')
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge_bot(self, ctx, amount: int = 5):
        """ Purges <n> messages by bots. """
        await self.base_purge(ctx, amount, lambda m: m.author.bot)

    @purge.command(name='emoji', aliases=['emojis'])
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge_emoji(self, ctx, amount: int = 5, minimum_emoji: int = 3):
        """ Purges <n> messages with at least 3 emoji (by default). """
        def message_check(msg):
            emoji_count = sum(1 for c in msg.content if c in emoji.UNICODE_EMOJI)
            return emoji_count >= minimum_emoji
        await self.base_purge(ctx, amount, message_check)

    @commands.command()
    @commands.guild_only()
    async def clean(self, ctx):
        """ Removes recent messages posted by the bot. """
        try:
            await ctx.channel.purge(limit=50, check=lambda m: m.author == ctx.bot.user)
        except discord.NotFound:
            pass

    async def _check_who_action(self, ctx, action, target, action_past_tense):
        al_action = getattr(discord.AuditLogAction, action)
        try:
            target_id = int(target)
        except ValueError:
            target_id = None

        # scan the audit logs for the action they specified
        async for entry in ctx.guild.audit_logs(limit=None):<commit_msg>Make d?purge emoji remove custom emoji<commit_after>"""
Contains commands that relate to server moderation and management.
"""
import logging
import re

import discord
import emoji
from discord.ext import commands

from dog import Cog
from dog.core import checks, converters
from dog.core.converters import DeleteDays
from dog.core.utils.formatting import describe

logger = logging.getLogger(__name__)

CUSTOM_EMOJI_REGEX = re.compile(r'<:([a-zA-Z_0-9-]+):(\d+)>')


class Mod(Cog):
    async def __global_check(self, ctx: commands.Context):
        # do not handle guild-specific command disables in dms
        if not isinstance(ctx.channel, discord.abc.GuildChannel):
            return True

        # role names that cannot use dog
        banned_names = (
            'Can\'t Use Dog', 'can\'t use dog', 'Dog Plonk', 'dog plonk', 'Banned from Dog', 'banned from dog'
        )

        if any(discord.utils.get(ctx.author.roles, name=name) for name in banned_names):
            return False

        return not await self.bot.command_is_disabled(ctx.guild, ctx.command.name)

    async def on_message(self, message: discord.Message):
        # do not handle invisibility in dms
        if isinstance(message.channel, discord.abc.PrivateChannel):
            return

        if await self.bot.config_is_set(message.guild, 'invisible_nag'):
            if message.author.status is discord.Status.offline:
                reply = 'Hey {0.mention}! You\'re invisible. Stop being invisible, please. Thanks.'
                await message.channel.send(reply.format(message.author))

    async def base_purge(self, ctx: commands.Context, limit: int, check=None, **kwargs):
        # check if it's too much
        if limit > 5000:
            await ctx.send('Too many messages to purge. 5,000 is the maximum.')
            return

        # purge the actual command message too
        limit += 1

        try:
            msgs = await ctx.channel.purge(limit=limit, check=check, **kwargs)
            await ctx.send(f'Purge complete. Removed {len(msgs)} message(s).', delete_after=2.5)
        except discord.NotFound:
            pass  # ignore not found errors

    @commands.group(invoke_without_command=True)
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge(self, ctx, amount: int):
        """
        Purges messages the last <n> messages.

        This includes the purge command message. The bot will send a message
        upon completion, but will automatically be deleted.

        Note: The <n> that you specify will be the amount of messages checked,
              not deleted. This only applies to purge subcommands.
        """
        await self.base_purge(ctx, amount)

    @purge.command(name='by', aliases=['from'])
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge_by(self, ctx, target: discord.Member, amount: int = 5):
        """ Purges <n> messages from someone. """
        await self.base_purge(ctx, amount, lambda m: m.author == target)

    @purge.command(name='embeds', aliases=['e'])
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge_embeds(self, ctx, amount: int = 5):
        """ Purges <n> messages containing embeds. """
        await self.base_purge(ctx, amount, lambda m: len(m.embeds) != 0)

    @purge.command(name='attachments', aliases=['images', 'uploads', 'i'])
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge_attachments(self, ctx, amount: int = 5):
        """ Purges <n> messages containing attachments. """
        await self.base_purge(ctx, amount, lambda m: len(m.attachments) != 0)

    @purge.command(name='bot')
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge_bot(self, ctx, amount: int = 5):
        """ Purges <n> messages by bots. """
        await self.base_purge(ctx, amount, lambda m: m.author.bot)

    @purge.command(name='emoji', aliases=['emojis'])
    @commands.guild_only()
    @checks.bot_perms(manage_messages=True, read_message_history=True)
    @checks.is_moderator()
    async def purge_emoji(self, ctx, amount: int = 5, minimum_emoji: int = 1):
        """ Purges any message in the last <n> messages with emoji. """
        def message_check(msg):
            emoji_count = sum(1 for c in msg.content if c in emoji.UNICODE_EMOJI)
            return emoji_count >= minimum_emoji or CUSTOM_EMOJI_REGEX.search(msg.content) is not None
        await self.base_purge(ctx, amount, message_check)

    @commands.command()
    @commands.guild_only()
    async def clean(self, ctx):
        """ Removes recent messages posted by the bot. """
        try:
            await ctx.channel.purge(limit=50, check=lambda m: m.author == ctx.bot.user)
        except discord.NotFound:
            pass

    async def _check_who_action(self, ctx, action, target, action_past_tense):
        al_action = getattr(discord.AuditLogAction, action)
        try:
            target_id = int(target)
        except ValueError:
            target_id = None

        # scan the audit logs for the action they specified
        async for entry in ctx.guild.audit_logs(limit=None):
{'fraction_non_alphanumeric': 0.109647102183728, 'fraction_numerical': 0.004514880678153506, 'mean_word_length': 2.9642074506939373, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2679163', 'n_tokens_mistral': 3424, 'n_tokens_neox': 3283, 'n_words': 913}