Discord has become the primary hub for memecoin communities, with successful projects maintaining active servers of 10,000-100,000+ members. Custom Discord bots automate essential functions, enhance community engagement, and provide unique features that distinguish professional projects from amateur operations. This comprehensive tutorial guides you through building production-ready Discord bots tailored for memecoin communities.
What is a Discord Bot?
A Discord bot is an automated program that interacts with Discord servers through the Discord API. Bots can respond to commands, monitor channels, manage roles, send alerts, and perform countless other functions without human intervention.
Why Memecoins Need Custom Bots
Memecoin communities have unique requirements that generic bots cannot address:
- Price tracking: Real-time token prices from DEXs and CEXs
- Holder verification: Confirm wallet holdings for role assignment
- Launch coordination: Automated announcements and event scheduling
- Anti-scam protection: Filter malicious links and impersonators
- Community engagement: Games, rewards, and interactive features
Prerequisites for Bot Development
Before starting development, ensure you have:
Technical Requirements
- Node.js 18+: JavaScript runtime environment
- Code editor: VS Code recommended (free and feature-rich)
- Basic JavaScript knowledge: Variables, functions, async/await
- Git: Version control for code management
- Discord account: For creating and testing bots
Non-Technical Requirements
- Discord server: A test server for development
- Bot application: Created through Discord Developer Portal
- Hosting plan: Where your bot will run 24/7
Step 1: Create Discord Bot Application
Access Developer Portal
- Navigate to Discord Developer Portal
- Log in with your Discord account
- Click "New Application"
- Name your bot (e.g., "MemecoinHelper")
- Accept Terms of Service and create
Configure Bot Settings
- Select "Bot" from left sidebar
- Click "Add Bot" if not already created
- Configure these settings:
- Public Bot: Off (unless you want others to invite it)
- Require OAuth2 Code Grant: Off
- Privileged Gateway Intents: Enable all three
- PRESENCE INTENT
- SERVER MEMBERS INTENT
- MESSAGE CONTENT INTENT
Generate Bot Token
- Click "Reset Token" to generate a new token
- Copy and save this token securely—it cannot be viewed again
- Treat this token like a password; never share it publicly
Create Invite Link
- Navigate to "OAuth2" > "URL Generator"
- Select "bot" scope
- Select required permissions:
- Read Messages/View Channels
- Send Messages
- Manage Messages
- Embed Links
- Attach Files
- Read Message History
- Use Slash Commands
- Manage Roles (optional)
Step 2: Project Setup
Initialize Node.js Project
Open terminal and create project:
mkdir memecoin-bot
cd memecoin-bot
npm init -y
Install Dependencies
npm install discord.js dotenv axios
npm install --save-dev nodemon
Package purposes:
- discord.js: Official Discord API wrapper
- dotenv: Environment variable management
- axios: HTTP client for API requests
- nodemon: Auto-restart during development
Project Structure
Create this file structure:
memecoin-bot/
├── commands/
│ ├── price.js
│ ├── holder.js
│ └── help.js
├── events/
│ ├── ready.js
│ └── messageCreate.js
├── utils/
│ └── api.js
├── .env
├── config.json
├── index.js
└── package.json
Environment Configuration
Create .env file:
DISCORD_TOKEN=your_bot_token_here
COINGECKO_API_KEY=your_coingecko_key_optional
ETHERSCAN_API_KEY=your_etherscan_key
Step 3: Basic Bot Implementation
Main Bot File (index.js)
const { Client, GatewayIntentBits, Collection } = require('discord.js');
const fs = require('fs');
const path = require('path');
require('dotenv').config();
// Create client with required intents
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers,
],
});
// Command collection
client.commands = new Collection();
// Load commands
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(path.join(commandsPath, file));
client.commands.set(command.data.name, command);
}
// Ready event
client.once('ready', () => {
console.log(`🤖 Logged in as ${client.user.tag}`);
client.user.setActivity('!help | MemecoinBot', { type: 'WATCHING' });
});
// Command interaction handler
client.on('interactionCreate', async interaction => {
if (!interaction.isChatInputCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({
content: 'Error executing command!',
ephemeral: true
});
}
});
// Login
client.login(process.env.DISCORD_TOKEN);
Step 4: Essential Commands for Memecoin Bots
Price Command
Create commands/price.js:
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
const axios = require('axios');
module.exports = {
data: new SlashCommandBuilder()
.setName('price')
.setDescription('Get current token price')
.addStringOption(option =>
option.setName('token')
.setDescription('Token name or symbol')
.setRequired(true)),
async execute(interaction) {
const token = interaction.options.getString('token').toLowerCase();
await interaction.deferReply();
try {
// Fetch price from CoinGecko
const response = await axios.get(
`https://api.coingecko.com/api/v3/simple/price?ids=${token}&vs_currencies=usd&include_24hr_change=true`
);
const data = response.data[token];
if (!data) {
return interaction.editReply('Token not found. Check the CoinGecko ID.');
}
const embed = new EmbedBuilder()
.setColor(0x00ff00)
.setTitle(`${token.toUpperCase()} Price`)
.addFields(
{ name: 'Current Price', value: `${data.usd.toLocaleString()}`, inline: true },
{ name: '24h Change', value: `${data.usd_24h_change?.toFixed(2)}%`, inline: true }
)
.setTimestamp()
.setFooter({ text: 'Powered by CoinGecko' });
await interaction.editReply({ embeds: [embed] });
} catch (error) {
await interaction.editReply('Error fetching price. Try again later.');
}
},
};
Holder Verification Command
Create commands/holder.js:
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
const axios = require('axios');
module.exports = {
data: new SlashCommandBuilder()
.setName('verify')
.setDescription('Verify your token holdings')
.addStringOption(option =>
option.setName('wallet')
.setDescription('Your wallet address')
.setRequired(true))
.addStringOption(option =>
option.setName('token')
.setDescription('Token contract address')
.setRequired(true)),
async execute(interaction) {
const wallet = interaction.options.getString('wallet');
const tokenAddress = interaction.options.getString('token');
await interaction.deferReply({ ephemeral: true });
try {
// Check balance via Etherscan API
const response = await axios.get(
`https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=${tokenAddress}&address=${wallet}&tag=latest&apikey=${process.env.ETHERSCAN_API_KEY}`
);
const balance = parseInt(response.data.result) / 1e18;
// Assign roles based on holdings
const guild = interaction.guild;
const member = interaction.member;
let roleAssigned = null;
if (balance >= 1000000) {
// Whale role
const whaleRole = guild.roles.cache.find(r => r.name === '🋠Whale');
if (whaleRole) {
await member.roles.add(whaleRole);
roleAssigned = '🋠Whale';
}
} else if (balance >= 100000) {
// Holder role
const holderRole = guild.roles.cache.find(r => r.name === '🚀 Holder');
if (holderRole) {
await member.roles.add(holderRole);
roleAssigned = '🚀 Holder';
}
}
const embed = new EmbedBuilder()
.setColor(0x5865F2)
.setTitle('Wallet Verified!')
.addFields(
{ name: 'Wallet', value: `${wallet.slice(0, 6)}...${wallet.slice(-4)}`, inline: true },
{ name: 'Balance', value: `${balance.toLocaleString()} tokens`, inline: true }
);
if (roleAssigned) {
embed.addFields({ name: 'Role Assigned', value: roleAssigned, inline: true });
}
await interaction.editReply({ embeds: [embed] });
} catch (error) {
await interaction.editReply('Error verifying wallet. Check addresses and try again.');
}
},
};
Help Command
Create commands/help.js:
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('help')
.setDescription('Show available commands'),
async execute(interaction) {
const embed = new EmbedBuilder()
.setColor(0x5865F2)
.setTitle('🤖 MemecoinBot Commands')
.setDescription('Available commands for the community:')
.addFields(
{ name: '/price <token>', value: 'Get current token price from CoinGecko' },
{ name: '/verify <wallet> <token>', value: 'Verify your holdings and get roles' },
{ name: '/chart <token>', value: 'View token chart (coming soon)' },
{ name: '/announcements', value: 'Subscribe to price alerts' }
)
.setFooter({ text: 'MemecoinBot - Powered by MemecoinLab' });
await interaction.reply({ embeds: [embed] });
},
};
Step 5: Moderation Features
Auto-Moderation for Scam Protection
Add to your main index.js:
// Scam link detection
const scamPatterns = [
/discord.gift/i,
/frees*nitro/i,
/steams*giveaway/i,
/currency.com/i,
];
client.on('messageCreate', async message => {
if (message.author.bot) return;
// Check for scam patterns
const isScam = scamPatterns.some(pattern => pattern.test(message.content));
if (isScam) {
await message.delete();
await message.author.send('Your message was deleted for containing suspicious content.');
// Log to moderation channel
const logChannel = message.guild.channels.cache.find(c => c.name === 'mod-logs');
if (logChannel) {
logChannel.send(`🚨 Deleted potential scam from ${message.author.tag}: ${message.content.slice(0, 100)}`);
}
}
});
Anti-Spam Protection
// Simple anti-spam
const userMessages = new Map();
client.on('messageCreate', async message => {
if (message.author.bot) return;
const userId = message.author.id;
const now = Date.now();
if (!userMessages.has(userId)) {
userMessages.set(userId, []);
}
const timestamps = userMessages.get(userId);
timestamps.push(now);
// Keep only last 5 seconds
const recent = timestamps.filter(t => now - t < 5000);
userMessages.set(userId, recent);
// If more than 5 messages in 5 seconds, mute
if (recent.length > 5) {
try {
const muteRole = message.guild.roles.cache.find(r => r.name === 'Muted');
if (muteRole) {
await message.member.roles.add(muteRole);
await message.channel.send(`🔇 ${message.author} has been muted for spam.`);
}
} catch (err) {
console.error('Failed to mute user:', err);
}
}
});
Step 6: Advanced Features
Price Alert System
const { EmbedBuilder } = require('discord.js');
// Store alerts
const priceAlerts = new Map();
// Check prices periodically
async function checkPriceAlerts(client, channelId) {
for (const [userId, alert] of priceAlerts) {
try {
const response = await axios.get(
`https://api.coingecko.com/api/v3/simple/price?ids=${alert.token}&vs_currencies=usd`
);
const currentPrice = response.data[alert.token]?.usd;
if (currentPrice && currentPrice >= alert.targetPrice) {
const channel = await client.channels.fetch(channelId);
const user = await client.users.fetch(userId);
const embed = new EmbedBuilder()
.setColor(0x00ff00)
.setTitle('🎯 Price Alert Triggered!')
.setDescription(`${alert.token.toUpperCase()} has reached your target price!`)
.addFields(
{ name: 'Target', value: `${alert.targetPrice}`, inline: true },
{ name: 'Current', value: `${currentPrice}`, inline: true }
);
await channel.send({ content: `<@${userId}>`, embeds: [embed] });
priceAlerts.delete(userId);
}
} catch (err) {
console.error('Error checking price alerts:', err);
}
}
}
// Run every minute
setInterval(() => checkPriceAlerts(client, 'alerts-channel-id'), 60000);
Community Engagement Games
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
// Simple prediction game
const predictions = new Map();
module.exports = {
data: new SlashCommandBuilder()
.setName('predict')
.setDescription('Predict if price will go up or down')
.addStringOption(option =>
option.setName('direction')
.setDescription('Your prediction')
.setRequired(true)
.addChoices(
{ name: '📈 Up', value: 'up' },
{ name: '📉 Down', value: 'down' }
)),
async execute(interaction) {
const direction = interaction.options.getString('direction');
const userId = interaction.user.id;
predictions.set(userId, {
direction,
timestamp: Date.now(),
startPrice: await getCurrentPrice()
});
await interaction.reply({
content: `Prediction recorded! Check back in 24 hours for results.`,
ephemeral: true
});
},
};
Step 7: Hosting and Deployment
Free Hosting Options
| Platform | Free Tier | Limitations | Best For |
|---|---|---|---|
| Railway | $5 credit/month | Sleeps after inactivity | Development/testing |
| Render | 750 hours/month | Sleeps after 15 min inactive | Small bots |
| Fly.io | 3 VMs free | Limited resources | Production testing |
| Oracle Cloud | Always free | Requires credit card | Long-term hosting |
Production Hosting (Recommended)
For reliable 24/7 operation:
| Platform | Cost | Features | Best For |
|---|---|---|---|
| DigitalOcean | $4-6/mo | Full control, reliable | Most bots |
| Linode | $5/mo | Simple, affordable | Budget hosting |
| Vultr | $2.5-5/mo | Multiple locations | Global communities |
| Heroku | $5-7/mo | Easy deployment | Non-technical teams |
Deployment Steps
Option 1: Railway (Recommended for beginners)
- Install Railway CLI:
npm install -g @railway/cli - Login:
railway login - Initialize:
railway init - Set environment variables:
railway variables set DISCORD_TOKEN=your_token - Deploy:
railway up
Option 2: DigitalOcean Droplet
- Create droplet (Ubuntu, $4-6/mo)
- SSH into server
- Install Node.js:
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - - Clone your repository
- Install PM2:
sudo npm install -g pm2 - Start bot:
pm2 start index.js --name memecoin-bot - Save PM2 config:
pm2 save && pm2 startup
Best Practices
Security
- Never share your bot token
- Use environment variables for secrets
- Implement rate limiting
- Validate all user inputs
- Log all administrative actions
Performance
- Cache frequently accessed data
- Use async/await for API calls
- Implement error handling
- Monitor memory usage
- Set up logging
Community Management
- Clear command documentation
- Responsive error messages
- Regular feature updates
- Community feedback integration
- Active moderation support
Common Mistakes to Avoid
- Missing intents: Bot can't read messages or access members
- Hardcoded tokens: Security risk and deployment issues
- No error handling: Bot crashes on API failures
- Blocking operations: Freezes bot during long tasks
- Missing rate limits: API bans and performance issues
- No logging: Impossible to debug issues
- Over-permissioning: Security risk and trust issues
Summary
Custom Discord bots provide essential functionality for memecoin communities, from price tracking to moderation and engagement features. Start with basic commands and gradually add advanced features as your community grows. Proper hosting ensures 24/7 availability, while security best practices protect your community and project.
Need help with custom bot development? Contact MemecoinLab for professional Discord bot development services tailored to your memecoin community.
Related MemecoinLab Resources
Use these internal resources to continue from research into execution:
