├── .github └── FUNDING.yml ├── src ├── events │ ├── raw.js │ ├── ready.js │ ├── voiceStateUpdate.js │ ├── interactionCreate.js │ └── messageCreate.js ├── player │ ├── nodeReconnect.js │ ├── nodeDisconnect.js │ ├── nodeError.js │ ├── nodeConnect.js │ └── trackStart.js ├── schema │ ├── Playlist.js │ └── Guild.js ├── index.js ├── bot.js ├── structures │ ├── convertTime.js │ ├── Magmastream.js │ ├── logger.js │ ├── Client.js │ └── Util.js ├── commands │ ├── Message │ │ ├── Music │ │ │ ├── stop.js │ │ │ ├── replay.js │ │ │ ├── pause.js │ │ │ ├── resume.js │ │ │ ├── previous.js │ │ │ ├── leave.js │ │ │ ├── volume.js │ │ │ ├── skip.js │ │ │ ├── loop.js │ │ │ ├── seek.js │ │ │ ├── join.js │ │ │ └── play.js │ │ ├── Information │ │ │ ├── uptime.js │ │ │ ├── ping.js │ │ │ ├── invite.js │ │ │ └── help.js │ │ ├── Playlist │ │ │ ├── pl-reset.js │ │ │ ├── pl-remove.js │ │ │ ├── pl-state.js │ │ │ ├── pl-play.js │ │ │ ├── pl-view.js │ │ │ └── pl-add.js │ │ └── Config │ │ │ ├── 247.js │ │ │ └── prefix.js │ └── Slash │ │ ├── Music │ │ ├── replay.js │ │ ├── stop.js │ │ ├── pause.js │ │ ├── resume.js │ │ ├── previous.js │ │ ├── leave.js │ │ ├── volume.js │ │ ├── skip.js │ │ ├── loop.js │ │ ├── seek.js │ │ ├── join.js │ │ └── play.js │ │ ├── Information │ │ ├── ping.js │ │ ├── uptime.js │ │ ├── invite.js │ │ └── help.js │ │ ├── Playlist │ │ ├── pl-reset.js │ │ ├── pl-remove.js │ │ ├── pl-state.js │ │ ├── pl-play.js │ │ ├── pl-view.js │ │ └── pl-add.js │ │ └── Config │ │ ├── 247.js │ │ └── prefix.js └── config.js ├── package.json ├── LICENSE └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | 2 | ko_fi: coolmusic 3 | -------------------------------------------------------------------------------- /src/events/raw.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client, data) => { 2 | client.manager.updateVoiceState(data); 3 | }; 4 | -------------------------------------------------------------------------------- /src/player/nodeReconnect.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client, node) => { 2 | client.logger.log(`Node "${node.options.identifier}" Reconnected.` , "log"); 3 | }; 4 | -------------------------------------------------------------------------------- /src/player/nodeDisconnect.js: -------------------------------------------------------------------------------- 1 | module.exports = (client, node, reason) => { 2 | client.logger.log(`Node "${node.options.identifier}" Disconnected , Reason: ${JSON.stringify(reason)}.` , "warn"); 3 | }; -------------------------------------------------------------------------------- /src/player/nodeError.js: -------------------------------------------------------------------------------- 1 | module.exports = (client, node, error) => { 2 | client.logger.log(`Error while trying to connect "${node.options.identifier}" , Error: ${error.message}.` , "error"); 3 | 4 | }; -------------------------------------------------------------------------------- /src/schema/Playlist.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require("mongoose"); 2 | 3 | module.exports = model( 4 | "Playlist", 5 | new Schema({ 6 | userID: { type: String, required: true }, 7 | private: { type: Boolean, default: false }, 8 | songs: { type: Array, default: [] }, 9 | createdAt: { type: Date, default: Date.now }, 10 | lastUpdatedAt: { type: Date, default: Date.now }, 11 | }) 12 | ); -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const { ClusterManager, ReClusterManager } = require("discord-hybrid-sharding"); 2 | const { token } = require("./config"); 3 | const manager = new ClusterManager("./src/bot.js", { 4 | token: token, 5 | totalShards: "auto", 6 | shardsPerClusters: 1, 7 | totalClusters: "auto", 8 | mode: 'process', 9 | }); 10 | 11 | manager.extend(new ReClusterManager()); 12 | manager.on('clusterDestroy', (cluster) => console.log(`Destroyed shard ${cluster.id}`)); 13 | manager.spawn(); 14 | -------------------------------------------------------------------------------- /src/schema/Guild.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require("mongoose"); 2 | const { prefix: defaultPrefix } = require("../config"); 3 | 4 | module.exports = model( 5 | "Guild", 6 | new Schema({ 7 | id: { type: String }, 8 | prefix: { type: String, default: defaultPrefix }, 9 | alwaysinvc: { 10 | enabled: { type: Boolean, default: false }, 11 | textChannel: { type: String, default: null }, 12 | voiceChannel: { type: String, default: null }, 13 | }, 14 | }) 15 | ); 16 | 17 | -------------------------------------------------------------------------------- /src/bot.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, WebhookClient } = require("discord.js"); 2 | const { inspect } = require('util') 3 | new (require("./structures/Client"))().load(); 4 | 5 | 6 | process.removeAllListeners("warning"); 7 | process.on('unhandledRejection', (reason, p) => { 8 | console.log(reason, p); 9 | }); 10 | 11 | process.on('uncaughtException', (err, origin) => { 12 | console.log(err, origin); 13 | }); 14 | 15 | process.on('uncaughtExceptionMonitor', (err, origin) => { 16 | console.log(err, origin); 17 | }); 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tunes", 3 | "version": "1.2.1", 4 | "description": "A Discord bot for playing music with support for multiple streaming platforms.", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "start": "node src/index.js", 8 | "test": "echo \"No tests specified\" && exit 0" 9 | }, 10 | "dependencies": { 11 | "chalk": "^4.1.2", 12 | "discord-hybrid-sharding": "^2.2.0", 13 | "discord.js": "^14.16.2", 14 | "magmastream": "^2.5.14", 15 | "mongoose": "^8.6.3", 16 | "moment": "^2.30.1", 17 | "undici": "^5.28.4" 18 | }, 19 | "engines": { 20 | "node": ">=20.0.0" 21 | }, 22 | "author": "Itz Random", 23 | "license": "MIT" 24 | } 25 | -------------------------------------------------------------------------------- /src/structures/convertTime.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | convertTime: function (duration) { 4 | var milliseconds = parseInt((duration % 1000) / 100), 5 | seconds = parseInt((duration / 1000) % 60), 6 | minutes = parseInt((duration / (1000 * 60)) % 60), 7 | hours = parseInt((duration / (1000 * 60 * 60)) % 24); 8 | 9 | hours = hours < 10 ? "0" + hours : hours; 10 | minutes = minutes < 10 ? "0" + minutes : minutes; 11 | seconds = seconds < 10 ? "0" + seconds : seconds; 12 | 13 | if (duration < 3600000) { 14 | return minutes + ":" + seconds; 15 | } else { 16 | return hours + ":" + minutes + ":" + seconds; 17 | } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/commands/Message/Music/stop.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "stop", 5 | permission: "", 6 | description: "Stops the music", 7 | usage: "", 8 | settings: { 9 | ownerOnly: false, 10 | inVoiceChannel: true, 11 | sameVoiceChannel: true, 12 | musicnotplaying: true, 13 | musicplaying: true, 14 | }, 15 | /** 16 | * @param {{ message: import("discord.js").Message }} 17 | */ 18 | run: async ({ message, player }) => { 19 | player.destroy(); 20 | 21 | return message.channel.send({ 22 | embeds: [ 23 | new EmbedBuilder() 24 | .setColor("Blue") 25 | .setDescription("Stop playing music."), 26 | ], 27 | }); 28 | }, 29 | }; 30 | -------------------------------------------------------------------------------- /src/commands/Slash/Music/replay.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "replay", 5 | description: "Plays the song from the beginning", 6 | settings: { 7 | ownerOnly: false, 8 | inVoiceChannel: true, 9 | sameVoiceChannel: true, 10 | musicnotplaying: true, 11 | musicplaying: true, 12 | }, 13 | /** 14 | * @param {{ client: import("../../structures/Client"), interaction: import("discord.js").CommandInteraction}} 15 | */ 16 | run: async (client, interaction, player) => { 17 | player.seek(0); 18 | return interaction.editReply({ 19 | embeds: [ 20 | new EmbedBuilder() 21 | .setColor("Blue") 22 | .setDescription(`Replaying the current song.`), 23 | ], 24 | }); 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /src/commands/Message/Music/replay.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "replay", 5 | description: "Plays the song from starting", 6 | usage: "", 7 | settings: { 8 | ownerOnly: false, 9 | inVoiceChannel: true, 10 | sameVoiceChannel: true, 11 | musicnotplaying: true, 12 | musicplaying: true, 13 | }, 14 | /** 15 | * @param {{ client: import("../../structures/Client"), message: import("discord.js").Message}} 16 | */ 17 | run: async ({ client, message , player}) => { 18 | 19 | player.seek(0); 20 | return message.channel.send({ 21 | embeds: [ 22 | new EmbedBuilder() 23 | .setColor("Blue") 24 | .setDescription(`Replaying the current song.`), 25 | ], 26 | }); 27 | }, 28 | }; -------------------------------------------------------------------------------- /src/commands/Slash/Music/stop.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "stop", 5 | description: "Stops the music", 6 | settings: { 7 | ownerOnly: false, 8 | inVoiceChannel: true, 9 | sameVoiceChannel: true, 10 | musicnotplaying: true, 11 | musicplaying: true, 12 | }, 13 | /** 14 | * @param {{ client: import("../../../structures/Client"), interaction: import("discord.js").CommandInteraction }} 15 | */ 16 | run: async (client, interaction, player) => { 17 | player.destroy(); 18 | 19 | return interaction.editReply({ 20 | embeds: [ 21 | new EmbedBuilder() 22 | .setColor("Blue") 23 | .setDescription("Stop playing music."), 24 | ], 25 | }); 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /src/commands/Slash/Information/ping.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "ping", 5 | description: "Shows the bot's latency", 6 | settings: { 7 | ownerOnly: false, 8 | inVoiceChannel: false, 9 | sameVoiceChannel: false, 10 | musicnotplaying: false, 11 | musicplaying: false, 12 | }, 13 | /** 14 | * @param {{ client: import("../../../structures/Client"), interaction: import("discord.js").CommandInteraction }} 15 | */ 16 | run: async (client, interaction) => { 17 | await interaction.editReply({ 18 | embeds: [ 19 | new EmbedBuilder() 20 | .setColor("Blue") 21 | .setDescription(`API Latency - \`${Math.trunc(client.ws.ping)}\` ms`), 22 | ], 23 | }); 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /src/commands/Message/Information/uptime.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "uptime", 5 | description: "Get the uptime of the bot", 6 | settings: { 7 | ownerOnly: false, 8 | inVoiceChannel: false, 9 | sameVoiceChannel: false, 10 | musicnotplaying: false, 11 | musicplaying: false, 12 | }, 13 | /** 14 | * @param {{ client: import("../../../structures/Client"), message: import("discord.js").Message }} 15 | */ 16 | run: async ({ client, message }) => { 17 | return await message.channel.send({ 18 | embeds: [ 19 | new EmbedBuilder() 20 | .setColor("Blue") 21 | .setDescription( 22 | `Last Restarted ` 23 | ), 24 | ], 25 | }); 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /src/commands/Message/Information/ping.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "ping", 5 | aliases: ["latency"], 6 | permission: "", 7 | description: "Shows the bot's latency", 8 | usage: "", 9 | settings: { 10 | ownerOnly: false, 11 | inVoiceChannel: false, 12 | sameVoiceChannel: false, 13 | musicnotplaying: false, 14 | musicplaying: false, 15 | }, 16 | /** 17 | * @param {{ client: import("../../../structures/Client"), message: import("discord.js").Message }} 18 | */ 19 | run: async ({ client, message }) => { 20 | return await message.channel.send({ 21 | embeds: [ 22 | new EmbedBuilder() 23 | .setColor("Blue") 24 | .setDescription(`API Latency - \`${Math.trunc(client.ws.ping)}\` ms`), 25 | ], 26 | }); 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /src/commands/Slash/Information/uptime.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "uptime", 5 | description: "Get the uptime of the bot", 6 | settings: { 7 | ownerOnly: false, 8 | inVoiceChannel: false, 9 | sameVoiceChannel: false, 10 | musicnotplaying: false, 11 | musicplaying: false, 12 | }, 13 | /** 14 | * @param {{ client: import("../../../structures/Client"), interaction: import("discord.js").CommandInteraction }} 15 | */ 16 | run: async (client, interaction) => { 17 | await interaction.editReply({ 18 | embeds: [ 19 | new EmbedBuilder() 20 | .setColor("Blue") 21 | .setDescription( 22 | `Last Restarted ` 23 | ), 24 | ], 25 | }); 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /src/player/nodeConnect.js: -------------------------------------------------------------------------------- 1 | const db = require("../schema/Guild"); 2 | 3 | module.exports = async (client, node) => { 4 | client.logger.log(`Node "${node.options.identifier}" connected.`, "log"); 5 | 6 | let i = 0; 7 | const maindata = await db.find(); 8 | for (const data of maindata) { 9 | i++; 10 | const index = maindata.indexOf(data); 11 | setTimeout(async () => { 12 | const text = client.channels.cache.get(data.alwaysinvc.textChannel); 13 | const guild = client.guilds.cache.get(data.id); 14 | const voice = client.channels.cache.get( 15 | data.alwaysinvc.voiceChannel 16 | ); 17 | if (!guild || !text || !voice) return; 18 | 19 | a = client.manager.create({ 20 | guild: guild.id, 21 | textChannel: text?.id, 22 | voiceChannel: voice.id, 23 | selfDeafen: true, 24 | volume: 100, 25 | }); 26 | if (a.state !== "CONNECTED") { 27 | a.connect(); 28 | } 29 | }), 30 | index * 20000; 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /src/commands/Message/Music/pause.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "pause", 5 | permission: "", 6 | description: "Pauses the current song", 7 | usage: "", 8 | settings: { 9 | ownerOnly: false, 10 | inVoiceChannel: true, 11 | sameVoiceChannel: true, 12 | musicnotplaying: true, 13 | musicplaying: true, 14 | }, 15 | /** 16 | * @param {{ message: import("discord.js").Message }} 17 | */ 18 | run: async ({ message, player }) => { 19 | if (player.paused) { 20 | return message.channel.send({ 21 | embeds: [ 22 | new EmbedBuilder() 23 | .setColor("Red") 24 | .setDescription(`The Song is Already Paused.`), 25 | ], 26 | }); 27 | } 28 | player.pause(true); 29 | return message.channel.send({ 30 | embeds: [ 31 | new EmbedBuilder() 32 | .setColor("Blue") 33 | .setDescription(`⏸️ Paused the song.`), 34 | ], 35 | }); 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /src/commands/Message/Music/resume.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "resume", 5 | permission: "", 6 | description: "Resumes the current song", 7 | usage: "", 8 | settings: { 9 | ownerOnly: false, 10 | inVoiceChannel: true, 11 | sameVoiceChannel: true, 12 | musicnotplaying: true, 13 | musicplaying: true, 14 | }, 15 | /** 16 | * @param {{ message: import("discord.js").Message }} 17 | */ 18 | run: async ({ message, player }) => { 19 | if (!player.paused) { 20 | return message.channel.send({ 21 | embeds: [ 22 | new EmbedBuilder() 23 | .setColor("Red") 24 | .setDescription(`The Song is Already Playing.`), 25 | ], 26 | }); 27 | } 28 | player.pause(false); 29 | return message.channel.send({ 30 | embeds: [ 31 | new EmbedBuilder() 32 | .setColor("Blue") 33 | .setDescription(`▶️ Resumed the song.`), 34 | ], 35 | }); 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /src/commands/Slash/Music/pause.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "pause", 5 | description: "Pauses the current song", 6 | settings: { 7 | ownerOnly: false, 8 | inVoiceChannel: true, 9 | sameVoiceChannel: true, 10 | musicnotplaying: true, 11 | musicplaying: true, 12 | }, 13 | /** 14 | * @param {{ client: import("../../../structures/Client"), interaction: import("discord.js").CommandInteraction }} 15 | */ 16 | run: async (client, interaction, player) => { 17 | if (player.paused) { 18 | return interaction.editReply({ 19 | embeds: [ 20 | new EmbedBuilder() 21 | .setColor("Red") 22 | .setDescription(`The Song is Already Paused.`), 23 | ], 24 | }); 25 | } 26 | player.pause(true); 27 | return interaction.editReply({ 28 | embeds: [ 29 | new EmbedBuilder() 30 | .setColor("Blue") 31 | .setDescription(`⏸️ Paused the song.`), 32 | ], 33 | }); 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /src/commands/Slash/Music/resume.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "resume", 5 | description: "Resumes the current song", 6 | settings: { 7 | ownerOnly: false, 8 | inVoiceChannel: true, 9 | sameVoiceChannel: true, 10 | musicnotplaying: true, 11 | musicplaying: true, 12 | }, 13 | /** 14 | * @param {{ client: import("../../../structures/Client"), interaction: import("discord.js").CommandInteraction }} 15 | */ 16 | run: async (client, interaction, player) => { 17 | if (!player.paused) { 18 | return interaction.editReply({ 19 | embeds: [ 20 | new EmbedBuilder() 21 | .setColor("Red") 22 | .setDescription(`The Song is Already Playing.`), 23 | ], 24 | }); 25 | } 26 | player.pause(false); 27 | return interaction.editReply({ 28 | embeds: [ 29 | new EmbedBuilder() 30 | .setColor("Blue") 31 | .setDescription(`▶️ Resumed the song.`), 32 | ], 33 | }); 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /src/commands/Slash/Information/invite.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "invite", 5 | description: "Get the bot's invite link.", 6 | settings: { 7 | ownerOnly: false, 8 | inVoiceChannel: false, 9 | sameVoiceChannel: false, 10 | musicnotplaying: false, 11 | musicplaying: false, 12 | }, 13 | /** 14 | * @param {{ client: import("../../../structures/Client"), interaction: import("discord.js").CommandInteraction }} 15 | */ 16 | run: async (client, interaction) => { 17 | await interaction.editReply({ 18 | embeds: [ 19 | new EmbedBuilder() 20 | .setColor("Blue") 21 | .setDescription( 22 | `• [Invite **${client.user.username}** to your server](https://discord.com/oauth2/authorize?client_id=${client.user.id}&permissions=12888394808&scope=bot%20identify%20applications.commands) \n` + 23 | `• [Join the support server](https://discord.gg/cool-music-support-925619107460698202)` 24 | ), 25 | ], 26 | }); 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /src/events/ready.js: -------------------------------------------------------------------------------- 1 | const { 2 | REST, 3 | Routes, 4 | ApplicationCommandType, 5 | ActivityType, 6 | } = require("discord.js"); 7 | 8 | /** 9 | * @param {import("../structures/Client")} client 10 | */ 11 | 12 | module.exports = async (client) => { 13 | client.logger.log(`launched cluster #${client.cluster.id}.`, "ready"); 14 | client.manager.init(client.user.id); 15 | client.user.setActivity({ 16 | name: `Tunes in HD`, 17 | type: ActivityType.Playing, 18 | }); 19 | if (client.cluster.id === 0) { 20 | const rest = new REST({ version: "10" }).setToken(client.token); 21 | let appCommand = []; 22 | client.slashCommands 23 | .filter(({ category }) => category !== "Owner") 24 | .map(({ description, name, options }) => { 25 | appCommand.push({ 26 | name, 27 | description, 28 | options, 29 | type: ApplicationCommandType.ChatInput, 30 | dmPermission: false, 31 | }); 32 | }); 33 | await rest.put(Routes.applicationCommands(client.user.id), { 34 | body: appCommand, 35 | }); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /src/commands/Message/Information/invite.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "invite", 5 | aliases: ["inv"], 6 | description: "Get the bot's invite link.", 7 | usage: "", 8 | settings: { 9 | ownerOnly: false, 10 | inVoiceChannel: false, 11 | sameVoiceChannel: false, 12 | musicnotplaying: false, 13 | musicplaying: false, 14 | }, 15 | /** 16 | * @param {{ client: import("../../../structures/Client"), message: import("discord.js").Message }} 17 | */ 18 | run: async ({ client, message }) => { 19 | return await message.channel.send({ 20 | embeds: [ 21 | new EmbedBuilder() 22 | .setColor("Blue") 23 | .setDescription( 24 | `• [Invite **${client.user.username}** to your server](https://discord.com/oauth2/authorize?client_id=${client.user.id}&permissions=12888394808&scope=bot%20identify%20applications.commands) \n` + 25 | `• [Join the support server](https://discord.gg/cool-music-support-925619107460698202)` 26 | ), 27 | ], 28 | }); 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /src/structures/Magmastream.js: -------------------------------------------------------------------------------- 1 | const { readdirSync } = require("fs"); 2 | const { Manager } = require("magmastream"); 3 | const config = require("../config"); 4 | 5 | module.exports = class Magmastream extends Manager { 6 | constructor(client) { 7 | super({ 8 | nodes: config.nodes, 9 | autoPlay: true, 10 | defaultSearchPlatform: config.defaultsource, 11 | clientName: "Tunes", 12 | send: (id, payload) => this._sendPayload(id, payload), 13 | }); 14 | 15 | this.client = client; 16 | this._loadMagmastreamEvents(); 17 | } 18 | 19 | _sendPayload(id, payload) { 20 | const guild = this.client.guilds.cache.get(id); 21 | if (guild) return guild.shard.send(payload); 22 | } 23 | 24 | _loadMagmastreamEvents() { 25 | let i = 0; 26 | readdirSync("./src/player/").forEach((file) => { 27 | const event = require(`../player/${file}`); 28 | const eventName = file.split(".")[0]; 29 | this.on(eventName, event.bind(null, this.client)); 30 | ++i; 31 | }); 32 | console.log(`Loaded a total of ${i} Magmastream event(s)`); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024-2025 Itz Random 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 | -------------------------------------------------------------------------------- /src/commands/Message/Music/previous.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "previous", 5 | aliases: ["prev", "back"], 6 | permission: "", 7 | description: "Plays the previous song", 8 | usage: "", 9 | settings: { 10 | ownerOnly: false, 11 | inVoiceChannel: true, 12 | sameVoiceChannel: true, 13 | musicnotplaying: true, 14 | musicplaying: true, 15 | }, 16 | /** 17 | * @param {{ client: import("../../structures/Client"), message: import("discord.js").Message}} 18 | */ 19 | run: async ({ client, message , player}) => { 20 | if (!player.queue.previous) { 21 | return message.channel.send({ 22 | embeds: [ 23 | new EmbedBuilder() 24 | .setColor("Red") 25 | .setDescription(`There is no previous song.`), 26 | ], 27 | }); 28 | } 29 | player.queue.unshift(player.queue.previous); 30 | player.stop(); 31 | return message.channel.send({ 32 | embeds: [ 33 | new EmbedBuilder() 34 | .setColor("Blue") 35 | .setDescription(`Started playing the previous song.`), 36 | ], 37 | }); 38 | }, 39 | }; -------------------------------------------------------------------------------- /src/commands/Slash/Music/previous.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "previous", 5 | aliases: ["prev", "back"], 6 | permission: "", 7 | description: "Plays the previous song", 8 | usage: "", 9 | settings: { 10 | ownerOnly: false, 11 | inVoiceChannel: true, 12 | sameVoiceChannel: true, 13 | musicnotplaying: true, 14 | musicplaying: true, 15 | }, 16 | /** 17 | * @param {{ client: import("../../structures/Client"), interaction: import("discord.js").CommandInteraction}} 18 | */ 19 | run: async (client, interaction, player) => { 20 | if (!player.queue.previous) { 21 | return interaction.editReply({ 22 | embeds: [ 23 | new EmbedBuilder() 24 | .setColor("Red") 25 | .setDescription(`There is no previous song.`), 26 | ], 27 | }); 28 | } 29 | player.queue.unshift(player.queue.previous); 30 | player.stop(); 31 | return interaction.editReply({ 32 | embeds: [ 33 | new EmbedBuilder() 34 | .setColor("Blue") 35 | .setDescription(`Started playing the previous song.`), 36 | ], 37 | }); 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /src/structures/logger.js: -------------------------------------------------------------------------------- 1 | const chalk = require("chalk"); 2 | const moment = require("moment"); 3 | 4 | module.exports = class Logger { 5 | static log (content, type = "log") { 6 | const date = `${moment().format("DD-MM-YYYY hh:mm:ss")}`; 7 | switch (type) { 8 | 9 | case "log": { 10 | return console.log(`[${chalk.gray(date)}]: [${chalk.black.bgBlue(type.toUpperCase())}] ${content}`); 11 | } 12 | case "warn": { 13 | return console.log(`[${chalk.gray(date)}]: [${chalk.black.bgYellow(type.toUpperCase())}] ${content}`); 14 | } 15 | case "error": { 16 | return console.log(`[${chalk.gray(date)}]: [${chalk.black.bgRed(type.toUpperCase())}] ${content}`); 17 | } 18 | case "debug": { 19 | return console.log(`[${chalk.gray(date)}]: [${chalk.black.bgGreen(type.toUpperCase())}] ${content}`); 20 | } 21 | case "cmd": { 22 | return console.log(`[${chalk.gray(date)}]: [${chalk.black.bgWhite(type.toUpperCase())}] ${content}`); 23 | } 24 | case "event": { 25 | return console.log(`[${chalk.gray(date)}]: [${chalk.black.bgWhite(type.toUpperCase())}] ${content}`); 26 | } 27 | case "ready": { 28 | return console.log(`[${chalk.gray(date)}]: [${chalk.black.bgBlueBright(type.toUpperCase())}] ${content}`); 29 | } 30 | default: throw new TypeError("Logger type must be either warn, debug, log, ready, cmd or error."); 31 | } 32 | } 33 | }; -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | token: 3 | "", // Your Bot Token 4 | mongo: 5 | "", // Your Mongo URL here 6 | prefix: "", // prefix here 7 | support: "", //support server link 8 | defaultsource: "", // your source here ( youtube , spotify , deezer , tidal , applemusic , jiosaavn , bandcamp etc ) THE SOURCE MUST BE ENABLED IN YOUR LAVALINK SERVER! 9 | nodes: [ 10 | { 11 | identifier: "", // Name of the Node 12 | host: "", // I.P Address of the Node 13 | port: 443, // Port of the Node 14 | password: "", // Password of the Node 15 | retryAmount: 1000, 16 | retrydelay: 10000, 17 | resumeStatus: false, 18 | resumeTimeout: 1000, 19 | secure: false, // true or false 20 | }, 21 | /* EXAMPLE LAVALINK 22 | { 23 | identifier: "Node1", // Name of the Node 24 | host: "node.lewdhutao.my.eu.org", // I.P Address of the Node 25 | port: 13592, // Port of the Node 26 | password: "youshallnotpass", // Password of the Node 27 | retryAmount: 1000, 28 | retrydelay: 10000, 29 | resumeStatus: false, 30 | resumeTimeout: 1000, 31 | secure: false, // true or false 32 | },*/ 33 | ], 34 | ownerID: ["", ""], 35 | spotify: [ 36 | { 37 | Id: "", 38 | Secret: "", 39 | }, 40 | { 41 | Id: "", 42 | Secret: "", 43 | }, 44 | ], 45 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | ## NOTE 4 | New Updates will be published in March or April 2025! 5 | 6 | ## Installation 7 | 8 | To install and run the bot locally, follow these steps: 9 | 10 | 1. **Clone the repository:** 11 | ```bash 12 | git clone https://github.com/ItzRandom23/Tunes.git 13 | ``` 14 | 15 | 2. **Navigate to the repository directory:** 16 | ```bash 17 | cd Tunes 18 | ``` 19 | 20 | 3. **Install the dependencies:** 21 | ```bash 22 | npm install 23 | ``` 24 | 25 | 4. **Start the bot:** 26 | ```bash 27 | npm start 28 | ``` 29 | 30 | ## Deploy on Cloud 31 | 32 | If you want to host this project 24/7 for free, you can try [Itz Random Cloud](https://dash.itzrandom.cloud). 33 | 34 | ## Support 35 | 36 | For support and to join our community, visit our [Discord server](https://discord.gg/cool-music-support-925619107460698202). 37 | 38 | ## Contributing 39 | 40 | If you'd like to contribute to the project, please fork the repository and submit a pull request with your changes. We welcome all contributions! 41 | 42 | ## Note 43 | 44 | The code uses the latest version of modules and dependencies to ensure compatibility and the latest features. 45 | -------------------------------------------------------------------------------- /src/commands/Message/Music/leave.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "leave", 5 | permission: "", 6 | aliases: ["disconnect", "dc", "leave"], 7 | description: "Leaves the voice channel", 8 | settings: { 9 | ownerOnly: false, 10 | inVoiceChannel: true, 11 | sameVoiceChannel: true, 12 | musicnotplaying: false, 13 | musicplaying: false, 14 | }, 15 | /** 16 | * @param {{ client: import("../../structures/Client"), message: import("discord.js").Message}} 17 | */ 18 | run: async ({ client, message, player, guildData }) => { 19 | if (!player) { 20 | return message.channel.send({ 21 | embeds: [ 22 | new EmbedBuilder() 23 | .setColor("Red") 24 | .setDescription(`I am not connected to a voice channel.`), 25 | ], 26 | }); 27 | } 28 | const voiceChannel = message.member.voice.channel; 29 | if (!voiceChannel) { 30 | return message.channel.send({ 31 | embeds: [ 32 | new EmbedBuilder() 33 | .setColor("Red") 34 | .setDescription( 35 | `You must be in a voice channel to use this command.` 36 | ), 37 | ], 38 | }); 39 | } 40 | 41 | player.destroy(); 42 | 43 | return message.channel.send({ 44 | embeds: [ 45 | new EmbedBuilder() 46 | .setColor("Blue") 47 | .setDescription("👋 Disconnected from the VC."), 48 | ], 49 | }); 50 | }, 51 | }; 52 | -------------------------------------------------------------------------------- /src/commands/Slash/Music/leave.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "leave", 5 | permission: "", 6 | description: "Leave the voice channel.", 7 | settings: { 8 | ownerOnly: false, 9 | inVoiceChannel: true, 10 | sameVoiceChannel: true, 11 | musicnotplaying: false, 12 | musicplaying: false, 13 | }, 14 | /** 15 | * @param {{ client: import("../../structures/Client"), interaction: import("discord.js").CommandInteraction, player: any, guildData: any }} 16 | */ 17 | run: async (client, interaction, player) => { 18 | if (!player) { 19 | return interaction.editReply({ 20 | embeds: [ 21 | new EmbedBuilder() 22 | .setColor("Red") 23 | .setDescription(`I'm not connected to any voice channel.`), 24 | ], 25 | }); 26 | } 27 | 28 | const voiceChannel = interaction.member.voice.channel; 29 | if (!voiceChannel) { 30 | return interaction.editReply({ 31 | embeds: [ 32 | new EmbedBuilder() 33 | .setColor("Red") 34 | .setDescription( 35 | `You need to be in a voice channel to use this command.` 36 | ), 37 | ], 38 | }); 39 | } 40 | 41 | player.destroy(); 42 | 43 | return interaction.editReply({ 44 | embeds: [ 45 | new EmbedBuilder() 46 | .setColor("Blue") 47 | .setDescription("👋 Disconnected from the voice channel."), 48 | ], 49 | }); 50 | }, 51 | }; 52 | -------------------------------------------------------------------------------- /src/commands/Slash/Playlist/pl-reset.js: -------------------------------------------------------------------------------- 1 | const PlaylistSchema = require("../../../schema/Playlist"); 2 | const { EmbedBuilder } = require("discord.js"); 3 | 4 | module.exports = { 5 | name: "pl-reset", 6 | permission: "", 7 | description: "Resets your playlist", 8 | usage: "", 9 | settings: { 10 | ownerOnly: false, 11 | inVoiceChannel: false, 12 | sameVoiceChannel: false, 13 | musicnotplaying: false, 14 | musicplaying: false, 15 | }, 16 | 17 | run: async (client, interaction) => { 18 | 19 | const data = await PlaylistSchema.findOne({ userID: interaction.member.id }); 20 | if (!data) { 21 | data = new PlaylistSchema({ 22 | userID: interaction.member.id, 23 | songs: [], 24 | private: false, 25 | createdAt: Date.now(), 26 | lastUpdatedAt: Date.now(), 27 | }); 28 | } 29 | await data.save(); 30 | if (!data.songs.length) return interaction.editReply({ 31 | embeds: [ 32 | new EmbedBuilder() 33 | .setColor("Red") 34 | .setDescription(`You don't have any songs in the playlist.`), 35 | ], 36 | }); 37 | data.songs = []; 38 | await data.save(); 39 | return interaction.editReply({ 40 | embeds: [ 41 | new EmbedBuilder() 42 | .setColor("Blue") 43 | .setDescription(`Cleared your playlist.`), 44 | ], 45 | }); 46 | } 47 | } -------------------------------------------------------------------------------- /src/commands/Message/Playlist/pl-reset.js: -------------------------------------------------------------------------------- 1 | const PlaylistSchema = require("../../../schema/Playlist"); 2 | const { EmbedBuilder } = require("discord.js"); 3 | 4 | module.exports = { 5 | name: "pl-reset", 6 | permission: "", 7 | description: "Resets your playlist", 8 | usage: "", 9 | settings: { 10 | ownerOnly: false, 11 | inVoiceChannel: false, 12 | sameVoiceChannel: false, 13 | musicnotplaying: false, 14 | musicplaying: false, 15 | }, 16 | 17 | /** 18 | * @param {{ client: import("../../structures/Client"), message: import("discord.js").Message }} 19 | */ 20 | 21 | run: async ({ client, message }) => { 22 | 23 | const data = await PlaylistSchema.findOne({ userID: message.author.id }); 24 | if (!data) { 25 | data = new PlaylistSchema({ 26 | userID: message.author.id, 27 | songs: [], 28 | private: false, 29 | createdAt: Date.now(), 30 | lastUpdatedAt: Date.now(), 31 | }); 32 | } 33 | await data.save(); 34 | if (!data.songs.length) return message.channel.send({ 35 | embeds: [ 36 | new EmbedBuilder() 37 | .setColor("Red") 38 | .setDescription(`You don't have any songs in the playlist.`), 39 | ], 40 | }); 41 | data.songs = []; 42 | await data.save(); 43 | return message.channel.send({ 44 | embeds: [ 45 | new EmbedBuilder() 46 | .setColor("Blue") 47 | .setDescription(`Cleared your playlist.`), 48 | ], 49 | }); 50 | } 51 | } -------------------------------------------------------------------------------- /src/commands/Slash/Config/247.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "247", 5 | permission: "ManageGuild", 6 | description: "Toggle 24/7 mode for the bot.", 7 | settings: { 8 | ownerOnly: false, 9 | inVoiceChannel: true, 10 | sameVoiceChannel: true, 11 | musicnotplaying: false, 12 | musicplaying: false, 13 | }, 14 | /** 15 | * @param {{ client: import("../../../structures/Client"), interaction: import("discord.js").CommandInteraction }} 16 | */ 17 | run: async (client, interaction, player, guildData) => { 18 | let toBeEnabled = !guildData.alwaysinvc.enabled; 19 | 20 | guildData.alwaysinvc.enabled = toBeEnabled; 21 | guildData.alwaysinvc.textChannel = toBeEnabled 22 | ? interaction.channel.id 23 | : null; 24 | guildData.alwaysinvc.voiceChannel = toBeEnabled 25 | ? interaction.member.voice.channel.id 26 | : null; 27 | guildData.save(); 28 | 29 | if (toBeEnabled && !player) { 30 | player = client.manager.create({ 31 | guild: interaction.guildId, 32 | textChannel: interaction.channelId, 33 | voiceChannel: interaction.member?.voice.channelId, 34 | selfDeafen: true, 35 | volume: 100, 36 | }); 37 | if (player.state !== "CONNECTED") player.connect(); 38 | } else if (!toBeEnabled && player && !player.queue.current) { 39 | setTimeout(() => player.destroy(), 150); 40 | } 41 | 42 | return interaction.editReply({ 43 | embeds: [ 44 | new EmbedBuilder() 45 | .setColor("Blue") 46 | .setDescription( 47 | `24/7 mode has been ${ 48 | toBeEnabled ? "**enabled**" : "**disabled**" 49 | }.` 50 | ), 51 | ], 52 | }); 53 | }, 54 | }; 55 | -------------------------------------------------------------------------------- /src/commands/Message/Music/volume.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "volume", 5 | aliases: ["v", "vol"], 6 | permission: "", 7 | description: "Increase or decrease the songs volume", 8 | usage: "[volume]", 9 | settings: { 10 | ownerOnly: false, 11 | inVoiceChannel: true, 12 | sameVoiceChannel: true, 13 | musicnotplaying: true, 14 | musicplaying: true, 15 | }, 16 | /** 17 | * @param {{ message: import("discord.js").Message }} 18 | */ 19 | run: async ({ message, player }) => { 20 | if (!message.args[0]) { 21 | return message.channel.send({ 22 | embeds: [ 23 | new EmbedBuilder() 24 | .setColor("Blue") 25 | .setDescription(`The current volume is **${player.volume}%**`), 26 | ], 27 | }); 28 | } 29 | 30 | let volume = parseInt(message.args[0]); 31 | if (isNaN(volume) || volume < 0 || volume > 100) { 32 | return message.channel.send({ 33 | embeds: [ 34 | new EmbedBuilder() 35 | .setColor("Red") 36 | .setDescription(`Enter a volume amount between \`0 - 100\`.`), 37 | ], 38 | }); 39 | } 40 | if (player.volume === volume) { 41 | return message.channel.send({ 42 | embeds: [ 43 | new EmbedBuilder() 44 | .setColor("Red") 45 | .setDescription(`Volume is already set to **${volume}%**`), 46 | ], 47 | }); 48 | } 49 | player.setVolume(volume); 50 | 51 | return message.channel.send({ 52 | embeds: [ 53 | new EmbedBuilder() 54 | .setColor("Blue") 55 | .setDescription( 56 | `Successfully changed the **volume** to **${player.volume}%**` 57 | ), 58 | ], 59 | }); 60 | }, 61 | }; 62 | -------------------------------------------------------------------------------- /src/commands/Message/Config/247.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "247", 5 | aliases: ["24/7", "24_7", "24h"], 6 | permission: "ManageGuild", 7 | description: "Toggle 24/7 mode for the bot.", 8 | usage: "", 9 | settings: { 10 | ownerOnly: false, 11 | inVoiceChannel: true, 12 | sameVoiceChannel: true, 13 | musicnotplaying: false, 14 | musicplaying: false, 15 | }, 16 | /** 17 | * @param {{ client: import("../../../structures/Client"), message: import("discord.js").Message }} 18 | */ 19 | run: async ({ client, message, player, guildData }) => { 20 | let toBeEnabled = !guildData.alwaysinvc.enabled; 21 | if (toBeEnabled) { 22 | guildData.alwaysinvc.enabled = true; 23 | guildData.alwaysinvc.textChannel = message.channel.id; 24 | guildData.alwaysinvc.voiceChannel = message.member.voice.channel.id; 25 | guildData.save(); 26 | 27 | if (!player) { 28 | const a = client.manager.create({ 29 | guild: message.guildId, 30 | textChannel: message.channelId, 31 | voiceChannel: message.member?.voice.channelId, 32 | selfDeafen: true, 33 | volume: 100, 34 | }); 35 | if (a.state !== "CONNECTED") a.connect(); 36 | } 37 | } else { 38 | guildData.alwaysinvc.enabled = false; 39 | guildData.alwaysinvc.textChannel = null; 40 | guildData.alwaysinvc.voiceChannel = null; 41 | guildData.save(); 42 | 43 | if (player && !player.queue.current) { 44 | setTimeout(() => player.destroy(), 150); 45 | } 46 | } 47 | return message.channel.send({ 48 | embeds: [ 49 | new EmbedBuilder() 50 | .setColor("Blue") 51 | .setDescription( 52 | `24/7 mode has been ${ 53 | toBeEnabled ? "**enabled**" : "**disabled**" 54 | }.` 55 | ), 56 | ], 57 | }); 58 | }, 59 | }; 60 | -------------------------------------------------------------------------------- /src/commands/Message/Music/skip.js: -------------------------------------------------------------------------------- 1 | const { ApplicationCommandOptionType, EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "skip", 5 | aliases: ["s", "next"], 6 | description: "Skips the current song or the provided number of songs", 7 | usage: "[skip-to]", 8 | settings: { 9 | ownerOnly: false, 10 | inVoiceChannel: true, 11 | sameVoiceChannel: true, 12 | musicnotplaying: true, 13 | musicplaying: true, 14 | }, 15 | options: [ 16 | { 17 | name: "position", 18 | description: "Enter the position to where you want to skip to", 19 | type: ApplicationCommandOptionType.Integer, 20 | required: false, 21 | }, 22 | ], 23 | /** 24 | * @param {{ client: import("../../structures/Client"), message: import("discord.js").Message}} 25 | */ 26 | run: async ({ client, message, player }) => { 27 | 28 | if (!player.queue.length) { 29 | return message.channel.send({ 30 | embeds: [ 31 | new EmbedBuilder() 32 | .setColor("Red") 33 | .setDescription(`There is no other song in the queue.`), 34 | ], 35 | }); 36 | } 37 | let skipTo = message.args[0]; 38 | if (!skipTo) { 39 | player.stop(); 40 | 41 | return message.channel.send({ 42 | embeds: [ 43 | new EmbedBuilder() 44 | .setColor("Blue") 45 | .setDescription(`Successfully **skipped** the current song.`), 46 | ], 47 | }); 48 | } 49 | skipTo = parseInt(skipTo); 50 | if (isNaN(skipTo) || skipTo <= 0 || skipTo > player.queue.length) { 51 | return message.channel.send({ 52 | embeds: [ 53 | new EmbedBuilder() 54 | .setColor("Red") 55 | .setDescription(`Enter the number between the total amount of songs queued.`), 56 | ], 57 | }); 58 | } 59 | player.stop(skipTo); 60 | 61 | return message.channel.send({ 62 | embeds: [ 63 | new EmbedBuilder() 64 | .setColor("Blue") 65 | .setDescription(`Successfully **skipped** to position you mentioned.`), 66 | ], 67 | }); 68 | }, 69 | }; 70 | -------------------------------------------------------------------------------- /src/commands/Slash/Music/volume.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, ApplicationCommandOptionType } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "volume", 5 | description: "Increase or decrease the songs volume", 6 | usage: "[volume]", 7 | settings: { 8 | ownerOnly: false, 9 | inVoiceChannel: true, 10 | sameVoiceChannel: true, 11 | musicnotplaying: true, 12 | musicplaying: true, 13 | }, 14 | options: [ 15 | { 16 | name: "volume", 17 | description: "Enter the volume amount to set", 18 | type: ApplicationCommandOptionType.Integer, 19 | required: false, 20 | }, 21 | ], 22 | /** 23 | * @param {{ client: import("../../../structures/Client"), interaction: import("discord.js").CommandInteraction }} 24 | */ 25 | run: async (client, interaction, player) => { 26 | if (!interaction.options.getInteger("volume")) { 27 | return interaction.editReply({ 28 | embeds: [ 29 | new EmbedBuilder() 30 | .setColor("Blue") 31 | .setDescription(`The current volume is **${player.volume}%**`), 32 | ], 33 | }); 34 | } 35 | 36 | let volume = interaction.options.getInteger("volume"); 37 | if (isNaN(volume) || volume < 0 || volume > 100) { 38 | return interaction.editReply({ 39 | embeds: [ 40 | new EmbedBuilder() 41 | .setColor("Red") 42 | .setDescription(`Enter a volume amount between \`0 - 100\`.`), 43 | ], 44 | }); 45 | } 46 | if (player.volume === volume) { 47 | return interaction.editReply({ 48 | embeds: [ 49 | new EmbedBuilder() 50 | .setColor("Red") 51 | .setDescription(`Volume is already set to **${volume}%**`), 52 | ], 53 | }); 54 | } 55 | player.setVolume(volume); 56 | 57 | return interaction.editReply({ 58 | embeds: [ 59 | new EmbedBuilder() 60 | .setColor("Blue") 61 | .setDescription( 62 | `Successfully changed the **volume** to **${player.volume}%**` 63 | ), 64 | ], 65 | }); 66 | }, 67 | }; 68 | -------------------------------------------------------------------------------- /src/commands/Message/Music/loop.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "loop", 5 | aliases: ["l", "repeat"], 6 | permission: "", 7 | description: "Loops the current song or queue", 8 | usage: "", 9 | settings: { 10 | ownerOnly: false, 11 | inVoiceChannel: true, 12 | sameVoiceChannel: true, 13 | musicnotplaying: true, 14 | musicplaying: true, 15 | }, 16 | /** 17 | * @param {{ client: import("../../structures/Client"), message: import("discord.js").Message }} 18 | */ 19 | run: async ({ client, message, player }) => { 20 | const mode = message.args[0]?.toLowerCase(); 21 | 22 | switch (mode) { 23 | case "song": { 24 | player.trackRepeat = !player.trackRepeat; 25 | const status = player.trackRepeat ? "enabled" : "disabled"; 26 | return message.channel.send({ 27 | embeds: [ 28 | new EmbedBuilder() 29 | .setColor("Blue") 30 | .setDescription(`Current song loop has been ${status}.`) 31 | ], 32 | }); 33 | } 34 | case "queue": { 35 | player.queueRepeat = !player.queueRepeat; 36 | const status = player.queueRepeat ? "enabled" : "disabled"; 37 | return message.channel.send({ 38 | embeds: [ 39 | new EmbedBuilder() 40 | .setColor("Blue") 41 | .setDescription(`Queue loop has been ${status}.`) 42 | ], 43 | }); 44 | } 45 | case "off": { 46 | player.trackRepeat = false; 47 | player.queueRepeat = false; 48 | return message.channel.send({ 49 | embeds: [ 50 | new EmbedBuilder() 51 | .setColor("Blue") 52 | .setDescription(`Looping has been disabled.`) 53 | ], 54 | }); 55 | } 56 | default: { 57 | return message.channel.send({ 58 | embeds: [ 59 | new EmbedBuilder() 60 | .setColor("Red") 61 | .setDescription(`Please use the command again and choose one of the following options: \`song\`, \`queue\`, or \`off\`.`) 62 | ], 63 | }); 64 | } 65 | } 66 | }, 67 | }; 68 | -------------------------------------------------------------------------------- /src/commands/Message/Information/help.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "help", 5 | aliases: ["h"], 6 | description: "Get the bot's help menu.", 7 | usage: "", 8 | settings: { 9 | ownerOnly: false, 10 | inVoiceChannel: false, 11 | sameVoiceChannel: false, 12 | musicnotplaying: false, 13 | musicplaying: false, 14 | }, 15 | /** 16 | * @param {{ client: import("../../../structures/Client"), message: import("discord.js").Message }} 17 | */ 18 | run: async ({ client, message }) => { 19 | const embed = new EmbedBuilder() 20 | .setTitle(` ${client.user.displayName} Help Menu`) 21 | .setThumbnail(client.user.displayAvatarURL()) 22 | .setColor("Blue") 23 | .setDescription( 24 | "Bringing you high-quality music and endless entertainment with our diverse range of free, easy-to-use commands." 25 | ); 26 | 27 | const configCommands = message.client.commands 28 | .filter((command) => command.category === "Config") 29 | .map((command) => `\`${command.name}\``); 30 | embed.addFields({ 31 | name: "Config Commands", 32 | value: `${configCommands.join(", ")}`, 33 | }); 34 | 35 | const musicCommands = message.client.commands 36 | .filter((command) => command.category === "Music") 37 | .map((command) => `\`${command.name}\``); 38 | embed.addFields({ 39 | name: "Music Commands", 40 | value: `${musicCommands.join(", ")}`, 41 | }); 42 | 43 | const infoCommands = message.client.commands 44 | .filter((command) => command.category === "Information") 45 | .map((command) => `\`${command.name}\``); 46 | embed.addFields({ 47 | name: "Information Commands", 48 | value: `${infoCommands.join(", ")}`, 49 | }); 50 | 51 | const playlistCommands = message.client.commands 52 | .filter((command) => command.category === "Playlist") 53 | .map((command) => `\`${command.name}\``); 54 | embed.addFields({ 55 | name: "Playlist Commands", 56 | value: `${playlistCommands.join(", ")}`, 57 | }); 58 | 59 | 60 | 61 | message.channel.send({ embeds: [embed] }); 62 | }, 63 | }; 64 | -------------------------------------------------------------------------------- /src/commands/Message/Music/seek.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "seek", 5 | description: "Seeks to the specified time in the current song", 6 | usage: "