File size: 4,643 Bytes
3c7e34b
 
2f70cd4
65bf94f
2f70cd4
65bf94f
3c7e34b
 
 
 
 
 
 
c35213b
27c6bb6
3c7e34b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c35213b
3c7e34b
 
 
 
 
 
 
 
 
 
 
 
 
6884445
 
a15a13b
9ba9cec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ff048f3
 
 
 
9ba9cec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
require('dotenv').config();

// Fix for Node 18+ IPv6 DNS resolution bug in Docker
const dns = require('node:dns');
dns.setDefaultResultOrder('ipv4first');

const {
    Client,
    GatewayIntentBits,
    Partials,
} = require('discord.js');

// ── Validate Environment ──────────────────────────────────────
const required = ['BOT_TOKEN', 'OWNER_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 || 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();