Beispiel #1
0
    def __init__(self, bot):
        super(AntiSpam, self).__init__(bot)
        # store values as functions so only what is needed is computed
        self.generators = {
            "max_messages": lambda m: 1,
            "max_newlines": lambda m: len(m.content.split("\n")) - 1,
            "max_mentions": lambda m: len(MENTION_MATCHER.findall(m.content)),
            "max_links": lambda m: len(URL_MATCHER.findall(m.content))
        }

        self.punishments = {
            "warn": self.warn_punishment,
            "mute": self.mute_punishment,
            "kick": self.kick_punishment,
            "temp_ban": self.temp_ban_punishment,
            "ban": self.ban_punishment
        }

        self.seriousness = {
            "warn": 1,
            "mute": 2,
            "kick": 3,
            "temp_ban": 4,
            "ban": 5
        }
        self.extra_actions = WeakValueDictionary()
        self.processed = deque(maxlen=500)
        self.censor_processed = deque(maxlen=50)
        self.running = True
        bot.loop.create_task(self.censor_detector())
Beispiel #2
0
async def clean(text,
                guild: discord.Guild = None,
                markdown=True,
                links=True,
                emoji=True,
                lookalikes=True):
    text = str(text)

    if guild is not None:
        # resolve user mentions
        for uid in set(ID_MATCHER.findall(text)):
            name = "@" + await username(int(uid), False, False)
            text = text.replace(f"<@{uid}>", name)
            text = text.replace(f"<@!{uid}>", name)

        # resolve role mentions
        for uid in set(ROLE_ID_MATCHER.findall(text)):
            role = discord.utils.get(guild.roles, id=int(uid))
            if role is None:
                name = "@UNKNOWN ROLE"
            else:
                name = "@" + role.name
            text = text.replace(f"<@&{uid}>", name)

        # resolve channel names
        for uid in set(CHANNEL_ID_MATCHER.findall(text)):
            channel = guild.get_channel(uid)
            if channel is None:
                name = "#UNKNOWN CHANNEL"
            else:
                name = "#" + channel.name
            text = text.replace(f"<@#{uid}>", name)

        # re-assemble emoji so such a way that they don't turn into twermoji

    urls = set(URL_MATCHER.findall(text))

    if lookalikes:
        text = replace_lookalikes(text)

    if markdown:
        text = escape_markdown(text)
    else:
        text = text.replace("@",
                            "@\u200b").replace("**",
                                               "*​*").replace("``", "`​`")

    if emoji:
        for e in set(EMOJI_MATCHER.findall(text)):
            a, b, c = zip(e)
            text = text.replace(f"<{a[0]}:{b[0]}:{c[0]}>",
                                f"<{a[0]}\\:{b[0]}\\:{c[0]}>")

    if links:
        #find urls last so the < escaping doesn't break it
        for url in urls:
            text = text.replace(escape_markdown(url), f"<{url}>")

    return text
Beispiel #3
0
    async def check_message(self, member, content, channel, message_id):
        if Permissioncheckers.get_user_lvl(member.guild, member) >= 2:
            return
        censorlist = Configuration.get_var(member.guild.id, "CENSORING",
                                           "TOKEN_CENSORLIST")
        word_censorlist = Configuration.get_var(member.guild.id, "CENSORING",
                                                "WORD_CENSORLIST")
        guilds = Configuration.get_var(member.guild.id, "CENSORING",
                                       "ALLOWED_INVITE_LIST")
        domain_list = Configuration.get_var(member.guild.id, "CENSORING",
                                            "DOMAIN_LIST")
        domains_allowed = Configuration.get_var(member.guild.id, "CENSORING",
                                                "DOMAIN_LIST_ALLOWED")
        full_message_list = Configuration.get_var(member.guild.id, "CENSORING",
                                                  "FULL_MESSAGE_LIST")
        censor_emoji_message = Configuration.get_var(
            member.guild.id, "CENSORING", "CENSOR_EMOJI_ONLY_MESSAGES")
        content = content.replace('\\', '')
        decoded_content = parse.unquote(content)

        if len(guilds) is not 0:
            codes = INVITE_MATCHER.findall(decoded_content)
            for code in codes:
                try:
                    invite: discord.Invite = await self.bot.fetch_invite(code)
                except discord.NotFound:
                    await self.censor_invite(member, message_id, channel, code,
                                             "INVALID INVITE", content)
                    return
                if invite.guild is None:
                    await self.censor_invite(member, message_id, channel, code,
                                             "DM group", content)
                    return
                else:
                    if invite.guild is None or (
                            not invite.guild.id in guilds
                            and invite.guild.id != member.guild.id):
                        await self.censor_invite(member, message_id, channel,
                                                 code, invite.guild.name,
                                                 content)
                        return

        content = content.lower()

        if content in full_message_list:
            await self.censor_message(message_id, content, channel, member, "",
                                      "_content")
            return

        for bad in (w.lower() for w in censorlist):
            if bad in content:
                await self.censor_message(message_id, content, channel, member,
                                          bad)
                return

        if len(word_censorlist) > 0:
            if channel.guild.id not in self.regexes:
                regex = re.compile(
                    r"\b(" +
                    '|'.join(re.escape(word)
                             for word in word_censorlist) + r")\b",
                    re.IGNORECASE)
                self.regexes[channel.guild.id] = regex
            else:
                regex = self.regexes[channel.guild.id]
            match = regex.findall(content)
            if len(match):
                await self.censor_message(message_id, content, channel, member,
                                          match[0], "_word")
                return

        if len(domain_list) > 0:
            link_list = URL_MATCHER.findall(content)
            for link in link_list:
                url = urlparse(link)
                domain = url.hostname
                if (domain in domain_list) is not domains_allowed:
                    await self.censor_message(message_id, content, channel,
                                              member, url.hostname,
                                              "_domain_blocked")
                    return

        if censor_emoji_message and content is not None and len(content) > 0:
            new_content = ''.join(c for c in content
                                  if c not in emoji.UNICODE_EMOJI)
            new_content = re.sub(EMOJI_REGEX, '', new_content)
            if new_content == '':
                await self.censor_message(message_id, content, channel, member,
                                          '', "_emoji_only")
                return
Beispiel #4
0
    async def check_message(self, message: discord.Message):
        if message.guild is None or \
                message.webhook_id is not None or \
                message.author == message.guild.me:
            return
        ctx = await self.bot.get_context(message)
        if Permissioncheckers.get_user_lvl(ctx.guild, ctx.author) >= 2:
            return
        censorlist = Configuration.get_var(message.guild.id, "CENSORING",
                                           "TOKEN_CENSORLIST")
        word_censorlist = Configuration.get_var(message.guild.id, "CENSORING",
                                                "WORD_CENSORLIST")
        guilds = Configuration.get_var(message.guild.id, "CENSORING",
                                       "ALLOWED_INVITE_LIST")
        domain_list = Configuration.get_var(message.guild.id, "CENSORING",
                                            "DOMAIN_LIST")
        domains_allowed = Configuration.get_var(message.guild.id, "CENSORING",
                                                "DOMAIN_LIST_ALLOWED")
        content = message.content.replace('\\', '')
        decoded_content = parse.unquote(content)
        censored = False
        if len(guilds) is not 0:
            codes = INVITE_MATCHER.findall(decoded_content)
            for code in codes:
                try:
                    invite: discord.Invite = await self.bot.fetch_invite(code)
                except discord.NotFound:
                    await self.censor_invite(ctx, code, "INVALID INVITE")
                    return
                if invite.guild is None:
                    await self.censor_invite(ctx, code, "DM group")
                    censored = True
                else:
                    if invite.guild is None or (
                            not invite.guild.id in guilds
                            and invite.guild.id != message.guild.id):
                        await self.censor_invite(ctx, code, invite.guild.name)
                        censored = True

        if not censored:
            content = content.lower()
            for bad in (w.lower() for w in censorlist):
                if bad in content:
                    await self.censor_message(message, bad)
                    censored = True
                    break

        if not censored and len(word_censorlist) > 0:
            if ctx.guild.id not in self.regexes:
                regex = re.compile(
                    r"\b(" +
                    '|'.join(re.escape(word)
                             for word in word_censorlist) + r")\b",
                    re.IGNORECASE)
                self.regexes[ctx.guild.id] = regex
            else:
                regex = self.regexes[ctx.guild.id]
            match = regex.findall(message.content)
            if len(match):
                await self.censor_message(message, match[0], "_word")
                censored = True

        if not censored and len(domain_list) > 0:
            link_list = URL_MATCHER.findall(message.content)
            for link in link_list:
                url = urlparse(link)
                domain = url.hostname
                if (domain in domain_list) is not domains_allowed:
                    await self.censor_message(message, url.hostname,
                                              "_domain_blocked")
                print(domain)
Beispiel #5
0
    async def check_message(self, member, content, channel, message_id, edit,
                            reply, attachments):
        if Permissioncheckers.get_user_lvl(member.guild, member) >= 2:
            return
        censorlist = Configuration.get_var(member.guild.id, "CENSORING",
                                           "TOKEN_CENSORLIST")
        word_censorlist = Configuration.get_var(member.guild.id, "CENSORING",
                                                "WORD_CENSORLIST")
        guilds = Configuration.get_var(member.guild.id, "CENSORING",
                                       "ALLOWED_INVITE_LIST")
        domain_list = Configuration.get_var(member.guild.id, "CENSORING",
                                            "DOMAIN_LIST")
        domains_allowed = Configuration.get_var(member.guild.id, "CENSORING",
                                                "DOMAIN_LIST_ALLOWED")
        full_message_list = Configuration.get_var(member.guild.id, "CENSORING",
                                                  "FULL_MESSAGE_LIST")
        censor_emoji_message = Configuration.get_var(
            member.guild.id, "CENSORING", "CENSOR_EMOJI_ONLY_MESSAGES")
        content = content.replace('\\', '')

        if Configuration.get_var(member.guild.id, "CENSORING", "IGNORE_IDS"):
            content = re.sub(r'(<(?:@|#|@&|@!)[0-9]{15,20}>)', '', content)
            content = re.sub(r'<a?:[^: \n]+:([0-9]{15,20})>', '', content)
            content = re.sub(
                r"(https://(?:canary|ptb)?\.?discord(?:app)?.com/channels/\d{15,20}/\d{15,20}/\d{15,20})",
                '', content)

        decoded_content = parse.unquote(content)

        if len(guilds) != 0:
            codes = INVITE_MATCHER.findall(decoded_content)
            for code in codes:
                try:
                    invite: disnake.Invite = await self.bot.fetch_invite(code)
                except disnake.NotFound:
                    await self.censor_invite(member, message_id, channel, code,
                                             "INVALID INVITE", content, edit,
                                             reply, attachments)
                    return
                if invite.guild is None:
                    await self.censor_invite(member, message_id, channel, code,
                                             "DM group", content, edit, reply,
                                             attachments)
                    return
                else:
                    if invite.guild is None or (
                            not invite.guild.id in guilds
                            and invite.guild.id != member.guild.id):
                        await self.censor_invite(member, message_id, channel,
                                                 code, invite.guild.name,
                                                 content, edit, reply,
                                                 attachments)
                        return

        content = content.lower()

        if content in full_message_list:
            await self.censor_message(message_id,
                                      content,
                                      channel,
                                      member,
                                      "",
                                      "_content",
                                      edit=edit,
                                      reply=reply,
                                      attachments=attachments)
            return

        for bad in (w.lower() for w in censorlist):
            if bad in content:
                await self.censor_message(message_id,
                                          content,
                                          channel,
                                          member,
                                          bad,
                                          edit=edit,
                                          reply=reply,
                                          attachments=attachments)
                return

        if len(word_censorlist) > 0:
            if channel.guild.id not in self.regexes:
                regex = re.compile(
                    r"(:?\b| )(" +
                    '|'.join(re.escape(word)
                             for word in word_censorlist) + r")(:?\b| )",
                    re.IGNORECASE | re.MULTILINE)
                self.regexes[channel.guild.id] = regex
            else:
                regex = self.regexes[channel.guild.id]
            match = regex.findall(content)
            if len(match) > 0:
                m = match[0]
                if isinstance(m, tuple):
                    m = m[1]
                await self.censor_message(message_id,
                                          content,
                                          channel,
                                          member,
                                          m,
                                          "_word",
                                          edit=edit,
                                          reply=reply,
                                          attachments=attachments)
                return

        if len(domain_list) > 0:
            link_list = URL_MATCHER.findall(content)
            for link in link_list:
                url = urlparse(link)
                domain = url.hostname
                if (domain in domain_list) is not domains_allowed:
                    await self.censor_message(message_id,
                                              content,
                                              channel,
                                              member,
                                              url.hostname,
                                              "_domain_blocked",
                                              edit=edit,
                                              reply=reply,
                                              attachments=attachments)
                    return

        if censor_emoji_message and content is not None and len(content) > 0:
            new_content = ''.join(c for c in content
                                  if c not in emoji.UNICODE_EMOJI)
            new_content = re.sub(EMOJI_REGEX, '', new_content)
            if new_content == '':
                await self.censor_message(message_id,
                                          content,
                                          channel,
                                          member,
                                          '',
                                          "_emoji_only",
                                          edit=edit,
                                          reply=reply,
                                          attachments=attachments)
                return