Skip to content

Instantly share code, notes, and snippets.

@ronenlazowski
Created March 26, 2025 19:14
Show Gist options
  • Save ronenlazowski/4850ccee0fe91cd2ff58ee350e41530f to your computer and use it in GitHub Desktop.
Save ronenlazowski/4850ccee0fe91cd2ff58ee350e41530f to your computer and use it in GitHub Desktop.
auto mod
import discord
from discord import app_commands, ui, Embed
from discord.ext import commands
import json
import os
import re
from collections import defaultdict
import asyncio
class AutoMod(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
self.json_file = "automod_rules.json"
self.profanity_file = "profanity_words.txt"
self.user_messages = defaultdict(list)
self.recent_messages = defaultdict(list)
self.profanity_words = self.load_profanity_words()
self.load_rules()
def load_profanity_words(self):
if os.path.exists(self.profanity_file):
with open(self.profanity_file, 'r') as file:
return [word.strip().lower() for word in file.readlines() if word.strip()]
return []
def load_rules(self):
if os.path.exists(self.json_file):
with open(self.json_file, "r") as file:
self.rules = json.load(file)
else:
self.rules = {}
def save_rules(self):
with open(self.json_file, "w") as file:
json.dump(self.rules, file, indent=4)
@app_commands.command(name="automod", description="Manage AutoMod settings (blocked words, links, etc.).")
@app_commands.checks.has_permissions(manage_messages=True)
async def automod_settings(self, interaction: discord.Interaction):
guild_id = str(interaction.guild_id)
rules = self.rules.get(guild_id, {})
view = AutoModView(self, guild_id, rules)
await interaction.response.send_message(
"Click a button to manage AutoMod rules:",
view=view,
ephemeral=True
)
@commands.Cog.listener()
async def on_message(self, message: discord.Message):
if message.author.bot:
return
guild_id = str(message.guild.id)
rules = self.rules.get(guild_id, {})
if rules.get("blocked_words", False):
blocked_words = rules.get("blocked_words", [])
if any(word.lower() in message.content.lower() for word in blocked_words):
await self.delete_message(message, "blocked word")
return
if rules.get("blocked_links", False):
if self.contains_link(message.content):
await self.delete_message(message, "blocked link")
return
if rules.get("profanity_filter", False):
if self.contains_profanity(message.content):
await self.delete_message(message, "profanity")
return
if rules.get("spam_detection", False):
if await self.is_spam(message):
await self.delete_message(message, "spam")
return
if rules.get("repeated_message_detection", False):
if await self.is_repeated_message(message):
await self.delete_message(message, "repeated message")
return
if rules.get("emoji_spam_detection", False):
if self.contains_emoji_spam(message.content):
await self.delete_message(message, "emoji spam")
return
if rules.get("flood_control", False):
if await self.is_flood(message):
await self.delete_message(message, "flood")
return
async def delete_message(self, message: discord.Message, reason: str):
try:
await message.delete()
await message.channel.send(
f"{message.author.mention}, your message was deleted due to {reason}.",
delete_after=5
)
except discord.errors.NotFound:
pass
except discord.errors.Forbidden:
pass
def contains_link(self, content: str):
link_pattern = r'https?://\S+|www\.\S+'
return bool(re.search(link_pattern, content))
def contains_profanity(self, content: str):
cleaned_content = re.sub(r'[^a-zA-Z\s]', '', content.lower())
return any(
word in cleaned_content.split() or
word in cleaned_content
for word in self.profanity_words
)
def contains_emoji_spam(self, content: str):
custom_emojis = re.findall(r'<a?:\w+:\d+>', content)
unicode_emojis = re.findall(
r'[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\U0001F680-\U0001F6FF\U0001F1E0-\U0001F1FF]', content)
total_emojis = custom_emojis + unicode_emojis
return len(total_emojis) > 5
async def is_spam(self, message: discord.Message):
guild_id = message.guild.id
user_id = message.author.id
current_time = message.created_at
self.user_messages[guild_id].append({
'content': message.content,
'timestamp': current_time
})
self.user_messages[guild_id] = [
msg for msg in self.user_messages[guild_id]
if (current_time - msg['timestamp']).total_seconds() < 10
]
if len(self.user_messages[guild_id]) > 4:
return True
similar_messages = [
msg for msg in self.user_messages[guild_id]
if self.messages_similar(msg['content'], message.content)
]
return len(similar_messages) > 2
def messages_similar(self, msg1: str, msg2: str, threshold: float = 0.8):
msg1 = re.sub(r'[^\w\s]', '', msg1.lower())
msg2 = re.sub(r'[^\w\s]', '', msg2.lower())
words1 = msg1.split()
words2 = msg2.split()
total_words = max(len(words1), len(words2))
matching_words = sum(1 for word in words1 if word in words2)
return matching_words / total_words >= threshold
async def is_repeated_message(self, message: discord.Message):
guild_id = message.guild.id
current_time = message.created_at
self.recent_messages[guild_id].append({
'content': message.content,
'author': message.author.id,
'timestamp': current_time
})
self.recent_messages[guild_id] = [
msg for msg in self.recent_messages[guild_id]
if (current_time - msg['timestamp']).total_seconds() < 30
]
similar_messages = [
msg for msg in self.recent_messages[guild_id]
if msg.get('content') == message.content and
msg.get('author') != message.author.id
]
return len(similar_messages) >= 2
async def is_flood(self, message: discord.Message):
guild_id = message.guild.id
channel_id = message.channel.id
current_time = message.created_at
self.recent_messages[guild_id].append({
'channel': channel_id,
'timestamp': current_time
})
self.recent_messages[guild_id] = [
msg for msg in self.recent_messages[guild_id]
if (current_time - msg['timestamp']).total_seconds() < 5
]
channel_messages = [
msg for msg in self.recent_messages[guild_id]
if msg.get('channel') == channel_id
]
return len(channel_messages) > 4
class AutoModView(ui.View):
def __init__(self, cog, guild_id, rules):
super().__init__()
self.cog = cog
self.guild_id = guild_id
self.rules = rules
self.update_button_states()
def update_button_states(self):
button_configs = [
(self.toggle_link_blocker, "blocked_links", "Link Blocker"),
(self.toggle_spam_detection, "spam_detection", "Spam Detection"),
(self.toggle_profanity_filter, "profanity_filter", "Profanity Filter"),
(self.toggle_repeated_message_detection, "repeated_message_detection", "Repeated Message Detection"),
(self.toggle_emoji_spam_detection, "emoji_spam_detection", "Emoji Spam Detection"),
(self.toggle_flood_control, "flood_control", "Flood Control")
]
for button, rule_key, label in button_configs:
current_value = self.rules.get(rule_key, False)
button.style = discord.ButtonStyle.green if current_value else discord.ButtonStyle.red
button.label = f"{label} ({'Enabled' if current_value else 'Disabled'})"
async def toggle_rule(self, interaction: discord.Interaction, rule_name: str, current_value: bool, label: str, button: ui.Button):
new_value = not current_value
self.rules[rule_name] = new_value
self.cog.rules.setdefault(self.guild_id, {})[rule_name] = new_value
self.cog.save_rules()
button.style = discord.ButtonStyle.green if new_value else discord.ButtonStyle.red
button.label = f"{label} ({'Enabled' if new_value else 'Disabled'})"
await interaction.response.edit_message(view=self)
status = "enabled" if new_value else "disabled"
await interaction.followup.send(f"{label} has been {status}.", ephemeral=True)
@ui.button(label="View Blocked Words", style=discord.ButtonStyle.blurple)
async def view_blocked_words(self, interaction: discord.Interaction, button: ui.Button):
blocked_words = self.rules.get("blocked_words", [])
blocked_words_str = ", ".join(blocked_words) or "No blocked words set."
await interaction.response.send_message(f"Blocked words: {blocked_words_str}", ephemeral=True)
@ui.button(label="Add Blocked Word", style=discord.ButtonStyle.green)
async def add_blocked_word(self, interaction: discord.Interaction, button: ui.Button):
await interaction.response.send_message("Please reply with the word you want to block.", ephemeral=True)
try:
word_msg = await self.cog.bot.wait_for(
"message",
check=lambda m: m.author == interaction.user and m.channel == interaction.channel,
timeout=30.0
)
except asyncio.TimeoutError:
await interaction.followup.send("Timed out. Please try again.", ephemeral=True)
return
word_to_add = word_msg.content.lower()
blocked_words = self.rules.setdefault("blocked_words", [])
if word_to_add not in blocked_words:
blocked_words.append(word_to_add)
self.cog.save_rules()
await interaction.followup.send(f"Blocked word `{word_to_add}` has been added.", ephemeral=True)
else:
await interaction.followup.send(f"Word `{word_to_add}` is already blocked.", ephemeral=True)
@ui.button(label="Remove Blocked Word", style=discord.ButtonStyle.red)
async def remove_blocked_word(self, interaction: discord.Interaction, button: ui.Button):
await interaction.response.send_message("Please reply with the word you want to remove.", ephemeral=True)
try:
word_msg = await self.cog.bot.wait_for(
"message",
check=lambda m: m.author == interaction.user and m.channel == interaction.channel,
timeout=30.0
)
except asyncio.TimeoutError:
await interaction.followup.send("Timed out. Please try again.", ephemeral=True)
return
word_to_remove = word_msg.content.lower()
blocked_words = self.rules.get("blocked_words", [])
if word_to_remove in blocked_words:
blocked_words.remove(word_to_remove)
self.cog.save_rules()
await interaction.followup.send(f"Blocked word `{word_to_remove}` has been removed.", ephemeral=True)
else:
await interaction.followup.send(f"Word `{word_to_remove}` is not in the blocked words list.",
ephemeral=True)
@ui.button(label="Link Blocker (Disabled)", style=discord.ButtonStyle.red)
async def toggle_link_blocker(self, interaction: discord.Interaction, button: ui.Button):
await self.toggle_rule(interaction, "blocked_links", self.rules.get("blocked_links", False), "Link Blocker", button)
@ui.button(label="Spam Detection (Disabled)", style=discord.ButtonStyle.red)
async def toggle_spam_detection(self, interaction: discord.Interaction, button: ui.Button):
await self.toggle_rule(interaction, "spam_detection", self.rules.get("spam_detection", False), "Spam Detection", button)
@ui.button(label="Profanity Filter (Disabled)", style=discord.ButtonStyle.red)
async def toggle_profanity_filter(self, interaction: discord.Interaction, button: ui.Button):
await self.toggle_rule(interaction, "profanity_filter", self.rules.get("profanity_filter", False), "Profanity Filter", button)
@ui.button(label="Repeated Message Detection (Disabled)", style=discord.ButtonStyle.red)
async def toggle_repeated_message_detection(self, interaction: discord.Interaction, button: ui.Button):
await self.toggle_rule(interaction, "repeated_message_detection",
self.rules.get("repeated_message_detection", False),
"Repeated Message Detection", button)
@ui.button(label="Emoji Spam Detection (Disabled)", style=discord.ButtonStyle.red)
async def toggle_emoji_spam_detection(self, interaction: discord.Interaction, button: ui.Button):
await self.toggle_rule(interaction, "emoji_spam_detection",
self.rules.get("emoji_spam_detection", False),
"Emoji Spam Detection", button)
@ui.button(label="Flood Control (Disabled)", style=discord.ButtonStyle.red)
async def toggle_flood_control(self, interaction: discord.Interaction, button: ui.Button):
await self.toggle_rule(interaction, "flood_control",
self.rules.get("flood_control", False),
"Flood Control", button)
@ui.button(label="List AutoMod Features", style=discord.ButtonStyle.blurple)
async def list_automod_features(self, interaction: discord.Interaction, button: ui.Button):
features = {
"Link Blocker": "blocked_links",
"Spam Detection": "spam_detection",
"Profanity Filter": "profanity_filter",
"Repeated Message Detection": "repeated_message_detection",
"Emoji Spam Detection": "emoji_spam_detection",
"Flood Control": "flood_control"
}
embed = Embed(
title="🛡 Server AutoMod Feature Status",
description=f"AutoMod features for {interaction.guild.name}",
color=discord.Color.blue()
)
for feature_name, rule_key in features.items():
status = "✅ Enabled" if self.rules.get(rule_key, False) else "❌ Disabled"
embed.add_field(name=feature_name, value=status, inline=False)
await interaction.response.send_message(embed=embed, ephemeral=True)
async def setup(bot: commands.Bot):
await bot.add_cog(AutoMod(bot))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment