wsb-bott / src /index.js
APRKDEV's picture
Upload 37 files
94473c9 verified
require('dotenv').config();
// Fix for Node 18+ IPv6 DNS and HuggingFace Discord Block
const dns = require('node:dns');
dns.setServers(['8.8.8.8', '1.1.1.1']);
dns.setDefaultResultOrder('ipv4first');
const {
Client,
GatewayIntentBits,
Partials,
} = require('discord.js');
// ── Validate Environment ──────────────────────────────────────
const required = ['BOT_TOKEN', 'OWNER_ID', 'SUPABASE_URL', 'SUPABASE_SERVICE_ROLE_KEY'];
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 || 3001;
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'}`);
async function startBot(retryCount = 0) {
if (retryCount > 10) {
console.error('❌ MAX RETRIES REACHED. Bot failed to connect.');
process.exit(1);
}
console.log(` ⏳ Connecting to Discord... (Attempt ${retryCount + 1})`);
const loginTimeout = setTimeout(() => {
console.error('❌ LOGIN TIMED OUT after 60s β€” Discord gateway unreachable');
}, 60000);
try {
await client.login(token);
clearTimeout(loginTimeout);
console.log(' βœ… Login promise resolved');
} catch (err) {
clearTimeout(loginTimeout);
console.error(`❌ LOGIN FAILED: ${err.message}`);
if (err.message.includes('ENOTFOUND') || err.message.includes('EAI_AGAIN')) {
console.log(' πŸ“‘ DNS/Network error detected. Retrying in 10s...');
setTimeout(() => startBot(retryCount + 1), 10000);
} else {
console.error(' ⚠️ Non-network error. Exiting.');
process.exit(1);
}
}
}
// Debug logging for network issues
client.on('debug', (info) => {
if (info.includes('Gateway')) console.log(`[DEBUG] ${info}`);
});
startBot();