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 Jochem, Infrastructure Expert, 5-10 years 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.

Jochem

About the Author

Jochem, Infrastructure Expert, expert in game server hosting, VPS infrastructure, and 24/7 streaming solutions with 5-10 years experience.

Since 2023
500+ servers hosted
4.8/5 avg rating

I specialize in Minecraft, FiveM, Rust, and 24/7 streaming infrastructure, operating enterprise-grade AMD Ryzen 9 hardware in Netherlands datacenters.

View my full bio and credentials →

Keep Your Bot Online 24/7

Reliable Discord bot hosting powered by enterprise AMD Ryzen 9 hardware. Start free, upgrade anytime with guaranteed uptime.

Building a Discord Moderation Bot: AutoMod and Custom Rules