Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ build/
env/
lib64
.mypy_cache/
.ruff_cache/
.pytest_cache
tmp
.coverage
.python-version
.venv
.vscode
82 changes: 82 additions & 0 deletions bot/extensions/name_moderation_cog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import logging

from discord import Member
from discord.errors import Forbidden
from discord.ext.commands import Cog

from bot import app
from bot.grace import Grace
from bot.helpers.log_helper import notice
from bot.services.random_name_service import make_random_name

logger = logging.getLogger(__name__)


class NameModerationCog(
Cog, name="Names", description="Checks and changes user's nickname."
):
"""
A cog that checks when a member joins if they have a bad word in their name,
and changes their name in case they do.

Configure in the .env file like this:
BLACKLISTED_NAMES = bad_word1, bad_word2, bad_word3,...
"""

def __init__(self, bot: Grace):
self.bot: Grace = bot
self.bad_words = set(app.config.get("name_moderation", "blacklist", []))

@property
def moderation_channel(self):
return self.bot.get_channel_by_name("moderation_logs")

@Cog.listener()
async def on_member_join(self, member: Member) -> None:
"""Chnage a user's nickname if it contains a bad word.

:param member: The member to check their username or display name.
:type member: discord.Member
"""

name = member.display_name

if not self.contains_bad_word(name):
return

try:
good_name = make_random_name()
await member.edit(nick=good_name)

log = notice("NAME", f"Username of {name} was changed.")
log.add_field(
"Reason: ",
f"User {name} joined with an inappropriate name, thus it was changed to {good_name}.",
)

if self.moderation_channel:
await log.send(self.moderation_channel)

await member.send(
f"Your name has an inappropriate word in it, thus it was changed from {name} to {good_name}."
)

except Forbidden:
logger.info("User left before we could send them a message.")

def contains_bad_word(self, name: str) -> bool:
"""Checks if a name has a bad word in it.

:param name: The name to check.
:type name: str

:return: True if the name has a bad word, otherwise false.
:rtype: bool
"""
lowered = name.lower()

return any(bad_word in lowered for bad_word in self.bad_words)


async def setup(bot: Grace):
await bot.add_cog(NameModerationCog(bot))
Loading
Loading