File size: 4,733 Bytes
e5c9966
 
94473c9
e5c9966
94473c9
e5c9966
 
 
 
 
 
 
 
 
94473c9
e5c9966
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
134
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();