如何优化discord.py机器人的反垃圾(Anti-spam)功能?
Optimized Anti-Spam Discord Bot Implementation
Let's tackle your anti-spam bot optimizations step by step. Below is a polished solution that addresses all three of your requirements, with clear explanations for each change:
Key Requirements Addressed
- Exempt Specific Roles: Skip anti-spam checks for admins/moderators (supports both administrator permissions and custom role names)
- Exempt Spam Channel: Disable all spam checks in a dedicated spam channel
- Delete Duplicate Messages: Track recent message content to remove repeats, alongside the existing rate-limiting logic
Full Optimized Code
import os import discord from discord.ext import commands import datetime intents = discord.Intents.all() bot = commands.Bot(command_prefix='$', intents=intents) # Configuration - tweak these values to match your server needs TIME_WINDOW_MS = 5000 MAX_MSG_PER_WINDOW = 5 # Replace with your spam channel's ID (right-click channel -> Copy ID) SPAM_CHANNEL_ID = 123456789012345678 # Replace with role names you want to exempt (e.g., ["Admin", "Moderator"]) EXEMPT_ROLE_NAMES = ["Admin", "Moderator"] # Track message timestamps for rate limiting author_msg_times = {} # Track recent message content for duplicate detection author_recent_messages = {} @bot.event async def on_message(message): # Ignore bot messages to prevent loops or false positives if message.author.bot: return # 1. Check if user is exempt from anti-spam checks is_exempt = False # First check if user has administrator permissions if message.author.guild_permissions.administrator: is_exempt = True # Then check if user has any of the specified exempt roles else: for role in message.author.roles: if role.name in EXEMPT_ROLE_NAMES: is_exempt = True break # 2. Check if message is sent in the spam-exempt channel if message.channel.id == SPAM_CHANNEL_ID: is_exempt = True # Skip all checks if user or channel is exempt if is_exempt: await bot.process_commands(message) return # --- Rate Limiting (Refactored Original Logic) --- author_id = message.author.id curr_time = datetime.datetime.now().timestamp() * 1000 # Initialize entry for new users if author_id not in author_msg_times: author_msg_times[author_id] = [] author_msg_times[author_id].append(curr_time) # Remove expired timestamps using list comprehension for cleaner code expr_time = curr_time - TIME_WINDOW_MS author_msg_times[author_id] = [t for t in author_msg_times[author_id] if t >= expr_time] # --- Duplicate Message Detection --- if author_id not in author_recent_messages: author_recent_messages[author_id] = [] # Normalize message content to catch minor variations (extra spaces, capitalization) message_content = message.content.strip().lower() is_duplicate = message_content in author_recent_messages[author_id] # Keep only the last 3 messages to check for repeats (adjust this number as needed) author_recent_messages[author_id].append(message_content) if len(author_recent_messages[author_id]) > 3: author_recent_messages[author_id].pop(0) # Take action if spam or duplicate is detected if len(author_msg_times[author_id]) > MAX_MSG_PER_WINDOW or is_duplicate: try: await message.delete() # Send a temporary warning that auto-deletes after 5 seconds await message.channel.send(f"{message.author.mention}, please stop spamming or sending duplicate messages!", delete_after=5) except discord.errors.Forbidden: # Handle cases where the bot lacks permission to delete messages await message.channel.send("I don't have permission to delete spam messages! Please update my permissions.", delete_after=5) else: print(f"Compliant message from {message.author.display_name}") # Don't forget to process bot commands at the end await bot.process_commands(message) bot.run(os.getenv('token'))
Key Improvements Explained
- Role/Channel Exemption:
- Uses both administrator permissions and custom role names to cover different server setups
- Targets the spam channel by ID (more reliable than channel names, which can be changed)
- Duplicate Detection:
- Normalizes message content (stripped and lowercase) to catch subtle repeats like "Hello" vs "hello "
- Tracks the last 3 messages per user (adjustable) to avoid overloading memory
- Error Handling:
- Adds a try/except block to gracefully handle missing permissions
- Ignores bot messages to prevent self-triggering
- Uses
delete_after=5for warnings to keep channels uncluttered
- Code Cleanup:
- Renamed variables for better readability (e.g.,
TIME_WINDOW_MSinstead oftime_window_milliseconds) - Replaced manual list removal with list comprehensions for cleaner expired timestamp handling
- Added a dedicated configuration section for easy adjustments
- Renamed variables for better readability (e.g.,
Before deploying, make sure to:
- Replace
SPAM_CHANNEL_IDwith your actual spam channel's ID - Update
EXEMPT_ROLE_NAMESto match your server's admin/moderator role names - Ensure your bot has the necessary permissions (Manage Messages, Read Message History, etc.) in your server
内容的提问来源于stack exchange,提问作者Dweller




