Skip to content

Commit 57413e1

Browse files
committed
Personalize intro acknowledgements
1 parent 93f9ecf commit 57413e1

2 files changed

Lines changed: 55 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ This repository's source code is open source under the MIT license. See
4141
locks, slowmode, case history, and raid cleanup
4242
- SQLite-backed case history, warning points, temp-ban scheduling, and server
4343
config
44+
- personalized welcome and intro-channel acknowledgement messages so new
45+
members do not all get the same canned response
4446
- native Discord AutoMod rules for spam, mention raids, hate-speech presets,
4547
and known scam-link patterns
4648
- local Memact Guard deletion for strong profanity, offensive extremist or

cogs/automod.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import asyncio
44
from collections import defaultdict, deque
5+
import re
56
import time
67
from datetime import datetime, timedelta
78

@@ -42,6 +43,42 @@
4243
"http://memact.com",
4344
"http://www.memact.com",
4445
]
46+
INTRO_TOPIC_KEYWORDS: tuple[tuple[str, tuple[str, ...]], ...] = (
47+
("builder/dev", ("app", "bot", "code", "coding", "developer", "javascript", "programming", "python", "tech")),
48+
("creative", ("art", "artist", "design", "drawing", "editing", "music", "photography", "video", "writer")),
49+
("gaming", ("fortnite", "game", "gaming", "minecraft", "roblox", "steam", "valorant")),
50+
("student", ("college", "school", "student", "study", "university")),
51+
("anime/media", ("anime", "manga", "movie", "series", "show")),
52+
("Memact", ("community", "memact", "server")),
53+
)
54+
INTRO_ACK_TEMPLATES = (
55+
"Welcome, {name}. {detail} Glad to have you in {guild}.",
56+
"Appreciate the intro, {name}. {detail} Settle in and make yourself at home.",
57+
"{name}, intro received. {detail} You are officially more than just a username here.",
58+
"Nice to meet you, {name}. {detail} The server has a little more context now.",
59+
)
60+
61+
62+
def _intro_word_count(content: str) -> int:
63+
return len(re.findall(r"[A-Za-z0-9][A-Za-z0-9_'-]*", content))
64+
65+
66+
def _contains_intro_keyword(content: str, keyword: str) -> bool:
67+
return re.search(rf"(?<![a-z0-9]){re.escape(keyword.casefold())}(?![a-z0-9])", content) is not None
68+
69+
70+
def _intro_detail(content: str) -> str:
71+
normalized = content.casefold()
72+
for label, keywords in INTRO_TOPIC_KEYWORDS:
73+
if any(_contains_intro_keyword(normalized, keyword) for keyword in keywords):
74+
return f"Noted the {label} angle from your intro."
75+
76+
word_count = _intro_word_count(content)
77+
if word_count >= 45:
78+
return "That was a proper intro, not a drive-by hello."
79+
if word_count >= 18:
80+
return "Clean intro, just enough signal for people to say hi back."
81+
return "Short and sweet intro, which still counts."
4582

4683

4784
class AutomodCog(commands.Cog):
@@ -298,10 +335,26 @@ async def _acknowledge_intro_message(self, message: nextcord.Message) -> None:
298335
return
299336
if not self.bot.db.mark_intro_acknowledgement(message.guild.id, message.author.id, message_id=message.id):
300337
return
338+
display_name = getattr(message.author, "display_name", message.author.name).strip() or message.author.name
339+
safe_name = display_name[:40]
340+
template = INTRO_ACK_TEMPLATES[(message.author.id + message.id) % len(INTRO_ACK_TEMPLATES)]
341+
acknowledgement = template.format(
342+
name=safe_name,
343+
guild=message.guild.name,
344+
detail=_intro_detail(message.clean_content or message.content),
345+
)
301346
try:
302347
await message.add_reaction("\U0001f44b")
303348
except (nextcord.Forbidden, nextcord.HTTPException):
304349
pass
350+
try:
351+
await message.reply(
352+
acknowledgement,
353+
mention_author=False,
354+
allowed_mentions=nextcord.AllowedMentions.none(),
355+
)
356+
except (nextcord.Forbidden, nextcord.HTTPException):
357+
pass
305358

306359
def _age_hours(self, then: datetime | None) -> float:
307360
if then is None:

0 commit comments

Comments
 (0)