[Filter] Filter based on words for non-phrases (#2262)

Filters based strictly on words (ignoring punctuation) if filter entry isn't a phrase.
This commit is contained in:
Caleb Johnson 2019-02-12 22:14:12 -05:00 committed by Toby Harradine
parent 820be2a0ae
commit ac8b1fc108

View File

@ -1,11 +1,13 @@
import discord
from typing import Union
import re
from typing import Union, Set
from redbot.core import checks, Config, modlog, commands
from redbot.core.bot import Red
from redbot.core.i18n import Translator, cog_i18n
from redbot.core.utils.chat_formatting import pagify
RE_WORD_SPLIT = re.compile(r"[^\w]")
_ = Translator("Filter", __file__)
@ -317,17 +319,38 @@ class Filter(commands.Cog):
return removed
async def filter_hits(
self, text: str, server_or_channel: Union[discord.Guild, discord.TextChannel]
) -> Set[str]:
if isinstance(server_or_channel, discord.Guild):
word_list = set(await self.settings.guild(server_or_channel).filter())
elif isinstance(server_or_channel, discord.TextChannel):
word_list = set(
await self.settings.guild(server_or_channel.guild).filter()
+ await self.settings.channel(server_or_channel).filter()
)
else:
raise TypeError("%r should be Guild or TextChannel" % server_or_channel)
content = text.lower()
msg_words = set(RE_WORD_SPLIT.split(content))
filtered_phrases = {x for x in word_list if len(RE_WORD_SPLIT.split(x)) > 1}
filtered_words = word_list - filtered_phrases
hits = {p for p in filtered_phrases if p in content}
hits |= filtered_words & msg_words
return hits
async def check_filter(self, message: discord.Message):
server = message.guild
author = message.author
word_list = set(
await self.settings.guild(server).filter()
+ await self.settings.channel(message.channel).filter()
)
filter_count = await self.settings.guild(server).filterban_count()
filter_time = await self.settings.guild(server).filterban_time()
user_count = await self.settings.member(author).filter_count()
next_reset_time = await self.settings.member(author).next_reset_time()
if filter_count > 0 and filter_time > 0:
if message.created_at.timestamp() >= next_reset_time:
next_reset_time = message.created_at.timestamp() + filter_time
@ -336,36 +359,36 @@ class Filter(commands.Cog):
user_count = 0
await self.settings.member(author).filter_count.set(user_count)
if word_list:
for w in word_list:
if w in message.content.lower():
try:
await message.delete()
except discord.HTTPException:
pass
else:
if filter_count > 0 and filter_time > 0:
user_count += 1
await self.settings.member(author).filter_count.set(user_count)
if (
user_count >= filter_count
and message.created_at.timestamp() < next_reset_time
):
reason = _("Autoban (too many filtered messages.)")
try:
await server.ban(author, reason=reason)
except discord.HTTPException:
pass
else:
await modlog.create_case(
self.bot,
server,
message.created_at,
"filterban",
author,
server.me,
reason,
)
hits = await self.filter_hits(message.content, message.channel)
if hits:
try:
await message.delete()
except discord.HTTPException:
pass
else:
if filter_count > 0 and filter_time > 0:
user_count += 1
await self.settings.member(author).filter_count.set(user_count)
if (
user_count >= filter_count
and message.created_at.timestamp() < next_reset_time
):
reason = _("Autoban (too many filtered messages.)")
try:
await server.ban(author, reason=reason)
except discord.HTTPException:
pass
else:
await modlog.create_case(
self.bot,
server,
message.created_at,
"filterban",
author,
server.me,
reason,
)
async def on_message(self, message: discord.Message):
if isinstance(message.channel, discord.abc.PrivateChannel):