require('dotenv').config(); const { Client, GatewayIntentBits, Partials, } = require('discord.js'); // ── Validate Environment ────────────────────────────────────── const required = ['BOT_TOKEN', 'OWNER_ID', 'GUILD_ID']; console.log(' 📋 ENV CHECK:', required.map(k => `${k}=${process.env[k] ? '✅' : '❌'}`).join(' | ')); for (const key of required) { if (!process.env[key] || process.env[key].includes('YOUR_')) { console.error(`❌ Missing or placeholder env var: ${key}`); console.error(' Please fill in your .env file before starting.'); process.exit(1); } } // ── Create Client ───────────────────────────────────────────── const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMessageReactions, GatewayIntentBits.DirectMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildPresences, ], partials: [ Partials.Message, Partials.Channel, Partials.Reaction, Partials.User, Partials.GuildMember, ], }); // ── Load Event Handlers ─────────────────────────────────────── const events = [ require('./events/ready'), require('./events/messageCreate'), require('./events/messageReactionAdd'), require('./events/messageReactionRemove'), require('./events/guildMemberUpdate'), require('./events/guildMemberAdd'), require('./events/guildMemberRemove'), require('./events/interactionCreate'), ]; for (const event of events) { if (event.once) { client.once(event.name, (...args) => event.execute(client, ...args)); } else { client.on(event.name, (...args) => event.execute(client, ...args)); } } // ── Error Handling ──────────────────────────────────────────── client.on('error', (err) => { console.error('[Client Error]', err); }); process.on('unhandledRejection', (err) => { console.error('[Unhandled Rejection]', err); }); process.on('uncaughtException', (err) => { console.error('[Uncaught Exception]', err); process.exit(1); }); // ── Keep-Alive HTTP Server (for Render / Glitch + UptimeRobot) ─ const http = require('http'); const PORT = process.env.PORT || 3000; http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ status: 'alive', bot: client.user?.tag || 'starting...', uptime: Math.floor(process.uptime()) + 's', })); }).listen(PORT, () => { console.log(` 🌐 Keep-alive server on port ${PORT}`); }); // ── Login ───────────────────────────────────────────────────── const token = process.env.BOT_TOKEN; console.log(` 🔑 Token: ${token ? token.slice(0, 10) + '...' + token.slice(-5) : 'MISSING'}`); console.log(' ⏳ Connecting to Discord...'); const loginTimeout = setTimeout(() => { console.error('❌ LOGIN TIMED OUT after 30s — Discord gateway unreachable'); }, 30000); client.login(token).then(() => { clearTimeout(loginTimeout); console.log(' ✅ Login promise resolved'); }).catch(err => { clearTimeout(loginTimeout); console.error('❌ LOGIN FAILED:', err.message); process.exit(1); });