Building a Discord Moderation Bot: AutoMod and Custom Rules

Published on

How to build moderation features for your Discord bot. Covers auto-moderation, word filters, spam detection, logging, and integration with Discord's built-in AutoMod.

Written by Space-Node Team – Infrastructure Team – 15+ years combined experience in game server hosting, VPS infrastructure, and 24/7 streaming solutions. Read author bio →

Server moderation is the most common reason communities build custom bots. While Discord's built-in AutoMod handles basics, custom bots provide the flexibility that growing communities need.

Discord's Built-in AutoMod

Before building custom moderation, use Discord's native AutoMod:

  • Keyword filtering
  • Spam detection
  • Mention spam protection
  • Link blocking

Configure through Server Settings → Safety Setup → AutoMod.

Custom AutoMod Features

Word Filter

const bannedWords = ['badword1', 'badword2'];
const bannedPatterns = [/discord\.gg\/[a-zA-Z0-9]+/i]; // Block invite links

client.on('messageCreate', async message => {
    if (message.author.bot) return;
    
    const content = message.content.toLowerCase();
    
    // Check banned words
    if (bannedWords.some(word => content.includes(word))) {
        await message.delete();
        await message.channel.send({
            content: `${message.author}, that word isn't allowed here.`,
            allowedMentions: { users: [message.author.id] }
        });
        await logModAction(message.guild, message.author, 'automod', 'Banned word detected');
        return;
    }
    
    // Check patterns
    if (bannedPatterns.some(pattern => pattern.test(message.content))) {
        await message.delete();
        return;
    }
});

Spam Detection

const messageCache = new Map();

client.on('messageCreate', async message => {
    if (message.author.bot) return;
    
    const key = message.author.id;
    const now = Date.now();
    
    if (!messageCache.has(key)) {
        messageCache.set(key, []);
    }
    
    const userMessages = messageCache.get(key);
    userMessages.push(now);
    
    // Keep only messages from last 5 seconds
    const recent = userMessages.filter(t => now - t < 5000);
    messageCache.set(key, recent);
    
    // More than 5 messages in 5 seconds = spam
    if (recent.length > 5) {
        await message.member.timeout(60000, 'Spam detection');
        await message.channel.send(`${message.author} has been muted for spam.`);
    }
});

Raid Protection

Detect mass joins:

const joinCache = [];

client.on('guildMemberAdd', async member => {
    const now = Date.now();
    joinCache.push({ id: member.id, time: now });
    
    // Clean old entries
    while (joinCache.length > 0 && now - joinCache[0].time > 10000) {
        joinCache.shift();
    }
    
    // More than 10 joins in 10 seconds = potential raid
    if (joinCache.length > 10) {
        // Enable verification level
        await member.guild.setVerificationLevel(4); // VERY_HIGH
        // Alert admins
        const alertChannel = member.guild.channels.cache.find(c => c.name === 'mod-alerts');
        if (alertChannel) {
            await alertChannel.send('@here Potential raid detected! Verification level increased.');
        }
    }
});

Warning System

// Track warnings in database
async function warnUser(guildId, userId, moderatorId, reason) {
    const warning = await db.prepare(`
        INSERT INTO warnings (guild_id, user_id, moderator_id, reason)
        VALUES (?, ?, ?, ?)
    `).run(guildId, userId, moderatorId, reason);
    
    // Check total warnings
    const count = db.prepare(
        'SELECT COUNT(*) as count FROM warnings WHERE guild_id = ? AND user_id = ?'
    ).get(guildId, userId).count;
    
    // Auto-escalation
    if (count >= 3) {
        // Auto-timeout after 3 warnings
        const member = await guild.members.fetch(userId);
        await member.timeout(3600000, 'Accumulated 3 warnings');
    }
    
    return { warningId: warning.lastInsertRowid, totalWarnings: count };
}

Logging

Mod Log Channel

async function logModAction(guild, user, action, reason, moderator) {
    const logChannel = guild.channels.cache.find(c => c.name === 'mod-log');
    if (!logChannel) return;
    
    const embed = {
        color: action === 'ban' ? 0xFF0000 : action === 'warn' ? 0xFFAA00 : 0x00FF00,
        title: `${action.toUpperCase()}`,
        fields: [
            { name: 'User', value: `${user.tag} (${user.id})`, inline: true },
            { name: 'Moderator', value: moderator ? moderator.tag : 'AutoMod', inline: true },
            { name: 'Reason', value: reason || 'No reason provided' }
        ],
        timestamp: new Date().toISOString()
    };
    
    await logChannel.send({ embeds: [embed] });
}

Audit Trail

Log every moderation action to the database for accountability and appeals:

INSERT INTO mod_actions (guild_id, target_id, moderator_id, action, reason, timestamp)
VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP);

Deployment

A moderation bot needs true 24/7 uptime - it can't protect your server while offline. Space-Node's Discord Bot hosting provides reliable uptime, even on the free plan, ensuring your moderation bot is always active.

For larger communities (1000+ members), consider the Middle or Large plan for the additional RAM needed to cache member data and process messages efficiently.

Space-Node Team

About the Author

Space-Node Team – Infrastructure Team – Experts in game server hosting, VPS infrastructure, and 24/7 streaming solutions with 15+ years combined experience.

Since 2023
500+ servers hosted
4.8/5 avg rating

Our team specializes in Minecraft, FiveM, Rust, and 24/7 streaming infrastructure, operating enterprise-grade AMD Ryzen 9 hardware in Netherlands datacenters. We maintain GDPR compliance and ISO 27001-aligned security standards.

View Space-Node's full team bio and credentials →

Launch Your VPS Today

Get started with professional VPS hosting powered by enterprise hardware. Instant deployment and 24/7 support included.

Building a Discord Moderation Bot: AutoMod and Custom Rules