This project is a Discord bot developed in Node.js that aims to create a more human-like and interactive presence in Discord servers.
Features
- System Information Command: The bot can provide detailed system information about the host machine, including CPU usage, memory usage, disk usage, and the number of removable drives.
- AI-Powered Conversations: Using Googleβs Gemini AI, the bot can engage in natural language conversations with users. It responds to messages contextually and can initiate conversations on its own.
- Dynamic Personality: The bot randomly selects personality traits for each interaction, making its responses more varied and human-like.
- Context Awareness: It maintains a conversation history for each channel, allowing it to provide more relevant and coherent responses.
- Proactive Engagement: The bot can spontaneously start conversations using predefined conversation starters, adding to its human-like behavior.
- Customizable Interaction Rate: The frequency of the botβs responses and conversation initiations can be adjusted to suit different server environments.
- Secure Configuration: Sensitive information like API keys and tokens are stored in environment variables for security.
Technologies Used
- NodeJS
- Gemini AI API
- discord.js
Source Code
npm install discord.js dotenv systeminformation @google/generative-ai
Donβt forget to create a .env with variables (GOOGLE_API_KEY and DISCORD_TOKEN) for your discord and gemini api tokens.
const { Client, GatewayIntentBits } = require('discord.js');
const si = require('systeminformation');
const { GoogleGenerativeAI } = require('@google/generative-ai');
require('dotenv').config();
const PREFIX = '!';
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
});
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);
const model = genAI.getGenerativeModel({ model: 'gemini-pro' });
// Conversation history (limited to last 10 messages per channel)
const conversationHistory = new Map();
// Personality traits
const traits = [
"curious", "witty", "empathetic", "knowledgeable", "playful",
"sarcastic", "optimistic", "philosophical", "creative", "analytical"
];
// Random conversation starters
const conversationStarters = [
"I've been thinking about...",
"Did anyone else notice that...",
"I'm curious, what do you all think about...",
"Here's a random thought:",
"I can't help but wonder...",
"Hypothetically speaking, what if...",
"This might be off-topic, but...",
"I recently learned that...",
"Has anyone ever considered...",
"Just for fun, imagine if..."
];
client.once('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
setInterval(initiateConversation, 1000 * 60 * 30); // Initiate conversation every 30 minutes
});
client.on('messageCreate', async (message) => {
if (message.author.bot) return;
updateConversationHistory(message.channel.id, `${message.author.username}: ${message.content}`);
if (message.content.startsWith(PREFIX)) {
const [command, ...args] = message.content.slice(PREFIX.length).trim().split(/ +/);
if (command === 'sysinfo') {
await handleSysInfo(message);
}
} else {
if (Math.random() < 0.15) { // 15% chance to respond
await generateResponse(message);
}
}
});
async function handleSysInfo(message) {
try {
const cpu = await si.currentLoad();
const mem = await si.mem();
const disk = await si.fsSize();
const drives = await si.blockDevices();
const removableDrives = drives.filter(drive =>
drive.removable || drive.type === 'usb' || drive.type === 'sd'
).length;
const info = `
Here's what I found about the system:
β’ CPU is working at ${cpu.currentLoad.toFixed(2)}% capacity
β’ Memory is ${((mem.used / mem.total) * 100).toFixed(2)}% full
β’ Main disk is ${((disk[0].used / disk[0].size) * 100).toFixed(2)}% occupied
β’ There are ${removableDrives} removable drives connected
Anything else you'd like to know about the system?
`;
message.reply(info);
} catch (error) {
console.error('Error fetching system information:', error);
message.reply("Oops! I ran into a snag while fetching that info. Maybe the system is shy today?");
}
}
async function generateResponse(message) {
const history = getConversationHistory(message.channel.id);
const personality = traits[Math.floor(Math.random() * traits.length)];
const prompt = `
You are a friendly AI assistant in a Discord chat. Your personality is ${personality}.
Recent conversation:
${history.join('\n')}
Respond to the last message in a natural, conversational way. Keep your response brief (1-3 sentences).
`;
try {
const result = await model.generateContent(prompt);
const response = await result.response;
message.reply(response.text());
updateConversationHistory(message.channel.id, `Bot: ${response.text()}`);
} catch (error) {
console.error('Error generating response with Gemini:', error);
}
}
function updateConversationHistory(channelId, message) {
if (!conversationHistory.has(channelId)) {
conversationHistory.set(channelId, []);
}
const history = conversationHistory.get(channelId);
history.push(message);
if (history.length > 10) {
history.shift();
}
}
function getConversationHistory(channelId) {
return conversationHistory.get(channelId) || [];
}
async function initiateConversation() {
const channels = client.channels.cache.filter(channel => channel.type === 0); // Text channels
for (const [_, channel] of channels) {
if (Math.random() < 0.3) { // 30% chance to initiate in each channel
const starter = conversationStarters[Math.floor(Math.random() * conversationStarters.length)];
const personality = traits[Math.floor(Math.random() * traits.length)];
const prompt = `
You are a friendly AI assistant in a Discord chat. Your personality is ${personality}.
Start a conversation with: "${starter}"
Keep your message brief (1-3 sentences) and engaging to encourage responses.
`;
try {
const result = await model.generateContent(prompt);
const response = await result.response;
channel.send(response.text());
updateConversationHistory(channel.id, `Bot: ${response.text()}`);
} catch (error) {
console.error('Error generating conversation starter:', error);
}
}
}
}
client.login(process.env.DISCORD_TOKEN);
ββββββ β ββββββ