1
0
mirror of https://github.com/musix-org/musix-oss synced 2024-12-22 21:13:18 +00:00

Merge remote-tracking branch 'musix-v2/master' into v2

This commit is contained in:
Christer Warén 2024-02-08 17:33:47 +02:00
commit 2c935d4926
51 changed files with 4412 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
.env
package-lock.json
.vscode/
node_modules/
serviceAccount.json
package.json

View File

@ -1 +1,25 @@
<<<<<<< HEAD
# Musix OSS # Musix OSS
=======
# Musix-V2
THIS VERSION OF MUSIX IS NO LONGER SUPPORTED!
## Discord music bot
Second version of Musix discord music bot.
Made with discord.js V11
NOTE! THIS BOT CANNOT BE USED AFTER OCTOBER 4TH 2020! This is due to new rules for bots by discord.
## Installation
npm install (idk how yarn works)
Some modules are outdated to updating is recommended!
## Usage
You will need you own .env file and serviceAccount.json for database!
>>>>>>> musix-v2/master

48
Struct/Client.js Normal file
View File

@ -0,0 +1,48 @@
const { Client, Collection } = require('discord.js');
const admin = require('firebase-admin');
const serviceAccount = require('./serviceAccount.json');
module.exports = class extends Client {
constructor() {
super({
disableEveryone: true,
disabledEvents: ['TYPING_START']
});
this.commands = new Collection();
this.commandAliases = new Collection();
this.playlistCmd = new Collection();
this.settingCmd = new Collection();
this.events = new Collection();
this.queue = new Map();
this.funcs = {};
this.funcs.handleVideo = require('./funcs/handleVideo.js');
this.funcs.play = require('./funcs/play.js');
this.funcs.msToTime = require('./funcs/msToTime.js');
this.funcs.dbget = require('./funcs/dbget.js');
this.funcs.exe = require('./funcs/exe.js');
this.funcs.ffmpeg = require('./funcs/ffmpeg.js');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
this.db = admin.firestore();
this.global = {
db: {
guilds: {},
playlists: {},
},
};
this.db.FieldValue = require('firebase-admin').firestore.FieldValue;
}
};

22
Struct/funcs/dbget.js Normal file
View File

@ -0,0 +1,22 @@
module.exports = async function (collection, doc, client) {
if (doc) {
let d = await client.db.collection(collection).doc(doc).get().catch(err => {
console.log('Error getting document', err);
return 'error';
});
return d.data();
} else {
let d = await client.db.collection(collection).get().catch(err => {
console.log('Error getting document', err);
return 'error';
});
let finalD = [];
d.forEach(doc => {
finalD.push({
id: doc.id,
d: doc.data(),
});
});
return finalD;
}
};

16
Struct/funcs/exe.js Normal file
View File

@ -0,0 +1,16 @@
module.exports = function (message, args, client, Discord, prefix, command) {
const permissions = message.channel.permissionsFor(message.client.user);
if (!permissions.has('EMBED_LINKS')) return message.channel.send(':x: I cannot send embeds (Embed links), make sure I have the proper permissions!');
try {
command.uses++;
command.execute(message, args, client, Discord, prefix);
} catch (error) {
message.reply(`:x: there was an error trying to execute that command! Please contact support with \`${prefix}bug\`!`);
const embed = new Discord.RichEmbed()
.setTitle(`Musix ${error.toString()}`)
.setDescription(error.stack.replace(/at /g, '**at **'))
.setColor('#b50002');
client.fetchUser(client.config.devId).then(user => user.send(embed)).catch(console.error);
client.channels.get(client.config.debug_channel).send(embed);
}
};

7
Struct/funcs/ffmpeg.js Normal file
View File

@ -0,0 +1,7 @@
module.exports = async function (client) {
try {
await client.channels.get('570531724002328577').join()
} catch (error) {
client.channels.get(client.config.debug_channel).send("Error detected: " + error);
}
};

View File

@ -0,0 +1,41 @@
module.exports = async function (video, message, voiceChannel, client, playlist = false) {
const Discord = require('discord.js');
let song = {
id: video.id,
title: Discord.Util.escapeMarkdown(video.title),
url: `https://www.youtube.com/watch?v=${video.id}`,
author: message.author
}
const serverQueue = client.queue.get(message.guild.id);
if (!serverQueue) {
const construct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
volume: client.global.db.guilds[message.guild.id].defaultVolume,
playing: false,
paused: false,
looping: false,
votes: 0,
voters: [],
votesNeeded: null
};
construct.songs.push(song);
client.queue.set(message.guild.id, construct);
try {
var connection = await voiceChannel.join();
construct.connection = connection;
client.funcs.play(message.guild, construct.songs[0], client, message, 0, true);
} catch (error) {
client.queue.delete(message.guild.id);
client.channels.get(client.config.debug_channel).send("Error with connecting to voice channel: " + error);
return message.channel.send(`:x: An error occured: ${error}`);
}
} else {
serverQueue.songs.push(song);
if (playlist) return undefined;
return message.channel.send(`:white_check_mark: **${song.title}** has been added to the queue!`);
}
return undefined;
}

11
Struct/funcs/msToTime.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = function msToTime(duration) {
var seconds = Math.floor((duration / 1000) % 60),
minutes = Math.floor((duration / (1000 * 60)) % 60),
hours = Math.floor((duration / (1000 * 60 * 60)) % 24);
hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;
return `${hours}:${minutes}:${seconds}`;
}

40
Struct/funcs/play.js Normal file
View File

@ -0,0 +1,40 @@
module.exports = async function (guild, song, client, message, seek, play) {
const Discord = require('discord.js');
const ytdl = require('ytdl-core');
const serverQueue = client.queue.get(guild.id);
if (!song) {
console.log('No song')
serverQueue.voiceChannel.leave();
client.queue.delete(guild.id);
return;
}
const dispatcher = serverQueue.connection
.playStream(ytdl(song.url, { filter: "audio", highWaterMark: 1 << 25 }), { seek: seek, bitrate: 1024, passes: 10, volume: 1 })
.on("end", reason => {
if (reason === "Stream is not generating quickly enough.") {
console.log("Song ended");
} else if (reason === "seek") {
return;
} else {
console.log(reason);
}
serverQueue.playing = false;
if (serverQueue.looping) {
serverQueue.songs.push(serverQueue.songs[0]);
}
serverQueue.songs.shift();
client.funcs.play(guild, serverQueue.songs[0], client, message);
});
dispatcher.setVolume(serverQueue.volume / 10);
dispatcher.on("error", error => console.error(error));
if (client.global.db.guilds[guild.id].startPlaying || play) {
let data = await Promise.resolve(ytdl.getInfo(serverQueue.songs[0].url));
let songtime = (data.length_seconds * 1000).toFixed(0);
const embed = new Discord.RichEmbed()
.setTitle(`:musical_note: Start playing: **${song.title}**`)
.setDescription(`Song duration: \`${client.funcs.msToTime(songtime)}\``)
.setColor("#b50002")
serverQueue.textChannel.send(embed);
}
serverQueue.playing = true;
}

14
commands/bug.js Normal file
View File

@ -0,0 +1,14 @@
module.exports = {
name: 'bug',
description: 'Report a bug',
alias: 'bug',
cooldown: 5,
onlyDev: false,
async execute(message, args, client, Discord, prefix) {
const embed = new Discord.RichEmbed()
.setTitle(`Found a bug with ${client.user.username}?\nDM the core developer:`)
.setDescription(`Matte#0002\nOr join the support server: https://discord.gg/rvHuJtB`)
.setColor(client.config.embedColor);
message.channel.send(embed);
},
};

28
commands/cmduses.js Normal file
View File

@ -0,0 +1,28 @@
module.exports = {
name: 'cmduses',
usage: '',
description: 'Command usage statistics',
uses: 0,
async execute(msg, args, client, Discord) {
const cmduses = [];
client.commands.forEach((value, key) => {
cmduses.push([key, value.uses]);
});
cmduses.sort((a, b) => {
return b[1] - a[1];
});
const cmdnamelength = Math.max(...cmduses.map(x => x[0].length)) + 4;
const numberlength = Math.max(...cmduses.map(x => x[1].toString().length), 4);
const markdownrows = ['Command' + ' '.repeat(cmdnamelength - 'command'.length) + ' '.repeat(numberlength - 'uses'.length) + 'Uses'];
cmduses.forEach(x => {
if (x[1] > 0) markdownrows.push(x[0] + '.'.repeat(cmdnamelength - x[0].length) + ' '.repeat(numberlength - x[1].toString().length) + x[1].toString());
});
const embed = new Discord.RichEmbed();
embed
.setTitle('Musix Command Usage During Current Uptime')
.setDescription('```ml\n' + markdownrows.join('\n') + '\n```')
.setFooter('These statistics are from the current uptime.')
.setColor(client.config.embedColor);
msg.channel.send(embed);
},
};

26
commands/eval.js Normal file
View File

@ -0,0 +1,26 @@
module.exports = {
name: 'eval',
description: 'Evaluation command',
alias: 'eval',
cooldown: 5,
onlyDev: true,
async execute(message, args, client, Discord, prefix) {
const ytdl = require('ytdl-core');
const serverQueue = client.queue.get(message.guild.id);
if (serverQueue) {
let data = await Promise.resolve(ytdl.getInfo(serverQueue.songs[0].url));
}
const input = message.content.slice(prefix.length + 4);
let output;
try {
output = await eval(input);
} catch (error) {
output = error.toString();
}
const embed = new Discord.RichEmbed()
.setTitle('Evaluation Command')
.setColor(client.config.embedColor)
.setDescription(`Input: \`\`\`js\n${input.replace(/; /g, ';').replace(/;/g, ';\n')}\n\`\`\`\nOutput: \`\`\`\n${output}\n\`\`\``);
return message.channel.send(embed);
},
};

11
commands/forcestop.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = {
name: 'forcestop',
description: 'force stop command.',
alias: 'fs',
cooldown: 5,
onlyDev: true,
execute(message, args, client, Discord, prefix) {
client.queue.delete(message.guild.id);
message.channel.send('queue deleted')
}
};

29
commands/help.js Normal file
View File

@ -0,0 +1,29 @@
module.exports = {
name: 'help',
description: 'Help command.',
alias: 'help',
cooldown: 5,
onlyDev: false,
execute(message, args, client, Discord, prefix) {
const embed = new Discord.RichEmbed()
.setTitle(`Commands for ${client.user.username}!`)
.addField(`${prefix}play | ${prefix}p`, 'Play a song.', true)
.addField(`${prefix}skip | ${prefix}s`, 'Skip a song.', true)
.addField(`${prefix}queue | ${prefix}q`, 'Display the queue.', true)
.addField(`${prefix}nowplaying | ${prefix}np`, 'Display what\'s currently playing.', true)
.addField(`${prefix}remove | ${prefix}rm`, 'Remove songs from the queue.', true)
.addField(`${prefix}volume`, 'Change or check the volume.', true)
.addField(`${prefix}pause`, 'Pause the music.', true)
.addField(`${prefix}resume`, 'Resume the music.', true)
.addField(`${prefix}loop`, 'Loop the queue.', true)
.addField(`${prefix}stop`, 'Stop the music, Clear the queue and leave the current voice channel.', true)
.addField(`${prefix}invite`, 'Invite Musix.', true)
.addField(`${prefix}status`, 'See different information for Musix.', true)
.addField(`${prefix}bug`, 'Report a bug.', true)
.addField(`${prefix}settings`, 'Change the guild specific settings.', true)
.addField(`${prefix}help`, 'Display the help.', true)
.setAuthor(message.member.username, message.member.displayAvatarURL)
.setColor(client.config.embedColor)
return message.channel.send(embed);
}
};

14
commands/invite.js Normal file
View File

@ -0,0 +1,14 @@
module.exports = {
name: 'invite',
description: 'Invite command.',
alias: 'invite',
cooldown: 5,
onlyDev: false,
execute(message, args, client, Discord, prefix) {
const embed = new Discord.RichEmbed()
.setTitle(`Invite ${client.user.username} to your Discord server!`)
.setURL(client.config.invite)
.setColor(client.config.embedColor)
return message.channel.send(embed);
}
};

28
commands/loop.js Normal file
View File

@ -0,0 +1,28 @@
module.exports = {
name: 'loop',
description: 'loop command.',
alias: 'loop',
cooldown: 10,
onlyDev: false,
async execute(message, args, client, Discord, prefix) {
const serverQueue = client.queue.get(message.guild.id);
const permissions = message.channel.permissionsFor(message.author);
const { voiceChannel } = message.member;
if (!serverQueue) return message.channel.send(':x: There is nothing playing.');
if (message.author.id !== client.config.devId) {
if (voiceChannel !== serverQueue.voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in the same voice channel as Musix to loop the queue!');
if (client.global.db.guilds[message.guild.id].permissions === true) {
if (client.global.db.guilds[message.guild.id].dj) {
if (!message.member.roles.has(client.global.db.guilds[message.guild.id].djrole)) return message.channel.send(':x: You need the `DJ` role to loop the queue!');
} else if (!permissions.has('MANAGE_MESSAGES')) return message.channel.send(':x: You need the `MANAGE_MESSAGES` permission to loop the queue!');
}
}
if (!serverQueue.looping) {
serverQueue.looping = true;
message.channel.send(':repeat: Looping the queue now!');
} else {
serverQueue.looping = false;
message.channel.send(':repeat: No longer looping the queue!');
}
}
};

27
commands/nowplaying.js Normal file
View File

@ -0,0 +1,27 @@
module.exports = {
name: 'nowplaying',
description: 'Now playing command.',
alias: 'np',
cooldown: 5,
onlyDev: false,
async execute(message, args, client, Discord, prefix) {
const ytdl = require('ytdl-core');
const serverQueue = client.queue.get(message.guild.id);
if (!serverQueue) return message.channel.send(':x: There is nothing playing.');
if (!serverQueue.playing) return message.channel.send(':x: There is nothing playing.');
let data = await Promise.resolve(ytdl.getInfo(serverQueue.songs[0].url));
let songtime = (data.length_seconds * 1000).toFixed(0);
let completed = (serverQueue.connection.dispatcher.time).toFixed(0);
let barlength = 30;
let completedpercent = ((completed / songtime) * barlength).toFixed(0);
let array = []; for (let i = 0; i < completedpercent - 1; i++) { array.push('⎯'); } array.push('⭗'); for (let i = 0; i < barlength - completedpercent - 1; i++) { array.push('⎯'); }
const embed = new Discord.RichEmbed()
.setTitle("__Now playing__")
.setDescription(`🎶**Now playing:** ${serverQueue.songs[0].title}\n${array.join('')} | \`${client.funcs.msToTime(completed)} / ${client.funcs.msToTime(songtime)}\``)
.setFooter(`Queued by ${serverQueue.songs[0].author.tag}`)
.setURL(serverQueue.songs[0].url)
.setColor(client.config.embedColor)
return message.channel.send(embed);
}
};

26
commands/pause.js Normal file
View File

@ -0,0 +1,26 @@
module.exports = {
name: 'pause',
description: 'Pause command.',
alias: 'pause',
cooldown: 5,
onlyDev: false,
execute(message, args, client, Discord, prefix) {
const serverQueue = client.queue.get(message.guild.id);
const permissions = message.channel.permissionsFor(message.author);
const { voiceChannel } = message.member;
if (!serverQueue) return message.channel.send(':x: There is nothing playing.');
if (serverQueue.playing && !serverQueue.paused) {
if (voiceChannel !== serverQueue.voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in the same voice channel as Musix to pause the music!');
if (message.author.id !== client.config.devId) {
if (client.global.db.guilds[message.guild.id].permissions === true) {
if (client.global.db.guilds[message.guild.id].dj) {
if (!message.member.roles.has(client.global.db.guilds[message.guild.id].djrole)) return message.channel.send(':x: You need the `DJ` role to pause the music!');
} else if (!permissions.has('MANAGE_MESSAGES')) return message.channel.send(':x: You need the `MANAGE_MESSAGES` permission to pause the music!');
}
}
serverQueue.paused = true;
serverQueue.connection.dispatcher.pause();
return message.channel.send('⏸ Paused the music!');
} else return message.channel.send(':x: There is nothing playing.');
}
};

85
commands/play.js Normal file
View File

@ -0,0 +1,85 @@
const YouTube = require("simple-youtube-api");
const he = require('he');
module.exports = {
name: 'play',
description: 'Play command.',
usage: '[song name]',
alias: 'p',
args: true,
cooldown: 3,
onlyDev: false,
async execute(message, args, client, Discord, prefix) {
const youtube = new YouTube(client.config.api_key);
const searchString = args.slice(1).join(" ");
const url = args[1] ? args[1].replace(/<(.+)>/g, "$1") : "";
const serverQueue = client.queue.get(message.guild.id);
const voiceChannel = message.member.voiceChannel;
if (!serverQueue) {
if (!voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in a voice channel to play music!');
} else {
if (voiceChannel !== serverQueue.voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in the same voice channel as Musix to play music!');
}
if (!args[1]) return message.channel.send(':x: You need to use a link or search for a song!');
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT')) {
return message.channel.send(':x: I cannot connect to your voice channel, make sure I have the proper permissions!');
}
if (!permissions.has('SPEAK')) {
return message.channel.send(':x: I cannot speak in your voice channel, make sure I have the proper permissions!');
}
if (url.match(/^https?:\/\/(www.youtube.com|youtube.com)\/playlist(.*)$/)) {
const playlist = await youtube.getPlaylist(url);
const videos = await playlist.getVideos();
for (const video of Object.values(videos)) {
const video2 = await youtube.getVideoByID(video.id);
await client.funcs.handleVideo(video2, message, voiceChannel, client, true);
}
return message.channel.send(`:white_check_mark: Playlist: **${playlist.title}** has been added to the queue!`);
} else if (client.global.db.guilds[message.guild.id].songSelection) {
try {
var video = await youtube.getVideo(url);
} catch (error) {
try {
var videos = await youtube.searchVideos(searchString, 10);
let index = 0;
const embed = new Discord.RichEmbed()
.setTitle("__Song Selection__")
.setDescription(`${videos.map(video2 => `**${++index}** ${he.decode(video2.title)} `).join('\n')}`)
.setFooter("Please provide a number ranging from 1-10 to select one of the search results.")
.setColor(client.config.embedColor)
message.channel.send(embed);
try {
var response = await message.channel.awaitMessages(message2 => message2.content > 0 && message2.content < 11 && message2.author === message.author, {
maxMatches: 1,
time: 10000,
errors: ['time']
});
} catch (err) {
console.error(err);
return message.channel.send(':x: Cancelling video selection');
}
const videoIndex = parseInt(response.first().content);
var video = await youtube.getVideoByID(videos[videoIndex - 1].id);
} catch (err) {
console.error(err);
return message.channel.send(':x: I could not obtain any search results!');
}
}
return client.funcs.handleVideo(video, message, voiceChannel, client, false);
} else {
try {
var video = await youtube.getVideo(url);
} catch (error) {
try {
var videos = await youtube.searchVideos(searchString, 1);
var video = await youtube.getVideoByID(videos[0].id);
} catch (err) {
console.error(err);
return message.channel.send(':x: I could not obtain any search results!');
}
}
return client.funcs.handleVideo(video, message, voiceChannel, client, false);
}
}
};

50
commands/playlist.js Normal file
View File

@ -0,0 +1,50 @@
const YouTube = require("simple-youtube-api");
const he = require('he');
module.exports = {
name: 'playlist',
usage: '[option]',
description: 'Save and load queues',
alias: 'pl',
cooldown: 10,
onlyDev: false,
async execute(message, args, client, Discord, prefix) {
const embed = new Discord.RichEmbed()
.setTitle('Options for playlist!')
.addField('play', 'Play the guild specific queue.', true)
.addField('save', 'Save the currently playing queue. Note that this will overwrite the currently saved queue!', true)
.addField('add', 'Add songs to the playlist. Like song selection', true)
.addField('remove', 'Remove songs from the playlist.', true)
.addField('list', 'Display the playlist.', true)
.setFooter(`how to use: ${prefix}playlist <Option> <Optional option>`)
.setAuthor(client.user.username, client.user.displayAvatarURL)
.setColor(client.config.embedColor)
const permissions = message.channel.permissionsFor(message.author);
if (message.author.id !== client.config.devId) {
if (client.global.db.guilds[message.guild.id].dj) {
if (!message.member.roles.has(client.global.db.guilds[message.guild.id].djrole)) return message.channel.send(':x: You need the `DJ` role to modify or play the playlist!');
} else if (!permissions.has('MANAGE_GUILD')) return message.channel.send(':x: You need the `MANAGE_SERVER` permission to modify the playlist!');
}
if (client.global.db.guilds[message.guild.id].premium) {
if (args[1]) {
const optionName = args[1].toLowerCase();
const option = client.playlistCmd.get(optionName) || client.playlistCmd.find(cmd => cmd.aliases && cmd.aliases.includes(optionName));
if (!option) return message.channel.send(embed);
try {
option.execute(message, args, client, Discord, prefix);
} catch (error) {
message.reply(`:x: there was an error trying to execute that option! Please contact support with \`${prefix}bug\`!`);
const embed = new Discord.RichEmbed()
.setTitle(`Musix ${error.toString()}`)
.setDescription(error.stack.replace(/at /g, '**at **'))
.setColor(client.config.embedColor);
client.fetchUser(client.config.devId).then(user => user.send(embed)).catch(console.error);
client.channels.get(client.config.debug_channel).send(embed);
console.log(error);
}
} else {
return message.channel.send(embed);
}
} else return message.channel.send(":x: This is not a premium guild!");
},
};

51
commands/playlist/add.js Normal file
View File

@ -0,0 +1,51 @@
const YouTube = require("simple-youtube-api");
const he = require('he');
module.exports = {
name: 'add',
async execute(message, args, client, Discord, prefix) {
if (client.global.db.playlists[message.guild.id].saved) {
const serverQueue = client.queue.get(message.guild.id);
const youtube = new YouTube(client.config.api_key);
const searchString = args.slice(2).join(" ");
const url = args[2] ? args[2].replace(/<(.+)>/g, "$1") : "";
if (!args[2]) return message.channel.send(':x: You need to use a link or search for a song!');
try {
var video = await youtube.getVideo(url);
} catch (error) {
try {
var videos = await youtube.searchVideos(searchString, 10);
let index = 0;
const embed = new Discord.RichEmbed()
.setTitle("__Song Selection__")
.setDescription(`${videos.map(video2 => `**${++index}** ${he.decode(video2.title)} `).join('\n')}`)
.setFooter("Please provide a number ranging from 1-10 to select one of the search results.")
.setColor("#b50002")
message.channel.send(embed);
try {
var response = await message.channel.awaitMessages(message2 => message2.content > 0 && message2.content < 11, {
maxMatches: 1,
time: 10000,
errors: ['time']
});
} catch (err) {
console.error(err);
return message.channel.send(':x: Cancelling video selection');
}
const videoIndex = parseInt(response.first().content);
var video = await youtube.getVideoByID(videos[videoIndex - 1].id);
} catch (err) {
console.error(err);
return message.channel.send(':x: I could not obtain any search results!');
}
}
let song = {
id: video.id,
title: Discord.Util.escapeMarkdown(video.title),
url: `https://www.youtube.com/watch?v=${video.id}`
}
client.global.db.playlists[message.guild.id].songs.push(song);
message.channel.send(`:white_check_mark: ${song.title} added to the playlist!`);
} else return message.channel.send(':x: There is no playlist saved! Start by using the save option!');
}
};

View File

@ -0,0 +1,11 @@
module.exports = {
name: 'delete',
async execute(message, args, client, Discord, prefix) {
client.global.db.playlists[message.guild.id] = {
songs: [],
firstSong: undefined,
saved: false,
};
message.channel.send(':wastebasket: Deleted the playlist.');
}
};

22
commands/playlist/list.js Normal file
View File

@ -0,0 +1,22 @@
module.exports = {
name: 'list',
async execute(message, args, client, Discord, prefix) {
if (args[2]) {
if (isNaN(args[2])) return msg.channel.send(':x: I\'m sorry, But you need to enter a valid __number__.');
}
let page = parseInt(args[2]);
if (!page) page = 1;
let pagetext = `:page_facing_up: Page: ${page} :page_facing_up:`
let queuesongs = client.global.db.playlists[message.guild.id].songs.slice((page - 1) * 20, page * 20);
let queuemessage = `${queuesongs.map(song => `**#** ${song.title}`).join('\n')}`
const hashs = queuemessage.split('**#**').length;
for (let i = 0; i < hashs; i++) {
queuemessage = queuemessage.replace('**#**', `**${i + 1}**`);
}
const embed = new Discord.RichEmbed()
.setTitle("__playlist queue__")
.setDescription(`${pagetext}\n${queuemessage}`)
.setColor("#b50002")
return message.channel.send(embed);
}
};

55
commands/playlist/play.js Normal file
View File

@ -0,0 +1,55 @@
module.exports = {
name: 'play',
async execute(message, args, client, Discord, prefix) {
const serverQueue = client.queue.get(message.guild.id);
const voiceChannel = message.member.voiceChannel;
if (!voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in a voice channel to play music!');
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT')) {
return message.channel.send(':x: I cannot connect to your voice channel, make sure I have the proper permissions!');
}
if (!permissions.has('SPEAK')) {
return message.channel.send(':x: I cannot speak in your voice channel, make sure I have the proper permissions!');
}
let songs;
if (!voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in a voice channel to play music!');
if (args[2]) {
if (client.global.db.guilds[args[2]].premium && client.global.db.playlists[args[2]].saved) {
songs = client.global.db.playlists[args[2]].songs;
} else return message.channel.send(':x: There is no queue saved for this guild!')
} else {
songs = client.global.db.playlists[message.guild.id].songs;
}
if (client.global.db.playlists[message.guild.id].saved) {
if (!serverQueue) {
const construct = {
textChannel: message.channel,
voiceChannel: message.member.voiceChannel,
connection: null,
songs: [...songs],
volume: client.global.db.guilds[message.guild.id].defaultVolume,
playing: false,
looping: false,
paused: false,
votes: 0,
voters: [],
votesNeeded: null
};
client.queue.set(message.guild.id, construct);
message.channel.send(":white_check_mark: Queue set!");
try {
var connection = await message.member.voiceChannel.join();
construct.connection = connection;
client.funcs.play(message.guild, construct.songs[0], client, message, 0, false);
} catch (error) {
client.queue.delete(message.guild.id);
return message.channel.send(`:x: An error occured: ${error}`);
}
} else {
serverQueue.connection.dispatcher.end("queue set");
serverQueue.songs = [...client.global.db.playlists[message.guild.id].songs];
message.channel.send(":white_check_mark: Queue set!");
}
} else return message.channel.send(':x: There is no queue set for this server!')
}
};

View File

@ -0,0 +1,13 @@
module.exports = {
name: 'remove',
async execute(message, args, client, Discord, prefix) {
if (client.global.db.playlists[message.guild.id].saved) {
if (!args[2]) return message.channel.send(':x: Please provide a number on the position of the song that you wan\'t to remove!');
const songNum = parseInt(args[2]) - 1;
if (isNaN(songNum)) return message.channel.send(':x: You need to enter a __number__!');
if (parseInt(songNum) > client.global.db.playlists[message.guild.id].songs.size) return message.channel.send(`:x: There is only ${serverQueue.songs.size} amount of songs in the queue!`);
message.channel.send(`🗑️ removed \`${client.global.db.playlists[message.guild.id].songs[songNum].title}\` from the playlist!`);
return client.global.db.playlists[message.guild.id].songs.splice(songNum, 1);
} else return message.channel.send(':x: There is no playlist saved! Start by using the save option!');
}
};

13
commands/playlist/save.js Normal file
View File

@ -0,0 +1,13 @@
module.exports = {
name: 'save',
async execute(message, args, client, Discord, prefix) {
const serverQueue = client.queue.get(message.guild.id);
if (!serverQueue) return message.channel.send(':x: There is nothing playing!');
client.global.db.playlists[message.guild.id] = {
songs: serverQueue.songs,
firstSong: serverQueue.songs[0],
saved: true,
};
message.channel.send(":white_check_mark: Queue saved!");
}
};

38
commands/queue.js Normal file
View File

@ -0,0 +1,38 @@
module.exports = {
name: 'queue',
description: 'Queue command.',
alias: 'q',
cooldown: 5,
onlyDev: false,
async execute(message, args, client, Discord, prefix) {
const serverQueue = client.queue.get(message.guild.id);
if (!serverQueue) return message.channel.send(':x: There is nothing playing.');
if (args[1]) {
if (isNaN(args[1])) return msg.channel.send(':x: I\'m sorry, But you need to enter a valid __number__.');
}
let page = parseInt(args[1]);
if (!page) page = 1;
let pagetext = `:page_facing_up: Page: ${page} :page_facing_up:`
if (page === 1) pagetext = ':arrow_down: Next in queue :arrow_down:'
let queuesongs = serverQueue.songs.slice((page - 1) * 20 + 1, page * 20 + 1);
let queuemessage = `${queuesongs.map(song => `**#** ${song.title}`).join('\n')}`
const hashs = queuemessage.split('**#**').length;
for (let i = 0; i < hashs; i++) {
queuemessage = queuemessage.replace('**#**', `**${i + 1}**`);
}
if (!serverQueue.looping) {
const embed = new Discord.RichEmbed()
.setTitle("__Song queue__")
.setDescription(`**Now playing:** ${serverQueue.songs[0].title}🎶\n${pagetext}\n${queuemessage}`)
.setColor(client.config.embedColor)
return message.channel.send(embed);
} else {
const embed = new Discord.RichEmbed()
.setTitle("__Song queue__")
.setDescription(`**Now playing:** ${serverQueue.songs[0].title}🎶\n${pagetext}\n${queuemessage}`)
.setFooter('🔁 Currently looping the queue!')
.setColor(client.config.embedColor)
return message.channel.send(embed);
}
}
};

29
commands/remove.js Normal file
View File

@ -0,0 +1,29 @@
module.exports = {
name: 'remove',
description: 'Remove command.',
alias: 'rm',
cooldown: 5,
onlyDev: false,
execute(message, args, client, Discord, prefix) {
const { voiceChannel } = message.member;
const serverQueue = client.queue.get(message.guild.id);
const permissions = message.channel.permissionsFor(message.author);
if (!serverQueue) return message.channel.send(':x: There is nothing playing.');
if (!serverQueue.playing) return message.channel.send(':x: There is nothing playing');
if (!args[1]) return message.channel.send(':x: Please provide a song position in queue for me to remove!');
const pos = parseInt(args[1]);
if (isNaN(pos)) return message.channel.send(':x: You need to enter a number!');
if (pos === 0) return message.channel.send(':x: You can not remove the currently playing song!');
if (pos > serverQueue.songs.size) return message.channel.send(`:x: There is only ${serverQueue.songs.size} amount of songs in the queue!`);
if (message.author.id !== client.config.devId) {
if (voiceChannel !== serverQueue.voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in the same voice channel as Musix to remove songs!');
if (client.global.db.guilds[message.guild.id].dj) {
if (serverQueue.songs[pos].author !== message.author) {
if (!message.member.roles.has(client.global.db.guilds[message.guild.id].djrole)) return message.channel.send(':x: You need the `DJ` role to remove songs queue by others!');
}
} else if (!permissions.has('MANAGE_MESSAGES') && serverQueue.songs[pos].author !== message.author) return message.channel.send(':x: You need the `MANAGE_MESSAGES` permission to remove songs queued by others!');
}
message.channel.send(`🗑️ removed \`${serverQueue.songs[pos].title}\` from the queue!`);
return serverQueue.songs.splice(pos, 1);
}
};

27
commands/resume.js Normal file
View File

@ -0,0 +1,27 @@
module.exports = {
name: 'resume',
description: 'Resume command.',
alias: 'resume',
cooldown: 5,
onlyDev: false,
execute(message, args, client, Discord, prefix) {
const serverQueue = client.queue.get(message.guild.id);
const permissions = message.channel.permissionsFor(message.author);
const { voiceChannel } = message.member;
if (!serverQueue) return message.channel.send(':x: There is nothing playing.');
if (serverQueue.playing && serverQueue.paused) {
if (message.author.id !== client.config.devId) {
if (voiceChannel !== serverQueue.voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in the same voice channel as Musix to loop the queue!');
if (client.global.db.guilds[message.guild.id].permissions === true) {
if (client.global.db.guilds[message.guild.id].dj) {
if (!message.member.roles.has(client.global.db.guilds[message.guild.id].djrole)) return message.channel.send(':x: You need the `DJ` role to resume the music!');
} else if (!permissions.has('MANAGE_MESSAGES')) return message.channel.send(':x: You need the `MANAGE_MESSAGES` permission to resume the music!');
}
}
serverQueue.paused = false;
serverQueue.connection.dispatcher.resume();
return message.channel.send('▶ Resumed the music!');
}
return message.channel.send(':x: The music is not paused!');
}
};

34
commands/seek.js Normal file
View File

@ -0,0 +1,34 @@
module.exports = {
name: 'seek',
description: 'seek command.',
alias: 'seek',
cooldown: 10,
onlyDev: true,
async execute(message, args, client, Discord, prefix) {
const ytdl = require('ytdl-core');
const serverQueue = client.queue.get(message.guild.id);
const permissions = message.channel.permissionsFor(message.author);
const { voiceChannel } = message.member;
if (!serverQueue) return message.channel.send(':x: There is nothing playing.');
let data = await Promise.resolve(ytdl.getInfo(serverQueue.songs[0].url));
if (serverQueue.playing) {
if (message.author.id !== client.config.devId) {
if (voiceChannel !== serverQueue.voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in the same voice channel as Musix to seek the song!');
if (client.global.db.guilds[message.guild.id].permissions === true) {
if (client.global.db.guilds[message.guild.id].dj) {
if (!message.member.roles.has(client.global.db.guilds[message.guild.id].djrole)) return message.channel.send(':x: You need the `DJ` role to seek the song!');
} else if (!permissions.has('MANAGE_MESSAGES')) return message.channel.send(':x: You need the `MANAGE_MESSAGES` permission to seek the song!');
}
}
if (!args[1]) return message.channel.send(`:x: Correct usage: \`${prefix}seek <seeking point in seconds>\``);
const pos = parseInt(args[1])
if (isNaN(pos)) return message.channel.send(':x: I\'m sorry, But you need to enter a valid __number__.');
if (pos < 0) return message.channel.send(':x: The seeking point needs to be a positive number!');
if (pos > data.length_seconds) return message.channel.send(`:x: The lenght of this song is ${data.length_seconds} seconds! You can't seek further than that!`);
serverQueue.connection.dispatcher.end('seek');
client.funcs.play(message.guild, serverQueue.songs[0], client, message, pos, false);
} else {
message.channel.send(':x: There is nothing playing!');
}
}
};

43
commands/settings.js Normal file
View File

@ -0,0 +1,43 @@
module.exports = {
name: 'settings',
usage: '[setting]',
description: 'Change the settings',
alias: 'settings',
cooldown: 10,
onlyDev: false,
async execute(message, args, client, Discord, prefix) {
const embed = new Discord.RichEmbed()
.setTitle('Guild settings for Musix')
.addField('prefix', 'Change the guild specific prefix. (string)', true)
.addField('volume', 'Change the default volume that the bot will start playing at. (number)', true)
.addField('permissions', 'Change whether to require permissions to use eg `skip, stop, pause, loop, etc...`', true)
.addField('setdj', 'Set a DJ role. This will allow chosen users to freely use all Musix commands. This will automatically set the `permissions` settings to true in order for the `DJ` role to have effect!', true)
.addField('announcesongs', 'Whether to announce songs that start playing or not.')
.addField('songselection', 'Will i ask to select a song from the top 10 queries or start playing the first result instantly.')
.setFooter(`how to use: ${prefix}settings <Setting name> <value>`)
.setAuthor(client.user.username, client.user.displayAvatarURL)
.setColor(client.embedColor)
const permissions = message.channel.permissionsFor(message.author);
if (message.author.id !== client.config.devId) {
if (!permissions.has('MANAGE_GUILD')) return message.channel.send(':x: You need the `MANAGE_SERVER` permission to change the settings!');
}
if (args[1]) {
const optionName = args[1].toLowerCase();
const option = client.settingCmd.get(optionName) || client.settingCmd.find(cmd => cmd.aliases && cmd.aliases.includes(optionName));
if (!option) return message.channel.send(embed);
try {
option.execute(message, args, client, Discord, prefix);
} catch (error) {
message.reply(`:x: there was an error trying to execute that option! Please contact support with \`${prefix}bug\`!`);
const embed = new Discord.RichEmbed()
.setTitle(`Musix ${error.toString()}`)
.setDescription(error.stack.replace(/at /g, '**at **'))
.setColor(client.config.embedColor);
client.fetchUser(client.config.devId).then(user => user.send(embed)).catch(console.error);
client.channels.get(client.config.debug_channel).send(embed);
}
} else {
return message.channel.send(embed);
}
},
};

View File

@ -0,0 +1,12 @@
module.exports = {
name: 'announcesongs',
async execute(message, args, client, Discord, prefix) {
if (client.global.db.guilds[message.guild.id].startPlaying) {
client.global.db.guilds[message.guild.id].startPlaying = false;
return message.channel.send(':white_check_mark: announcesongs now set to `false`!');
} else {
client.global.db.guilds[message.guild.id].startPlaying = true;
return message.channel.send(':white_check_mark: announcesongs now set to `true`!');
}
}
};

View File

@ -0,0 +1,17 @@
module.exports = {
name: 'permissions',
async execute(message, args, client, Discord, prefix) {
if (!args[2]) return message.channel.send(`🔒 Permission requirement: \`${client.global.db.guilds[message.guild.id].permissions}\``);
if (args[2] === 'true') {
if (!client.global.db.guilds[message.guild.id].permissions) {
client.global.db.guilds[message.guild.id].permissions = true;
message.channel.send(`:white_check_mark: Permissions requirement now set to: \`true\``);
} else return message.channel.send(':x: That value is already `true`!');
} else if (args[2] === 'false') {
if (client.global.db.guilds[message.guild.id].permissions) {
client.global.db.guilds[message.guild.id].permissions = false;
message.channel.send(`:white_check_mark: Permissions requirement now set to: \`false\``);
} else return message.channel.send(':x: That value is already `false`!');
} else return message.channel.send(':x: Please define a boolean! (true/false)');
}
};

View File

@ -0,0 +1,8 @@
module.exports = {
name: 'prefix',
async execute(message, args, client, Discord, prefix) {
if (!args[2]) return message.channel.send(`Current prefix: \`${client.global.db.guilds[message.guild.id].prefix}\``);
client.global.db.guilds[message.guild.id].prefix = args[2];
message.channel.send(`:white_check_mark: New prefix set to: \`${args[2]}\``);
}
};

View File

@ -0,0 +1,14 @@
module.exports = {
name: 'reset',
async execute(message, args, client, Discord, prefix) {
client.global.db.guilds[message.guild.id] = {
prefix: client.config.prefix,
defaultVolume: 5,
permissions: false,
premium: false,
dj: false,
djrole: null
};
message.channel.send(':white_check_mark: Reset __all__ guild settings!');
}
};

View File

@ -0,0 +1,28 @@
module.exports = {
name: 'setdj',
async execute(message, args, client, Discord, prefix) {
if (!client.global.db.guilds[message.guild.id].dj) {
if (!client.global.db.guilds[message.guild.id].permissions) {
client.global.db.guilds[message.guild.id].permissions = true;
}
if (message.guild.roles.find(x => x.name === "DJ")) {
client.global.db.guilds[message.guild.id].djrole = message.guild.roles.find(x => x.name === "DJ").id;
message.channel.send(':white_check_mark: I found a `DJ` role from this guild! This role is now the DJ role.');
client.global.db.guilds[message.guild.id].dj = true;
} else {
const permissions = message.channel.permissionsFor(message.client.user);
if (!permissions.has('MANAGE_ROLES')) return message.channel.send(':x: I cannot create roles (Manage roles), make sure I have the proper permissions! I will need this permission to create a `DJ` role since i did not find one!');
message.guild.createRole({
name: 'DJ',
})
.then(role => client.global.db.guilds[message.guild.id].djrole = role.id)
.catch(console.error)
client.global.db.guilds[message.guild.id].dj = true;
message.channel.send(':white_check_mark: I did not find a role `DJ` so i have created one for you!');
}
} else {
client.global.db.guilds[message.guild.id].dj = false;
message.channel.send(':white_check_mark: `DJ` now set to `false`');
}
}
};

View File

@ -0,0 +1,34 @@
module.exports = {
name: 'setpremium',
async execute(message, args, client, Discord, prefix) {
if (message.author.id !== client.config.devId) return;
if (args[2]) {
const guild = client.guilds.get(args[2]);
if (!client.global.db.guilds[guild.id].premium) {
client.global.db.playlists[guild.id] = {
songs: [],
firstSong: undefined,
saved: false,
};
client.global.db.guilds[guild.id].premium = true;
message.channel.send(`:white_check_mark: Guild ${guild.name} | ${guild.id} is now premium! :tada:`)
} else {
client.global.db.guilds[guild.id].premium = false;
message.channel.send(`:white_check_mark: Guild ${guild.name} | ${guild.id} is no longer premium!`)
}
} else {
if (!client.global.db.guilds[message.guild.id].premium) {
client.global.db.playlists[message.guild.id] = {
songs: [],
firstSong: undefined,
saved: false,
};
client.global.db.guilds[message.guild.id].premium = true;
message.channel.send(':white_check_mark: This guild is now premium! :tada:')
} else {
client.global.db.guilds[message.guild.id].premium = false;
message.channel.send(":white_check_mark: This guild is no longer premium!")
}
}
}
};

View File

@ -0,0 +1,12 @@
module.exports = {
name: 'songselection',
async execute(message, args, client, Discord, prefix) {
if (!client.global.db.guilds[message.guild.id].songSelection) {
message.channel.send(':white_check_mark: Songselection now set to `true`!');
client.global.db.guilds[message.guild.id].songSelection = true;
} else {
client.global.db.guilds[message.guild.id].songSelection = false;
message.channel.send(':white_check_mark: Songselection now set to `false`');
}
}
};

View File

@ -0,0 +1,10 @@
module.exports = {
name: 'volume',
async execute(message, args, client, Discord, prefix) {
if (!args[2]) return message.channel.send(`:speaker: Current default volume is: \`${client.global.db.guilds[message.guild.id].defaultVolume}\``);
if (isNaN(args[2])) return message.channel.send(':x: I\'m sorry, But the default volume needs to be a valid __number__.');
if (args[2].length > 2) return message.channel.send(':x: The default volume must be below `100` for quality and safety resons.');
client.global.db.guilds[message.guild.id].defaultVolume = args[2];
message.channel.send(`:white_check_mark: Default volume set to: \`${args[2]}\``);
}
};

22
commands/shuffle.js Normal file
View File

@ -0,0 +1,22 @@
module.exports = {
name: 'Shuffle',
description: 'Shuffle command.',
alias: 'shuffle',
cooldown: 5,
onlyDev: false,
execute(message, args, client, Discord, prefix) {
const serverQueue = client.queue.get(message.guild.id);
let currentIndex = serverQueue.songs.length,
temporaryValue,
randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = serverQueue.songs[currentIndex];
serverQueue.songs[currentIndex] = serverQueue.songs[randomIndex];
serverQueue.songs[randomIndex] = temporaryValue;
}
}
};

49
commands/skip.js Normal file
View File

@ -0,0 +1,49 @@
module.exports = {
name: 'skip',
description: 'Skip command.',
alias: 's',
cooldown: 5,
onlyDev: false,
execute(message, args, client, Discord, prefix) {
const { voiceChannel } = message.member;
const serverQueue = client.queue.get(message.guild.id);
const permissions = message.channel.permissionsFor(message.author);
if (!serverQueue) return message.channel.send(':x: There is nothing playing that I could skip for you.');
if (!serverQueue.playing) return message.channel.send(':x: There is nothing playing that I could skip for you.');
if (message.author.id !== client.config.devId) {
if (voiceChannel !== serverQueue.voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in the same voice channel as Musix to skip the song!');
if (client.global.db.guilds[message.guild.id].permissions === true) {
if (!message.member.roles.has(client.global.db.guilds[message.guild.id].djrole) && !permissions.has('MANAGE_MESSAGES')) {
return vote(serverQueue, message, client);
} else {
return skipSong(serverQueue, message);
}
} else {
return vote(serverQueue, message, client);
}
} else {
return skipSong(serverQueue, message);
}
}
};
function skipSong(serverQueue, message) {
message.channel.send(':fast_forward: Skipped the song!');
serverQueue.connection.dispatcher.end('skipped');
};
function vote(serverQueue, message) {
serverQueue.votesNeeded = Math.floor(message.guild.voiceConnection.channel.members.size / 2);
serverQueue.votesNeeded.toFixed();
if (message.guild.voiceConnection.channel.members.size > 2) {
if (serverQueue.voters.includes(message.member.id)) return message.channel.send(':x: You have already voted to skip!');
serverQueue.votes++;
serverQueue.voters.push(message.member.id);
if (serverQueue.votes >= serverQueue.votesNeeded) {
serverQueue.voters = [];
serverQueue.votes = 0;
serverQueue.votesNeeded = null;
return skipSong(serverQueue, message);
} else return message.channel.send(`:x: Not enough votes! ${serverQueue.votes} / ${serverQueue.votesNeeded}!`);
} else {
return skipSong(serverQueue, message);
}
};

21
commands/status.js Normal file
View File

@ -0,0 +1,21 @@
module.exports = {
name: 'status',
description: 'Status command.',
alias: 'status',
cooldown: 5,
onlyDev: false,
execute(message, args, client, Discord, prefix) {
const uptime = client.funcs.msToTime(client.uptime);
const ping = Math.floor(client.ping * 10) / 10;
const embed = new Discord.RichEmbed()
.setTitle(`Status for ${client.user.username}`)
.addField(':signal_strength: Ping', ping, true)
.addField(':stopwatch: Uptime', uptime, true)
.addField(`:play_pause: Currently playing music on`, `${client.voiceConnections.size} guild(s)`, true)
.addField(`💿 Operating system`, process.platform, true)
.setAuthor(client.user.username, client.user.displayAvatarURL)
.setColor(client.config.embedColor)
return message.channel.send(embed);
}
};

26
commands/stop.js Normal file
View File

@ -0,0 +1,26 @@
module.exports = {
name: 'stop',
description: 'Stop command.',
alias: 'stop',
cooldown: 5,
onlyDev: false,
execute(message, args, client, Discord, prefix) {
const { voiceChannel } = message.member;
const serverQueue = client.queue.get(message.guild.id);
const permissions = message.channel.permissionsFor(message.author);
if (!serverQueue) return message.channel.send(':x: There is nothing playing that I could stop for you.');
if (!serverQueue.playing) return message.channel.send(':x: There is nothing playing that I could stop for you.');
if (message.author.id !== client.config.devId) {
if (voiceChannel !== serverQueue.voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in the same voice channel as Musix to stop the music!');
if (client.global.db.guilds[message.guild.id].permissions === true) {
if (client.global.db.guilds[message.guild.id].dj) {
if (!message.member.roles.has(client.global.db.guilds[message.guild.id].djrole)) return message.channel.send(':x: You need the `DJ` role to stop the music!');
} else if (!permissions.has('MANAGE_CHANNELS')) return message.channel.send(':x: You need the `MANAGE_CHANNELS` permission to stop the music!');
}
}
serverQueue.songs = [];
serverQueue.looping = false;
serverQueue.connection.dispatcher.end('Stopped');
message.channel.send(':stop_button: Stopped the music!')
}
};

30
commands/volume.js Normal file
View File

@ -0,0 +1,30 @@
module.exports = {
name: 'volume',
description: 'Volume command.',
alias: 'volume',
cooldown: 5,
onlyDev: false,
execute(message, args, client, Discord, prefix) {
const { voiceChannel } = message.member;
const serverQueue = client.queue.get(message.guild.id);
const permissions = message.channel.permissionsFor(message.author);
if (!serverQueue) return message.channel.send(':x: There is nothing playing.');
if (!serverQueue.playing) return message.channel.send(':x: There is nothing playing.');
if (!args[1]) return message.channel.send(`:loud_sound: The current volume is: **${serverQueue.volume}**`);
const volume = parseFloat(args[1]);
if (message.author.id !== client.config.devId) {
if (!voiceChannel) return message.channel.send(':x: I\'m sorry but you need to be in a voice channel to change the volume!');
if (client.global.db.guilds[message.guild.id].permissions === true) {
if (client.global.db.guilds[message.guild.id].dj) {
if (!message.member.roles.has(client.global.db.guilds[message.guild.id].djrole)) return message.channel.send(':x: You need the `DJ` role to change the volume!');
} else if (!permissions.has('MANAGE_CHANNELS')) return message.channel.send(':x: You need the `MANAGE_CHANNELS` permission to change the volume!');
}
}
if (isNaN(volume)) return message.channel.send(':x: I\'m sorry, But you need to enter a valid __number__.');
if (volume > 100) return message.channel.send(':x: The max volume is `100`!');
if (volume < 0) return message.channel.send(':x: The volume needs to be a positive number!');
serverQueue.volume = volume;
serverQueue.connection.dispatcher.setVolume(volume / 5);
return message.channel.send(`:loud_sound: I set the volume to: **${volume}**`);
}
};

9
config/config.js Normal file
View File

@ -0,0 +1,9 @@
module.exports = {
token: process.env.TOKEN,
api_key: process.env.API_KEY,
debug_channel: "634718645188034560",
devId: "360363051792203779",
prefix: ">",
embedColor: "#b50002",
invite: "https://discordapp.com/api/oauth2/authorize?client_id=607266889537945605&permissions=271600640&redirect_uri=https%3A%2F%2Fdiscordapp.com%2Foauth2%2Fauthorize%3Fclient_id%3D607266889537945605%26%3Bscope%3Dbot%26%3Bpermissions%3D0&scope=bot",
}

23
events/guildcreate.js Normal file
View File

@ -0,0 +1,23 @@
module.exports = {
name: 'guildcreate',
async execute(client, guild) {
client.db.collection('guilds').doc(guild.id).set({
prefix: client.config.prefix,
defaultVolume: 5,
permissions: false,
premium: false,
dj: false,
djrole: null,
startPlaying: true
});
client.global.db.guilds[guild.id] = {
prefix: client.config.prefix,
defaultVolume: 5,
permissions: false,
premium: false,
dj: false,
djrole: null,
startPlaying: true
};
}
}

25
events/message.js Normal file
View File

@ -0,0 +1,25 @@
module.exports = {
name: 'message',
async execute(client, message, Discord) {
if (message.author.bot || !message.guild) return;
let prefix = client.global.db.guilds[message.guild.id].prefix;
const args = message.content.slice(prefix.length).split(' ');
if (message.mentions.users.first()) {
if (message.mentions.users.first().id === client.user.id) {
if (!args[1]) return;
if (args[1] === 'prefix') return message.channel.send(`My prefix here is: \`${prefix}\`.`);
if (args[1] === 'help') {
const command = client.commands.get("help");
return client.funcs.exe(message, args, client, Discord, prefix, command);
}
}
}
if (!message.content.startsWith(prefix)) return;
if (!args[0]) return;
const commandName = args[0].toLowerCase();
const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)) || client.commandAliases.get(commandName);
if (!command && message.content !== `${prefix}`) return;
if (command.onlyDev && message.author.id !== client.config.devId) return message.channel.send(':x: You are not allowed to do that!');
client.funcs.exe(message, args, client, Discord, prefix, command);
}
}

41
events/ready.js Normal file
View File

@ -0,0 +1,41 @@
module.exports = {
name: 'ready',
async execute(client, dbl, Discord) {
const remoteMusixGuildsData = await client.funcs.dbget('guilds', null, client);
const remoteMusixPlaylistsData = await client.funcs.dbget('playlists', null, client);
remoteMusixGuildsData.forEach(guildData => {
client.global.db.guilds[guildData.id] = guildData.d;
});
remoteMusixPlaylistsData.forEach(guildData => {
client.global.db.playlists[guildData.id] = guildData.d;
});
console.log('- DB Set -');
client.user.setActivity(`@${client.user.username} help | 🎶`, { type: 'LISTENING' });
client.user.setStatus('dnd');
dbl.postStats(client.guilds.size);
console.log('- Activated -');
setInterval(async () => {
client.guilds.forEach(guild => {
client.db.collection('guilds').doc(guild.id).set({
prefix: client.global.db.guilds[guild.id].prefix,
defaultVolume: client.global.db.guilds[guild.id].defaultVolume,
permissions: client.global.db.guilds[guild.id].permissions,
premium: client.global.db.guilds[guild.id].premium,
dj: client.global.db.guilds[guild.id].dj,
djrole: client.global.db.guilds[guild.id].djrole,
startPlaying: client.global.db.guilds[guild.id].startPlaying
});
if (client.global.db.guilds[guild.id].premium) {
client.db.collection('playlists').doc(guild.id).set({
songs: client.global.db.playlists[guild.id].songs,
saved: client.global.db.playlists[guild.id].saved,
});
}
});
dbl.postStats(client.guilds.size);
}, 1800000);
setInterval(() => {
client.funcs.ffmpeg(client, Discord);
}, 7200000);
}
}

58
index.js Normal file
View File

@ -0,0 +1,58 @@
const Discord = require('discord.js');
const MusicClient = require('./Struct/Client');
const client = new MusicClient({});
const DBL = require("dblapi.js");
const dbl = new DBL(process.env.DBLTOKEN, client);
const fs = require('fs');
require('dotenv/config');
client.config = require('./config/config.js');
const commandFiles = fs.readdirSync('./commands/').filter(f => f.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
command.uses = 0;
client.commands.set(command.name, command);
client.commandAliases.set(command.alias, command);
}
const eventFiles = fs.readdirSync('./events/').filter(f => f.endsWith('.js'));
for (const file of eventFiles) {
const event = require(`./events/${file}`);
client.events.set(event.name, event);
}
const playlistFiles = fs.readdirSync('./commands/playlist/').filter(f => f.endsWith('.js'));
for (const file of playlistFiles) {
const option = require(`./commands/playlist/${file}`);
client.playlistCmd.set(option.name, option);
}
const settingFiles = fs.readdirSync('./commands/settings/').filter(f => f.endsWith('.js'));
for (const file of settingFiles) {
const option = require(`./commands/settings/${file}`);
client.settingCmd.set(option.name, option);
}
client.on('ready', async () => {
const eventName = 'ready';
const event = client.events.get(eventName) || client.events.find(ent => ent.aliases && ent.aliases.includes(eventName));
event.execute(client, dbl, Discord);
});
client.on('message', message => {
const eventName = 'message';
const event = client.events.get(eventName) || client.events.find(ent => ent.aliases && ent.aliases.includes(eventName));
event.execute(client, message, Discord);
});
client.on('guildCreate', async (guild) => {
const eventName = 'guildcreate';
const event = client.events.get(eventName) || client.events.find(ent => ent.aliases && ent.aliases.includes(eventName));
event.execute(client, guild);
});
dbl.on('error', error => {
console.log(`Error with DBL! ${error}`);
})
client.login(client.config.token).catch(err => { console.log('- Failed To Login -> ' + err); });

3052
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

32
package.json Normal file
View File

@ -0,0 +1,32 @@
{
"name": "Musix",
"version": "2.21.1",
"description": "",
"main": "index.js",
"scripts": {
"start": "node ."
},
"keywords": [],
"author": "MatteZ02",
"license": "MIT",
"homepage": "https://https://github.com/MatteZ02/Musix",
"repository": {
"type": "git",
"url": "https://https://github.com/MatteZ02/Musix"
},
"dependencies": {
"dblapi.js": "^2.4.0",
"discord.js": "^11.6.4",
"dotenv": "^8.2.0",
"ffmpeg-static": "^4.2.0",
"firebase": "^6.6.2",
"firebase-admin": "^8.11.0",
"fs": "0.0.1-security",
"he": "^1.2.0",
"ms": "^2.1.2",
"node-opus": "^0.3.3",
"request": "^2.88.2",
"simple-youtube-api": "^5.2.1",
"ytdl-core": "^0.29.7"
}
}