Skip to content

Instantly share code, notes, and snippets.

@nirewen
Created October 27, 2018 21:36
Show Gist options
  • Save nirewen/f3f6b939ac272ef96763bde5144e027c to your computer and use it in GitHub Desktop.
Save nirewen/f3f6b939ac272ef96763bde5144e027c to your computer and use it in GitHub Desktop.
A music player based on Eris
//"ty&": {"category": "Música", "dir": "commands/music/", "color": "red"},
const reload = require('require-reload')(require),
config = reload('../config.json'),
utils = reload('./utils.js'),
playlists = reload('../db/playlists.json'),
YTDL = require('ytdl-core');
class Player {
constructor(bot, guild) {
this.bot = bot;
this.guild = guild;
this.queue = [];
this.repeat = {
one: false,
queue: false,
};
this.channels = {};
this.connection;
this.playlists = playlists;
this.timeout;
}
add(video, first = false) {
if (first) return this.queue.splice(1, 0, video);
return this.queue.push(video);
}
setChannels(text, voice, connection) {
this.channels = {text, voice};
this.connection = connection;
}
play() {
clearTimeout(this.timeout);
if (this.queue[0].source == 'YT')
this.connection.play(YTDL(this.queue[0].url, {filter: 'audioonly'}));
if (this.queue[0].source == 'MP3')
this.connection.play(this.queue[0].url);
config.cycleGames = false;
this.guild.shard.client.editStatus(null, {
name: this.queue[0].title,
type: 2
});
let repeat = '';
if (this.repeat.queue)
repeat = this.bot.emojis.getEmoji('repeatq');
else if (this.repeat.one)
repeat = this.bot.emojis.getEmoji('repeat1');
let msgEnviada;
this.channels.text.createMessage({
content: `${this.bot.emojis.getEmoji('forward')}${repeat} Tocando agora em **${this.channels.voice.name}**:`,
embed: {
url: this.queue[0].url,
author: {
name: this.queue[0].channelTitle,
url: this.queue[0].channelURL,
icon_url: this.queue[0].channelAvatar
},
title: this.queue[0].title,
fields: [
{
name: 'Duração',
value: utils.secondsToHms(this.queue[0].duration),
inline: true
},
{
name: 'Visualizações',
value: Number(this.queue[0].views).toLocaleString('pt-BR').replace(/,/g,'.'),
inline: true
}
],
footer: {
text: `Pedido por ${this.queue[0].sender.username}`,
icon_url: this.queue[0].sender.avatarURL
},
timestamp: this.queue[0].addedIn,
thumbnail: {
url: this.queue[0].thumbs.default
},
color: this.bot.colors.blue
}
}).then(sentMsg => msgEnviada = sentMsg);
this.connection.once('end', () => {
this.timeout = setTimeout(() => {
this.stop();
this.channels.text.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('green_tick')} Saindo do canal de voz por inatividade...`,
color: this.bot.colors.green
}
});
}, 10 * 60 * 1000);
if (this.repeat.one) {
if (this.queue[0]) {
msgEnviada.delete();
return this.play(this.connection);
}
}
if (!this.repeat.one && this.repeat.queue) {
msgEnviada.edit({
content: `${this.bot.emojis.getEmoji('forward')}\`[${new Date(msgEnviada.timestamp).toLocaleString()}]\` Tocado **${this.queue[0].title}**`,
embed: ''
});
this.add(this.queue[0]);
this.queue.splice(0, 1);
if (this.queue[0])
return this.play(this.connection);
} else {
msgEnviada.edit({
content: `${this.bot.emojis.getEmoji('forward')}\`[${new Date(msgEnviada.timestamp).toLocaleString()}]\` Tocado **${this.queue[0].title}**`,
embed: ''
});
this.queue.splice(0, 1);
if (this.queue[0])
return this.play(this.connection);
}
});
}
formatString(string, values) {
for (let val in values) {
string = string.replace(new RegExp(`\\$\\{${val}\\}`, 'g'), values[val]);
}
return string;
}
skip(author, index) {
let messages = {
default: {
embed: {
title: `${this.bot.emojis.getEmoji('skip')} Skip`,
description: 'O DJ decidiu pular',
color: this.bot.colors.orange
}
},
number: {
embed: {
description:`${this.bot.emojis.getEmoji('red_null')} Você precisa especificar um número`,
color: this.bot.colors.red
}
},
resident: {
embed: {
title: `${this.bot.emojis.getEmoji('skip')} Skip`,
description: 'A música ${num} foi removida por um DJ Residente',
color: this.bot.colors.orange
}
},
removeSuccess: {
embed: {
description: `${this.bot.emojis.getEmoji('green_remove')}` + "Você removeu a música **${titulo}** da lista",
color: this.bot.colors.green
}
},
lessThree: {
embed: {
title: `${this.bot.emojis.getEmoji('skip')} Skip`,
description: '${skips}/3. Mais ${remaining} pessoa${plural} ${pluraltwo} necessária${plural} para pular.',
color: this.bot.colors.orange
}
},
threeSkips: {
embed: {
title: `${this.bot.emojis.getEmoji('skip')} Skip`,
description: '3 pedidos foram contados! Removendo a música ${title}',
color: this.bot.colors.orange
}
},
alreadyVoted: {
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} Você já votou para pular nessa música`,
color: this.bot.colors.red
}
},
noSong: {
embed: {
description: `${this.bot.emojis.getEmoji('red_null')} Não há nenhuma música nessa posição`,
color: this.bot.colors.red
}
},
dj: {
offline: {
embed: {
title: `${this.bot.emojis.getEmoji('skip')} Skip`,
description: 'O DJ não está mais online e não há pessoas suficientes escutando para pular a música. Pulando...',
color: this.bot.colors.orange
}
},
left: {
embed: {
title: `${this.bot.emojis.getEmoji('skip')} Skip`,
description: 'O DJ não está mais no servidor. Pulando...',
color: this.bot.colors.orange
}
}
}
};
return new Promise((resolve, reject) => {
if (index) {
let num = Number(index);
if (isNaN(num)) {
if (author.roles.sortedRoles.find(r => r.name == "DJ") && index == '-f') {
this.connection.stopPlaying();
messages.resident.embed.description = this.formatString(messages.resident.embed.description, {num});
return resolve(messages.resident);
}
return reject(messages.number);
}
if (this.queue[num]) {
if (this.queue[num].sender.id == author.id) {
let titulo = this.queue[num].title;
this.queue.splice(num, 1);
messages.removeSuccess.embed.description = this.formatString(messages.removeSuccess.embed.description, {titulo});
return resolve(messages.removeSuccess);
}
if (author.roles.sortedRoles.find(r => r.name == "DJ")) {
this.queue.splice(num, 1);
messages.resident.embed.description = this.formatString(messages.resident.embed.description, {num});
return resolve(messages.resident);
} else {
if ((this.queue[num].skips + 1) == 3) {
this.queue.splice(num, 1);
messages.threeSkips.embed.description = this.formatString(messages.threeSkips.embed.description, {title: '**' + this.queue[num].title + '**'});
return resolve(messages.threeSkips);
} else {
if (this.queue[num].votedSkip.has(author.id))
return reject(messages.alreadyVoted);
else {
this.queue[num].skips = this.queue[num].skips + 1;
this.queue[num].votedSkip.add(author.id);
messages.lessThree.embed.description = this.formatString(messages.lessThree.embed.description, {
skips: this.queue[num].skips,
remaining: 3 - this.queue[num].skips,
plural: utils.s(3 - this.queue[num].skips)[0],
pluraltwo: utils.s(3 - this.queue[num].skips)[1]
});
return resolve(messages.lessThree);
}
}
}
} else
return reject(messages.noSong);
} else {
if (this.queue[0].sender.id == author.id) {
this.connection.stopPlaying();
return resolve(messages.default);
}
if (author.roles.sortedRoles.find(r => r.name == "DJ")) {
this.connection.stopPlaying();
messages.resident.embed.description = this.formatString(messages.resident.embed.description, {num: 'atual'});
return resolve(messages.resident);
}
if (!this.guild.members.get(this.queue[0].sender.id)) {
this.connection.stopPlaying();
return resolve(messages.dj.left);
}
if (this.guild.members.get(this.queue[0].sender.id).status == 'offline' && this.connection.voiceMembers.size < 4) {
this.connection.stopPlaying();
return resolve(messages.dj.offline);
}
if (this.queue[0].votedSkip.has(author.id))
return resolve(messages.alreadyVoted);
else {
if ((this.queue[0].skips + 1) == 3) {
this.connection.stopPlaying();
messages.threeSkips.embed.description = this.formatString(messages.threeSkips.embed.description, {title: 'atual'});
return resolve(messages.threeSkips);
} else {
this.queue[0].skips += 1;
this.queue[0].votedSkip.add(author.id);
messages.lessThree.embed.description = this.formatString(messages.lessThree.embed.description, {
skips: this.queue[0].skips,
remaining: 3 - this.queue[0].skips,
plural: utils.s(3 - this.queue[0].skips)[0],
pluraltwo: utils.s(3 - this.queue[0].skips)[1]
});
return resolve(messages.lessThree);
}
}
}
});
}
showQueue(page = 1) {
if (this.queue.length == 0) {
return {
embed: {
description: `${this.bot.emojis.getEmoji('null')} Nada está tocando, adicione algo com \`ty&play <música>\``,
color: this.bot.colors.red
}
};
}
if (typeof page == "string") {
switch (page) {
case 'pop': {
if (this.queue && this.queue.length > 0) {
this.queue.pop();
return {
embed: {
description: `${this.bot.emojis.getEmoji('green_remove')} Última música da fila removida`,
color: this.bot.colors.green
}
};
}
}
case 'clear': {
if (this.queue[0]) {
this.queue = [this.queue[0]];
return {
embed: {
description: `${this.bot.emojis.getEmoji('green_tick')} Fila limpa`,
color: this.bot.colors.green
}
};
} else {
return {
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} A fila já está limpa`,
color: this.bot.colors.red
}
};
}
}
case 'shift': {
if (this.queue[1]) {
this.queue.splice(1, 1);
return {
embed: {
description: `${this.bot.emojis.getEmoji('green_remove')} A próxima música foi removida da fila`,
color: this.bot.colors.green
}
};
}
}
}
}
if (this.queue.length > 0 && page > 0) {
let queue = this.queue;
let lista = queue.map((song, index) => {
if (index === 0) return;
let musicPos = utils.zero(index);
return `\`${musicPos}\` \`${utils.secondsToHms(song.duration)}\` ${song.title} - ${song.sender.mention}`;
}),
maxLength = this.queue[0].duration,
currentTime = this.connection.current.playTime / 1000,
track = ~~((currentTime * 80) / maxLength),
remaining = 80 - track;
let pageCount = Math.ceil(lista.length / 10);
if (pageCount > 1 && page < pageCount) {
pageCount = `${Math.ceil(lista.length / 10)} | Use ty&queue ${page + 1} para ver a próxima página`;
} else if (pageCount > 1 && page == pageCount) {
pageCount = `${Math.ceil(lista.length / 10)} | Use ty&queue ${page - 1} para ver a página anterior`;
}
let songList = lista.splice((page - 1) * 10, 10),
pauseStatus = this.connection.paused == true ? ':pause_button: ' : '',
repeat = '';
if (this.repeat.queue)
repeat = this.bot.emojis.getEmoji('repeatq');
else if (this.repeat.one)
repeat = this.bot.emojis.getEmoji('repeat1');
if (songList.length > 1) {
lista = [{name: 'Próximas', value: songList.join('\n')}];
lista.unshift({name: 'Atual', value: `${queue[0].title} - ${queue[0].sender.mention}\n:arrow_forward: ~~${'\u200b '.repeat(track)}~~:radio_button:${'\u200b '.repeat(remaining)}\`${utils.secondsToHms(currentTime)} / ${utils.secondsToHms(this.queue[0].duration)}\``});
} else {
lista = [];
lista.push({name: 'Atual', value: `${queue[0].title} - ${queue[0].sender.mention}\n:arrow_forward: ~~${'\u200b '.repeat(track)}~~:radio_button:${'\u200b '.repeat(remaining)}\`${utils.secondsToHms(currentTime)} / ${utils.secondsToHms(this.queue[0].duration)}\``});
}
if (page > pageCount || page < 1) {
return {
embed: {
description: `${this.bot.emojis.getEmoji('null')} Página não encontrada`,
color: this.bot.colors.white
}
};
}
if (songList.length > 0) {
return {
embed: {
author: {
name: this.guild.name,
icon_url: this.guild.iconURL
},
description: `${repeat}${pauseStatus} Fila | ${queue.length} músicas | \`${utils.secondsToHms(queue.reduce((total, crr) => {return Number(total) + Number(crr.duration)}, 0))}\``,
fields: lista,
footer: {
text: `Página ${page} de ${pageCount}`
},
color: this.bot.colors.orange
}
};
}
}
}
prettyList(playlistName, playlist, page = 1) {
if (playlist.queue.length == 0) return {
embed: {
title: playlistName,
description: "Nenhuma música",
fields: [
{
name: 'Criador',
value: playlist.creator.name,
inline: true
}
],
color: this.bot.colors.red
}
};
let lista = playlist.queue.map((song, index) => {
let musicPos = utils.zero(index);
return `\`${musicPos}\` ${song.title} \`${utils.secondsToHms(song.duration)}\``;
});
let pageCount = Math.ceil(lista.length / 10);
if (pageCount > 1 && page < pageCount) {
pageCount = `${Math.ceil(lista.length / 10)} | Use ty&playlist ${playlistName} ${page + 1} para ver a próxima página`;
} else if (pageCount > 1 && page == pageCount) {
pageCount = `${Math.ceil(lista.length / 10)} | Use ty&playlist ${playlistName} ${page - 1} para ver a página anterior`;
}
let songList = lista.splice((page - 1) * 10, 10);
if (page > pageCount || page < 1) {
return {
embed: {
description: `${this.bot.emojis.getEmoji('null')} Página não encontrada`,
color: this.bot.colors.red
}
};
}
return {
embed: {
title: playlistName,
description: songList.join('\n'),
fields: [
{
name: 'Criador',
value: playlist.creator.name,
inline: true
},
{
name: 'Tamanho',
value: `${playlist.queue.length} música${utils.s(playlist.queue.length - 1)[0]} (${utils.secondsToHms(Number(playlist.queue.reduce((total, crr) => {return total + crr.duration}, 0)))})`,
inline: true
}
],
footer: {
text: `Página ${page} de ${pageCount}`
},
color: this.bot.colors.orange
}
};
}
stop() {
this.repeat1 = false;
this.repeatq = false;
clearTimeout(this.timeout);
this.queue = [];
if (this.connection) {
this.bot.leaveVoiceChannel(this.connection.channelID);
this.connection = null;
}
return {
embed: {
description: `${this.bot.emojis.getEmoji('green_tick')} Lista limpa e música parada`,
color: this.bot.colors.green
}
};
}
playlist(msg, method, playlist, songs) {
switch(method) {
case 'add': {
if (playlists[this.guild.id][playlist].creator.id == msg.author.id) {
for (let i in songs) {
playlists[this.guild.id][playlist].queue.push(songs[i]);
}
utils.safeSave('db/playlists', '.json', JSON.stringify(playlists));
return;
} else {
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} Você não é o criador dessa playlist`,
color: this.bot.colors.red
}
});
}
}
case 'create': {
if (!playlists[this.guild.id]) playlists[this.guild.id] = {};
playlists[this.guild.id][playlist] = {
name: playlist,
creator: {
name: msg.author.username,
id: msg.author.id
},
queue: []
};
utils.safeSave('db/playlists', '.json', JSON.stringify(playlists));
break;
}
case 'remove': {
if (playlists[this.guild.id][playlist].creator.id == msg.author.id) {
let musica = playlists[this.guild.id][playlist].queue[songs];
playlists[this.guild.id][playlist].queue.splice(songs, 1);
utils.safeSave('db/playlists', '.json', JSON.stringify(playlists));
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('remove')} Música **${musica.title}** deletada da playlist **${playlist}**`,
color: this.bot.colors.red
}
});
} else {
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')}Você não pode deletar músicas de uma playlist que não é sua`,
color: this.bot.colors.red
}
});
}
}
case 'play': {
for (let i in playlists[this.guild.id][playlist].queue) {
this.queue.add(playlists[this.guild.id][playlist].queue[i]);
}
if (!this.bot.voiceConnections.has(this.guild.id)) {
return this.bot.joinVoiceChannel(msg.member.voiceState.channelID).then(connection => {
this.setChannels(msg.channel, this.guild.channels.get(connection.channelID), connection);
this.play();
}).catch(err => {
if (err.message == 'Insufficient permission to connect to voice channel') {
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} Permissões insuficientes para entrar no canal`,
color: this.bot.colors.red
}
});
}
});
}
break;
}
case 'pop': {
if (playlists[this.guild.id][playlist].creator.id == msg.author.id) {
let musica = playlists[this.guild.id][playlist].queue[playlists[this.guild.id][playlist].queue.length - 1];
playlists[this.guild.id][playlist].queue.pop();
utils.safeSave('db/playlists', '.json', JSON.stringify(playlists));
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('remove')} Música **${musica.title}** deletada da playlist **${playlist}**`,
color: this.bot.colors.red
}
});
} else {
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} Você não pode deletar músicas de uma playlist que não é sua`,
color: this.bot.colors.red
}
});
}
}
case 'shift': {
if (playlists[this.guild.id][playlist].creator.id == msg.author.id) {
let musica = playlists[this.guild.id][playlist].queue[1];
playlists[this.guild.id][playlist].queue.shift();
utils.safeSave('db/playlists', '.json', JSON.stringify(playlists));
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('remove')} Música **${musica.title}** deletada da playlist **${playlist}**`,
color: this.bot.colors.red
}
});
} else {
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} Você não pode deletar músicas de uma playlist que não é sua`,
color: this.bot.colors.red
}
});
}
}
case 'rename': {
if (playlists[this.guild.id][playlist].creator.id == msg.author.id) {
if (playlist !== songs) {
Object.defineProperty(playlists[this.guild.id], songs, Object.getOwnPropertyDescriptor(playlists[this.guild.id], playlist));
delete playlists[this.guild.id][playlist];
}
utils.safeSave('db/playlists', '.json', JSON.stringify(playlists));
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('green_tick')} Playlist **${playlist}** renomeada para **${songs}**`,
color: this.bot.colors.green
}
});
} else {
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} Você não pode deletar músicas de uma playlist que não é sua`,
color: this.bot.colors.red
}
});
}
}
case 'delete': {
if (playlists[this.guild.id][playlist].creator.id == msg.author.id) {
delete playlists[this.guild.id][playlist];
utils.safeSave('db/playlists', '.json', JSON.stringify(playlists));
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('green_remove')} Playlist **${playlist}** deletada`,
color: this.bot.colors.green
}
});
} else {
return msg.channel.createMessage({
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} Você não pode deletar uma playlist que não é sua`,
color: this.bot.colors.red
}
});
}
}
}
}
repeat(msg, method) {
switch (method) {
case 'q':
case 'queue': {
this.repeatq = !this.repeatq;
let answer = ['desativada', 'ativada'][+this.repeatq];
return {
embed: {
description: `${this.bot.emojis.getEmoji('green_tick')} Repetição de fila ${answer}`,
color: this.bot.colors.green
}
};
}
case '1': {
this.repeat1 = !this.repeat1;
let answer = ['desativada', 'ativada'][+this.repeat1];
return {
embed: {
description: `${this.bot.emojis.getEmoji('green_tick')} Repetição de música ${answer}`,
color: this.bot.colors.green
}
};
}
}
}
pause() {
if (this.connection.paused == false && this.connection.playing) {
this.connection.pause();
return {
embed: {
description: `${this.bot.emojis.getEmoji('green_tick')} Pause ativado`,
color: this.bot.colors.green
}
};
}
if (this.connection.playing && this.connection.paused) {
this.connection.resume();
return {
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} Pause desativado`,
color: this.bot.colors.red
}
};
} else {
return {
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} Nada está tocando como nada está pausado`,
color: this.bot.colors.red
}
};
}
}
shuffle() {
if (this.queue.length == 0) return {
embed: {
description: `${this.bot.emojis.getEmoji('red_tick')} Não tem nenhuma música na lista desse servidor`,
color: this.bot.colors.red
}
};
this.queue.sort(() => 0.5 - Math.random());
return {
embed: {
description: `${this.bot.emojis.getEmoji('green_tick')} Lista embaralhada com sucesso`,
color: this.bot.colors.green
}
};
}
toString() {
return `[${this.constructor.name} ${this.guild.id}]`;
}
}
module.exports = Player;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment