├── .github └── FUNDING.yml ├── config └── config.json ├── commands ├── info │ ├── ping.js │ ├── uptime.js │ └── help.js └── music │ ├── clearqueue.js │ ├── leave.js │ ├── stop.js │ ├── queueloop.js │ ├── trackloop.js │ ├── pause.js │ ├── resume.js │ ├── skip.js │ ├── shuffle.js │ ├── volume.js │ ├── join.js │ ├── remove.js │ ├── bassboost.js │ ├── speed.js │ ├── move.js │ ├── skipto.js │ ├── nowplaying.js │ ├── seek.js │ ├── queue.js │ ├── forward.js │ ├── rewind.js │ ├── filter.js │ ├── playtop.js │ ├── playskip.js │ └── play.js ├── events ├── ready.js ├── interactionCreate.js ├── messageCreate.js └── voiceStateUpdate.js ├── slashCommands ├── info │ └── ping.js └── music │ ├── leave.js │ ├── clearqueue.js │ ├── stop.js │ ├── queueloop.js │ ├── trackloop.js │ ├── pause.js │ ├── resume.js │ ├── skip.js │ ├── shuffle.js │ ├── join.js │ ├── volume.js │ ├── remove.js │ ├── nowplaying.js │ ├── bassboost.js │ ├── speed.js │ ├── skipto.js │ ├── queue.js │ ├── move.js │ ├── seek.js │ ├── forward.js │ ├── rewind.js │ ├── filter.js │ ├── playtop.js │ ├── playskip.js │ └── play.js ├── LICENSE ├── README.md ├── package.json ├── index.js └── util ├── handler.js └── musicUtils.js /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ["https://milrato.dev", "https://bero.milrato.dev", "https://discord.gg/milrato"] 2 | -------------------------------------------------------------------------------- /config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "token": "", 3 | "prefix": "$", 4 | "YOUTUBE_LOGIN_COOKIE": "optional" 5 | } 6 | -------------------------------------------------------------------------------- /commands/info/ping.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | name: "ping", 4 | description: "Show the Bot's ping", 5 | run: async (client, message, args, prefix) => { 6 | message.reply({ 7 | content: `:ping_pong: **PONG! Api Ping is: \`${client.ws.ping}ms\`**` 8 | }).catch(() => null); 9 | }, 10 | }; -------------------------------------------------------------------------------- /events/ready.js: -------------------------------------------------------------------------------- 1 | module.exports = (client) => { 2 | console.log(`${client.getTime()} :: Logged in as ${client.user.tag}!`); 3 | client.user.setActivity(`${client.config.prefix}help | /help | Fast-Music`, {type: "PLAYING"}) 4 | setInterval(() => { 5 | client.user.setActivity(`${client.config.prefix}help | /help | Fast-Music`, {type: "PLAYING"}) 6 | }, 600_00) 7 | } -------------------------------------------------------------------------------- /slashCommands/info/ping.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | name: "ping", 4 | aliases: ["latency"], 5 | description: "Show the Bot's ping", 6 | run: async (client, interaction, args) => { 7 | interaction.reply({ 8 | content: `:ping_pong: **PONG! Api Ping is: \`${client.ws.ping}ms\`**`, 9 | ephemeral: true 10 | }).catch(() => null); 11 | }, 12 | }; -------------------------------------------------------------------------------- /commands/info/uptime.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | name: "uptime", 4 | description: "Show the Bot's uptime", 5 | run: async (client, message, args, prefix) => { 6 | let date = new Date() 7 | let timestamp = date.getTime() - Math.floor(client.uptime); 8 | message.reply({ 9 | content: `⬆️⏳ **I'm running since and was started !**` 10 | }).catch(() => null); 11 | }, 12 | }; -------------------------------------------------------------------------------- /commands/info/help.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | module.exports = { 3 | name: "help", 4 | aliases: ["h"], 5 | description: "Show all of the Commands", 6 | run: async (client, message, args, prefix) => { 7 | return message.reply({embeds: [new MessageEmbed() 8 | .setColor("FUCHSIA") 9 | .setTitle(`👍 **Here is a list of all of my Commands**`) 10 | .addFields(client.commands.map(d => { 11 | return { 12 | name: `\`${prefix}${d.name}\``, 13 | value: `> *${d.description}*`, 14 | inline: true 15 | } 16 | })) 17 | ]}).catch(() => null); 18 | }, 19 | }; -------------------------------------------------------------------------------- /events/interactionCreate.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client, interaction) => { 2 | // Slash Command Handling 3 | if (interaction.isCommand()) { 4 | const cmd = client.slashCommands.get(interaction.commandName); 5 | if (!cmd) return interaction.reply({ content: "❌ An error occured." }).catch(() => null); 6 | 7 | const args = []; 8 | 9 | for (let option of interaction.options.data) { 10 | if (option.type === "SUB_COMMAND") { 11 | if (option.name) args.push(option.name); 12 | option.options?.forEach((x) => { 13 | if (x.value) args.push(x.value); 14 | }); 15 | } else if (option.value) args.push(option.value); 16 | } 17 | interaction.member = interaction.guild.members.cache.get(interaction.user.id) || await interaction.guild.members.fetch(interaction.user.id).catch(() => null) 18 | 19 | cmd.run(client, interaction, args, "/"); 20 | } 21 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Tomato6966 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # light-music-bot 2 | A super light, fast and simple tho advanced Music Bot, without any Music Manager Packages like Lavalink, discord-player or distube. Technically providing up to all filters of lavalink, but limited to 19 predefined ones, with speed and bassboost control, as well as everything in slash Commands and message Commands! 3 | 4 | ## Installation & Get Started 5 | 6 | - 1. in the `./config/config.json` File paste your Token 7 | - 2. in the `./index.js` adjust the SlashCommands Deployment Settings 8 | - *After deployed, globally once, disable it!* 9 | - 3. Start the bot: `npm install` and then `node .` 10 | 11 | ## Hosting Requirements: 12 | 13 | - **RAM:** 40-50mb on idle, + 15-20mb / Audio Connection (for more than 100+ Servers, 250mb Ram recommended) 14 | - **CPU:** 2-8% of a 2ghz CORE on idle, 20% of a 2ghz Core, while fetching youtube, 30% of a 2ghz Core, while changing the FILTERS 15 | 16 | ## Support Server: 17 | 18 | > https://discord.gg/milrato 19 | 20 | ## Credits 21 | 22 | > *If you consider using this Bot, make sure to credit either this Repository or, Tomato#6966 on Discord or the Support Discord Server https://discord.gg/milrato. THANKS!* 23 | -------------------------------------------------------------------------------- /commands/music/clearqueue.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "clearqueue", 4 | description: "Cleares the Queue", 5 | run: async (client, message, args, prefix) => { 6 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(message.guild.id); 9 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 11 | 12 | const queue = client.queues.get(message.guild.id); // get the queue 13 | if(!queue) { 14 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 15 | } 16 | // no new songs (and no current) 17 | queue.tracks = [ queue.tracks[0] ]; 18 | // skip the track 19 | 20 | return message.reply(`🪣 **Successfully cleared the Queue.**`).catch(() => null); 21 | }, 22 | }; -------------------------------------------------------------------------------- /commands/music/leave.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "leave", 4 | aliases: ["disconnect", "dis", "stopleave"], 5 | description: "Leaves a Voice Channel and stops playing", 6 | run: async (client, message, args, prefix) => { 7 | try { 8 | if(!message.member.voice.channelId) return message.reply({content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 9 | 10 | const oldConnection = getVoiceConnection(message.guild.id); 11 | if(!oldConnection) return message.reply({content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 12 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply({content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 13 | 14 | await client.leaveVoiceChannel(message.member.voice.channel); 15 | 16 | message.reply({content: "👍 Left your VC!"}).catch(() => null); 17 | } catch(e) { 18 | console.error(e); 19 | message.reply({content: `❌ Could not join your VC because: \`\`\`${e.message || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 20 | } 21 | }, 22 | }; -------------------------------------------------------------------------------- /commands/music/stop.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "stop", 4 | description: "Stops playing and cleares the Queue", 5 | run: async (client, message, args, prefix) => { 6 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(message.guild.id); 9 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 11 | 12 | const queue = client.queues.get(message.guild.id); // get the queue 13 | if(!queue) { 14 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 15 | } 16 | // no new songs (and no current) 17 | queue.tracks = []; 18 | // skip the track 19 | oldConnection.state.subscription.player.stop(); 20 | 21 | return message.reply(`🛑 **Successfully stopped playing and cleared the Queue.**`).catch(() => null); 22 | }, 23 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@discordjs/opus": "^0.5.3", 4 | "@discordjs/voice": "^0.8.0", 5 | "discord-ytdl-core": "^5.0.4", 6 | "discord.js": "^13.6.0", 7 | "ffmpeg-static": "^4.4.1", 8 | "libsodium-wrappers": "^0.7.10", 9 | "youtube-sr": "^4.1.15", 10 | "ytdl-core": "^4.11.0" 11 | }, 12 | "name": "lightmusicbot", 13 | "version": "1.3.0", 14 | "main": "index.js", 15 | "scripts": { 16 | "test": "echo \"Error: no test specified\" && exit 1" 17 | }, 18 | "author": "tomato#6966", 19 | "license": "MIT", 20 | "description": "A super light, fast and simple tho advanced Music Bot, without any Music Manager Packages like Lavalink, discord-player or distube. Technically providing up to all filters of lavalink, but limited to 19 predefined ones, with speed and bassboost control, as well as everything in slash Commands and message Commands!", 21 | "devDependencies": {}, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/Tomato6966/light-music-bot.git" 25 | }, 26 | "keywords": [ 27 | "music", 28 | "bot", 29 | "musicbot", 30 | "discordjs" 31 | ], 32 | "bugs": { 33 | "url": "https://github.com/Tomato6966/light-music-bot/issues" 34 | }, 35 | "homepage": "https://github.com/Tomato6966/light-music-bot#readme" 36 | } 37 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { Client, Intents, Collection, MessageEmbed } = require('discord.js'); //v13 2 | const { getVoiceConnection } = require("@discordjs/voice"); 3 | 4 | const client = new Client(clientSettingsObject()); 5 | // Slash Commands deployment settings 6 | client.deploySlash = { 7 | enabled: true, 8 | guild: false, // false | "ID" (if it's false, just set global once, and then never needed again!) 9 | } 10 | // Global config file 11 | client.config = require("./config/config.json"); 12 | 13 | // Create global collection 14 | client.commands = new Collection(); 15 | client.slashCommands = new Collection(); 16 | client.queues = new Collection(); 17 | 18 | // load music-util-function 19 | require("./util/musicUtils.js")(client); 20 | 21 | // load handler 22 | require("./util/handler.js")(client); 23 | 24 | client.login(client.config.token); 25 | 26 | function clientSettingsObject() { 27 | return { 28 | shards: "auto", 29 | allowedMentions: { 30 | parse: ["roles", "users", /* "everyone" */], 31 | repliedUser: false, //set true if you want to ping the bot on reply messages 32 | }, 33 | failIfNotExists: false, 34 | partials: ['MESSAGE', 'CHANNEL', 'REACTION'], 35 | intents: [ 36 | Intents.FLAGS.GUILDS, 37 | Intents.FLAGS.GUILD_MESSAGES, 38 | Intents.FLAGS.GUILD_VOICE_STATES 39 | ] 40 | } 41 | } -------------------------------------------------------------------------------- /slashCommands/music/leave.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "leave", 4 | description: "Leaves a Voice Channel and stops playing", 5 | run: async (client, interaction, args, prefix) => { 6 | try { 7 | if(!interaction.member.voice.channelId) return interaction.reply(({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"})).catch(() => null); 8 | 9 | const oldConnection = getVoiceConnection(interaction.guild.id); 10 | if(!oldConnection) return interaction.reply({ ephemeral: true, content:"👎 **I'm not connected somewhere!**"}).catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content:"👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 12 | 13 | await client.leaveVoiceChannel(interaction.member.voice.channel); 14 | 15 | interaction.reply({ ephemeral: false, content:"👍 Left your VC!"}).catch(() => null); 16 | } catch(e) { 17 | console.error(e); 18 | interaction.reply({ ephemeral: true, content:`❌ Could not join your VC because: \`\`\`${e.interaction || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 19 | } 20 | }, 21 | }; -------------------------------------------------------------------------------- /commands/music/queueloop.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "queueloop", 4 | aliases: ["loopqueue", "qloop", "queuloop"], 5 | description: "Toggles the Queue-Loop", 6 | run: async (client, message, args, prefix) => { 7 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue) { 15 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 16 | } 17 | if(queue.trackloop) queue.trackloop = false 18 | 19 | // no new songs (and no current) 20 | queue.queueloop = !queue.queueloop 21 | // skip the track 22 | 23 | return message.reply(`🔂 **Queue-Loop is now \`${queue.queueloop ? "Enabled" : "Disabled"}\`**`).catch(() => null); 24 | }, 25 | }; -------------------------------------------------------------------------------- /commands/music/trackloop.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "trackloop", 4 | aliases: ["looptrack", "songloop", "loopsong"], 5 | description: "Toggles the Track-Loop", 6 | run: async (client, message, args, prefix) => { 7 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue) { 15 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 16 | } 17 | if(queue.queueloop) queue.queueloop = false 18 | 19 | // no new songs (and no current) 20 | queue.trackloop = !queue.trackloop 21 | // skip the track 22 | 23 | return message.reply(`🔁 **Track-Loop is now \`${queue.trackloop ? "Enabled" : "Disabled"}\`**`).catch(() => null); 24 | }, 25 | }; -------------------------------------------------------------------------------- /commands/music/pause.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "pause", 4 | aliases: ["break"], 5 | description: "Pauses the current Track", 6 | run: async (client, message, args, prefix) => { 7 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**"); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue) { 15 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 16 | } 17 | // if already paused 18 | if(queue.paused) return message.reply(`👎 **Track already paused**`).catch(() => null); 19 | 20 | queue.paused = true; 21 | 22 | // skip the track 23 | oldConnection.state.subscription.player.pause(); 24 | 25 | return message.reply(`⏸️ **Successfully paused the Track**`).catch(() => null); 26 | }, 27 | }; -------------------------------------------------------------------------------- /slashCommands/music/clearqueue.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "clearqueue", 4 | description: "Cleares the Queue", 5 | run: async (client, interaction, args, prefix) => { 6 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(interaction.guild.id); 9 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 11 | 12 | const queue = client.queues.get(interaction.guild.id); // get the queue 13 | if(!queue) { 14 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 15 | } 16 | // no new songs (and no current) 17 | queue.tracks = [ queue.tracks[0] ]; 18 | // skip the track 19 | 20 | return interaction.reply({ ephemeral: false, content: `🪣 **Successfully cleared the Queue.**`}).catch(() => null); 21 | }, 22 | }; -------------------------------------------------------------------------------- /events/messageCreate.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require("discord.js"); 2 | module.exports = async (client, message) => { 3 | // Slash Command Handling 4 | if (message.author.bot || !message.guild) return 5 | let { prefix } = client.config; 6 | const prefixRegex = new RegExp(`^(<@!?${client.user.id}>|${escapeRegex(prefix)})\\s*`); 7 | if (!prefixRegex.test(message.content)) return 8 | const [, matchedPrefix] = message.content.match(prefixRegex); 9 | const [ cmdName, ...args ] = message.content.slice(matchedPrefix.length).trim().split(/ +/g); 10 | if (args.length === 0){ 11 | if(matchedPrefix.includes(client.user.id)) 12 | return message.reply({embeds: [new MessageEmbed() 13 | .setColor("FUCHSIA") 14 | .setTitle(`👍 **To see all Commands type: \`${prefix}help\` / \`/help\`**`) 15 | ]}).catch(() => null); 16 | } 17 | const cmd = client.commands.get(cmdName.toLowerCase()) || client.commands.find(c => c.aliases?.includes(cmdName.toLowerCase())); 18 | 19 | if (!cmd) return; 20 | try { 21 | cmd.run(client, message, args, prefix); 22 | } catch (e){ 23 | console.error(e); 24 | message.channel.send(`❌ Something went wrong, while running the ${cmd.name} Command`).catch(() => null); 25 | } 26 | 27 | } 28 | 29 | 30 | function escapeRegex(str) { 31 | return str.replace(/[.*+?^${}()|[\]\\]/g, `\\$&`); 32 | } 33 | -------------------------------------------------------------------------------- /commands/music/resume.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "resume", 4 | aliases: ["res", "con", "continue"], 5 | description: "Resumes the current, paused Track", 6 | run: async (client, message, args, prefix) => { 7 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue) { 15 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 16 | } 17 | // if already paused 18 | if(!queue.paused) return message.reply(`👎 **Track is not paused**`).catch(() => null); 19 | 20 | queue.paused = false; 21 | 22 | // skip the track 23 | oldConnection.state.subscription.player.unpause(); 24 | 25 | return message.reply(`▶️ **Successfully resumed the Track**`).catch(() => null); 26 | }, 27 | }; -------------------------------------------------------------------------------- /commands/music/skip.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "skip", 4 | aliases: ["s", "fs", "forceskip"], 5 | description: "Skips the current Track", 6 | run: async (client, message, args, prefix) => { 7 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue) { 15 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 16 | } 17 | // no new songs (and no current) 18 | if(!queue.tracks || queue.tracks.length <= 1) { 19 | return message.reply(`👎 **Nothing to skip**`).catch(() => null); 20 | } 21 | queue.skipped = true; 22 | // skip the track 23 | oldConnection.state.subscription.player.stop(); 24 | 25 | return message.reply(`⏭️ **Successfully skipped the Track**`).catch(() => null); 26 | }, 27 | }; -------------------------------------------------------------------------------- /slashCommands/music/stop.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "stop", 4 | description: "Stops playing and cleares the Queue", 5 | run: async (client, interaction, args, prefix) => { 6 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(interaction.guild.id); 9 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 11 | 12 | const queue = client.queues.get(interaction.guild.id); // get the queue 13 | if(!queue) { 14 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 15 | } 16 | // no new songs (and no current) 17 | queue.tracks = []; 18 | // skip the track 19 | oldConnection.state.subscription.player.stop(); 20 | 21 | return interaction.reply({ ephemeral: false, content: `🛑 **Successfully stopped playing and cleared the Queue.**`}).catch(() => null); 22 | }, 23 | }; -------------------------------------------------------------------------------- /commands/music/shuffle.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "shuffle", 4 | description: "Shuffles (mixes) the Queue", 5 | run: async (client, message, args, prefix) => { 6 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(message.guild.id); 9 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 11 | 12 | const queue = client.queues.get(message.guild.id); // get the queue 13 | if(!queue) { 14 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 15 | } 16 | 17 | // no new songs (and no current) 18 | queue.tracks = shuffleArray(queue.tracks); 19 | 20 | // shuffled the Queue 21 | return message.reply(`🔀 **Successfully shuffled the Queue.**`).catch(() => null); 22 | }, 23 | }; 24 | 25 | function shuffleArray(a) { 26 | let cI = a.length, rI; 27 | while(cI != 0) { 28 | rI = Math.floor(Math.random() * cI); 29 | cI --; 30 | [a[cI], a[rI]] = [a[rI], a[cI]]; 31 | } 32 | return a; 33 | } -------------------------------------------------------------------------------- /slashCommands/music/queueloop.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "queueloop", 4 | description: "Toggles the Queue-Loop", 5 | run: async (client, interaction, args, prefix) => { 6 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(interaction.guild.id); 9 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 11 | 12 | const queue = client.queues.get(interaction.guild.id); // get the queue 13 | if(!queue) { 14 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 15 | } 16 | if(queue.trackloop) queue.trackloop = false 17 | 18 | // no new songs (and no current) 19 | queue.queueloop = !queue.queueloop 20 | // skip the track 21 | 22 | return interaction.reply({ ephemeral: false, content: `🔂 **Queue-Loop is now \`${queue.queueloop ? "Enabled" : "Disabled"}\`**`}).catch(() => null); 23 | }, 24 | }; -------------------------------------------------------------------------------- /slashCommands/music/trackloop.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "trackloop", 4 | description: "Toggles the Track-Loop", 5 | run: async (client, interaction, args, prefix) => { 6 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(interaction.guild.id); 9 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 11 | 12 | const queue = client.queues.get(interaction.guild.id); // get the queue 13 | if(!queue) { 14 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 15 | } 16 | if(queue.queueloop) queue.queueloop = false 17 | 18 | // no new songs (and no current) 19 | queue.trackloop = !queue.trackloop 20 | // skip the track 21 | 22 | return interaction.reply({ ephemeral: false, content: `🔁 **Track-Loop is now \`${queue.trackloop ? "Enabled" : "Disabled"}\`**`}).catch(() => null); 23 | }, 24 | }; -------------------------------------------------------------------------------- /commands/music/volume.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "volume", 4 | aliases: ["vol"], 5 | description: "Changes the Volume of the Music", 6 | run: async (client, message, args, prefix) => { 7 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**") 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue) { 15 | return message.reply(`👎 **Nothing playing right now**`); 16 | } 17 | if(!args[0] || isNaN(args[0]) || Number(args[0]) < 1 || Number(args[0]) > 150) return message.reply(`👎 **No __valid__ Volume between 1 and 100 % provided!** Usage: \`${prefix}volume 25\``).catch(() => null); 18 | const volume = Number(args[0]); 19 | queue.volume = volume; 20 | 21 | // change the volume 22 | oldConnection.state.subscription.player.state.resource.volume.setVolume(volume / 100); 23 | 24 | return message.reply(`🔊 **Successfully changed the Volume to \`${volume}%\`**`).catch(() => null); 25 | }, 26 | }; -------------------------------------------------------------------------------- /slashCommands/music/pause.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "pause", 4 | description: "Pauses the current Track", 5 | run: async (client, interaction, args, prefix) => { 6 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(interaction.guild.id); 9 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 11 | 12 | const queue = client.queues.get(interaction.guild.id); // get the queue 13 | if(!queue) { 14 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 15 | } 16 | // if already paused 17 | if(queue.paused) return interaction.reply({ ephemeral: true, content: `👎 **Track already paused**`}).catch(() => null); 18 | 19 | queue.paused = true; 20 | 21 | // skip the track 22 | oldConnection.state.subscription.player.pause(); 23 | 24 | return interaction.reply({ ephemeral: false, content: `⏸️ **Successfully paused the Track**`}).catch(() => null); 25 | }, 26 | }; -------------------------------------------------------------------------------- /slashCommands/music/resume.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "resume", 4 | description: "Resumes the current, paused Track", 5 | run: async (client, interaction, args, prefix) => { 6 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(interaction.guild.id); 9 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 11 | 12 | const queue = client.queues.get(interaction.guild.id); // get the queue 13 | if(!queue) { 14 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 15 | } 16 | // if already paused 17 | if(!queue.paused) return interaction.reply({ ephemeral: true, content: `👎 **Track is not paused**`}).catch(() => null); 18 | 19 | queue.paused = false; 20 | 21 | // skip the track 22 | oldConnection.state.subscription.player.unpause(); 23 | 24 | return interaction.reply({ ephemeral: false, content: `▶️ **Successfully resumed the Track**`}).catch(() => null); 25 | }, 26 | }; -------------------------------------------------------------------------------- /slashCommands/music/skip.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "skip", 4 | description: "Skips the current Track", 5 | run: async (client, interaction, args, prefix) => { 6 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(interaction.guild.id); 9 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 11 | 12 | const queue = client.queues.get(interaction.guild.id); // get the queue 13 | if(!queue) { 14 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 15 | } 16 | // no new songs (and no current) 17 | if(!queue.tracks || queue.tracks.length <= 1) { 18 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing to skip**`}).catch(() => null); 19 | } 20 | queue.skipped = true; 21 | // skip the track 22 | oldConnection.state.subscription.player.stop(); 23 | 24 | return interaction.reply({ ephemeral: false, content: `⏭️ **Successfully skipped the Track**`}).catch(() => null); 25 | }, 26 | }; -------------------------------------------------------------------------------- /commands/music/join.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { Permissions } = require("discord.js"); 3 | module.exports = { 4 | name: "join", 5 | description: "Joins a Voice Channel", 6 | run: async (client, message, args, prefix) => { 7 | try { 8 | if(!message.member.voice.channelId) return message.reply({content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 9 | 10 | const oldConnection = getVoiceConnection(message.guild.id); 11 | if(oldConnection) return message.reply({ content: `👎 **I'm already connected in <#${oldConnection.joinConfig.channelId}>**!`}).catch(() => null); 12 | 13 | if(!message.member.voice.channel?.permissionsFor(message.guild?.me)?.has(Permissions.FLAGS.CONNECT)) { 14 | return message.reply({content: `👎 **I'm missing the Permission to Connect to your Voice-Channel!**`}).catch(() => null); 15 | } 16 | if(!message.member.voice.channel?.permissionsFor(message.guild?.me)?.has(Permissions.FLAGS.SPEAK)) { 17 | return message.reply({content: `👎 **I'm missing the Permission to speak in your Voice-Channel!**`}).catch(() => null); 18 | } 19 | 20 | await client.joinVoiceChannel(message.member.voice.channel); 21 | message.reply({content: "🔗 **Joined your VC!**"}).catch(() => null); 22 | } catch(e) { 23 | console.error(e); 24 | message.reply({content: `❌ Could not join your VC because: \`\`\`${e.message || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 25 | } 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /slashCommands/music/shuffle.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "shuffle", 4 | description: "Shuffles (mixes) the Queue", 5 | run: async (client, interaction, args, prefix) => { 6 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(interaction.guild.id); 9 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 11 | 12 | const queue = client.queues.get(interaction.guild.id); // get the queue 13 | if(!queue) { 14 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 15 | } 16 | 17 | // no new songs (and no current) 18 | queue.tracks = shuffleArray(queue.tracks); 19 | 20 | // shuffled the Queue 21 | return interaction.reply({ ephemeral: true, content: `🔀 **Successfully shuffled the Queue.**`}).catch(() => null); 22 | }, 23 | }; 24 | 25 | function shuffleArray(a) { 26 | let cI = a.length, rI; 27 | while(cI != 0) { 28 | rI = Math.floor(Math.random() * cI); 29 | cI --; 30 | [a[cI], a[rI]] = [a[rI], a[cI]]; 31 | } 32 | return a; 33 | } -------------------------------------------------------------------------------- /commands/music/remove.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "remove", 4 | aliases: ["delete"], 5 | description: "Removes a specific Track from the Queue", 6 | run: async (client, message, args, prefix) => { 7 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue) { 15 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 16 | } 17 | // no new songs (and no current) 18 | if(!queue.tracks || queue.tracks.length <= 1) { 19 | return message.reply(`👎 **Nothing to skip**`).catch(() => null); 20 | } 21 | if(!args[0] || isNaN(args[0]) || Number(args[0]) > queue.tracks.length) 22 | return message.reply({ content: `👎 **There are just ${queue.tracks.length} Songs in the Queue, can't remove the ${!isNaN(args[0]) ? client.queuePos(Number(args[0])) : args[0]} Song.**`}) 23 | 24 | queue.skipped = true; 25 | 26 | queue.tracks.splice(args[0], 1) 27 | 28 | return message.reply(`⏭️ **Successfully removed the ${client.queuePos(Number(args[0]))} Track!**`).catch(() => null); 29 | }, 30 | }; -------------------------------------------------------------------------------- /events/voiceStateUpdate.js: -------------------------------------------------------------------------------- 1 | const { Permissions } = require("discord.js"); 2 | const { getVoiceConnection } = require("@discordjs/voice") 3 | module.exports = async (client, oldState, newState) => { 4 | // Stage Channel self suspress 5 | if(newState.id == client.user.id && newState.channelId && newState.channel.type == "GUILD_STAGE_VOICE" && newState.suppress) { 6 | if(newState.channel?.permissionsFor(newState.guild.me)?.has(Permissions.FLAGS.MUTE_MEMBERS)) { 7 | await newState.guild.me.voice.setSuppressed(false).catch(() => null); 8 | } 9 | } 10 | 11 | if(newState.id == client.user.id) return; 12 | 13 | // Destroy connection if channel gets emtpy 14 | function stateChange(one, two) { 15 | if(one === false && two === true || one === true && two === false) return true; 16 | else return false; 17 | } 18 | const o = oldState, n = newState; 19 | if(stateChange(o.streaming, n.streaming) || 20 | stateChange(o.serverDeaf, n.serverDeaf) || 21 | stateChange(o.serverMute, n.serverMute) || 22 | stateChange(o.selfDeaf, n.selfDeaf) || 23 | stateChange(o.selfMute, n.selfMute) || 24 | stateChange(o.selfVideo, n.selfVideo) || 25 | stateChange(o.suppress, n.suppress)) return; 26 | // channel joins 27 | if(!o.channelId && n.channelId) { 28 | return; 29 | } 30 | // channel leaves 31 | if(!n.channelId && o.channelId || n.channelId && o.channelId) { 32 | const connection = getVoiceConnection(n.guild.id); 33 | if(o.channel.members.filter(m => !m.user.bot && !m.voice.selfDeaf && !m.voice.serverDeaf).size >= 1) return; 34 | if(connection && connection.joinConfig.channelId == o.channelId) connection.destroy(); 35 | return; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /commands/music/bassboost.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "bassboost", 4 | aliases: ["bass", "bb"], 5 | description: "Changes the Bassboost Level of the Music", 6 | run: async (client, message, args, prefix) => { 7 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**") 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue) { 15 | return message.reply(`👎 **Nothing playing right now**`); 16 | } 17 | if(args[0] === undefined || isNaN(args[0]) || Number(args[0]) < 0 || Number(args[0]) > 20) return message.reply(`👎 **No __valid__ Bassboost-Level between 0 and 20 db provided!** Usage: \`${prefix}bassboost 6\``).catch(() => null); 18 | const bassboost = Number(args[0]); 19 | queue.effects.bassboost = bassboost; 20 | 21 | // change the Basslevel 22 | queue.filtersChanged = true; 23 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 24 | oldConnection.state.subscription.player.stop(); 25 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, curPos)); 26 | 27 | return message.reply(`🎚 **Successfully changed the Bassboost-Level to \`${bassboost}db\`**`).catch(() => null); 28 | }, 29 | }; -------------------------------------------------------------------------------- /slashCommands/music/join.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { Permissions } = require("discord.js"); 3 | module.exports = { 4 | name: "join", 5 | description: "Joins a Voice Channel", 6 | run: async (client, interaction, args, prefix) => { 7 | try { 8 | if(!interaction.member.voice.channelId) return interaction.reply(({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"})).catch(() => null); 9 | 10 | const oldConnection = getVoiceConnection(interaction.guild.id); 11 | if(oldConnection) return interaction.reply({ ephemeral: true, content:`👎 **I'm already connected in <#${oldConnection.joinConfig.channelId}>**!`}).catch(() => null); 12 | 13 | if(!interaction.member.voice.channel?.permissionsFor(interaction.guild?.me)?.has(Permissions.FLAGS.CONNECT)) { 14 | return interaction.reply({ephemeral: true, content: "👎 **I'm missing the Permission to Connect to your Voice-Channel!**"}).catch(() => null); 15 | } 16 | if(!interaction.member.voice.channel?.permissionsFor(interaction.guild?.me)?.has(Permissions.FLAGS.SPEAK)) { 17 | return interaction.reply({ephemeral: true, content: "👎 **I'm missing the Permission to Speak in your Voice-Channel!**"}).catch(() => null); 18 | } 19 | 20 | await client.joinVoiceChannel(interaction.member.voice.channel); 21 | interaction.reply({ ephemeral: false, content:"🔗 **Joined your VC!**"}).catch(() => null); 22 | } catch(e) { 23 | console.error(e); 24 | interaction.reply({ ephemeral: true, content:`❌ Could not join your VC because: \`\`\`${e.interaction || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 25 | } 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /commands/music/speed.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "speed", 4 | description: "Changes the Speed of the Music", 5 | run: async (client, message, args, prefix) => { 6 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(message.guild.id); 9 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**") 10 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 11 | 12 | const queue = client.queues.get(message.guild.id); // get the queue 13 | if(!queue) { 14 | return message.reply(`👎 **Nothing playing right now**`); 15 | } 16 | if(args[0] === undefined || isNaN(args[0]) || Number(args[0]) < 50 || Number(args[0]) > 300) return message.reply(`👎 **No __valid__ Bassboost-Level between 50 and 300 % provided!** (100 % == normal speed)\n Usage: \`${prefix}speed 125\``).catch(() => null); 17 | const speed = Number(args[0]); 18 | queue.effects.speed = Math.floor(speed) / 100; 19 | 20 | // change the Basslevel 21 | queue.filtersChanged = true; 22 | const curPos = oldConnection.state.subscription.player.state.resource?.playbackDuration || 0; 23 | oldConnection.state.subscription.player.stop(); 24 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, curPos)); 25 | 26 | return message.reply(`🎚 **Successfully changed the Speed to \`${Math.floor(speed) / 100}x\` of the Original Speed (${speed}%)**`).catch(() => null); 27 | }, 28 | }; -------------------------------------------------------------------------------- /slashCommands/music/volume.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "volume", 4 | description: "Changes the Volume of the Music", 5 | options: [ 6 | { 7 | name: "volume", 8 | description: "Then Volume you want to set", 9 | type: "INTEGER", 10 | required: true, 11 | }, 12 | ], 13 | run: async (client, interaction, args, prefix) => { 14 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 15 | // get an old connection 16 | const oldConnection = getVoiceConnection(interaction.guild.id); 17 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}) 18 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 19 | 20 | const queue = client.queues.get(interaction.guild.id); // get the queue 21 | if(!queue) { 22 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}); 23 | } 24 | if(!args[0] || isNaN(args[0]) || Number(args[0]) < 1 || Number(args[0]) > 150) return interaction.reply({ ephemeral: true, content: `👎 **No __valid__ Volume between 1 and 100 % provided!** Usage: \`${prefix}volume 25\``}).catch(() => null); 25 | const volume = Number(args[0]); 26 | queue.volume = volume; 27 | 28 | // change the volume 29 | oldConnection.state.subscription.player.state.resource.volume.setVolume(volume / 100); 30 | 31 | return interaction.reply({ ephemeral: false, content: `🔊 **Successfully changed the Volume to \`${volume}%\`**`}).catch(() => null); 32 | }, 33 | }; -------------------------------------------------------------------------------- /commands/music/move.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "move", 4 | description: "Moves a Song in the Queue", 5 | run: async (client, message, args, prefix) => { 6 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 7 | // get an old connection 8 | const oldConnection = getVoiceConnection(message.guild.id); 9 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 10 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 11 | 12 | const queue = client.queues.get(message.guild.id); // get the queue 13 | if(!queue) { 14 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 15 | } 16 | if(!args[0] || isNaN(args[0]) || Number(args[0]) < 1 || !args[1] || isNaN(args[1]) || Number(args[1]) < 1) 17 | return message.reply(`👎 **From where to where shall I move?** Usage: \`${prefix}move \``).catch(() => null); 18 | 19 | queue.tracks = arrayMove(queue.tracks, args[0], args[1]) 20 | 21 | return message.reply(`🪣 **Successfully moved the \`${client.queuePos(args[0])} Song\` to \`${client.queuePos(args[1])} Position\` in the Queue.**`).catch(() => null); 22 | }, 23 | }; 24 | 25 | 26 | 27 | function arrayMove(array, from, to) { 28 | try { 29 | array = [...array]; 30 | const startIndex = from < 0 ? array.length + from : from; 31 | if (startIndex >= 0 && startIndex < array.length) { 32 | const endIndex = to < 0 ? array.length + to : to; 33 | const [item] = array.splice(from, 1); 34 | array.splice(endIndex, 0, item); 35 | } 36 | return array; 37 | } catch (e) { 38 | console.log(String(e.stack).grey.bgRed) 39 | } 40 | } -------------------------------------------------------------------------------- /commands/music/skipto.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "skipto", 4 | aliases: ["jump", "jumpto"], 5 | description: "Skips to a specific Track in the Queue", 6 | run: async (client, message, args, prefix) => { 7 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue) { 15 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 16 | } 17 | // no new songs (and no current) 18 | if(!queue.tracks || queue.tracks.length <= 1) { 19 | return message.reply(`👎 **Nothing to skip**`).catch(() => null); 20 | } 21 | if(!args[0] || isNaN(args[0]) || Number(args[0]) > queue.tracks.length) 22 | return message.reply({ content: `👎 **There are just ${queue.tracks.length} Songs in the Queue, can't skip to ${args[0]}th Song.**`}) 23 | 24 | queue.skipped = true; 25 | 26 | // if there is a queueloop: remove the current track but keep the rest 27 | if(queue.queueloop) { 28 | for(let i = 1; i <= args[0] - 1; i++) 29 | queue.tracks.push(queue.tracks[i]) 30 | } 31 | queue.tracks = queue.tracks.slice(args[0] - 1) 32 | 33 | // skip the track 34 | oldConnection.state.subscription.player.stop(); 35 | 36 | return message.reply(`⏭️ **Successfully skipped ${args[0]} Track(s)**`).catch(() => null); 37 | }, 38 | }; -------------------------------------------------------------------------------- /commands/music/nowplaying.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { MessageEmbed } = require("discord.js"); 3 | module.exports = { 4 | name: "nowplaying", 5 | aliases: ["np", "current", "cur"], 6 | description: "Shows information about the current track", 7 | run: async (client, message, args, prefix) => { 8 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 9 | // get an old connection 10 | const oldConnection = getVoiceConnection(message.guild.id); 11 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 12 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 13 | 14 | const queue = client.queues.get(message.guild.id); // get the queue 15 | if(!queue || !queue.tracks || !queue.tracks[0]) { 16 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 17 | } 18 | const song = queue.tracks[0]; 19 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 20 | 21 | const songEmbed = new MessageEmbed().setColor("FUCHSIA") 22 | .setTitle(`${song.title}`) 23 | .setURL(client.getYTLink(song.id)) 24 | .addField(`ℹ️ **Upload-Channel:**`, `> ${song ? `[${song.channel.name}](${song.channel.url})` : `\`Unknown\``}`, true) 25 | .addField(`📅 **Upload-At:**`, `> ${song.uploadedAt}`, true) 26 | .addField(`💯 **Requester:**`, `> ${song.requester} \`${song.requester.tag}\``, true) 27 | .addField(`⏳ **Duration:**`, `> ${client.createBar(song.duration, curPos)}\n> **${client.formatDuration(curPos)} / ${song.durationFormatted}**`) 28 | if(song?.thumbnail?.url) songEmbed.setImage(`${song?.thumbnail?.url}`); 29 | 30 | return message.reply({content: `ℹ️ **Nowplaying Track**`, embeds: [songEmbed]}).catch(() => null); 31 | }, 32 | }; -------------------------------------------------------------------------------- /slashCommands/music/remove.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "remove", 4 | description: "Removes a specific Track from the Queue", 5 | options: [ 6 | { 7 | name: "position", 8 | description: "Song Position to remove", 9 | type: "INTEGER", 10 | required: true, 11 | }, 12 | ], 13 | run: async (client, interaction, args, prefix) => { 14 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 15 | // get an old connection 16 | const oldConnection = getVoiceConnection(interaction.guild.id); 17 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 18 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 19 | 20 | const queue = client.queues.get(interaction.guild.id); // get the queue 21 | if(!queue) { 22 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 23 | } 24 | // no new songs (and no current) 25 | if(!queue.tracks || queue.tracks.length <= 1) { 26 | return interaction.reply(`👎 **Nothing to skip**`).catch(() => null); 27 | } 28 | if(!args[0] || isNaN(args[0]) || Number(args[0]) > queue.tracks.length) 29 | return interaction.reply({ ephemeral: true, content:`👎 **There are just ${queue.tracks.length} Songs in the Queue, can't remove the ${!isNaN(args[0]) ? client.queuePos(Number(args[0])) : args[0]} Song.**`}) 30 | 31 | queue.skipped = true; 32 | 33 | queue.tracks.splice(args[0], 1) 34 | 35 | return interaction.reply({ ephemeral: false, content: `⏭️ **Successfully removed the ${client.queuePos(Number(args[0]))} Track!**`}).catch(() => null); 36 | }, 37 | }; -------------------------------------------------------------------------------- /slashCommands/music/nowplaying.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { MessageEmbed } = require("discord.js"); 3 | module.exports = { 4 | name: "nowplaying", 5 | description: "Shows information about the current track", 6 | run: async (client, interaction, args, prefix) => { 7 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(interaction.guild.id); 10 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 12 | 13 | const queue = client.queues.get(interaction.guild.id); // get the queue 14 | if(!queue || !queue.tracks || !queue.tracks[0]) { 15 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 16 | } 17 | const song = queue.tracks[0]; 18 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 19 | 20 | const songEmbed = new MessageEmbed().setColor("FUCHSIA") 21 | .setTitle(`${song.title}`) 22 | .setURL(client.getYTLink(song.id)) 23 | .addField(`ℹ️ **Upload-Channel:**`, `> ${song ? `[${song.channel.name}](${song.channel.url})` : `\`Unknown\``}`, true) 24 | .addField(`📅 **Upload-At:**`, `> ${song.uploadedAt}`, true) 25 | .addField(`💯 **Requester:**`, `> ${song.requester} \`${song.requester.tag}\``, true) 26 | .addField(`⏳ **Duration:**`, `> ${client.createBar(song.duration, curPos)}\n> **${client.formatDuration(curPos)} / ${song.durationFormatted}**`) 27 | if(song?.thumbnail?.url) songEmbed.setImage(`${song?.thumbnail?.url}`); 28 | 29 | return interaction.reply({ ephemeral: false, content:`ℹ️ **Nowplaying Track**`, embeds: [songEmbed]}).catch(() => null); 30 | }, 31 | }; -------------------------------------------------------------------------------- /slashCommands/music/bassboost.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "bassboost", 4 | args: ["bass", "bb"], 5 | description: "Changes the Bassboost Level of the Music", 6 | options: [ 7 | { 8 | name: "gain_level", 9 | description: "Bassboost level between 0 and 20", 10 | type: "INTEGER", 11 | required: true, 12 | }, 13 | ], 14 | run: async (client, interaction, args, prefix) => { 15 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 16 | // get an old connection 17 | const oldConnection = getVoiceConnection(interaction.guild.id); 18 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**" }) 19 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 20 | 21 | const queue = client.queues.get(interaction.guild.id); // get the queue 22 | if(!queue) { 23 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}); 24 | } 25 | if(args[0] === undefined || isNaN(args[0]) || Number(args[0]) < 0 || Number(args[0]) > 20) return interaction.reply({ ephemeral: true, content: `👎 **No __valid__ Bassboost-Level between 0 and 20 db provided!** Usage: \`${prefix}bassboost 6\``}).catch(() => null); 26 | const bassboost = Number(args[0]); 27 | queue.effects.bassboost = bassboost; 28 | 29 | // change the Basslevel 30 | queue.filtersChanged = true; 31 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 32 | oldConnection.state.subscription.player.stop(); 33 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, curPos)); 34 | 35 | return interaction.reply({ ephemeral: false, content: `🎚 **Successfully changed the Bassboost-Level to \`${bassboost}db\`**`}).catch(() => null); 36 | }, 37 | }; -------------------------------------------------------------------------------- /commands/music/seek.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "seek", 4 | description: "Seeks to a specific Position (sec)", 5 | run: async (client, message, args, prefix) => { 6 | try { 7 | if(!message.member.voice.channelId) return message.reply({content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 8 | 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply({content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply({content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue || !queue.tracks || !queue.tracks[0]) { 15 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 16 | } 17 | 18 | if(!args[0] || isNaN(args[0])) return message.reply({ content: `👎 **You forgot to add the seeking-time!** Usage: \`${prefix}seek \``}).catch(() => null); 19 | 20 | if(Number(args[0]) < 0 || Number(args[0]) > Math.floor(queue.tracks[0].duration / 1000 - 1)) 21 | return message.reply({ content: `👎 **The Seek-Number-Pos must be between \`0\` and \`${Math.floor(queue.tracks[0].duration / 1000 - 1)}\`!**`}).catch(() => null); 22 | 23 | const newPos = Number(args[0]) * 1000; 24 | // set Filterschanged to true 25 | queue.filtersChanged = true; 26 | // seek 27 | oldConnection.state.subscription.player.stop(); 28 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, newPos)); 29 | 30 | message.reply({content: `⏩ **Seeked to \`${client.formatDuration(newPos)}\`**!`}).catch(() => null); 31 | } catch(e) { 32 | console.error(e); 33 | message.reply({content: `❌ Could not join your VC because: \`\`\`${e.message || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 34 | } 35 | }, 36 | }; -------------------------------------------------------------------------------- /slashCommands/music/speed.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "speed", 4 | description: "Changes the Speed of the Music", 5 | options: [ 6 | { 7 | name: "playback_speed", 8 | description: "Speed % between 50 and 300 (100 = normal)", 9 | type: "INTEGER", 10 | required: true, 11 | }, 12 | ], 13 | run: async (client, interaction, args, prefix) => { 14 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 15 | // get an old connection 16 | const oldConnection = getVoiceConnection(interaction.guild.id); 17 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}) 18 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 19 | 20 | const queue = client.queues.get(interaction.guild.id); // get the queue 21 | if(!queue) { 22 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}); 23 | } 24 | if(args[0] === undefined || isNaN(args[0]) || Number(args[0]) < 50 || Number(args[0]) > 300) return interaction.reply({ ephemeral: true, content: `👎 **No __valid__ Bassboost-Level between 50 and 300 % provided!** (100 % == normal speed)\n Usage: \`${prefix}speed 125\``}).catch(() => null); 25 | const speed = Number(args[0]); 26 | queue.effects.speed = Math.floor(speed) / 100; 27 | 28 | // change the Basslevel 29 | queue.filtersChanged = true; 30 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 31 | oldConnection.state.subscription.player.stop(); 32 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, curPos)); 33 | 34 | return interaction.reply({ ephemeral: false, content: `🎚 **Successfully changed the Speed to \`${Math.floor(speed) / 100}x\` of the Original Speed (${speed}%)**`}).catch(() => null); 35 | }, 36 | }; -------------------------------------------------------------------------------- /commands/music/queue.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { MessageEmbed } = require("discord.js"); 3 | module.exports = { 4 | name: "queue", 5 | aliases: ["list"], 6 | description: "Show the current Queue-List", 7 | run: async (client, message, args, prefix) => { 8 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 9 | // get an old connection 10 | const oldConnection = getVoiceConnection(message.guild.id); 11 | if(!oldConnection) return message.reply("👎 **I'm not connected somewhere!**").catch(() => null); 12 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 13 | 14 | const queue = client.queues.get(message.guild.id); // get the queue 15 | if(!queue || !queue.tracks || !queue.tracks[0]) { 16 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 17 | } 18 | const e2n = s => s ? "✅ Enabled" : "❌ Disabled" 19 | const song = queue.tracks[0]; 20 | const queueEmbed = new MessageEmbed().setColor("FUCHSIA") 21 | .setTitle(`First 15 Songs in the Queue`) 22 | .setDescription(`**CURRENT:** \`0th)\` \`${song.durationFormatted}\` - [${song.title}](${client.getYTLink(song.id)}) - ${song.requester}`) 23 | .addField("**Track-loop:**", `> ${e2n(queue.trackloop)}`, true) 24 | .addField("**Queue-loop:**", `> ${e2n(queue.queueloop)}`, true) 25 | .addField("**Autoplay:**", `> ${e2n(queue.autoplay)}`, true) 26 | .addFields( 27 | queue.tracks.slice(1).slice(0, 15).map((track, index) => { 28 | return { 29 | name: `\`${client.queuePos(index + 1)})\` Track \`${track.durationFormatted}\``, 30 | value: `> [${track.title}](${client.getYTLink(track.id)}) - ${track.requester}`, 31 | inline: true 32 | } 33 | }) 34 | ) 35 | return message.reply({content: `ℹ️ **Currently there are ${queue.tracks.length - 1} Tracks in the Queue**`, embeds: [queueEmbed]}).catch(() => null); 36 | }, 37 | }; -------------------------------------------------------------------------------- /slashCommands/music/skipto.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "skipto", 4 | description: "Skips to a specific Track in the Queue", 5 | options: [ 6 | { 7 | name: "position", 8 | description: "To what track you want to skip?", 9 | type: "INTEGER", 10 | required: true, 11 | }, 12 | ], 13 | run: async (client, interaction, args, prefix) => { 14 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 15 | // get an old connection 16 | const oldConnection = getVoiceConnection(interaction.guild.id); 17 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 18 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 19 | 20 | const queue = client.queues.get(interaction.guild.id); // get the queue 21 | if(!queue) { 22 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 23 | } 24 | // no new songs (and no current) 25 | if(!queue.tracks || queue.tracks.length <= 1) { 26 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing to skip**`}).catch(() => null); 27 | } 28 | if(!args[0] || isNaN(args[0]) || Number(args[0]) > queue.tracks.length) 29 | return interaction.reply({ ephemeral: true, content:`👎 **There are just ${queue.tracks.length} Songs in the Queue, can't skip to ${args[0]}th Song.**`}) 30 | 31 | queue.skipped = true; 32 | 33 | // if there is a queueloop: remove the current track but keep the rest 34 | if(queue.queueloop) { 35 | for(let i = 1; i <= args[0] - 1; i++) 36 | queue.tracks.push(queue.tracks[i]) 37 | } 38 | queue.tracks = queue.tracks.slice(args[0] - 1) 39 | 40 | // skip the track 41 | oldConnection.state.subscription.player.stop(); 42 | 43 | return interaction.reply({ ephemeral: false, content: `⏭️ **Successfully skipped ${args[0]} Track(s)**`}).catch(() => null); 44 | }, 45 | }; -------------------------------------------------------------------------------- /slashCommands/music/queue.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { MessageEmbed } = require("discord.js"); 3 | module.exports = { 4 | name: "queue", 5 | description: "Show the current Queue-List", 6 | run: async (client, interaction, args, prefix) => { 7 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 8 | // get an old connection 9 | const oldConnection = getVoiceConnection(interaction.guild.id); 10 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 12 | 13 | const queue = client.queues.get(interaction.guild.id); // get the queue 14 | if(!queue || !queue.tracks || !queue.tracks[0]) { 15 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 16 | } 17 | const e2n = s => s ? "✅ Enabled" : "❌ Disabled" 18 | const song = queue.tracks[0]; 19 | const queueEmbed = new MessageEmbed().setColor("FUCHSIA") 20 | .setTitle(`First 15 Songs in the Queue`) 21 | .setDescription(`**CURRENT:** \`0th)\` \`${song.durationFormatted}\` - [${song.title}](${client.getYTLink(song.id)}) - ${song.requester}`) 22 | .addField("**Track-loop:**", `> ${e2n(queue.trackloop)}`, true) 23 | .addField("**Queue-loop:**", `> ${e2n(queue.queueloop)}`, true) 24 | .addField("**Autoplay:**", `> ${e2n(queue.autoplay)}`, true) 25 | .addFields( 26 | queue.tracks.slice(1).slice(0, 15).map((track, index) => { 27 | return { 28 | name: `\`${client.queuePos(index + 1)})\` Track \`${track.durationFormatted}\``, 29 | value: `> [${track.title}](${client.getYTLink(track.id)}) - ${track.requester}`, 30 | inline: true 31 | } 32 | }) 33 | ) 34 | return interaction.reply({ ephemeral: false, content:`ℹ️ **Currently there are ${queue.tracks.length - 1} Tracks in the Queue**`, embeds: [queueEmbed]}).catch(() => null); 35 | }, 36 | }; -------------------------------------------------------------------------------- /commands/music/forward.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "forward", 4 | aliases: ["fwd"], 5 | description: "Forwards for X (secs)", 6 | run: async (client, message, args, prefix) => { 7 | try { 8 | if(!message.member.voice.channelId) return message.reply({content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 9 | 10 | const oldConnection = getVoiceConnection(message.guild.id); 11 | if(!oldConnection) return message.reply({content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 12 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply({content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 13 | 14 | const queue = client.queues.get(message.guild.id); // get the queue 15 | if(!queue || !queue.tracks || !queue.tracks[0]) { 16 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 17 | } 18 | 19 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 20 | 21 | if(!args[0] || isNaN(args[0])) return message.reply({ content: `👎 **You forgot to add the forwarding-time!** Usage: \`${prefix}forward \``}).catch(() => null); 22 | 23 | if(Number(args[0]) < 0 || Number(args[0]) > Math.floor((queue.tracks[0].duration - curPos) / 1000 - 1)) 24 | return message.reply({ content: `👎 **The Forward-Number-Pos must be between \`0\` and \`${Math.floor((queue.tracks[0].duration - curPos) / 1000 - 1)}\`!**`}).catch(() => null); 25 | 26 | const newPos = curPos + Number(args[0]) * 1000; 27 | // set Filterschanged to true 28 | queue.filtersChanged = true; 29 | // seek 30 | oldConnection.state.subscription.player.stop(); 31 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, newPos)); 32 | 33 | message.reply({content: `⏩ **Forwarded for \`${args[0]}s\` to \`${client.formatDuration(newPos)}\`**!`}).catch(() => null); 34 | } catch(e) { 35 | console.error(e); 36 | message.reply({content: `❌ Could not join your VC because: \`\`\`${e.message || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 37 | } 38 | }, 39 | }; -------------------------------------------------------------------------------- /commands/music/rewind.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "rewind", 4 | description: "Rewinds for X (secs)", 5 | run: async (client, message, args, prefix) => { 6 | try { 7 | if(!message.member.voice.channelId) return message.reply({content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 8 | 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply({content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 11 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply({content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 12 | 13 | const queue = client.queues.get(message.guild.id); // get the queue 14 | if(!queue || !queue.tracks || !queue.tracks[0]) { 15 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 16 | } 17 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 18 | 19 | if(!args[0] || isNaN(args[0])) return message.reply({ content: `👎 **You forgot to add the rewinding-time!** Usage: \`${prefix}rewind \``}).catch(() => null); 20 | if(Math.floor(curPos / 1000 - 1) <= 0) return message.reply({ content: `👎 **There is nothing to rewind, play a song long enough!**`}).catch(() => null); 21 | if(Number(args[0]) < 0 || Number(args[0]) > Math.floor((curPos) / 1000 - 1)) 22 | return message.reply({ content: `👎 **The Rewind-Number-Pos must be between \`0\` and \`${Math.floor((curPos) / 1000 - 1)}\`!**`}).catch(() => null); 23 | 24 | const newPos = curPos - Number(args[0]) * 1000; 25 | // set Filterschanged to true 26 | queue.filtersChanged = true; 27 | // seek 28 | oldConnection.state.subscription.player.stop(); 29 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, newPos)); 30 | 31 | message.reply({content: `⏪ **Rewinded for \`${args[0]}s\` to \`${client.formatDuration(newPos)}\`**!`}).catch(() => null); 32 | } catch(e) { 33 | console.error(e); 34 | message.reply({content: `❌ Could not join your VC because: \`\`\`${e.message || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 35 | } 36 | }, 37 | }; -------------------------------------------------------------------------------- /slashCommands/music/move.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "move", 4 | description: "Moves a Song in the Queue", 5 | options: [ 6 | { 7 | name: "from", 8 | description: "From Position to move", 9 | type: "INTEGER", 10 | required: true, 11 | }, 12 | { 13 | name: "to", 14 | description: "New Position to move it to", 15 | type: "INTEGER", 16 | required: true, 17 | }, 18 | ], 19 | run: async (client, interaction, args, prefix) => { 20 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 21 | // get an old connection 22 | const oldConnection = getVoiceConnection(interaction.guild.id); 23 | if(!oldConnection) return interaction.reply({ ephemeral: true, content: "👎 **I'm not connected somewhere!**"}).catch(() => null); 24 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 25 | 26 | const queue = client.queues.get(interaction.guild.id); // get the queue 27 | if(!queue) { 28 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 29 | } 30 | if(!args[0] || isNaN(args[0]) || Number(args[0]) < 1 || !args[1] || isNaN(args[1]) || Number(args[1]) < 1) 31 | return interaction.reply({ ephemeral: true, content: `👎 **From where to where shall I move?** Usage: \`${prefix}move \``}).catch(() => null); 32 | 33 | queue.tracks = arrayMove(queue.tracks, args[0], args[1]) 34 | 35 | return interaction.reply({ ephemeral: false, content: `🪣 **Successfully moved the \`${client.queuePos(args[0])} Song\` to \`${client.queuePos(args[1])} Position\` in the Queue.**`}).catch(() => null); 36 | }, 37 | }; 38 | 39 | 40 | 41 | function arrayMove(array, from, to) { 42 | try { 43 | array = [...array]; 44 | const startIndex = from < 0 ? array.length + from : from; 45 | if (startIndex >= 0 && startIndex < array.length) { 46 | const endIndex = to < 0 ? array.length + to : to; 47 | const [item] = array.splice(from, 1); 48 | array.splice(endIndex, 0, item); 49 | } 50 | return array; 51 | } catch (e) { 52 | console.log(String(e.stack).grey.bgRed) 53 | } 54 | } -------------------------------------------------------------------------------- /slashCommands/music/seek.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "seek", 4 | description: "Seeks to a specific Position (sec)", 5 | options: [ 6 | { 7 | name: "position", 8 | description: "To what Time in Seconds you want to seek?", 9 | type: "INTEGER", 10 | required: true, 11 | }, 12 | ], 13 | run: async (client, interaction, args, prefix) => { 14 | try { 15 | if(!interaction.member.voice.channelId) return interaction.reply(({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"})).catch(() => null); 16 | 17 | const oldConnection = getVoiceConnection(interaction.guild.id); 18 | if(!oldConnection) return interaction.reply({ ephemeral: true, content:"👎 **I'm not connected somewhere!**"}).catch(() => null); 19 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content:"👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 20 | 21 | const queue = client.queues.get(interaction.guild.id); // get the queue 22 | if(!queue || !queue.tracks || !queue.tracks[0]) { 23 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 24 | } 25 | 26 | if(!args[0] || isNaN(args[0])) return interaction.reply({ ephemeral: true, content:`👎 **You forgot to add the seeking-time!** Usage: \`${prefix}seek \``}).catch(() => null); 27 | 28 | if(Number(args[0]) < 0 || Number(args[0]) > Math.floor(queue.tracks[0].duration / 1000 - 1)) 29 | return interaction.reply({ ephemeral: true, content:`👎 **The Seek-Number-Pos must be between \`0\` and \`${Math.floor(queue.tracks[0].duration / 1000 - 1)}\`!**`}).catch(() => null); 30 | 31 | const newPos = Number(args[0]) * 1000; 32 | // set Filterschanged to true 33 | queue.filtersChanged = true; 34 | // seek 35 | oldConnection.state.subscription.player.stop(); 36 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, newPos)); 37 | 38 | interaction.reply({ ephemeral: true, content:`⏩ **Seeked to \`${client.formatDuration(newPos)}\`**!`}).catch(() => null); 39 | } catch(e) { 40 | console.error(e); 41 | interaction.reply({ ephemeral: false, content:`❌ Could not join your VC because: \`\`\`${e.interaction || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 42 | } 43 | }, 44 | }; -------------------------------------------------------------------------------- /slashCommands/music/forward.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "forward", 4 | description: "Forwards for X (secs)", 5 | options: [ 6 | { 7 | name: "time", 8 | description: "For how many seconds do you want to forward?", 9 | type: "INTEGER", 10 | required: true, 11 | }, 12 | ], 13 | run: async (client, interaction, args, prefix) => { 14 | try { 15 | if(!interaction.member.voice.channelId) return interaction.reply(({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"})).catch(() => null); 16 | 17 | const oldConnection = getVoiceConnection(interaction.guild.id); 18 | if(!oldConnection) return interaction.reply({ ephemeral: true, content:"👎 **I'm not connected somewhere!**"}).catch(() => null); 19 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content:"👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 20 | 21 | const queue = client.queues.get(interaction.guild.id); // get the queue 22 | if(!queue || !queue.tracks || !queue.tracks[0]) { 23 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 24 | } 25 | 26 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 27 | 28 | if(!args[0] || isNaN(args[0])) return interaction.reply({ ephemeral: true, content:`👎 **You forgot to add the forwarding-time!** Usage: \`${prefix}forward \``}).catch(() => null); 29 | 30 | if(Number(args[0]) < 0 || Number(args[0]) > Math.floor((queue.tracks[0].duration - curPos) / 1000 - 1)) 31 | return interaction.reply({ ephemeral: true, content:`👎 **The Forward-Number-Pos must be between \`0\` and \`${Math.floor((queue.tracks[0].duration - curPos) / 1000 - 1)}\`!**`}).catch(() => null); 32 | 33 | const newPos = curPos + Number(args[0]) * 1000; 34 | // set Filterschanged to true 35 | queue.filtersChanged = true; 36 | // seek 37 | oldConnection.state.subscription.player.stop(); 38 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, newPos)); 39 | 40 | interaction.reply({ ephemeral: false, content:`⏩ **Forwarded for \`${args[0]}s\` to \`${client.formatDuration(newPos)}\`**!`}).catch(() => null); 41 | } catch(e) { 42 | console.error(e); 43 | interaction.reply({ ephemeral: true, content:`❌ Could not join your VC because: \`\`\`${e.interaction || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 44 | } 45 | }, 46 | }; -------------------------------------------------------------------------------- /slashCommands/music/rewind.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | module.exports = { 3 | name: "rewind", 4 | description: "Rewinds for X (secs)", 5 | options: [ 6 | { 7 | name: "time", 8 | description: "For how many seconds do you want to rewind?", 9 | type: "INTEGER", 10 | required: true, 11 | }, 12 | ], 13 | run: async (client, interaction, args, prefix) => { 14 | try { 15 | if(!interaction.member.voice.channelId) return interaction.reply(({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"})).catch(() => null); 16 | 17 | const oldConnection = getVoiceConnection(interaction.guild.id); 18 | if(!oldConnection) return interaction.reply({ ephemeral: true, content:"👎 **I'm not connected somewhere!**"}).catch(() => null); 19 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content:"👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 20 | 21 | const queue = client.queues.get(interaction.guild.id); // get the queue 22 | if(!queue || !queue.tracks || !queue.tracks[0]) { 23 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 24 | } 25 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 26 | 27 | if(!args[0] || isNaN(args[0])) return interaction.reply({ ephemeral: true, content:`👎 **You forgot to add the rewinding-time!** Usage: \`${prefix}rewind \``}).catch(() => null); 28 | if(Math.floor(curPos / 1000 - 1) <= 0) return interaction.reply({ ephemeral: true, content:`👎 **There is nothing to rewind, play a song long enough!**`}).catch(() => null); 29 | if(Number(args[0]) < 0 || Number(args[0]) > Math.floor((curPos) / 1000 - 1)) 30 | return interaction.reply({ ephemeral: true, content:`👎 **The Rewind-Number-Pos must be between \`0\` and \`${Math.floor((curPos) / 1000 - 1)}\`!**`}).catch(() => null); 31 | 32 | const newPos = curPos - Number(args[0]) * 1000; 33 | // set Filterschanged to true 34 | queue.filtersChanged = true; 35 | // seek 36 | oldConnection.state.subscription.player.stop(); 37 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, newPos)); 38 | 39 | interaction.reply({ ephemeral: true, content:`⏪ **Rewinded for \`${args[0]}s\` to \`${client.formatDuration(newPos)}\`**!`}).catch(() => null); 40 | } catch(e) { 41 | console.error(e); 42 | interaction.reply({ ephemeral: false, content:`❌ Could not join your VC because: \`\`\`${e.interaction || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 43 | } 44 | }, 45 | }; -------------------------------------------------------------------------------- /util/handler.js: -------------------------------------------------------------------------------- 1 | const { readdirSync } = require(`fs`); 2 | module.exports = async (client) => { 3 | // Commands 4 | console.log(`${client.getTime()} :: Loading Commands`); 5 | readdirSync(`${process.cwd()}/commands/`) 6 | .forEach((directory) => { 7 | const commands = readdirSync(`${process.cwd()}/commands/${directory}/`) 8 | .filter((file) => file.endsWith(`.js`)) 9 | .forEach(file => { 10 | let pull = require(`${process.cwd()}/commands/${directory}/${file}`); 11 | client.commands.set(pull.name, pull); 12 | }) 13 | }) 14 | 15 | // Events 16 | console.log(`${client.getTime()} :: Loading Events`); 17 | readdirSync(`${process.cwd()}/events/`).filter((file) => file.endsWith(`.js`)) 18 | .forEach((file) => { 19 | const pull = require(`${process.cwd()}/events/${file}`) 20 | let eventName = file.split(`.`)[0]; 21 | client.on(eventName, pull.bind(null, client)); 22 | }); 23 | 24 | // Slash Commands 25 | console.log(`${client.getTime()} :: Loading SlashCommands`); 26 | const slashCommandsArray = []; 27 | readdirSync(`${process.cwd()}/slashCommands/`) 28 | .forEach((directory) => { 29 | readdirSync(`${process.cwd()}/slashCommands/${directory}/`) 30 | .filter((file) => file.endsWith(`.js`)) 31 | .forEach(file => { 32 | let pull = require(`${process.cwd()}/slashCommands/${directory}/${file}`); 33 | client.slashCommands.set(pull.name, pull); 34 | slashCommandsArray.push(pull); 35 | }) 36 | }) 37 | 38 | 39 | client.on(`ready`, async () => { 40 | if(client.deploySlash.enabled) { 41 | if(client.deploySlash.guild) { 42 | client.guilds.cache.get(client.deploySlash.guild).commands.set(slashCommandsArray); 43 | } else { 44 | client.application.commands.set(slashCommandsArray); 45 | } 46 | 47 | } 48 | }); 49 | 50 | process.on('unhandledRejection', (reason, p) => { 51 | console.log('\n\n\n\n\n=== unhandled Rejection ==='.toUpperCase()); 52 | console.log('Reason: ', reason.stack ? String(reason.stack) : String(reason)); 53 | console.log('=== unhandled Rejection ===\n\n\n\n\n'.toUpperCase()); 54 | }); 55 | process.on("uncaughtException", (err, origin) => { 56 | console.log('\n\n\n\n\n\n=== uncaught Exception ==='.toUpperCase()); 57 | console.log('Exception: ', err.stack ? err.stack : err) 58 | console.log('=== uncaught Exception ===\n\n\n\n\n'.toUpperCase()); 59 | }) 60 | process.on('uncaughtExceptionMonitor', (err, origin) => { 61 | console.log('=== uncaught Exception Monitor ==='.toUpperCase()); 62 | }); 63 | process.on('multipleResolves', (type, promise, reason) => { 64 | /* console.log('\n\n\n\n\n=== multiple Resolves ==='.toUpperCase()); 65 | console.log(type, promise, reason); 66 | console.log('=== multiple Resolves ===\n\n\n\n\n'.toUpperCase()); 67 | */ 68 | }); 69 | }; -------------------------------------------------------------------------------- /commands/music/filter.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { MessageActionRow, MessageSelectMenu, MessageEmbed } = require("discord.js"); 3 | module.exports = { 4 | name: "filter", 5 | description: "Applys/Removes Filters of the Queue", 6 | run: async (client, message, args, prefix) => { 7 | try { 8 | if(!message.member.voice.channelId) return message.reply({content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 9 | const oldConnection = getVoiceConnection(message.guild.id); 10 | if(!oldConnection) return message.reply({ content: `👎 **I'm not connected somewhere**!`}).catch(() => null); 11 | 12 | const queue = client.queues.get(message.guild.id); 13 | if(!queue) return message.reply({ content: `👎 **I'm nothing playing right now.**`}).catch(() => null); 14 | 15 | const options = Object.keys(queue.effects) 16 | 17 | const Menu = new MessageSelectMenu() 18 | .setCustomId("filter_changing") 19 | .setPlaceholder("Pic Filters to enable/disable") 20 | .setMaxValues(options.filter(o => o != "bassboost" && o != "speed").length) 21 | .addOptions(options.filter(o => o != "bassboost" && o != "speed").map(option => { 22 | return { 23 | label: `${option.charAt(0).toUpperCase()}${option.slice(1)}`, 24 | value: option, 25 | description: `${queue.effects[option] ? `Enabled: ` : `Disabled: `} A ${option}-ish Audio-Effect`, 26 | emoji: queue.effects[option] ? `✅` : "❌" 27 | } 28 | })) 29 | const msg = await message.channel.send({ 30 | content: "🔗 Pick what filter(s) you want to change!", 31 | components: [new MessageActionRow().addComponents(Menu)] 32 | }).catch(console.error) 33 | if(!msg) return; 34 | const collector = msg.createMessageComponentCollector({ 35 | filter: (i => i.isSelectMenu() && i.customId == "filter_changing" && i.user.id == message.author.id), 36 | time: 60_000, 37 | max: 1 38 | }) 39 | collector.on("collect", i => { 40 | i.values.forEach(option => queue.effects[option] = !queue.effects[option]) 41 | i.reply({ 42 | content: `Changed ${i.values.length} Filter(s) to:\n> *Will be applied with the next Skip*`, 43 | embeds: [ 44 | new MessageEmbed() 45 | .setColor("FUCHSIA") 46 | .setTitle("Current Filters") 47 | .setDescription(Object.keys(queue.effects).filter(o => o != "bassboost" && o != "speed").map(option => `> **\`${option.charAt(0).toUpperCase()}${option.slice(1)}\`** - ${queue.effects[option] ? `✅ Enabled` : `❌ Disabled:`}`).join("\n\n")) 48 | ] 49 | }) 50 | // will be removed on .stop(); 51 | queue.tracks = [ queue.tracks[0], ...queue.tracks ]; 52 | queue.filtersChanged = true; 53 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 54 | oldConnection.state.subscription.player.stop(); 55 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, curPos)); 56 | }) 57 | collector.on("end", e => { 58 | msg.edit({ 59 | content: msg.content, 60 | components: [new MessageActionRow().addComponents(Menu.setDisabled(true))] 61 | }).catch(() => null) 62 | }) 63 | } catch(e) { 64 | console.error(e); 65 | message.reply({content: `❌ Something went wrong: \`\`\`${e.message || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 66 | } 67 | }, 68 | }; -------------------------------------------------------------------------------- /slashCommands/music/filter.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { MessageActionRow, MessageSelectMenu, MessageEmbed } = require("discord.js"); 3 | module.exports = { 4 | name: "filter", 5 | description: "Applys/Removes Filters of the Queue", 6 | run: async (client, interaction, args, prefix) => { 7 | try { 8 | if(!interaction.member.voice.channelId) return interaction.reply(({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"})).catch(() => null); 9 | const oldConnection = getVoiceConnection(interaction.guild.id); 10 | if(!oldConnection) return interaction.reply({ ephemeral: true, content:`👎 **I'm not connected somewhere**!`}).catch(() => null); 11 | 12 | const queue = client.queues.get(interaction.guild.id); 13 | if(!queue) return interaction.reply({ ephemeral: true, content:`👎 **I'm nothing playing right now.**`}).catch(() => null); 14 | 15 | const options = Object.keys(queue.effects) 16 | 17 | const Menu = new MessageSelectMenu() 18 | .setCustomId("filter_changing") 19 | .setPlaceholder("Pic Filters to enable/disable") 20 | .setMaxValues(options.filter(o => o != "bassboost" && o != "speed").length) 21 | .addOptions(options.filter(o => o != "bassboost" && o != "speed").map(option => { 22 | return { 23 | label: `${option.charAt(0).toUpperCase()}${option.slice(1)}`, 24 | value: option, 25 | description: `${queue.effects[option] ? `Enabled: ` : `Disabled: `} A ${option}-ish Audio-Effect`, 26 | emoji: queue.effects[option] ? `✅` : "❌" 27 | } 28 | })) 29 | await interaction.deferReply(); 30 | let msg = await interaction.followUp({ 31 | content: "🔗 Pick what filter(s) you want to change!", 32 | components: [new MessageActionRow().addComponents(Menu)] 33 | }).catch(console.error) 34 | if(!msg) return; 35 | msg = await msg.fetch().catch(console.warn); 36 | const collector = msg.createMessageComponentCollector({ 37 | filter: (i => i.isSelectMenu() && i.customId == "filter_changing" && i.user.id == interaction.user.id), 38 | time: 60_000, 39 | max: 1 40 | }) 41 | collector.on("collect", i => { 42 | i.values.forEach(option => queue.effects[option] = !queue.effects[option]) 43 | i.reply({ 44 | content: `Changed ${i.values.length} Filter(s) to:\n> *Will be applied with the next Skip*`, 45 | embeds: [ 46 | new MessageEmbed() 47 | .setColor("FUCHSIA") 48 | .setTitle("Current Filters") 49 | .setDescription(Object.keys(queue.effects).filter(o => o != "bassboost" && o != "speed").map(option => `> **\`${option.charAt(0).toUpperCase()}${option.slice(1)}\`** - ${queue.effects[option] ? `✅ Enabled` : `❌ Disabled:`}`).join("\n\n")) 50 | ] 51 | }) 52 | // will be removed on .stop(); 53 | queue.tracks = [ queue.tracks[0], ...queue.tracks ]; 54 | queue.filtersChanged = true; 55 | const curPos = oldConnection.state.subscription.player.state.resource.playbackDuration; 56 | oldConnection.state.subscription.player.stop(); 57 | oldConnection.state.subscription.player.play(client.getResource(queue, queue.tracks[0].id, curPos)); 58 | }) 59 | collector.on("end", e => { 60 | msg.edit({ 61 | content: msg.content, 62 | components: [new MessageActionRow().addComponents(Menu.setDisabled(true))] 63 | }).catch(() => null) 64 | }) 65 | } catch(e) { 66 | console.error(e); 67 | interaction.reply({ ephemeral: true, content:`❌ Something went wrong: \`\`\`${e.interaction || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 68 | } 69 | }, 70 | }; -------------------------------------------------------------------------------- /commands/music/playtop.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { default: YouTube } = require('youtube-sr'); 3 | const { Permissions } = require("discord.js"); 4 | module.exports = { 5 | name: "playtop", 6 | aliases: ["pt"], 7 | description: "Plays Music in your Voice Channel and positions it to the queue top", 8 | run: async (client, message, args, prefix) => { 9 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 10 | if(!message.member.voice.channel?.permissionsFor(message.guild?.me)?.has(Permissions.FLAGS.CONNECT)) { 11 | return message.reply({ content: "👎 **I'm missing the Permission to Connect to your Voice-Channel!**"}).catch(() => null); 12 | } 13 | if(!message.member.voice.channel?.permissionsFor(message.guild?.me)?.has(Permissions.FLAGS.SPEAK)) { 14 | return message.reply({ content: "👎 **I'm missing the Permission to Speak in your Voice-Channel!**"}).catch(() => null); 15 | } 16 | 17 | // get an old connection 18 | const oldConnection = getVoiceConnection(message.guild.id); 19 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 20 | const queue = client.queues.get(message.guild.id); // get the queue 21 | if(!queue) { 22 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 23 | } 24 | const track = args.join(" "); 25 | if(!args[0]) return message.reply(`👎 Please add the wished Music via: \`${prefix}playtop \``).catch(() => null); 26 | // Regexpressions for testing the search string 27 | const youtubRegex = /^(https?:\/\/)?(www\.)?(m\.|music\.)?(youtube\.com|youtu\.?be)\/.+$/gi; 28 | const playlistRegex = /^.*(list=)([^#\&\?]*).*/gi; 29 | const songRegex = /^.*(watch\?v=)([^#\&\?]*).*/gi; 30 | // variables for song, and playlist 31 | let song = null; 32 | let playlist = null; 33 | // Use the regex expressions 34 | const isYT = youtubRegex.exec(track); 35 | const isSong = songRegex.exec(track); 36 | const isList = playlistRegex.exec(track) 37 | 38 | try { 39 | // try to play the requested song 40 | const m = await message.reply(`🔍 *Searching **${track}** ...*`).catch(() => null); 41 | // get song from the link 42 | if(isYT && isSong && !isList) { 43 | song = await YouTube.getVideo(track); 44 | } 45 | // get playlist from the link 46 | else if(isYT && !isSong && isList) { 47 | playlist = await YouTube.getPlaylist(track).then(playlist => playlist.fetch()); 48 | } 49 | // get playlist & song from the link 50 | else if(isYT && isSong && isList) { 51 | song = await YouTube.getVideo(`https://www.youtube.com/watch?v=${isSong[2]}`); 52 | playlist = await YouTube.getPlaylist(`https://www.youtube.com/playlist?list=${isList[2]}`).then(playlist => playlist.fetch()); 53 | } 54 | // otherwise search for it 55 | else { 56 | song = await YouTube.searchOne(track); 57 | } 58 | if(!song && !playlist) return m.edit(`❌ **Failed looking up for ${track}!**`); 59 | /* FOR NO PLAYLIST REQUESTS */ 60 | if(!playlist) { 61 | // Add the song to the queue 62 | queue.tracks = [queue.tracks[0], client.createSong(song, message.author), ...queue.tracks.slice(1)] 63 | // edit the loading message 64 | return m.edit(`▶️ **Queued at \`1st\`: __${song.title}__** - \`${song.durationFormatted}\``).catch(() => null); 65 | } 66 | /* FOR PLAYLIST REQUEST */ 67 | else { 68 | // get the song, or the first playlist song 69 | song = song ? song : playlist.videos[0]; 70 | // remove the song which got added 71 | const index = playlist.videos.findIndex(s => s.id == song.id) || 0; 72 | playlist.videos.splice(index, 1) 73 | const playlistSongs = [] 74 | // Add the playlist songs to the queue 75 | playlist.videos.forEach(song => playlistSongs.push(client.createSong(song, message.author))) 76 | queue.tracks = [queue.tracks[0], client.createSong(song, message.author), ...playlistSongs, ...queue.tracks.slice(1)] 77 | // edit the loading message 78 | return m.edit(`👍 **Queued at \`1st\`: __${song.title}__** - \`${song.durationFormatted}\`\n> **Added \`${playlist.videos.length - 1} Songs\` from the Playlist:**\n> __**${playlist.title}**__`).catch(() => null); 79 | } 80 | 81 | } catch (e){ console.error(e); 82 | return message.reply(`❌ Could not play the Song because: \`\`\`${e.message || e}`.substring(0, 1950) + `\`\`\``).catch(() => null); 83 | } 84 | }, 85 | }; 86 | -------------------------------------------------------------------------------- /commands/music/playskip.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { default: YouTube } = require('youtube-sr'); 3 | const { Permissions } = require("discord.js"); 4 | module.exports = { 5 | name: "playskip", 6 | aliases: ["ps"], 7 | description: "Plays Music in your Voice Channel and skips to it", 8 | run: async (client, message, args, prefix) => { 9 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 10 | if(!message.member.voice.channel?.permissionsFor(message.guild?.me)?.has(Permissions.FLAGS.CONNECT)) { 11 | return message.reply({ content: "👎 **I'm missing the Permission to Connect to your Voice-Channel!**"}).catch(() => null); 12 | } 13 | if(!message.member.voice.channel?.permissionsFor(message.guild?.me)?.has(Permissions.FLAGS.SPEAK)) { 14 | return message.reply({ content: "👎 **I'm missing the Permission to Speak in your Voice-Channel!**"}).catch(() => null); 15 | } 16 | 17 | // get an old connection 18 | const oldConnection = getVoiceConnection(message.guild.id); 19 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 20 | const queue = client.queues.get(message.guild.id); // get the queue 21 | if(!queue) { 22 | return message.reply(`👎 **Nothing playing right now**`).catch(() => null); 23 | } 24 | const track = args.join(" "); 25 | if(!args[0]) return message.reply(`👎 Please add the wished Music via: \`${prefix}playskip \``).catch(() => null); 26 | // Regexpressions for testing the search string 27 | const youtubRegex = /^(https?:\/\/)?(www\.)?(m\.|music\.)?(youtube\.com|youtu\.?be)\/.+$/gi; 28 | const playlistRegex = /^.*(list=)([^#\&\?]*).*/gi; 29 | const songRegex = /^.*(watch\?v=)([^#\&\?]*).*/gi; 30 | // variables for song, and playlist 31 | let song = null; 32 | let playlist = null; 33 | // Use the regex expressions 34 | const isYT = youtubRegex.exec(track); 35 | const isSong = songRegex.exec(track); 36 | const isList = playlistRegex.exec(track) 37 | 38 | try { 39 | // try to play the requested song 40 | const m = await message.reply(`🔍 *Searching **${track}** ...*`).catch(() => null); 41 | // get song from the link 42 | if(isYT && isSong && !isList) { 43 | song = await YouTube.getVideo(track); 44 | } 45 | // get playlist from the link 46 | else if(isYT && !isSong && isList) { 47 | playlist = await YouTube.getPlaylist(track).then(playlist => playlist.fetch()); 48 | } 49 | // get playlist & song from the link 50 | else if(isYT && isSong && isList) { 51 | song = await YouTube.getVideo(`https://www.youtube.com/watch?v=${isSong[2]}`); 52 | playlist = await YouTube.getPlaylist(`https://www.youtube.com/playlist?list=${isList[2]}`).then(playlist => playlist.fetch()); 53 | } 54 | // otherwise search for it 55 | else { 56 | song = await YouTube.searchOne(track); 57 | } 58 | if(!song && !playlist) return m.edit(`❌ **Failed looking up for ${track}!**`); 59 | /* FOR NO PLAYLIST REQUESTS */ 60 | if(!playlist) { 61 | // Add the song to the queue 62 | queue.tracks = [queue.tracks[0], client.createSong(song, message.author), ...queue.tracks.slice(1)] 63 | // skip the track 64 | oldConnection.state.subscription.player.stop(); 65 | // edit the loading message 66 | return m.edit(`▶️ **Now playing and skipping to: __${song.title}__** - \`${song.durationFormatted}\``).catch(() => null); 67 | } 68 | /* FOR PLAYLIST REQUEST */ 69 | else { 70 | // get the song, or the first playlist song 71 | song = song ? song : playlist.videos[0]; 72 | // remove the song which got added 73 | const index = playlist.videos.findIndex(s => s.id == song.id) || 0; 74 | playlist.videos.splice(index, 1) 75 | const playlistSongs = [] 76 | // Add the playlist songs to the queue 77 | playlist.videos.forEach(song => playlistSongs.push(client.createSong(song, message.author))) 78 | queue.tracks = [queue.tracks[0], client.createSong(song, message.author), ...playlistSongs, ...queue.tracks.slice(1)] 79 | // skip the track 80 | oldConnection.state.subscription.player.stop(); 81 | // edit the loading message 82 | return m.edit(`👍 **Now playing and skipping to: __${song.title}__** - \`${song.durationFormatted}\`\n> **Added \`${playlist.videos.length - 1} Songs\` from the Playlist:**\n> __**${playlist.title}**__`).catch(() => null); 83 | } 84 | 85 | } catch (e){ console.error(e); 86 | return message.reply(`❌ Could not play the Song because: \`\`\`${e.message || e}`.substr(0, 1950) + `\`\`\``).catch(() => null); 87 | } 88 | }, 89 | }; 90 | -------------------------------------------------------------------------------- /slashCommands/music/playtop.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { default: YouTube } = require('youtube-sr'); 3 | const { Permissions } = require("discord.js"); 4 | module.exports = { 5 | name: "playtop", 6 | description: "Plays Music in your Voice Channel and positions it to the queue top", 7 | options: [ 8 | { 9 | name: "songtitle", 10 | description: "Title/Link of the Song/Playlist", 11 | type: "STRING", 12 | required: true, 13 | }, 14 | ], 15 | run: async (client, interaction, args, prefix) => { 16 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 17 | if(!interaction.member.voice.channel?.permissionsFor(interaction.guild?.me)?.has(Permissions.FLAGS.CONNECT)) { 18 | return interaction.reply({ephemeral: true, content: "👎 **I'm missing the Permission to Connect to your Voice-Channel!**"}).catch(() => null); 19 | } 20 | if(!interaction.member.voice.channel?.permissionsFor(interaction.guild?.me)?.has(Permissions.FLAGS.SPEAK)) { 21 | return interaction.reply({ephemeral: true, content: "👎 **I'm missing the Permission to Speak in your Voice-Channel!**"}).catch(() => null); 22 | } 23 | 24 | // get an old connection 25 | const oldConnection = getVoiceConnection(interaction.guild.id); 26 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 27 | const queue = client.queues.get(interaction.guild.id); // get the queue 28 | if(!queue) { 29 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 30 | } 31 | const track = args.join(" "); 32 | if(!args[0]) return interaction.reply({ ephemeral: true, content: `👎 Please add the wished Music via: \`${prefix}playtop \``}).catch(() => null); 33 | // Regexpressions for testing the search string 34 | const youtubRegex = /^(https?:\/\/)?(www\.)?(m\.|music\.)?(youtube\.com|youtu\.?be)\/.+$/gi; 35 | const playlistRegex = /^.*(list=)([^#\&\?]*).*/gi; 36 | const songRegex = /^.*(watch\?v=)([^#\&\?]*).*/gi; 37 | // variables for song, and playlist 38 | let song = null; 39 | let playlist = null; 40 | // Use the regex expressions 41 | const isYT = youtubRegex.exec(track); 42 | const isSong = songRegex.exec(track); 43 | const isList = playlistRegex.exec(track) 44 | 45 | try { 46 | // try to play the requested song 47 | await interaction.reply({ ephemeral: true, content: `🔍 *Searching **${track}** ...*`}).catch(() => null); 48 | // get song from the link 49 | if(isYT && isSong && !isList) { 50 | song = await YouTube.getVideo(track); 51 | } 52 | // get playlist from the link 53 | else if(isYT && !isSong && isList) { 54 | playlist = await YouTube.getPlaylist(track).then(playlist => playlist.fetch()); 55 | } 56 | // get playlist & song from the link 57 | else if(isYT && isSong && isList) { 58 | song = await YouTube.getVideo(`https://www.youtube.com/watch?v=${isSong[2]}`); 59 | playlist = await YouTube.getPlaylist(`https://www.youtube.com/playlist?list=${isList[2]}`).then(playlist => playlist.fetch()); 60 | } 61 | // otherwise search for it 62 | else { 63 | song = await YouTube.searchOne(track); 64 | } 65 | if(!song && !playlist) return interaction.editReply({ ephemeral: true, content: `❌ **Failed looking up for ${track}!**`}); 66 | /* FOR NO PLAYLIST REQUESTS */ 67 | if(!playlist) { 68 | // Add the song to the queue 69 | queue.tracks = [queue.tracks[0], client.createSong(song, interaction.user), ...queue.tracks.slice(1)] 70 | // edit the loading interaction 71 | return interaction.editReply({ ephemeral: false, content: `▶️ **Queued at \`1st\`: __${song.title}__** - \`${song.durationFormatted}\``}).catch(() => null); 72 | } 73 | /* FOR PLAYLIST REQUEST */ 74 | else { 75 | // get the song, or the first playlist song 76 | song = song ? song : playlist.videos[0]; 77 | // remove the song which got added 78 | const index = playlist.videos.findIndex(s => s.id == song.id) || 0; 79 | playlist.videos.splice(index, 1) 80 | const playlistSongs = [] 81 | // Add the playlist songs to the queue 82 | playlist.videos.forEach(song => playlistSongs.push(client.createSong(song, interaction.user))) 83 | queue.tracks = [queue.tracks[0], client.createSong(song, interaction.user), ...playlistSongs, ...queue.tracks.slice(1)] 84 | // edit the loading interaction 85 | return interaction.editReply({ ephemeral: false, content: `👍 **Queued at \`1st\`: __${song.title}__** - \`${song.durationFormatted}\`\n> **Added \`${playlist.videos.length - 1} Songs\` from the Playlist:**\n> __**${playlist.title}**__`}).catch(() => null); 86 | } 87 | 88 | } catch (e){ console.error(e); 89 | return interaction.reply({ ephemeral: true, content: `❌ Could not play the Song because: \`\`\`${e.interaction || e}`.substring(0, 1950) + `\`\`\``}).catch(() => null); 90 | } 91 | }, 92 | }; 93 | -------------------------------------------------------------------------------- /slashCommands/music/playskip.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { default: YouTube } = require('youtube-sr'); 3 | const { Permissions } = require("discord.js"); 4 | module.exports = { 5 | name: "playskip", 6 | description: "Plays Music in your Voice Channel and skips to it", 7 | options: [ 8 | { 9 | name: "songtitle", 10 | description: "Title/Link of the Song/Playlist", 11 | type: "STRING", 12 | required: true, 13 | }, 14 | ], 15 | run: async (client, interaction, args, prefix) => { 16 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **Please join a Voice-Channel first!**"}).catch(() => null); 17 | if(!interaction.member.voice.channel?.permissionsFor(interaction.guild?.me)?.has(Permissions.FLAGS.CONNECT)) { 18 | return interaction.reply({ephemeral: true, content: "👎 **I'm missing the Permission to Connect to your Voice-Channel!**"}).catch(() => null); 19 | } 20 | if(!interaction.member.voice.channel?.permissionsFor(interaction.guild?.me)?.has(Permissions.FLAGS.SPEAK)) { 21 | return interaction.reply({ephemeral: true, content: "👎 **I'm missing the Permission to Speak in your Voice-Channel!**"}).catch(() => null); 22 | } 23 | 24 | // get an old connection 25 | const oldConnection = getVoiceConnection(interaction.guild.id); 26 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 27 | const queue = client.queues.get(interaction.guild.id); // get the queue 28 | if(!queue) { 29 | return interaction.reply({ ephemeral: true, content: `👎 **Nothing playing right now**`}).catch(() => null); 30 | } 31 | const track = args.join(" "); 32 | if(!args[0]) return interaction.reply({ ephemeral: true, content: `👎 Please add the wished Music via: \`${prefix}playskip \``}).catch(() => null); 33 | // Regexpressions for testing the search string 34 | const youtubRegex = /^(https?:\/\/)?(www\.)?(m\.|music\.)?(youtube\.com|youtu\.?be)\/.+$/gi; 35 | const playlistRegex = /^.*(list=)([^#\&\?]*).*/gi; 36 | const songRegex = /^.*(watch\?v=)([^#\&\?]*).*/gi; 37 | // variables for song, and playlist 38 | let song = null; 39 | let playlist = null; 40 | // Use the regex expressions 41 | const isYT = youtubRegex.exec(track); 42 | const isSong = songRegex.exec(track); 43 | const isList = playlistRegex.exec(track) 44 | 45 | try { 46 | // try to play the requested song 47 | await interaction.reply({ ephemeral: true, content: `🔍 *Searching **${track}** ...*`}).catch(() => null); 48 | // get song from the link 49 | if(isYT && isSong && !isList) { 50 | song = await YouTube.getVideo(track); 51 | } 52 | // get playlist from the link 53 | else if(isYT && !isSong && isList) { 54 | playlist = await YouTube.getPlaylist(track).then(playlist => playlist.fetch()); 55 | } 56 | // get playlist & song from the link 57 | else if(isYT && isSong && isList) { 58 | song = await YouTube.getVideo(`https://www.youtube.com/watch?v=${isSong[2]}`); 59 | playlist = await YouTube.getPlaylist(`https://www.youtube.com/playlist?list=${isList[2]}`).then(playlist => playlist.fetch()); 60 | } 61 | // otherwise search for it 62 | else { 63 | song = await YouTube.searchOne(track); 64 | } 65 | if(!song && !playlist) return interaction.editReply({ ephemeral: true, content: `❌ **Failed looking up for ${track}!**`}); 66 | /* FOR NO PLAYLIST REQUESTS */ 67 | if(!playlist) { 68 | // Add the song to the queue 69 | queue.tracks = [queue.tracks[0], client.createSong(song, interaction.user), ...queue.tracks.slice(1)] 70 | // skip the track 71 | oldConnection.state.subscription.player.stop(); 72 | // edit the loading interaction 73 | return interaction.editReply({ ephemeral: false, content: `▶️ **Now playing and skipping to: __${song.title}__** - \`${song.durationFormatted}\``}).catch(() => null); 74 | } 75 | /* FOR PLAYLIST REQUEST */ 76 | else { 77 | // get the song, or the first playlist song 78 | song = song ? song : playlist.videos[0]; 79 | // remove the song which got added 80 | const index = playlist.videos.findIndex(s => s.id == song.id) || 0; 81 | playlist.videos.splice(index, 1) 82 | const playlistSongs = [] 83 | // Add the playlist songs to the queue 84 | playlist.videos.slice(1).forEach(song => playlistSongs.push(client.createSong(song, interaction.user))) 85 | queue.tracks = [queue.tracks[0], client.createSong(song, interaction.user), ...playlistSongs, ...queue.tracks.slice(1)] 86 | // skip the track 87 | oldConnection.state.subscription.player.stop(); 88 | // edit the loading interaction 89 | return interaction.editReply({ ephemeral: false, content: `👍 **Now playing and skipping to: __${song.title}__** - \`${song.durationFormatted}\`\n> **Added \`${playlist.videos.length - 1} Songs\` from the Playlist:**\n> __**${playlist.title}**__`}).catch(() => null); 90 | } 91 | 92 | } catch (e){ console.error(e); 93 | return interaction.reply({ ephemeral: true, content: `❌ Could not play the Song because: \`\`\`${e.interaction || e}`.substr(0, 1950) + `\`\`\``}).catch(() => null); 94 | } 95 | }, 96 | }; 97 | -------------------------------------------------------------------------------- /commands/music/play.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { default: YouTube } = require('youtube-sr'); 3 | const { Permissions } = require("discord.js"); 4 | module.exports = { 5 | name: "play", 6 | aliases: ["p"], 7 | description: "Plays Music in your Voice Channel", 8 | run: async (client, message, args, prefix) => { 9 | if(!message.member.voice.channelId) return message.reply("👎 **Please join a Voice-Channel first!**").catch(() => null); 10 | if(!message.member.voice.channel?.permissionsFor(message.guild?.me)?.has(Permissions.FLAGS.CONNECT)) { 11 | return message.reply({ content: "👎 **I'm missing the Permission to Connect to your Voice-Channel!**"}).catch(() => null); 12 | } 13 | if(!message.member.voice.channel?.permissionsFor(message.guild?.me)?.has(Permissions.FLAGS.SPEAK)) { 14 | return message.reply({ content: "👎 **I'm missing the Permission to Speak in your Voice-Channel!**"}).catch(() => null); 15 | } 16 | 17 | // get an old connection 18 | const oldConnection = getVoiceConnection(message.guild.id); 19 | if(oldConnection && oldConnection.joinConfig.channelId != message.member.voice.channelId) return message.reply("👎 **We are not in the same Voice-Channel**!").catch(() => null); 20 | 21 | const track = args.join(" "); 22 | if(!args[0]) return message.reply(`👎 Please add the wished Music via: \`${prefix}play \``).catch(() => null); 23 | // Regexpressions for testing the search string 24 | const youtubRegex = /^(https?:\/\/)?(www\.)?(m\.|music\.)?(youtube\.com|youtu\.?be)\/.+$/gi; 25 | const playlistRegex = /^.*(list=)([^#\&\?]*).*/gi; 26 | const songRegex = /^.*(watch\?v=)([^#\&\?]*).*/gi; 27 | // variables for song, and playlist 28 | let song = null; 29 | let playlist = null; 30 | // Use the regex expressions 31 | const isYT = youtubRegex.exec(track); 32 | const isSong = songRegex.exec(track); 33 | const isList = playlistRegex.exec(track) 34 | 35 | if(!oldConnection) { 36 | // try to join the voice channel 37 | try { 38 | await client.joinVoiceChannel(message.member.voice.channel) 39 | } catch (e){ console.error(e); 40 | return message.reply(`❌ Could not join the VC because: \`\`\`${e.message || e}`.substr(0, 1950) + `\`\`\``).catch(() => null); 41 | } 42 | } 43 | try { 44 | // try to play the requested song 45 | const m = await message.reply(`🔍 *Searching **${track}** ...*`).catch(() => null); 46 | // get the queue 47 | let queue = client.queues.get(message.guild.id); 48 | // If a fresh channel join is needed, and a old queue exists, delete it! 49 | if(!oldConnection && queue) { 50 | client.queues.delete(message.guild.id) 51 | queue = undefined; 52 | } 53 | // get song from the link 54 | if(isYT && isSong && !isList) { 55 | song = await YouTube.getVideo(track); 56 | } 57 | // get playlist from the link 58 | else if(isYT && !isSong && isList) { 59 | playlist = await YouTube.getPlaylist(track).then(playlist => playlist.fetch()); 60 | } 61 | // get playlist & song from the link 62 | else if(isYT && isSong && isList) { 63 | song = await YouTube.getVideo(`https://www.youtube.com/watch?v=${isSong[2]}`); 64 | playlist = await YouTube.getPlaylist(`https://www.youtube.com/playlist?list=${isList[2]}`).then(playlist => playlist.fetch()); 65 | } 66 | // otherwise search for it 67 | else { 68 | song = await YouTube.searchOne(track); 69 | } 70 | if(!song && !playlist) return m.edit(`❌ **Failed looking up for ${track}!**`); 71 | /* FOR NO PLAYLIST REQUESTS */ 72 | if(!playlist) { 73 | // if there is no queue create one and start playing 74 | if(!queue || queue.tracks.length == 0) { 75 | // get bitrate 76 | const bitrate = Math.floor(message.member.voice.channel.bitrate / 1000); 77 | // Add the playlist songs to the queue 78 | const newQueue = client.createQueue(song, message.author, message.channelId, bitrate) 79 | client.queues.set(message.guild.id, newQueue) 80 | // play the song in the voice channel 81 | await client.playSong(message.member.voice.channel, song); 82 | // edit the loading message 83 | return m.edit(`▶️ **Now Playing: __${song.title}__** - \`${song.durationFormatted}\``).catch(() => null); 84 | } 85 | // Add the song to the queue 86 | queue.tracks.push(client.createSong(song, message.author)) 87 | // edit the loading message 88 | return m.edit(`👍 **Queued at \`${client.queuePos(queue.tracks.length - 1)}\`: __${song.title}__** - \`${song.durationFormatted}\``).catch(() => null); 89 | } 90 | /* FOR PLAYLIST REQUEST */ 91 | else { 92 | // get the song, or the first playlist song 93 | song = song ? song : playlist.videos[0]; 94 | // remove the song which got added 95 | const index = playlist.videos.findIndex(s => s.id == song.id) || 0; 96 | playlist.videos.splice(index, 1) 97 | // if there is no queue create one and start playing 98 | if(!queue || queue.tracks.length == 0) { 99 | // get bitrate 100 | const bitrate = Math.floor(message.member.voice.channel.bitrate / 1000); 101 | // Add the playlist songs to the queue 102 | const newQueue = client.createQueue(song, message.author, message.channelId, bitrate) 103 | playlist.videos.forEach(song => newQueue.tracks.push(client.createSong(song, message.author))) 104 | client.queues.set(message.guild.id, newQueue) 105 | // play the song in the voice channel 106 | await client.playSong(message.member.voice.channel, song); 107 | // edit the loading message 108 | return m.edit(`▶️ **Now Playing: __${song.title}__** - \`${song.durationFormatted}\`\n> **Added \`${playlist.videos.length - 1} Songs\` from the Playlist:**\n> __**${playlist.title}**__`).catch(() => null); 109 | } 110 | // Add the playlist songs to the queue 111 | playlist.videos.forEach(song => queue.tracks.push(client.createSong(song, message.author))) 112 | // edit the loading message 113 | return m.edit(`👍 **Queued at \`${client.queuePos(queue.tracks.length - (playlist.videos.length - 1))}\`: __${song.title}__** - \`${song.durationFormatted}\`\n> **Added \`${playlist.videos.length - 1} Songs\` from the Playlist:**\n> __**${playlist.title}**__`).catch(() => null); 114 | } 115 | 116 | } catch (e){ console.error(e); 117 | return message.reply(`❌ Could not play the Song because: \`\`\`${e.message || e}`.substr(0, 1950) + `\`\`\``).catch(() => null); 118 | } 119 | }, 120 | }; 121 | -------------------------------------------------------------------------------- /slashCommands/music/play.js: -------------------------------------------------------------------------------- 1 | const { getVoiceConnection } = require("@discordjs/voice"); 2 | const { default: YouTube } = require('youtube-sr'); 3 | const { Permissions } = require("discord.js"); 4 | module.exports = { 5 | name: "play", 6 | description: "Plays Music in your Voice Channel", 7 | options: [ 8 | { 9 | name: "songtitle", 10 | description: "Title/Link of the Song/Playlist", 11 | type: "STRING", 12 | required: true, 13 | }, 14 | ], 15 | run: async (client, interaction, args, prefix) => { 16 | if(!interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content:"👎 **Please join a Voice-Channel first!**"}).catch(() => null); 17 | if(!interaction.member.voice.channel?.permissionsFor(interaction.guild?.me)?.has(Permissions.FLAGS.CONNECT)) { 18 | return interaction.reply({ephemeral: true, content: "👎 **I'm missing the Permission to Connect to your Voice-Channel!**"}).catch(() => null); 19 | } 20 | if(!interaction.member.voice.channel?.permissionsFor(interaction.guild?.me)?.has(Permissions.FLAGS.SPEAK)) { 21 | return interaction.reply({ephemeral: true, content: "👎 **I'm missing the Permission to Speak in your Voice-Channel!**"}).catch(() => null); 22 | } 23 | 24 | // get an old connection 25 | const oldConnection = getVoiceConnection(interaction.guild.id); 26 | if(oldConnection && oldConnection.joinConfig.channelId != interaction.member.voice.channelId) return interaction.reply({ ephemeral: true, content: "👎 **We are not in the same Voice-Channel**!"}).catch(() => null); 27 | 28 | const track = args.join(" "); 29 | if(!args[0]) return interaction.reply({ ephemeral: true, content:`👎 Please add the wished Music via: \`${prefix}play \``}).catch(() => null); 30 | // Regexpressions for testing the search string 31 | const youtubRegex = /^(https?:\/\/)?(www\.)?(m\.|music\.)?(youtube\.com|youtu\.?be)\/.+$/gi; 32 | const playlistRegex = /^.*(list=)([^#\&\?]*).*/gi; 33 | const songRegex = /^.*(watch\?v=)([^#\&\?]*).*/gi; 34 | // variables for song, and playlist 35 | let song = null; 36 | let playlist = null; 37 | // Use the regex expressions 38 | const isYT = youtubRegex.exec(track); 39 | const isSong = songRegex.exec(track); 40 | const isList = playlistRegex.exec(track) 41 | 42 | if(!oldConnection) { 43 | // try to join the voice channel 44 | try { 45 | await client.joinVoiceChannel(interaction.member.voice.channel) 46 | } catch (e){ console.error(e); 47 | return interaction.reply({ ephemeral: true, content:`❌ Could not join the VC because: \`\`\`${e.interaction || e}`.substr(0, 1950) + `\`\`\``}).catch(() => null); 48 | } 49 | } 50 | try { 51 | // try to play the requested song 52 | await interaction.reply({ ephemeral: true, content:`🔍 *Searching **${track}** ...*`}).catch(() => null); 53 | // get the queue 54 | let queue = client.queues.get(interaction.guild.id); 55 | // If a fresh channel join is needed, and a old queue exists, delete it! 56 | if(!oldConnection && queue) { 57 | client.queues.delete(interaction.guild.id) 58 | queue = undefined; 59 | } 60 | // get song from the link 61 | if(isYT && isSong && !isList) { 62 | song = await YouTube.getVideo(track); 63 | } 64 | // get playlist from the link 65 | else if(isYT && !isSong && isList) { 66 | playlist = await YouTube.getPlaylist(track).then(playlist => playlist.fetch()); 67 | } 68 | // get playlist & song from the link 69 | else if(isYT && isSong && isList) { 70 | song = await YouTube.getVideo(`https://www.youtube.com/watch?v=${isSong[2]}`); 71 | playlist = await YouTube.getPlaylist(`https://www.youtube.com/playlist?list=${isList[2]}`).then(playlist => playlist.fetch()); 72 | } 73 | // otherwise search for it 74 | else { 75 | song = await YouTube.searchOne(track); 76 | } 77 | if(!song && !playlist) return interaction.editReply({ ephemeral: true, content: `❌ **Failed looking up for ${track}!**`}); 78 | /* FOR NO PLAYLIST REQUESTS */ 79 | if(!playlist) { 80 | // if there is no queue create one and start playing 81 | if(!queue || queue.tracks.length == 0) { 82 | // get bitrate 83 | const bitrate = Math.floor(interaction.member.voice.channel.bitrate / 1000); 84 | // Add the playlist songs to the queue 85 | const newQueue = client.createQueue(song, interaction.user, interaction.channelId, bitrate) 86 | client.queues.set(interaction.guild.id, newQueue) 87 | // play the song in the voice channel 88 | await client.playSong(interaction.member.voice.channel, song); 89 | // edit the loading interaction 90 | return interaction.editReply({ ephemeral: false, content: `▶️ **Now Playing: __${song.title}__** - \`${song.durationFormatted}\``}).catch(() => null); 91 | } 92 | // Add the song to the queue 93 | queue.tracks.push(client.createSong(song, interaction.user)) 94 | // edit the loading interaction 95 | return interaction.editReply({ ephemeral: false, content: `👍 **Queued at \`${client.queuePos(queue.tracks.length - 1)}\`: __${song.title}__** - \`${song.durationFormatted}\`` }).catch(() => null); 96 | } 97 | /* FOR PLAYLIST REQUEST */ 98 | else { 99 | // get the song, or the first playlist song 100 | song = song ? song : playlist.videos[0]; 101 | // remove the song which got added 102 | const index = playlist.videos.findIndex(s => s.id == song.id) || 0; 103 | playlist.videos.splice(index, 1) 104 | // if there is no queue create one and start playing 105 | if(!queue || queue.tracks.length == 0) { 106 | // get bitrate 107 | const bitrate = Math.floor(interaction.member.voice.channel.bitrate / 1000); 108 | // Add the playlist songs to the queue 109 | const newQueue = client.createQueue(song, interaction.user, interaction.channelId, bitrate) 110 | playlist.videos.forEach(song => newQueue.tracks.push(client.createSong(song, interaction.user))) 111 | client.queues.set(interaction.guild.id, newQueue) 112 | // play the song in the voice channel 113 | await client.playSong(interaction.member.voice.channel, song); 114 | // edit the loading interaction 115 | return interaction.editReply({ ephemeral: false, content: `▶️ **Now Playing: __${song.title}__** - \`${song.durationFormatted}\`\n> **Added \`${playlist.videos.length - 1} Songs\` from the Playlist:**\n> __**${playlist.title}**__`}).catch(() => null); 116 | } 117 | // Add the playlist songs to the queue 118 | playlist.videos.forEach(song => queue.tracks.push(client.createSong(song, interaction.user))) 119 | // edit the loading interaction 120 | return interaction.editReply({ ephemeral: false, content: `👍 **Queued at \`${client.queuePos(queue.tracks.length - (playlist.videos.length - 1))}\`: __${song.title}__** - \`${song.durationFormatted}\`\n> **Added \`${playlist.videos.length - 1} Songs\` from the Playlist:**\n> __**${playlist.title}**__`}).catch(() => null); 121 | } 122 | 123 | } catch (e){ console.error(e); 124 | return interaction.reply({ ephemeral: true, content:`❌ Could not play the Song because: \`\`\`${e.interaction || e}`.substr(0, 1950) + `\`\`\``}).catch(() => null); 125 | } 126 | }, 127 | }; 128 | -------------------------------------------------------------------------------- /util/musicUtils.js: -------------------------------------------------------------------------------- 1 | const Discord = require('discord.js'); 2 | const dcYtdl = require("discord-ytdl-core"); 3 | const { joinVoiceChannel, getVoiceConnection, VoiceConnectionStatus, createAudioResource, createAudioPlayer, NoSubscriberBehavior } = require("@discordjs/voice"); 4 | const { default: YouTube } = require('youtube-sr'); 5 | module.exports = client => { 6 | const m2 = (t) => { 7 | return parseInt(t) < 10 ? `0${t}` : `${t}` 8 | } 9 | const m3 = (t) => { 10 | return parseInt(t) < 100 ? `0${m2(t)}` : `${t}` 11 | } 12 | client.formatDuration = (ms) => { 13 | const sec = parseInt(ms / 1000 % 60); 14 | const min = parseInt(ms / (1000*60) % 60); 15 | const hrs = parseInt(ms / (1000*60*60) % 24); 16 | if(sec >= 60) sec = 0; 17 | if(min >= 60) min = 0; 18 | if(hrs > 1) return `${m2(hrs)}:${m2(min)}:${m2(sec)}` 19 | return `${m2(min)}:${m2(sec)}` 20 | } 21 | client.createBar = (duration, position) => { 22 | try { 23 | const full = "▰"; 24 | const empty = "▱" 25 | const size = "▰▰▰▰▰▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱".length; 26 | const percent = duration == 0 ? null : Math.floor(position / duration * 100) 27 | const fullBars = Math.round(size * (percent / 100)); 28 | const emptyBars = size - fullBars; 29 | return `**${full.repeat(fullBars)}${empty.repeat(emptyBars)}**` 30 | } catch (e) { 31 | console.error(e) 32 | } 33 | } 34 | client.getTime = () => { 35 | const d = new Date; 36 | return `${m2(d.getHours())}:${m2(d.getMinutes())}:${m2(d.getSeconds())}.${m3(d.getMilliseconds())}` 37 | } 38 | 39 | client.getYTLink = (ID) => { 40 | return `https://www.youtube.com/watch?v=${ID}`; 41 | } 42 | 43 | client.joinVoiceChannel = async (channel) => { 44 | return new Promise(async (res, rej) => { 45 | const oldConnection = getVoiceConnection(channel.guild.id); 46 | if (oldConnection) return rej("I'm already connected in: <#" + oldConnection.joinConfig.channelId + ">"); 47 | const newConnection = joinVoiceChannel({ 48 | channelId: channel.id, 49 | guildId: channel.guild.id, 50 | adapterCreator: channel.guild.voiceAdapterCreator 51 | }); 52 | await delay(250); 53 | newConnection.on(VoiceConnectionStatus.Disconnected, async (oldState, newState) => { 54 | try { 55 | await Promise.race([ 56 | entersState(newConnection, VoiceConnectionStatus.Signalling, 5_000), 57 | entersState(newConnection, VoiceConnectionStatus.Connecting, 5_000), 58 | ]); 59 | // Seems to be reconnecting to a new channel - ignore disconnect 60 | } catch (error) { 61 | // Seems to be a real disconnect which SHOULDN'T be recovered from 62 | newConnection.destroy(); 63 | } 64 | }); 65 | newConnection.on(VoiceConnectionStatus.Destroyed, () => { 66 | // try to delete the queue 67 | client.queues.delete(channel.guild.id) 68 | }) 69 | return res("Connected to the Voice Channel"); 70 | }) 71 | }; 72 | 73 | client.leaveVoiceChannel = async (channel) => { 74 | return new Promise(async (res, rej) => { 75 | const oldConnection = getVoiceConnection(channel.guild.id); 76 | if (oldConnection) { 77 | if (oldConnection.joinConfig.channelId != channel.id) return rej("We aren't in the same channel!") 78 | try { 79 | oldConnection.destroy(); 80 | await delay(250); 81 | return res(true) 82 | } catch (e) { 83 | return rej(e) 84 | } 85 | } else { 86 | return rej("I'm not connected somwhere.") 87 | } 88 | }) 89 | 90 | } 91 | 92 | client.getResource = (queue, songInfoId, seekTime = 0) => { 93 | let Qargs = ""; 94 | let effects = queue?.effects || { 95 | bassboost: 4, 96 | speed: 1, 97 | } 98 | if(effects.normalizer) Qargs += `,dynaudnorm=f=200`; 99 | if(effects.bassboost) Qargs += `,bass=g=${effects.bassboost}` 100 | if(effects.speed) Qargs += `,atempo=${effects.speed}` 101 | if(effects["3d"]) Qargs += `,apulsator=hz=0.03` 102 | if(effects.subboost) Qargs += `,asubboost` 103 | if(effects.mcompand) Qargs += `,mcompand` 104 | if(effects.haas) Qargs += `,haas` 105 | if(effects.gate) Qargs += `,agate` 106 | if(effects.karaoke) Qargs += `,stereotools=mlev=0.03` 107 | if(effects.flanger) Qargs += `,flanger` 108 | if(effects.pulsator) Qargs += `,apulsator=hz=1` 109 | if(effects.surrounding) Qargs += `,surround` 110 | if(effects.vaporwave) Qargs += `,aresample=48000,asetrate=48000*0.8` 111 | if(effects.nightcore) Qargs += `,aresample=48000,asetrate=48000*1.5` 112 | if(effects.phaser) Qargs += `,aphaser=in_gain=0.4` 113 | if(effects.tremolo) Qargs += `,tremolo` 114 | if(effects.vibrato) Qargs += `,vibrato=f=6.5` 115 | if(effects.reverse) Qargs += `,areverse` 116 | if(effects.treble) Qargs += `,treble=g=5` 117 | if(Qargs.startsWith(",")) Qargs = Qargs.substring(1) 118 | const requestOpts = { 119 | filter: "audioonly", 120 | fmt: "mp3", 121 | highWaterMark: 1 << 62, 122 | liveBuffer: 1 << 62, 123 | dlChunkSize: 0, 124 | seek: Math.floor(seekTime / 1000), 125 | bitrate: queue?.bitrate || 128, 126 | quality: "lowestaudio", 127 | encoderArgs: Qargs ? ["-af", Qargs ] : ['-af', 'bass=g=6,dynaudnorm=f=200'] // queue.filters 128 | }; 129 | if(client.config.YOUTUBE_LOGIN_COOKIE && client.config.YOUTUBE_LOGIN_COOKIE.length > 10) { 130 | requestOpts.requestOptions = { 131 | headers: { 132 | cookie: client.config.YOUTUBE_LOGIN_COOKIE, 133 | } 134 | } 135 | } 136 | const resource = createAudioResource(dcYtdl(client.getYTLink(songInfoId), requestOpts), { 137 | inlineVolume: true 138 | }); 139 | const volume = queue && queue.volume && queue.volume <= 150 && queue.volume >= 1 ? (queue.volume / 100) : 0.15; // queue.volume / 100; 140 | resource.volume.setVolume(volume); 141 | resource.playbackDuration = seekTime; 142 | return resource; 143 | } 144 | 145 | client.playSong = async (channel, songInfo) => { 146 | return new Promise(async (res, rej) => { 147 | const oldConnection = getVoiceConnection(channel.guild.id); 148 | if (oldConnection) { 149 | if (oldConnection.joinConfig.channelId != channel.id) return rej("We aren't in the same channel!") 150 | try { 151 | const curQueue = client.queues.get(channel.guild.id); 152 | 153 | const player = createAudioPlayer({ 154 | behaviors: { 155 | noSubscriber: NoSubscriberBehavior.Stop, 156 | }, 157 | }); 158 | oldConnection.subscribe(player); 159 | 160 | const resource = client.getResource(curQueue, songInfo.id); 161 | // play the resource 162 | player.play(resource); 163 | 164 | // When the player plays a new song 165 | player.on("playing", (player) => { 166 | const queue = client.queues.get(channel.guild.id); 167 | // if filters changed, don't send something 168 | if(queue && queue.filtersChanged) { 169 | queue.filtersChanged = false; 170 | } else { 171 | client.sendQueueUpdate(channel.guild.id); 172 | } 173 | 174 | }); 175 | // When the player goes on idle 176 | player.on("idle", () => { 177 | const queue = client.queues.get(channel.guild.id); 178 | console.log(`${client.getTime()} :: QueueShift - Idle/Skip`) 179 | handleQueue(queue) 180 | }) 181 | // when an error happens 182 | player.on('error', error => { 183 | console.error(error); 184 | const queue = client.queues.get(channel.guild.id); 185 | console.log(`${client.getTime()} :: QueueShift - Error`) 186 | handleQueue(queue) 187 | }); 188 | 189 | async function handleQueue(queue) { 190 | if(queue && !queue.filtersChanged) { 191 | try { 192 | player.stop() 193 | if(queue && queue.tracks && queue.tracks.length > 1) { 194 | queue.previous = queue.tracks[0]; 195 | if(queue.trackloop && !queue.skipped) { 196 | if(queue.paused) queue.paused = false; 197 | player.play(client.getResource(queue, queue.tracks[0].id)) 198 | } else if(queue.queueloop && !queue.skipped) { 199 | const skipped = queue.tracks.shift(); 200 | queue.tracks.push(skipped); 201 | if(queue.paused) queue.paused = false; 202 | player.play(client.getResource(queue, queue.tracks[0].id)); 203 | } else { 204 | if(queue.skipped) queue.skipped = false; 205 | if(queue.paused) queue.paused = false; 206 | queue.tracks.shift(); 207 | player.play(client.getResource(queue, queue.tracks[0].id)); 208 | } 209 | } else if(queue && queue.tracks && queue.tracks.length <= 1) { // removes the nowplaying, if no upcoming and ends it 210 | queue.previous = queue.tracks[0]; 211 | if(queue.trackloop || queue.queueloop && !queue.skipped) { 212 | player.play(client.getResource(queue, queue.tracks[0].id)); 213 | } else { 214 | if(queue.skipped) queue.skipped = false; 215 | queue.tracks = []; 216 | } 217 | } 218 | } catch (e) { console.error(e) } 219 | } 220 | } 221 | return res(songInfo); 222 | } catch (e) { 223 | return rej(e) 224 | } 225 | } else { 226 | return rej("I'm not connected somwhere.") 227 | } 228 | }) 229 | 230 | } 231 | 232 | client.sendQueueUpdate = async (guildId) => { 233 | const queue = client.queues.get(guildId); 234 | if(!queue || !queue.tracks || queue.tracks.length == 0 || !queue.textChannel) return 235 | const textChannel = client.channels.cache.get(queue.textChannel) || await client.channels.fetch(queue.textChannel).catch(() => null); 236 | if(!textChannel) return 237 | const song = queue.tracks[0]; 238 | 239 | const songEmbed = new Discord.MessageEmbed().setColor("FUCHSIA") 240 | .setTitle(`${song.title}`) 241 | .setURL(client.getYTLink(song.id)) 242 | .addField(`**Duration:**`, `> \`${song.durationFormatted}\``, true) 243 | .addField(`**Requester:**`, `> ${song.requester} \`${song.requester.tag}\``, true) 244 | if(song?.thumbnail?.url) songEmbed.setImage(`${song?.thumbnail?.url}`); 245 | 246 | textChannel.send({ 247 | embeds: [ 248 | songEmbed 249 | ] 250 | }).catch(console.warn) 251 | } 252 | 253 | client.createSong = (song, requester) => { 254 | return { ...song, requester } 255 | } 256 | 257 | client.queuePos = (length) => { 258 | const str = { 259 | 1: "st", 260 | 2: "nd", 261 | 3: "rd", 262 | } 263 | return `${length}${str[length % 10] ? str[length % 10] : "th"}` 264 | } 265 | 266 | client.createQueue = (song, user, channelId, bitrate = 128) => { 267 | return { 268 | textChannel: channelId, 269 | paused: false, 270 | skipped: false, 271 | effects: { 272 | bassboost: 6, 273 | subboost: false, 274 | mcompand: false, 275 | haas: false, 276 | gate: false, 277 | karaoke: false, 278 | flanger: false, 279 | pulsator: false, 280 | surrounding: false, 281 | "3d": false, 282 | vaporwave: false, 283 | nightcore: false, 284 | phaser: false, 285 | normalizer: false, 286 | speed: 1, 287 | tremolo: false, 288 | vibrato: false, 289 | reverse: false, 290 | treble: false, 291 | }, 292 | trackloop: false, 293 | queueloop: false, 294 | filtersChanged: false, 295 | volume: 15, // queue volume, between 1 and 100 296 | tracks: [ client.createSong(song, user) ], 297 | previous: undefined, 298 | creator: user, 299 | bitrate: bitrate 300 | } 301 | } 302 | } 303 | 304 | function delay(ms) { 305 | return new Promise(r => setTimeout(() => r(2), ms)); 306 | } 307 | --------------------------------------------------------------------------------