diff --git a/.env.example b/.env.example index 82c53b42..52de87be 100644 --- a/.env.example +++ b/.env.example @@ -1,19 +1,42 @@ -DISCORD_TOKEN= -MONGO_TOKEN= -GIPHY_TOKEN= -WEBHOOK_ID= -WEBHOOK_TOKEN= -DISCORD_ID= - -# Not neccessary variables -# Wondering how to get these? Check out https://github.com/CorwinDev/Discord-Bot#requirements +# Required Environment Variables + +# Discord bot token (REQUIRED) +DISCORD_TOKEN=your_discord_token_here + +# MongoDB URI or Token (REQUIRED) +MONGO_TOKEN=your_mongo_uri_here + +# GIPHY API token for GIF functionality (REQUIRED) +GIPHY_TOKEN=your_giphy_token_here + +# Discord Webhook ID and Token (REQUIRED for bot logs) +WEBHOOK_ID=your_webhook_id_here +WEBHOOK_TOKEN=your_webhook_token_here + +# Discord User ID (REQUIRED for certain bot features) +DISCORD_ID=your_discord_user_id_here + + +# Optional Variables + +# Discord bot status (Optional) DISCORD_STATUS="Listening to meself, I'm a stupid bot, https://github.com/corwindev/discord-bot" -RADIO= -TOPGG_TOKEN= -SPOTIFY_CLIENT_ID= -SPOTIFY_CLIENT_SECRET= + +# URL to radio stream (Optional) +RADIO=your_radio_url_here + +# Top.gg API token for bot statistics (Optional) +TOPGG_TOKEN=your_topgg_token_here + +# Spotify API credentials (Optional, for music bot functionality) +SPOTIFY_CLIENT_ID=your_spotify_client_id_here +SPOTIFY_CLIENT_SECRET=your_spotify_client_secret_here + +# Lavalink configuration for music bot (Optional) LAVALINK_HOST=lava.link -LAVALINK_PASSWORD=I'm a secret +LAVALINK_PASSWORD=your_lavalink_password_here LAVALINK_PORT=80 LAVALINK_SECURE=false -OPENAI= + +# OpenAI API token (Optional, for AI integration) +OPENAI=your_openai_token_here diff --git a/src/bot.js b/src/bot.js index 59ad137d..b7e1b835 100644 --- a/src/bot.js +++ b/src/bot.js @@ -10,16 +10,10 @@ const AppleMusic = require("erela.js-apple"); // Discord client const client = new Discord.Client({ allowedMentions: { - parse: [ - 'users', - 'roles' - ], + parse: ['users', 'roles'], repliedUser: true }, autoReconnect: true, - disabledEvents: [ - "TYPING_START" - ], partials: [ Discord.Partials.Channel, Discord.Partials.GuildMember, @@ -49,7 +43,6 @@ const client = new Discord.Client({ restTimeOffset: 0 }); - const clientID = process.env.SPOTIFY_CLIENT_ID; const clientSecret = process.env.SPOTIFY_CLIENT_SECRET; if (clientID && clientSecret) { @@ -66,23 +59,22 @@ if (clientID && clientSecret) { ], nodes: [ { - host: process.env.LAVALINK_HOST || "lava.link", - port: parseInt(process.env.LAVALINK_PORT) || 80, - password: process.env.LAVALINK_PASSWORD || "CorwinDev", - secure: Boolean(process.env.LAVALINK_SECURE) || false + host: process.env.LAVALINK_HOST || "Your-LavaLink-Here", + port: parseInt(process.env.LAVALINK_PORT) || port, + password: process.env.LAVALINK_PASSWORD || "Your-LavaLink-Password-Here", + secure: Boolean(process.env.LAVALINK_SECURE) || " "true" for ssl enabled and "false" for diabled " }, { - host: "lavalink.techpoint.world", - port: 80, - password: "techpoint" + host: "Your-LavaLink-Here", + port: port, + password: "Your-LavaLink-Password-Here" }, ], send(id, payload) { const guild = client.guilds.cache.get(id); if (guild) guild.shard.send(payload); }, - }) - + }); } else { // Lavalink client client.player = new Manager({ @@ -93,24 +85,24 @@ if (clientID && clientSecret) { ], nodes: [ { - host: process.env.LAVALINK_HOST || "lava.link", - port: parseInt(process.env.LAVALINK_PORT) || 80, - password: process.env.LAVALINK_PASSWORD || "CorwinDev", - secure: Boolean(process.env.LAVALINK_SECURE) || false + host: process.env.LAVALINK_HOST || "Your-Other-LavaLink-Here", + port: parseInt(process.env.LAVALINK_PORT) || port, + password: process.env.LAVALINK_PASSWORD || "Your-LavaLink-Password-Here", + secure: Boolean(process.env.LAVALINK_SECURE) || " "true" for ssl enabled and "false" for diabled " }, ], send(id, payload) { const guild = client.guilds.cache.get(id); if (guild) guild.shard.send(payload); } - }) + }); } -const events = fs.readdirSync(`./src/events/music`).filter(files => files.endsWith('.js')); +const events = fs.readdirSync('./src/events/music').filter(file => file.endsWith('.js')); for (const file of events) { const event = require(`./events/music/${file}`); client.player.on(file.split(".")[0], event.bind(null, client)).setMaxListeners(0); -}; +} // Connect to database require("./database/connect")(); @@ -120,7 +112,13 @@ client.config = require('./config/bot'); client.changelogs = require('./config/changelogs'); client.emotes = require("./config/emojis.json"); client.webhooks = require("./config/webhooks.json"); -const webHooksArray = ['startLogs', 'shardLogs', 'errorLogs', 'dmLogs', 'voiceLogs', 'serverLogs', 'serverLogs2', 'commandLogs', 'consoleLogs', 'warnLogs', 'voiceErrorLogs', 'creditLogs', 'evalLogs', 'interactionLogs']; + +const webHooksArray = [ + 'startLogs', 'shardLogs', 'errorLogs', 'dmLogs', 'voiceLogs', 'serverLogs', + 'serverLogs2', 'commandLogs', 'consoleLogs', 'warnLogs', 'voiceErrorLogs', + 'creditLogs', 'evalLogs', 'interactionLogs' +]; + // Check if .env webhook_id and webhook_token are set if (process.env.WEBHOOK_ID && process.env.WEBHOOK_TOKEN) { for (const webhookName of webHooksArray) { @@ -156,71 +154,47 @@ client.login(process.env.DISCORD_TOKEN); process.on('unhandledRejection', error => { console.error('Unhandled promise rejection:', error); - if (error) if (error.length > 950) error = error.slice(0, 950) + '... view console for details'; - if (error.stack) if (error.stack.length > 950) error.stack = error.stack.slice(0, 950) + '... view console for details'; - if(!error.stack) return + if (error && error.length > 950) error = error.slice(0, 950) + '... view console for details'; + if (error.stack && error.stack.length > 950) error.stack = error.stack.slice(0, 950) + '... view console for details'; + if (!error.stack) return; + const embed = new Discord.EmbedBuilder() - .setTitle(`🚨・Unhandled promise rejection`) + .setTitle('🚨・Unhandled promise rejection') .addFields([ - { - name: "Error", - value: error ? Discord.codeBlock(error) : "No error", - }, - { - name: "Stack error", - value: error.stack ? Discord.codeBlock(error.stack) : "No stack error", - } + { name: "Error", value: error ? Discord.codeBlock(error) : "No error" }, + { name: "Stack error", value: error.stack ? Discord.codeBlock(error.stack) : "No stack error" } ]) - .setColor(client.config.colors.normal) - consoleLogs.send({ - username: 'Bot Logs', - embeds: [embed], - }).catch(() => { - console.log('Error sending unhandledRejection to webhook') - console.log(error) - }) + .setColor(client.config.colors.normal); + + consoleLogs.send({ username: 'Bot Logs', embeds: [embed] }) + .catch(() => console.log('Error sending unhandledRejection to webhook')); }); process.on('warning', warn => { console.warn("Warning:", warn); + const embed = new Discord.EmbedBuilder() - .setTitle(`🚨・New warning found`) - .addFields([ - { - name: `Warn`, - value: `\`\`\`${warn}\`\`\``, - }, - ]) - .setColor(client.config.colors.normal) - warnLogs.send({ - username: 'Bot Logs', - embeds: [embed], - }).catch(() => { - console.log('Error sending warning to webhook') - console.log(warn) - }) + .setTitle('🚨・New warning found') + .addFields([{ name: 'Warn', value: `\`\`\`${warn}\`\`\`` }]) + .setColor(client.config.colors.normal); + + warnLogs.send({ username: 'Bot Logs', embeds: [embed] }) + .catch(() => console.log('Error sending warning to webhook')); }); client.on(Discord.ShardEvents.Error, error => { - console.log(error) - if (error) if (error.length > 950) error = error.slice(0, 950) + '... view console for details'; - if (error.stack) if (error.stack.length > 950) error.stack = error.stack.slice(0, 950) + '... view console for details'; - if (!error.stack) return + console.log(error); + if (error && error.length > 950) error = error.slice(0, 950) + '... view console for details'; + if (error.stack && error.stack.length > 950) error.stack = error.stack.slice(0, 950) + '... view console for details'; + if (!error.stack) return; + const embed = new Discord.EmbedBuilder() - .setTitle(`🚨・A websocket connection encountered an error`) + .setTitle('🚨・A websocket connection encountered an error') .addFields([ - { - name: `Error`, - value: `\`\`\`${error}\`\`\``, - }, - { - name: `Stack error`, - value: `\`\`\`${error.stack}\`\`\``, - } + { name: 'Error', value: `\`\`\`${error}\`\`\`` }, + { name: 'Stack error', value: `\`\`\`${error.stack}\`\`\`` } ]) - .setColor(client.config.colors.normal) - consoleLogs.send({ - username: 'Bot Logs', - embeds: [embed], - }); + .setColor(client.config.colors.normal); + + consoleLogs.send({ username: 'Bot Logs', embeds: [embed] }); }); diff --git a/src/index.js b/src/index.js index 9b059c7f..e3499a83 100644 --- a/src/index.js +++ b/src/index.js @@ -2,20 +2,21 @@ const Discord = require('discord.js'); const chalk = require('chalk'); require('dotenv').config('./.env'); const axios = require('axios'); + // Check if is up to date -const { version } = require('.././package.json'); +const { version } = require('../package.json'); axios.get('https://api.github.com/repos/CorwinDev/Discord-Bot/releases/latest').then(res => { if (res.data.tag_name !== version) { - console.log(chalk.red.bgYellow(`Your bot is not up to date! Please update to the latest version!`, version + ' -> ' + res.data.tag_name)); + console.log(chalk.red.bgYellow("Your bot is not up to date! Please update to the latest version!", version + ' -> ' + res.data.tag_name)); } }).catch(err => { - console.log(chalk.red.bgYellow(`Failed to check if bot is up to date!`)); + console.log(chalk.red.bgYellow("Failed to check if bot is up to date!")); }); - const webhook = require("./config/webhooks.json"); const config = require("./config/bot.js"); const webHooksArray = ['startLogs', 'shardLogs', 'errorLogs', 'dmLogs', 'voiceLogs', 'serverLogs', 'serverLogs2', 'commandLogs', 'consoleLogs', 'warnLogs', 'voiceErrorLogs', 'creditLogs', 'evalLogs', 'interactionLogs']; + // Check if .env webhook_id and webhook_token are set if (process.env.WEBHOOK_ID && process.env.WEBHOOK_TOKEN) { for (const webhookName of webHooksArray) { @@ -24,7 +25,6 @@ if (process.env.WEBHOOK_ID && process.env.WEBHOOK_TOKEN) { } } - const startLogs = new Discord.WebhookClient({ id: webhook.startLogs.id, token: webhook.startLogs.token, @@ -40,24 +40,26 @@ const manager = new Discord.ShardingManager('./src/bot.js', { token: process.env.DISCORD_TOKEN, respawn: true }); + if (process.env.TOPGG_TOKEN) { const { AutoPoster } = require('topgg-autoposter'); AutoPoster(process.env.TOPGG_TOKEN, manager); } + console.clear(); -console.log(chalk.blue(chalk.bold(`System`)), (chalk.white(`>>`)), (chalk.green(`Starting up`)), (chalk.white(`...`))) -console.log(`\u001b[0m`) -console.log(chalk.red(`© CorwinDev | 2021 - ${new Date().getFullYear()}`)) -console.log(chalk.red(`All rights reserved`)) -console.log(`\u001b[0m`) -console.log(`\u001b[0m`) -console.log(chalk.blue(chalk.bold(`System`)), (chalk.white(`>>`)), chalk.red(`Version ${require(`${process.cwd()}/package.json`).version}`), (chalk.green(`loaded`))) -console.log(`\u001b[0m`); +console.log(chalk.blue(chalk.bold("System")), chalk.white(">>"), chalk.green("Starting up"), chalk.white("...")); +console.log("\u001b[0m"); +console.log(chalk.red(`© CorwinDev | 2021 - ${new Date().getFullYear()}`)); +console.log(chalk.red("All rights reserved")); +console.log("\u001b[0m"); +console.log("\u001b[0m"); +console.log(chalk.blue(chalk.bold("System")), chalk.white(">>"), chalk.red(`Version ${require(`${process.cwd()}/package.json`).version}`), chalk.green("loaded")); +console.log("\u001b[0m"); manager.on('shardCreate', shard => { let embed = new Discord.EmbedBuilder() - .setTitle(`🆙・Launching shard`) - .setDescription(`A shard has just been launched`) + .setTitle('🆙・Launching shard') + .setDescription('A shard has just been launched') .setFields([ { name: "🆔┆ID", @@ -65,19 +67,20 @@ manager.on('shardCreate', shard => { inline: true }, { - name: `📃┆State`, - value: `Starting up...`, + name: "📃┆State", + value: "Starting up...", inline: true } ]) - .setColor(config.colors.normal) + .setColor(config.colors.normal); + startLogs.send({ username: 'Bot Logs', embeds: [embed], }); - console.log(chalk.blue(chalk.bold(`System`)), (chalk.white(`>>`)), (chalk.green(`Starting`)), chalk.red(`Shard #${shard.id + 1}`), (chalk.white(`...`))) - console.log(`\u001b[0m`); + console.log(chalk.blue(chalk.bold("System")), chalk.white(">>"), chalk.green("Starting"), chalk.red(`Shard #${shard.id + 1}`), chalk.white("...")); + console.log("\u001b[0m"); shard.on("death", (process) => { const embed = new Discord.EmbedBuilder() @@ -88,7 +91,7 @@ manager.on('shardCreate', shard => { value: `${shard.id + 1}/${manager.totalShards}`, }, ]) - .setColor(config.colors.normal) + .setColor(config.colors.normal); shardLogs.send({ username: 'Bot Logs', embeds: [embed] @@ -107,7 +110,7 @@ manager.on('shardCreate', shard => { value: `\`${process.exitCode}\``, } ]) - .setColor(config.colors.normal) + .setColor(config.colors.normal); shardLogs.send({ username: 'Bot Logs', embeds: [embed] @@ -119,7 +122,7 @@ manager.on('shardCreate', shard => { const embed = new Discord.EmbedBuilder() .setTitle(`🚨・Shard ${shard.id + 1}/${manager.totalShards} disconnected`) .setDescription("Dumping socket close event...") - .setColor(config.colors.normal) + .setColor(config.colors.normal); shardLogs.send({ username: 'Bot Logs', embeds: [embed], @@ -129,7 +132,7 @@ manager.on('shardCreate', shard => { shard.on("shardReconnecting", () => { const embed = new Discord.EmbedBuilder() .setTitle(`🚨・Reconnecting shard ${shard.id + 1}/${manager.totalShards}`) - .setColor(config.colors.normal) + .setColor(config.colors.normal); shardLogs.send({ username: 'Bot Logs', embeds: [embed], @@ -137,10 +140,8 @@ manager.on('shardCreate', shard => { }); }); - manager.spawn(); - // Webhooks const consoleLogs = new Discord.WebhookClient({ id: webhook.consoleLogs.id, @@ -156,7 +157,7 @@ process.on('unhandledRejection', error => { console.error('Unhandled promise rejection:', error); if (error) if (error.length > 950) error = error.slice(0, 950) + '... view console for details'; if (error.stack) if (error.stack.length > 950) error.stack = error.stack.slice(0, 950) + '... view console for details'; - if (!error.stack) return + if (!error.stack) return; const embed = new Discord.EmbedBuilder() .setTitle(`🚨・Unhandled promise rejection`) .addFields([ @@ -168,14 +169,14 @@ process.on('unhandledRejection', error => { name: "Stack error", value: error.stack ? Discord.codeBlock(error.stack) : "No stack error", } - ]) + ]); consoleLogs.send({ username: 'Bot Logs', embeds: [embed], }).catch(() => { - console.log('Error sending unhandled promise rejection to webhook') - console.log(error) - }) + console.log('Error sending unhandled promise rejection to webhook'); + console.log(error); + }); }); process.on('warning', warn => { @@ -187,12 +188,12 @@ process.on('warning', warn => { name: `Warn`, value: `\`\`\`${warn}\`\`\``, }, - ]) + ]); warnLogs.send({ username: 'Bot Logs', embeds: [embed], }).catch(() => { - console.log('Error sending warning to webhook') - console.log(warn) - }) -}); \ No newline at end of file + console.log('Error sending warning to webhook'); + console.log(warn); + }); +});