diff --git a/bot.js b/bot.js new file mode 100644 index 0000000..034937c --- /dev/null +++ b/bot.js @@ -0,0 +1,127 @@ +const discord = require('discord.js'); +const fs = require('fs'); +const process = require('process'); + +const client = new discord.Client({presence: {status: 'online', activity: {type: 'LISTENING', name: 'k.help | v2.1'}}}); +client.commands = new discord.Collection(); +client.color = (0x70e1df); +client.start_time = Date.now() +client.prefix = "k."; +client.players = new discord.Collection(); +client.broadcast = client.voice.createBroadcast() + +const folders = fs.readdirSync('./commands') + +for (const folder of folders) { + const files = fs.readdirSync(`./commands/${folder}`).filter(file => file.endsWith('.js')); + for (const file of files) { + const command = require(`./commands/${folder}/${file}`); + client.commands.set(command.name, command); + } +} + +async function play() { + const songs = fs.readdirSync('./songs'); + const index = Math.floor(Math.random() * songs.length); + const song = songs[index]; + client.current = song.slice(0, -4); + + const embed = new discord.MessageEmbed() + .setTitle('Now Playing') + .setDescription(`${client.current}`) + .setColor(client.color) + .setFooter(`Use ${client.prefix}help for more commands!`, `${client.user.avatarURL()}`); + + if (client.players.size > 0) { + client.players.each(async player => player.controller = await player.channel.send(embed)) + } + + + client.broadcast.play(`./songs/${song}`) + .on('finish', async () => { + if (client.players.size > 0) { + client.players.each(async player => await player.controller.delete()) + } + await play(); + }); +} + + + + +client.on('ready', async () => { + console.log(`${client.user.tag} is online and serving ${client.guilds.cache.size} guilds`); + await play(); +}); + + + +client.on('message', async message => { + if (!message.content.startsWith(client.prefix) || message.author.bot) return; + + const args = message.content.slice(client.prefix.length).trim().split(/ +/); + const commandName = args.shift().toLowerCase(); + const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); + + if (!command) return; + if (command.ownerOnly && message.author.id != '313314995687391234') return; + + + try { + await command.execute(message, args); + } catch(error) { + console.error(error); + await message.channel.send('🛑 An unexpected error occurred while executing the command! Please report this to the owner. \n```' + error + '```') + + } + +}); + +client.on('guildCreate', async guild => { + + let channel = guild.channels.cache.find(channel => channel.type === 'text' && channel.permissionsFor(guild.me).has('SEND_MESSAGES')) + const embed = new discord.MessageEmbed() + .setTitle('Thank you for inviting Kanye Reloaded!') + .setDescription('You can start playing Kanye music by typing **kanye join** while in a voice channel. \n\nDo **kanye help** for more information on how to do any commands\n\n If you have any issues/question, feel free to join our [support server](https://discord.gg/bBeAQcftAr)') + .setColor(client.color) + .setFooter(`Use ${client.prefix}help for more commands!`, `${client.user.avatarURL()}`); + await channel.send(embed); + + channel = await client.channels.fetch('799402132105068545') + await channel.send(`<@313314995687391234>, I was added to **${guild.name}**! I'm now in **${client.guilds.cache.size}** guilds.`) + +}); + +client.on('guildDelete', async guild => { + const channel = await client.channels.fetch('799402132105068545') + await channel.send(`<@313314995687391234>, I was removed from **${guild.name}**. I'm now in **${client.guilds.cache.size}** guilds.`) +}); + +client.on('voiceStateUpdate', async (oldState, newState) => { + if (newState.member === newState.guild.me && !newState.connection && !client.players.get(oldState.guild.id).maybe_disconnect) { + const player = client.players.get(oldState.guild.id); + console.log('Detected forced disconnect, cleaning up...'); + try { + await player.controller.delete(); + } catch (err) {} + client.players.delete(player.message.guild.id); + } +}) + +process.on('SIGINT', async () => { + if (client.players.size > 0) { + for (const player of client.players.values()) { + player.maybe_disconnect = true; + player.voice.disconnect(); + await player.controller.delete(); + await player.channel.send(`⚠️ <@${player.dj.id}>, the bot is being manually restarted by the owner. Once the bot has restarted, you can use \`${client.prefix}join\` to rejoin the bot.`); + client.players.delete(player.message.guild.id); + } + + } + console.log('Shutting down now...'); + process.exit(); +}); + +client.login('ODIzOTc5MTUyOTI2NDQxNDkz.YFosYg.HrBjhcnXDKc0-cKTM6fQJ_TAWCg'); + diff --git a/commands/general/join.js b/commands/general/join.js new file mode 100644 index 0000000..b5ac551 --- /dev/null +++ b/commands/general/join.js @@ -0,0 +1,49 @@ +const { MessageEmbed } = require("discord.js"); + +class Player { + constructor(message) { + this.message = message; + this.channel = message.channel; + this.voice = message.guild.me.voice.connection; + this.dj = message.author; + this.joined_at = Date.now() + this.controller; + this.maybe_disconnect = false; + } +} + +module.exports = { + name: 'join', + aliases: ['join', 'joi', 'j', 'summon', 'su', 'con'], + description: 'Connect to a voice channel and plays Kanye music.', + async execute(message, args) { + if (!message.member.voice.channel) return message.channel.send('🛑 You must be in a channel first!').then(msg => msg.delete({ timeout: 5000 })); + + const perms = message.member.voice.channel.permissionsFor(message.guild.me) + if (!perms.has('CONNECT') || !perms.has('SPEAK')) return message.channel.send("🛑 I'm not allowed to enter your channel!").then(msg => msg.delete({ timeout: 5000 })); + + if (message.guild.me.voice.connection) { + if (message.guild.me.voice.connection.dispatcher && message.member.voice.channel != message.guild.me.voice.connection.channel) { + return message.channel.send("🛑 You can't move the bot while it's playing in another channel!").then(msg => msg.delete({ timeout: 5000 })); + } + if (message.member.voice.channel === message.guild.me.voice.connection.channel) { + return message.channel.send("🛑 I'm already in this channel!").then(msg => msg.delete({ timeout: 5000 })) + } + } + + const connection = await message.member.voice.channel.join() + await message.guild.me.voice.setSelfDeaf(true); + await message.react('✅'); + const player = new Player(message); + message.client.players.set(message.guild.id, player) + connection.play(message.client.broadcast); + const embed = new MessageEmbed() + .setTitle('Now playing') + .setDescription(`${message.client.current}`) + .setColor(message.client.color) + .setFooter(`Use ${message.client.prefix}help for more commands!`, `${message.client.user.avatarURL()}`); + player.controller = await message.channel.send(embed); + + + } +} \ No newline at end of file diff --git a/commands/general/leave.js b/commands/general/leave.js new file mode 100644 index 0000000..84e665b --- /dev/null +++ b/commands/general/leave.js @@ -0,0 +1,18 @@ +module.exports = { + name: 'leave', + description: 'Disconnects the player from the channel', + aliases: ['disconnect', 'dc', 'disc', 'lv', 'fuckoff'], + async execute(message, args) { + if (!message.member.voice.channel) return message.channel.send('🛑 You must be in a channel first!').then(msg => msg.delete({ timeout: 5000 })); + if (!message.guild.me.voice.connection) return message.channel.send("🛑 I'm not in a voice channel!").then(msg => msg.delete({ timeout: 5000 })); + if (message.member.voice.channel != message.guild.me.voice.connection.channel) return message.channel.send("🛑 You must be in the same channel as the bot in order to do that!").then(msg => msg.delete({ timeout: 5000 })); + const player = message.client.players.get(message.guild.id); + player.maybe_disconnect = true; + player.voice.disconnect(); + await player.controller.delete(); + message.client.players.delete(message.guild.id); + await message.react('👋'); + + + } +} \ No newline at end of file diff --git a/commands/general/nowplaying.js b/commands/general/nowplaying.js new file mode 100644 index 0000000..4f23e2d --- /dev/null +++ b/commands/general/nowplaying.js @@ -0,0 +1,18 @@ +const { MessageEmbed } = require("discord.js"); + +module.exports = { + name: 'nowplaying', + description: 'Shows the currently playing track', + aliases: ['np', 'current'], + async execute(message, args) { + if (!message.member.voice.channel) return message.channel.send('🛑 You must be in a channel first!').then(msg => msg.delete({ timeout: 5000 })); + if (!message.guild.me.voice.connection) return message.channel.send("🛑 I'm not in a voice channel!").then(msg => msg.delete({ timeout: 5000 })); + if (message.member.voice.channel != message.guild.me.voice.connection.channel) return message.channel.send("🛑 You must be in the same channel as the bot in order to do that!").then(msg => msg.delete({ timeout: 5000 })); + const embed = new MessageEmbed() + .setTitle('Now Playing') + .setDescription(`${message.client.current}`) + .setColor(message.client.color) + .setFooter(`Use ${message.client.prefix}help for more commands!`, `${message.client.user.avatarURL()}`); + message.channel.send(embed).then(msg => msg.delete({ timeout: 15000 })); + } +} \ No newline at end of file diff --git a/commands/info/about.js b/commands/info/about.js new file mode 100644 index 0000000..1af60a1 --- /dev/null +++ b/commands/info/about.js @@ -0,0 +1,28 @@ +const discord = require('discord.js'); +const osutils = require('node-os-utils'); +const humanizeDuration = require('humanize-duration') + +module.exports = { + name: 'about', + aliases: ['ab'], + description: 'Shows more info about the bot', + async execute(message, args) { + const meminfo = await osutils.mem.info(); + const cpu = await osutils.cpu.usage(); + const embed = new discord.MessageEmbed() + .setTitle('About') + .addField('Name', `${message.client.user.tag}`, true) + .addField('Servers', `${message.client.guilds.cache.size}`, true) + .addField('Members', `${message.client.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0)}`, true) + .addField('Owner', 'Clxud#6951', true) + .addField('Commands', `${message.client.commands.size}`, true) + .addField('Uptime', `\`${humanizeDuration(Date.now() - message.client.start_time)}\``, true) + .addField('Current Prefix', `\`${message.client.prefix}\``, true) + .addField('CPU', `${cpu}%`, true) + .addField('Memory', `${Math.round(meminfo.usedMemMb)} MB / ${Math.round(meminfo.totalMemMb)} MB`, true) + .setColor(message.client.color) + .setThumbnail(`${message.client.user.avatarURL()}`) + .setFooter(`Use ${message.client.prefix}help for more commands!`, `${message.client.user.avatarURL()}`); + await message.channel.send(embed); + } +} \ No newline at end of file diff --git a/commands/info/help.js b/commands/info/help.js new file mode 100644 index 0000000..abec864 --- /dev/null +++ b/commands/info/help.js @@ -0,0 +1,32 @@ +const { MessageEmbed } = require("discord.js"); + + +module.exports = { + name: 'help', + description: 'List all of my commands or info about a specific command.', + aliases: ['commands'], + async execute(message, args) { + const { commands } = message.client; + + if (!args.length) { + const embed= new MessageEmbed() + .setTitle(`${message.client.user.username} Help Menu`) + .setDescription(`Use ${message.client.prefix}help [command] for more info on a command.`) + .addField('Commands', `${commands.filter(command => !command.ownerOnly).map(command => `\`${command.name}\``).join(' ')}`) + .setColor(message.client.color); + return await message.channel.send(embed); + } + + const name = args[0].toLowerCase(); + const command = commands.get(name) || commands.find(c => c.aliases && c.aliases.includes(name)); + + if (!command) return await message.channel.send(`🛑 Invalid command, use \`${message.client.prefix}help\` for a valid list of commands`); + + const embed = new MessageEmbed() + .setTitle(command.aliases ? `[${command.name}|${command.aliases.join('|')}]` : `${command.name}`) + .setDescription(`${command.description}`) + .setColor(message.client.color); + + await message.channel.send(embed); + }, +}; \ No newline at end of file diff --git a/commands/info/invite.js b/commands/info/invite.js new file mode 100644 index 0000000..39d3f11 --- /dev/null +++ b/commands/info/invite.js @@ -0,0 +1,14 @@ +const discord = require('discord.js'); + +module.exports = { + name: 'invite', + aliases: ['inv'], + description: 'Sends the bots invite link', + async execute(message, args) { + const embed = new discord.MessageEmbed() + .setTitle('Invite me') + .setURL('https://discord.com/api/oauth2/authorize?client_id=821007014536019999&permissions=36719680&scope=bot') + .setColor(message.client.color); + await message.channel.send(embed) + } +} \ No newline at end of file diff --git a/commands/info/ping.js b/commands/info/ping.js new file mode 100644 index 0000000..a70740e --- /dev/null +++ b/commands/info/ping.js @@ -0,0 +1,12 @@ +const discord = require('discord.js'); + +module.exports = { + name: 'ping', + description: 'Sends the bots latency', + async execute(message, args) { + const embed = new discord.MessageEmbed() + .setTitle(`${Math.round(message.client.ws.ping)}ms`) + .setColor(message.client.color); + await message.channel.send(embed) + } +} \ No newline at end of file diff --git a/commands/info/uptime.js b/commands/info/uptime.js new file mode 100644 index 0000000..fe85d68 --- /dev/null +++ b/commands/info/uptime.js @@ -0,0 +1,13 @@ +const { MessageEmbed } = require('discord.js'); +const humanizeDuration = require('humanize-duration'); + +module.exports = { + name: 'uptime', + description: 'Shows the amount of time elapsed since the bot started', + async execute(message, args) { + const embed = new MessageEmbed() + .setTitle(`${humanizeDuration(Date.now() - message.client.start_time)}`) + .setColor(message.client.color); + await message.channel.send(embed); + } +} \ No newline at end of file diff --git a/commands/owner/player.js b/commands/owner/player.js new file mode 100644 index 0000000..a5425b1 --- /dev/null +++ b/commands/owner/player.js @@ -0,0 +1,48 @@ +const { MessageEmbed } = require("discord.js"); +const humanizeDuration = require('humanize-duration'); + +module.exports = { + name: 'player', + description: 'Commands for player features', + ownerOnly: true, + async execute(message, args) { + if (!args.length) { + const embed = new MessageEmbed() + .setTitle('player') + .setDescription('Commands for player features') + .addField('player info ', 'Sends useful info of a player using its associated guild ID') + .addField('player stop ', 'Destroys a player instance using its associated guild ID') + .setColor(message.client.color) + .setFooter(`Use ${message.client.prefix}help for more commands!`, `${message.client.user.avatarURL()}`); + return await message.channel.send(embed); + } + + if (!args[1]) return message.channel.send("🛑 You must specify a guild ID!").then(msg => msg.delete({ timeout: 5000 })); + const player = message.client.players.get(args[1]) + if (!player) return message.channel.send("🛑 That player doesn't exist!").then(msg => msg.delete({ timeout: 5000 })); + + switch (args[0]) { + case "info": + const embed = new MessageEmbed() + .setTitle(`Player Info (${player.message.guild.name})`) + .addField('Channel ID', `${player.voice.channel.id}`) + .addField('Now Playing', `${message.client.current}`) + .addField('DJ', `${player.dj.tag}`) + .addField('Duration', `${humanizeDuration(Date.now() - player.joined_at)}`) + .setColor(message.client.color) + .setFooter(`Use ${message.client.prefix}help for more commands!`, `${message.client.user.avatarURL()}`); + await message.channel.send(embed); + break; + case 'reset': + case 'stop': + player.maybe_disconnect = true; + player.voice.disconnect() + await player.controller.delete() + await player.channel.send(`⚠️ <@${player.dj.id}>, the player is being manually reset by the owner. You can use \`${message.client.prefix}join\` to rejoin the bot.`) + await message.channel.send(`✅ Sucessfully destroyed player in guild ${player.message.guild.id}`) + message.client.players.delete(player.message.guild.id) + break; + + } + } +} \ No newline at end of file diff --git a/commands/owner/players.js b/commands/owner/players.js new file mode 100644 index 0000000..444ee1b --- /dev/null +++ b/commands/owner/players.js @@ -0,0 +1,24 @@ +const { MessageEmbed } = require('discord.js'); +const rm = require('discord.js-reaction-menu') + +module.exports = { + name: 'players', + description: 'Shows all active players', + ownerOnly: true, + async execute(message, args) { + const pages = []; + const array_chunks = (array, chunk_size) => Array(Math.ceil(array.length / chunk_size)).fill().map((_, index) => index * chunk_size).map(begin => array.slice(begin, begin + chunk_size)); + const chunked = array_chunks(message.client.players.map(player => player), message.client.players.size >= 10 ? 10 : message.client.players.size); + chunked.forEach(items => { + const description = []; + items.forEach(player => description.push(`${player.channel.guild.name} - [\`${player.channel.guild.id}\`]`)); + const embed = new MessageEmbed({title: `Active Players (${message.client.players.size} total)`, description: description.join('\n'), color: message.client.color, footer: {text: `Page ${pages.length + 1}/${chunked.length} | Use ${message.client.prefix}help for more commands!`, iconURL: `${message.client.user.avatarURL()}`}}); + pages.push(embed); + }); + new rm.menu({ + channel: message.channel, + userID: message.author.id, + pages: pages + }); + } +} \ No newline at end of file diff --git a/commands/owner/reload.js b/commands/owner/reload.js new file mode 100644 index 0000000..9a0771a --- /dev/null +++ b/commands/owner/reload.js @@ -0,0 +1,30 @@ +const fs = require('fs'); + +module.exports = { + name: 'reload', + aliases: ['rl'], + description: 'Reloads a command', + args: true, + ownerOnly: true, + async execute(message, args) { + if (!args.length) return await message.channel.send('🛑 Hey stupid, you need to enter a command to reload...') + const commandName = args[0].toLowerCase(); + const command = message.client.commands.get(commandName) || message.client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); + + if (!command) return await message.channel.send(`🛑 Hey stupid, that's not a command...`); + + const commandFolders = fs.readdirSync('./commands'); + const folderName = commandFolders.find(folder => fs.readdirSync(`./commands/${folder}`).includes(`${command.name}.js`)); + + delete require.cache[require.resolve(`../${folderName}/${command.name}.js`)]; + + try { + const newCommand = require(`../${folderName}/${command.name}.js`); + message.client.commands.set(newCommand.name, newCommand); + await message.channel.send(`✅ Command \`${newCommand.name}\` reloaded.`); + } catch (error) { + console.error(error); + await message.channel.send(`🛑 There was an error reloading command \`${command.name}\`:\n\`${error.message}\``); + } + }, +}; \ No newline at end of file diff --git a/kanye server/bot.js b/kanye server/bot.js new file mode 100644 index 0000000..8313372 --- /dev/null +++ b/kanye server/bot.js @@ -0,0 +1,129 @@ +const discord = require('discord.js'); +const fs = require('fs'); +const process = require('process'); +const { AutoPoster } = require('topgg-autoposter') + +const client = new discord.Client({presence: {status: 'online', activity: {type: 'LISTENING', name: 'kanye help | v2.1'}}}); +client.commands = new discord.Collection(); +client.color = (0x70e1df); +client.start_time = Date.now() +client.prefix = "kanye "; +client.players = new discord.Collection(); +client.broadcast = client.voice.createBroadcast() + +const folders = fs.readdirSync('./commands') +const poster = AutoPoster('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjgyMTAwNzAxNDUzNjAxOTk5OSIsImJvdCI6dHJ1ZSwiaWF0IjoxNjIwMDc0MzUzfQ.iCrq7Akpm5_xEXsaddgxzRuOEK_TLh4L2wPf3OmaUqs', client) + +for (const folder of folders) { + const files = fs.readdirSync(`./commands/${folder}`).filter(file => file.endsWith('.js')); + for (const file of files) { + const command = require(`./commands/${folder}/${file}`); + client.commands.set(command.name, command); + } +} + +async function play() { + const songs = fs.readdirSync('./songs'); + const index = Math.floor(Math.random() * songs.length); + const song = songs[index]; + client.current = song.slice(0, -4); + + const embed = new discord.MessageEmbed() + .setTitle('Now Playing') + .setDescription(`${client.current}`) + .setColor(client.color) + .setFooter(`Use ${client.prefix}help for more commands!`, `${client.user.avatarURL()}`); + + if (client.players.size > 0) { + client.players.each(async player => player.controller = await player.channel.send(embed)) + } + + + client.broadcast.play(`./songs/${song}`) + .on('finish', async () => { + if (client.players.size > 0) { + client.players.each(async player => await player.controller.delete()) + } + await play(); + }); +} + + + + +client.on('ready', async () => { + console.log(`${client.user.tag} is online and serving ${client.guilds.cache.size} guilds`); + await play(); +}); + + + +client.on('message', async message => { + if (!message.content.startsWith(client.prefix) || message.author.bot) return; + + const args = message.content.slice(client.prefix.length).trim().split(/ +/); + const commandName = args.shift().toLowerCase(); + const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); + + if (!command) return; + if (command.ownerOnly && message.author.id != '313314995687391234') return; + + + try { + await command.execute(message, args); + } catch(error) { + console.error(error); + await message.channel.send('🛑 An unexpected error occurred while executing the command! Please report this to the owner. \n```' + error + '```') + + } + +}); + +client.on('guildCreate', async guild => { + + let channel = guild.channels.cache.find(channel => channel.type === 'text' && channel.permissionsFor(guild.me).has('SEND_MESSAGES')) + const embed = new discord.MessageEmbed() + .setTitle('Thank you for inviting Kanye Reloaded!') + .setDescription('You can start playing Kanye music by typing **kanye join** while in a voice channel. \n\nDo **kanye help** for more information on how to do any commands\n\n If you have any issues/question, feel free to join our [support server](https://discord.gg/bBeAQcftAr)') + .setColor(client.color) + .setFooter(`Use ${client.prefix}help for more commands!`, `${client.user.avatarURL()}`); + await channel.send(embed); + + channel = await client.channels.fetch('799402132105068545') + await channel.send(`<@313314995687391234>, I was added to **${guild.name}**! I'm now in **${client.guilds.cache.size}** guilds.`) + +}); + +client.on('guildDelete', async guild => { + const channel = await client.channels.fetch('799402132105068545') + await channel.send(`<@313314995687391234>, I was removed from **${guild.name}**. I'm now in **${client.guilds.cache.size}** guilds.`) +}); + +client.on('voiceStateUpdate', async (oldState, newState) => { + if (newState.member === newState.guild.me && !newState.connection && !client.players.get(oldState.guild.id).maybe_disconnect) { + const player = client.players.get(oldState.guild.id); + console.log('Detected forced disconnect, cleaning up...'); + try { + await player.controller.delete(); + } catch (err) {} + client.players.delete(player.message.guild.id); + } +}) + +process.on('SIGINT', async () => { + if (client.players.size > 0) { + for (const player of client.players.values()) { + player.maybe_disconnect = true; + player.voice.disconnect(); + await player.controller.delete(); + await player.channel.send(`⚠️ <@${player.dj.id}>, the bot is being manually restarted by the owner. Once the bot has restarted, you can use \`${client.prefix}join\` to rejoin the bot.`); + client.players.delete(player.message.guild.id); + } + + } + console.log('Shutting down now...'); + process.exit(); +}); + +client.login('ODIxMDA3MDE0NTM2MDE5OTk5.YE9cXQ.s3V7CkhpOhGAXG7xSupi-FtoANU'); + diff --git a/setup.bat b/setup.bat new file mode 100644 index 0000000..989c00e --- /dev/null +++ b/setup.bat @@ -0,0 +1 @@ +echo y & git push -u origin main \ No newline at end of file