Discord Bot with DALL-E 3 — Tutorial
Build a Discord bot that generates images on command. Complete code walkthrough. Free API key included.
Building a Discord Bot That Generates Images with DALL-E 3
Learn how to build a Discord bot that generates AI images when users type commands. This complete guide includes all the code you need.
What We'll Build
A Discord bot that:
- Responds to /generate command
- Generates images from text prompts
- Sends images directly to Discord channels
- Handles errors gracefully
- Supports different image sizes and styles
Prerequisites
- Node.js installed
- Discord account
- Imagify API key (get one free)
- Basic JavaScript knowledge
Step 1: Create Discord Application
1. Go to Discord Developer Portal
2. Click "New Application"
3. Name your application
4. Go to "Bot" section
5. Click "Add Bot"
6. Copy the bot token (keep it secret!)
7. Enable "Message Content Intent" under Privileged Gateway Intents
Step 2: Invite Bot to Server
1. Go to "OAuth2" → "URL Generator"
2. Select scopes: "bot" and "applications.commands"
3. Select bot permissions: "Send Messages", "Attach Files"
4. Copy the generated URL
5. Open URL in browser and invite bot to your server
Step 3: Set Up Project
Create a new directory:
mkdir discord-image-bot
cd discord-image-bot
npm init -y
Step 4: Install Dependencies
npm install discord.js axios dotenv
Step 5: Create Environment File
Create .env:
DISCORD_TOKEN=your_discord_bot_token
IMAGIFY_API_KEY=your_imagify_api_key
Step 6: Create Bot Code
Create index.js:
require('dotenv').config();
const { Client, GatewayIntentBits, SlashCommandBuilder, REST, Routes } = require('discord.js');
const axios = require('axios');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
]
});
// Register slash command
const commands = [
new SlashCommandBuilder()
.setName('generate')
.setDescription('Generate an AI image from text')
.addStringOption(option =>
option
.setName('prompt')
.setDescription('Describe the image you want to generate')
.setRequired(true)
)
.addStringOption(option =>
option
.setName('size')
.setDescription('Image size')
.setRequired(false)
.addChoices(
{ name: 'Square (1024x1024)', value: '1024x1024' },
{ name: 'Landscape (1792x1024)', value: '1792x1024' },
{ name: 'Portrait (1024x1792)', value: '1024x1792' }
)
)
.addStringOption(option =>
option
.setName('style')
.setDescription('Image style')
.setRequired(false)
.addChoices(
{ name: 'Standard', value: 'standard' },
{ name: 'Vivid', value: 'vivid' }
)
)
];
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
(async () => {
try {
console.log('Started refreshing application (/) commands.');
await rest.put(
Routes.applicationCommands(process.env.CLIENT_ID),
{ body: commands }
);
console.log('Successfully registered application commands.');
} catch (error) {
console.error(error);
}
})();
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on('interactionCreate', async interaction => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'generate') {
const prompt = interaction.options.getString('prompt');
const size = interaction.options.getString('size') || '1024x1024';
const style = interaction.options.getString('style') || 'standard';
await interaction.deferReply();
try {
// Generate image
const response = await axios.post(
'https://api.imagify.ca/api/images/generate',
{
prompt,
size,
style
},
{
headers: {
'X-API-Key': process.env.IMAGIFY_API_KEY,
'Content-Type': 'application/json'
}
}
);
const imageUrl = response.data.url;
// Download image
const imageResponse = await axios.get(imageUrl, {
responseType: 'arraybuffer'
});
// Send image to Discord
await interaction.editReply({
content: `Generated: "${prompt}"`,
files: [{
attachment: Buffer.from(imageResponse.data),
name: 'generated-image.png'
}]
});
} catch (error) {
console.error('Error generating image:', error);
const errorMessage = error.response?.data?.error || 'Failed to generate image';
await interaction.editReply({
content: `Error: ${errorMessage}`,
ephemeral: true
});
}
}
});
client.login(process.env.DISCORD_TOKEN);
Step 7: Update .env with Client ID
Get your Client ID from Discord Developer Portal and add to .env:
DISCORD_TOKEN=your_discord_bot_token
IMAGIFY_API_KEY=your_imagify_api_key
CLIENT_ID=your_client_id
Step 8: Run the Bot
node index.js
Step 9: Test the Bot
In Discord, type:
/generate prompt:A futuristic city at sunset
The bot should generate and send the image!
Advanced Features
Rate Limiting
Add rate limiting to prevent abuse:
const userCooldowns = new Map();
const COOLDOWN_TIME = 60000; // 1 minute
client.on('interactionCreate', async interaction => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'generate') {
const userId = interaction.user.id;
const lastUsed = userCooldowns.get(userId);
if (lastUsed && Date.now() - lastUsed < COOLDOWN_TIME) {
const remaining = Math.ceil((COOLDOWN_TIME - (Date.now() - lastUsed)) / 1000);
return interaction.reply({
content: `Please wait ${remaining} seconds before generating another image.`,
ephemeral: true
});
}
userCooldowns.set(userId, Date.now());
// ... rest of code
}
});
Image History
Store generated images:
const imageHistory = new Map();
// After generating
imageHistory.set(interaction.user.id, {
url: imageUrl,
prompt,
timestamp: Date.now()
});
// Add /history command
new SlashCommandBuilder()
.setName('history')
.setDescription('View your last generated image')
Error Handling
Better error messages:
catch (error) {
if (error.response?.status === 429) {
await interaction.editReply({
content: 'Rate limit exceeded. Please try again later.',
ephemeral: true
});
} else if (error.response?.status === 400) {
await interaction.editReply({
content: 'Invalid prompt. Please try a different description.',
ephemeral: true
});
} else {
await interaction.editReply({
content: 'An error occurred. Please try again later.',
ephemeral: true
});
}
}
Premium Features
Add premium user support:
const premiumUsers = new Set(['user_id_1', 'user_id_2']);
if (interaction.commandName === 'generate') {
const isPremium = premiumUsers.has(interaction.user.id);
const maxSize = isPremium ? '1792x1024' : '1024x1024';
// ... rest of code
}
Deployment
Using PM2
npm install -g pm2
pm2 start index.js --name discord-bot
pm2 save
pm2 startup
Using Docker
Create Dockerfile:
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "index.js"]
Build and run:
docker build -t discord-bot .
docker run -d --env-file .env discord-bot
Security Best Practices
1. Never commit .env file - Add to .gitignore
2. Use environment variables for all secrets
3. Validate user input before sending to API
4. Implement rate limiting to prevent abuse
5. Monitor API usage to detect unusual activity
Troubleshooting
Bot doesn't respond
- Check bot token is correct
- Verify bot has necessary permissions
- Ensure Message Content Intent is enabled
Images don't generate
- Verify API key is correct
- Check API rate limits
- Verify internet connection
Commands not showing
- Re-register commands (restart bot)
- Check CLIENT_ID is correct
- Verify bot is invited with correct permissions
Conclusion
You now have a fully functional Discord bot that generates AI images! Extend it with rate limiting, history, premium features, and more.
Get your free API key from Imagify and start building your Discord bot today!
Ready to Start Generating Images?
Get started with free credits and begin creating amazing AI-generated images today.
Get Started Free