138 lines
4.4 KiB
JavaScript
138 lines
4.4 KiB
JavaScript
require("dotenv").config();
|
|
const { Client, Events } = require("@fluxerjs/core");
|
|
|
|
const client = new Client();
|
|
|
|
// Your specific IDs for your server, make sure to set these in your .env file
|
|
const AUTO_ROLE_ID = process.env.AUTO_ROLE_ID;
|
|
const WELCOME_CHANNEL_ID = process.env.WELCOME_CHANNEL_ID;
|
|
const BOT_TOKEN = process.env.BOT_TOKEN;
|
|
|
|
// Safety check before attempting to log in
|
|
if (!BOT_TOKEN) {
|
|
console.error(
|
|
"CRITICAL ERROR: BOT_TOKEN is missing or undefined. Check your .env file!",
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
// Warn if other IDs are missing — bot can still run but join handling will be limited
|
|
if (!AUTO_ROLE_ID || !WELCOME_CHANNEL_ID) {
|
|
console.warn(
|
|
"Warning: AUTO_ROLE_ID and/or WELCOME_CHANNEL_ID are not set. Welcome messages or role assignment may fail.",
|
|
);
|
|
}
|
|
|
|
client.on(Events.Ready, () => {
|
|
/* This will log the bot's username and discriminator to the console when it successfully logs in
|
|
* For some reason, client.user.tag doesn't work, so we have to concatenate the username and discriminator manually.
|
|
*/
|
|
console.log(
|
|
`Online! Logged in as ${client.user.username}#${client.user.discriminator}`,
|
|
);
|
|
});
|
|
|
|
client.on(Events.GuildMemberAdd, async (member) => {
|
|
try {
|
|
await member.roles.add(AUTO_ROLE_ID);
|
|
console.log(`Assigned role to ${member.user.username}`);
|
|
|
|
// Fixed the error here. Needed client not member to fetch the channel.
|
|
const welcomeChannel = await client.channels.fetch(WELCOME_CHANNEL_ID);
|
|
// Avoid fetching a Role object that may not exist or be accessible from client-level managers.
|
|
// Use a role mention fallback which doesn't require resolving the Role name.
|
|
const roleMention = AUTO_ROLE_ID ? `<@&${AUTO_ROLE_ID}>` : 'a role';
|
|
if (welcomeChannel) {
|
|
// This is my example for my server welcome message, feel free to change it up to fit your server's vibe!
|
|
await welcomeChannel.send(
|
|
`Eh Bro! Welcome to the Hub, <@${member.user.id}>! Grab a seat and say hello. You also have the Role "Homies" now, so you can check out the channels and get involved!`,
|
|
);
|
|
}
|
|
} catch (error) {
|
|
console.error(
|
|
`Failed to handle join event for ${member.user.username}:`,
|
|
error,
|
|
);
|
|
}
|
|
});
|
|
|
|
// Log in and add reconnect/resiliency logic
|
|
client.on('error', (err) => {
|
|
console.error('Client error:', err);
|
|
});
|
|
|
|
client.on('shardError', (err) => {
|
|
console.error('Shard error:', err);
|
|
});
|
|
|
|
process.on('uncaughtException', (err) => {
|
|
console.error('Uncaught exception:', err);
|
|
});
|
|
|
|
process.on('unhandledRejection', (reason, promise) => {
|
|
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
|
});
|
|
|
|
// Reconnect/backoff helpers
|
|
let reconnectAttempts = 0;
|
|
let isConnecting = false;
|
|
const MAX_BACKOFF = 30000; // 30s
|
|
|
|
async function connectWithRetry() {
|
|
if (isConnecting) return;
|
|
isConnecting = true;
|
|
try {
|
|
// If the library provides a destroy/logout method, try to clean up first
|
|
if (typeof client.destroy === 'function') {
|
|
try {
|
|
client.destroy();
|
|
} catch (e) {
|
|
// ignore
|
|
}
|
|
}
|
|
|
|
await client.login(BOT_TOKEN);
|
|
reconnectAttempts = 0;
|
|
console.log('Successfully connected.');
|
|
} catch (err) {
|
|
reconnectAttempts += 1;
|
|
const delay = Math.min(MAX_BACKOFF, 1000 * Math.pow(2, Math.min(reconnectAttempts, 5)));
|
|
console.error(`Login attempt ${reconnectAttempts} failed:`, err);
|
|
console.log(`Retrying in ${delay}ms...`);
|
|
setTimeout(() => {
|
|
isConnecting = false;
|
|
connectWithRetry();
|
|
}, delay);
|
|
} finally {
|
|
isConnecting = false;
|
|
}
|
|
}
|
|
|
|
// Listen for common disconnect-like events and trigger reconnect attempts.
|
|
// Different client implementations emit different event names; guard each with a check.
|
|
try {
|
|
client.on('disconnect', (event) => {
|
|
console.warn('Client disconnected:', event);
|
|
setTimeout(connectWithRetry, 1000);
|
|
});
|
|
} catch (e) {}
|
|
|
|
try {
|
|
client.on('close', (code, reason) => {
|
|
console.warn('Connection closed:', code, reason);
|
|
setTimeout(connectWithRetry, 1000);
|
|
});
|
|
} catch (e) {}
|
|
|
|
// Periodic health check: if client isn't ready, try reconnecting.
|
|
setInterval(() => {
|
|
const healthy = client && client.user && client.user.username;
|
|
if (!healthy) {
|
|
console.warn('Health check: client not ready, attempting reconnect...');
|
|
connectWithRetry();
|
|
}
|
|
}, 30 * 1000);
|
|
|
|
// Start initial connection attempt
|
|
connectWithRetry();
|
|
// this is just a test bot for fluxer. First ECS bot
|