musicbot-addon
Version:
Uma simples extensão / bot de música baseada em Node.js. para projetos Discord.js. usando o YouTube.
870 lines (813 loc) • 93 kB
JavaScript
const ytdl = require('ytdl-core');
const { YTSearcher } = require('ytsearcher');
const ytpl = require('ytpl');
const Discord = require('discord.js');
const PACKAGE = require('./package.json');
exports.start = (client, options) => {
try {
if (process.version.slice(1).split('.')[0] < 8) console.error(new Error(`[MusicBot] node v8 or higher is needed, please update`));
function moduleAvailable(name) {
try {
require.resolve(name);
return true;
} catch (e) { }
return false;
};
if (moduleAvailable("ffmpeg-binaries")) console.error(new Error("[MUSIC] ffmpeg-binaries was found, this will likely cause problems"));
if (!moduleAvailable("ytdl-core") || !moduleAvailable("ytpl") || !moduleAvailable("ytsearcher")) console.error(new Error("[MUSIC] one or more youtube specific modules not found, this module will not work"));
class Music {
constructor(client, options) {
// Data Objects
this.commands = new Map();
this.commandsArray = [];
this.aliases = new Map();
this.queues = new Map();
this.client = client;
// Play Command options
this.play = {
enabled: (options.play == undefined ? true : (options.play && typeof options.play.enabled !== 'undefined' ? options.play && options.play.enabled : true)),
run: "playFunction",
alt: (options && options.play && options.play.alt) || [],
help: (options && options.play && options.play.help) || "Enfileire uma música / lista de reprodução por URL ou nome.",
name: (options && options.play && options.play.name) || "play",
usage: (options && options.play && options.play.usage) || null,
exclude: Boolean((options && options.play && options.play.exclude)),
masked: "play"
};
// Help Command options
this.help = {
enabled: (options.help == undefined ? true : (options.help && typeof options.help.enabled !== 'undefined' ? options.help && options.help.enabled : true)),
run: "helpFunction",
alt: (options && options.help && options.help.alt) || [],
help: (options && options.help && options.help.help) || "Ajuda para comandos.",
name: (options && options.help && options.help.name) || "help",
usage: (options && options.help && options.help.usage) || null,
exclude: Boolean((options && options.help && options.help.exclude)),
masked: "help"
};
// Pause Command options
this.pause = {
enabled: (options.pause == undefined ? true : (options.pause && typeof options.pause.enabled !== 'undefined' ? options.pause && options.pause.enabled : true)),
run: "pauseFunction",
alt: (options && options.pause && options.pause.alt) || [],
help: (options && options.pause && options.pause.help) || "Pausa na reprodução de música.",
name: (options && options.pause && options.pause.name) || "pause",
usage: (options && options.pause && options.pause.usage) || null,
exclude: Boolean((options && options.pause && options.pause.exclude)),
masked: "pause"
};
// Resume Command options
this.resume = {
enabled: (options.resume == undefined ? true : (options.resume && typeof options.resume.enabled !== 'undefined' ? options.resume && options.resume.enabled : true)),
run: "resumeFunction",
alt: (options && options.resume && options.resume.alt) || [],
help: (options && options.resume && options.resume.help) || "Retoma uma fila pausada.",
name: (options && options.resume && options.resume.name) || "resume",
usage: (options && options.resume && options.resume.usage) || null,
exclude: Boolean((options && options.resume && options.resume.exclude)),
masked: "resume"
};
// Leave Command options
this.leave = {
enabled: (options.leave == undefined ? true : (options.leave && typeof options.leave.enabled !== 'undefined' ? options.leave && options.leave.enabled : true)),
run: "leaveFunction",
alt: (options && options.leave && options.leave.alt) || [],
help: (options && options.leave && options.leave.help) || "Sai do canal de voz.",
name: (options && options.leave && options.leave.name) || "leave",
usage: (options && options.leave && options.leave.usage) || null,
exclude: Boolean((options && options.leave && options.leave.exclude)),
masked: "leave"
};
// Queue Command options
this.queue = {
enabled: (options.queue == undefined ? true : (options.queue && typeof options.queue.enabled !== 'undefined' ? options.queue && options.queue.enabled : true)),
run: "queueFunction",
alt: (options && options.queue && options.queue.alt) || [],
help: (options && options.queue && options.queue.help) || "Veja a fila atual.",
name: (options && options.queue && options.queue.name) || "queue",
usage: (options && options.queue && options.queue.usage) || null,
exclude: Boolean((options && options.queue && options.queue.exclude)),
masked: "queue"
};
// Nowplaying Command options
this.np = {
enabled: (options.np == undefined ? true : (options.np && typeof options.np.enabled !== 'undefined' ? options.np && options.np.enabled : true)),
run: "npFunction",
alt: (options && options.np && options.np.alt) || [],
help: (options && options.np && options.np.help) || "Mostra a musica que está sendo reproduzida.",
name: (options && options.np && options.np.name) || "np",
usage: (options && options.np && options.np.usage) || null,
exclude: Boolean((options && options.np && options.np.exclude)),
masked: "np"
};
// Loop Command options
this.loop = {
enabled: (options.loop == undefined ? true : (options.loop && typeof options.loop.enabled !== 'undefined' ? options.loop && options.loop.enabled : true)),
run: "loopFunction",
alt: (options && options.loop && options.loop.alt) || [],
help: (options && options.loop && options.loop.help) || "Define o estado do loop para a fila.",
name: (options && options.loop && options.loop.name) || "loop",
usage: (options && options.loop && options.loop.usage) || null,
exclude: Boolean((options && options.loop && options.loop.exclude)),
masked: "loop"
};
// Search Command options
this.search = {
enabled: (options.search == undefined ? true : (options.search && typeof options.search.enabled !== 'undefined' ? options.search && options.search.enabled : true)),
run: "searchFunction",
alt: (options && options.search && options.search.alt) || [],
help: (options && options.search && options.search.help) || "Pesquisa até 10 vídeos do YouTube.",
name: (options && options.search && options.search.name) || "search",
usage: (options && options.search && options.search.usage) || null,
exclude: Boolean((options && options.search && options.search.exclude)),
masked: "search"
};
// Clear Command options
this.clearqueue = {
enabled: (options.clearqueue == undefined ? true : (options.clearqueue && typeof options.clearqueue.enabled !== 'undefined' ? options.clearqueue && options.clearqueue.enabled : true)),
run: "clearFunction",
alt: (options && options.clear && options.clear.alt) || [],
help: (options && options.clear && options.clear.help) || "Limpa a fila inteira.",
name: (options && options.clear && options.clear.name) || "clear",
usage: (options && options.clear && options.clear.usage) || null,
exclude: Boolean((options && options.clearqueue && options.clearqueue.exclude)),
masked: "clearqueue"
};
// Volume Command options
this.volume = {
enabled: (options.volume == undefined ? true : (options.volume && typeof options.volume.enabled !== 'undefined' ? options.volume && options.volume.enabled : true)),
run: "volumeFunction",
alt: (options && options.volume && options.volume.alt) || [],
help: (options && options.volume && options.volume.help) || "Altera a saída do volume do bot.",
name: (options && options.volume && options.volume.name) || "volume",
usage: (options && options.volume && options.volume.usage) || null,
exclude: Boolean((options && options.volume && options.volume.exclude)),
masked: "volume"
};
this.remove = {
enabled: (options.remove == undefined ? true : (options.remove && typeof options.remove.enabled !== 'undefined' ? options.remove && options.remove.enabled : true)),
run: "removeFunction",
alt: (options && options.remove && options.remove.alt) || [],
help: (options && options.remove && options.remove.help) || "Remova uma música da fila por posição na fila.",
name: (options && options.remove && options.remove.name) || "remove",
usage: (options && options.remove && options.remove.usage) || "{{prefix}}remove [position]",
exclude: Boolean((options && options.remove && options.remove.exclude)),
masked: "remove"
};
// Skip Command options
this.skip = {
enabled: (options.skip == undefined ? true : (options.skip && typeof options.skip.enabled !== 'undefined' ? options.skip && options.skip.enabled : true)),
run: "skipFunction",
alt: (options && options.skip && options.skip.alt) || [],
help: (options && options.skip && options.skip.help) || "Pule uma música ou músicas com `skip [número]`",
name: (options && options.skip && options.skip.name) || "skip",
usage: (options && options.skip && options.skip.usage) || null,
exclude: Boolean((options && options.skip && options.skip.exclude)),
masked: "skip"
};
this.shuffle = {
enabled: (options.shuffle == undefined ? true : (options.shuffle && typeof options.shuffle.enabled !== 'undefined' ? options.shuffle && options.shuffle.enabled : true)),
run: "shuffleFunction",
alt: (options && options.shuffle && options.shuffle.alt) || [],
help: (options && options.shuffle && options.shuffle.help) || "Embaralhar a fila",
name: (options && options.shuffle && options.shuffle.name) || "shuffle",
usage: (options && options.shuffle && options.shuffle.usage) || null,
exclude: Boolean((options && options.shuffle && options.shuffle.exclude)),
masked: "shuffle"
};
this.deleteQueue = {
enabled: (options.deleteQueue == undefined ? true : (options.deleteQueue && typeof options.deleteQueue.enabled !== 'undefined' ? options.deleteQueue && options.deleteQueue.enabled : true)),
run: "deleteQueueFunction",
alt: (options && options.deleteQueue && options.deleteQueue.alt) || [],
help: (options && options.deleteQueue && options.deleteQueue.help) || "Excluir e refazer uma fila em andamento",
name: (options && options.deleteQueue && options.deleteQueue.name) || "deletequeue",
usage: (options && options.deleteQueue && options.deleteQueue.usage) || null,
exclude: Boolean((options && options.deleteQueue && options.deleteQueue.exclude)),
masked: "deletequeue"
};
this.embedColor = (options && options.embedColor) || 'GREEN';
this.anyoneCanSkip = (options && typeof options.anyoneCanSkip !== 'undefined' ? options && options.anyoneCanSkip : false);
this.anyoneCanLeave = (options && typeof options.anyoneCanLeave !== 'undefined' ? options && options.anyoneCanLeave : false);
this.djRole = (options && options.djRole) || "DJ";
this.anyoneCanPause = (options && typeof options.anyoneCanPause !== 'undefined' ? options && options.anyoneCanPause : false);
this.anyoneCanAdjust = (options && typeof options.anyoneCanAdjust !== 'undefined' ? options && options.anyoneCanAdjust : false);
this.youtubeKey = (options && options.youtubeKey);
this.botPrefix = (options && options.botPrefix) || "!";
this.defVolume = (options && options.defVolume) || 50;
if (options.maxQueueSize === 0) {
this.maxQueueSize = 0;
} else {
this.maxQueueSize = (options && options.maxQueueSize) || 50;
}
this.ownerOverMember = (options && typeof options.ownerOverMember !== 'undefined' ? options && options.ownerOverMember : false);
this.botAdmins = (options && options.botAdmins) || [];
this.ownerID = (options && options.ownerID);
this.logging = (options && typeof options.logging !== 'undefined' ? options && options.logging : true);
this.requesterName = (options && typeof options.requesterName !== 'undefined' ? options && options.requesterName : true);
this.inlineEmbeds = (options && typeof options.inlineEmbeds !== 'undefined' ? options && options.inlineEmbeds : false);
this.clearOnLeave = (options && typeof options.clearOnLeave !== 'undefined' ? options && options.clearOnLeave : true);
this.messageHelp = (options && typeof options.messageHelp !== 'undefined' ? options && options.messageHelp : false);
this.dateLocal = (options && options.dateLocal) || 'pt-BR';
this.bigPicture = (options && typeof options.bigPicture !== 'undefined' ? options && options.bigPicture : false);
this.messageNewSong = (options && typeof options.messageNewSong !== 'undefined' ? options && options.messageNewSong : true);
this.insertMusic = (options && typeof options.insertMusic !== 'undefined' ? options && options.insertMusic : false);
this.defaultPrefix = (options && options.defaultPrefix) || "!";
this.channelWhitelist = (options && options.channelWhitelist) || [];
this.channelBlacklist = (options && options.channelBlacklist) || [];
this.minShuffle = (options && options.shuffle) || 3;
this.bitRate = (options && options.bitRate) || "120000";
this.userSearching = new Map();
// Cooldown Settings
this.cooldown = {
enabled: (options && options.cooldown ? options && options.cooldown.enabled : true),
timer: parseInt((options && options.cooldown && options.cooldown.timer) || 10000),
exclude: (options && options.cooldown && options.cooldown.exclude) || ["volume", "queue", "pause", "resume", "np"]
};
this.musicPresence = options.musicPresence || false;
this.clearPresence = options.clearPresence || false;
this.nextPresence = (options && options.nextPresence) || null;
this.recentTalk = new Set();
}
checkVoice(mem, bot) {
return new Promise((resolve, reject) => {
if (!mem || !bot) reject("invalid args");
if (!mem.voiceChannel) reject("Você não está em um canal de voz!");
if (bot.voiceChannel) {
if (bot.voiceChannel.id == mem.voiceChannel.id) resolve(mem.voiceChannel)
else reject("Você está em um canal de voz diferente!")
} else {
resolve(mem.voiceChannel);
};
});
};
async updatePositions(obj, server) {
return new Promise((resolve, reject) => {
if (!server) reject("stage 0: no server passed for @updatePositions");
if (!obj) resolve(this.getQueue(server));
if (obj.working == true) reject("A fila já está executando uma tarefa!");
if (server != "000000") {
obj.working = true;
this.queues.set(server, obj);
}
try {
var songs = typeof obj == "object" ? Array.from(obj.songs) : [];
} catch (e) {
console.log("aidjbasiubd");
};
try {
if (!songs || songs.length <= 0 || typeof obj.songs != "object") {
if (this.debug) console.log("[MUSICBOT] @updatePositions: songs object was invalid, reseting queue for " + obj.id);
this.queues.set(obj.id, { songs: [], last: obj.last ? obj.last : null, loop: obj.loop ? obj.loop : "none", id: obj.id, volume: this.defVolume, oldSongs: [], working: false, needsRefresh: false })
resolve([])
}
let mm = 0;
var newsongs = [];
songs.forEach(s => {
try {
// console.log(s);
if (!s) return;
if (s.position !== mm) s.position = mm;
newsongs.push(s);
mm++;
} catch (e) {
console.log(e);
};
});
} catch (e) {
console.log(e);
if (server != "000000") {
obj.working = false;
this.queues.set(server, obj);
}
reject("stage 1: @updatePositions " + e)
};
obj.songs = newsongs;
obj.last.position = 0;
if (server != "000000") {
obj.working = false;
this.queues.set(server, obj);
}
setTimeout(() => {
resolve(obj);
}, 2000)
});
};
isAdmin(member) {
if (member.roles.find(r => r.name == this.djRole)) return true;
if (this.ownerOverMember && member.id === this.botOwner) return true;
if (this.botAdmins.includes(member.id)) return true;
return member.hasPermission("ADMINISTRATOR");
};
canSkip(member, queue) {
if (this.anyoneCanSkip) return true;
else if (this.botAdmins.includes(member.id)) return true;
else if (this.ownerOverMember && member.id === this.botOwner) return true;
else if (queue.last.requester === member.id) return true;
else if (this.isAdmin(member)) return true;
else return false;
};
canAdjust(member, queue) {
if (this.anyoneCanAdjust) return true;
else if (this.botAdmins.includes(member.id)) return true;
else if (this.ownerOverMember && member.id === this.botOwner) return true;
else if (queue.last.requester === member.id) return true;
else if (this.isAdmin(member)) return true;
else return false;
};
getQueue(server) {
if (!this.queues.has(server)) {
this.queues.set(server, { songs: [], last: null, loop: "none", id: server, volume: this.defVolume, oldSongs: [], working: false, needsRefresh: false });
};
return this.queues.get(server);
};
setLast(server, last) {
return new Promise((resolve, reject) => {
if (this.queues.has(server)) {
let q = this.queues.get(server);
q.last = last;
this.queues.set(server, q);
resolve(this.queues.get(server));
} else {
reject("no server queue");
};
});
};
emptyQueue(server) {
return new Promise((resolve, reject) => {
if (!server || typeof server != "string") reject("no server id passed or passed obj was no a string @emptyQueue")
this.queues.set(server, { songs: [], last: null, loop: "none", id: server, volume: this.defVolume, oldSongs: [], working: false, needsRefresh: false });
resolve(this.queues.get(server));
});
};
async updatePresence(queue, client, clear) {
return new Promise((resolve, reject) => {
if (this.nextPresence !== null) clear = false;
if (!queue || !client) reject("invalid arguments");
if (queue.songs.length > 0 && queue.last) {
client.user.setPresence({
game: {
name: "🎵 | " + queue.last.title,
type: 'PLAYING'
}
});
resolve(client.user.presence);
} else {
if (clear) {
client.user.setPresence({ game: { name: null } });
resolve(client.user.presence);
} else {
if (this.nextPresence !== null) {
let props;
if (this.nextPresence.status && ["online", "dnd", "idle", "invisible"].includes(this.nextPresence.status)) props.status = this.nextPresence.status;
if (this.nextPresence.afk && typeof this.nextPresence.afk == "boolean") props.afk = this.nextPresence.afk;
if (this.nextPresence.game && typeof this.nextPresence.game == "string") props.game = { name: this.nextPresence.game }
else if (this.nextPresence.game && typeof this.nextPresence.game == "object") props.game = this.nextPresence.game;
client.user.setPresence(props).catch((res) => {
console.error("[MUSICBOT] Could not update presence\n" + res);
client.user.setPresence({ game: { name: null } });
resolve(client.user.presence);
}).then((res) => {
resolve(res);
});
} else {
client.user.setPresence({
game: {
name: "🎵 | nada",
type: 'PLAYING'
}
});
}
resolve(client.user.presence);
};
};
});
};
updatePrefix(server, prefix) {
if (typeof prefix == undefined) prefix = this.defaultPrefix;
if (typeof this.botPrefix != "object") this.botPrefix = new Map();
this.botPrefix.set(server, { prefix: prefix });
};
};
var musicbot = new Music(client, options);
if (musicbot.insertMusic == true) client.music = musicbot;
else exports.bot = musicbot;
musicbot.searcher = new YTSearcher(musicbot.youtubeKey);
musicbot.changeKey = (key) => {
return new Promise((resolve, reject) => {
if (!key || typeof key !== "string") reject("key must be a string");
musicbot.youtubeKey = key;
musicbot.searcher.key = key;
resolve(musicbot);
});
};
client.on("ready", () => {
console.log(`------- Music Bot -------\n> Versão: ${PACKAGE.version}\n> Registro Extra: ${musicbot.logging}.\n> Versão do Node.js: ${process.version}\n------- Music Bot -------`);
if (musicbot.cooldown.exclude.includes("skip")) console.warn(`[MUSIC] Excluir o SKIP CMD das recargas pode causar problemas.`);
if (musicbot.cooldown.exclude.includes("remove")) console.warn(`[MUSIC] Excluir REMOVE CMD das recargas pode causar problemas.`);
setTimeout(() => { if (musicbot.musicPresence == true && musicbot.client.guilds.length > 1) console.warn(`[MUSIC] MusicPresence está ativado com mais de um servidor!`); }, 2000);
});
client.on("message", (msg) => {
if (msg.author.bot || musicbot.channelBlacklist.includes(msg.channel.id)) return;
if (musicbot.channelWhitelist.length > 0 && !musicbot.channelWhitelist.includes(msg.channel.id)) return;
const message = msg.content.trim();
const prefix = typeof musicbot.botPrefix == "object" ? (musicbot.botPrefix.has(msg.guild.id) ? musicbot.botPrefix.get(msg.guild.id).prefix : musicbot.defaultPrefix) : musicbot.botPrefix;
const command = message.substring(prefix.length).split(/[ \n]/)[0].trim();
const suffix = message.substring(prefix.length + command.length).trim();
const args = message.slice(prefix.length + command.length).trim().split(/ +/g);
if (message.startsWith(prefix) && msg.channel.type == "text") {
if (musicbot.commands.has(command)) {
let tCmd = musicbot.commands.get(command);
if (tCmd.enabled) {
if (!musicbot.cooldown.enabled == true && !musicbot.cooldown.exclude.includes(tCmd.masked)) {
if (musicbot.recentTalk.has(msg.author.id)) {
if (musicbot.cooldown.enabled == true && !musicbot.cooldown.exclude.includes(tCmd.masked)) return msg.channel.send(musicbot.note("fail", "Você deve esperar para usar os comandos de música novamente."));
}
musicbot.recentTalk.add(msg.author.id);
setTimeout(() => { musicbot.recentTalk.delete(msg.author.id) }, musicbot.cooldown.timer);
}
return musicbot[tCmd.run](msg, suffix, args);
}
} else if (musicbot.aliases.has(command)) {
let aCmd = musicbot.aliases.get(command);
if (aCmd.enabled) {
if (!musicbot.cooldown.enabled == true && !musicbot.cooldown.exclude.includes(aCmd.masked)) {
if (musicbot.recentTalk.has(msg.author.id)) {
if (musicbot.cooldown.enabled == true && !musicbot.cooldown.exclude.includes(aCmd.masked)) return msg.channel.send(musicbot.note("fail", "Você deve esperar para usar os comandos de música novamente."));
}
musicbot.recentTalk.add(msg.author.id);
setTimeout(() => { musicbot.recentTalk.delete(msg.author.id) }, musicbot.cooldown.timer);
}
return musicbot[aCmd.run](msg, suffix, args);
}
};
};
});
musicbot.playFunction = (msg, suffix, args, ignore) => {
if (msg.member.voiceChannel === undefined) return msg.channel.send(musicbot.note('fail', `Você não está em um canal de voz.`));
if (!suffix) return msg.channel.send(musicbot.note('fail', 'Nenhum vídeo especificado!'));
let q = musicbot.getQueue(msg.guild.id);
let vc = client.voiceConnections.find(val => val.channel.guild.id == msg.member.guild.id)
if (vc && vc.channel.id != msg.member.voiceChannel.id) return msg.channel.send(musicbot.note('fail', `Você deve estar no mesmo canal de voz que eu.`));
if (q.songs.length >= musicbot.maxQueueSize && musicbot.maxQueueSize !== 0) return msg.channel.send(musicbot.note('fail', 'Tamanho máximo da fila atingido!'));
var searchstring = suffix.trim();
if (searchstring.includes("https://youtu.be/") || searchstring.includes("https://www.youtube.com/") && searchstring.includes("&")) searchstring = searchstring.split("&")[0];
if (searchstring.startsWith('http') && searchstring.includes("list=")) {
msg.channel.send(musicbot.note("search", `Pesquisando itens da lista de reprodução~`));
var playid = searchstring.toString()
.split('list=')[1];
if (playid.toString()
.includes('?')) playid = playid.split('?')[0];
if (playid.toString()
.includes('&t=')) playid = playid.split('&t=')[0];
ytpl(playid, { limit: musicbot.maxQueueSize }, function (err, playlist) {
if (err) return msg.channel.send(musicbot.note('fail', `Ocorreu um erro ao buscar essa lista de reprodução!`));
if (playlist.items.length <= 0) return msg.channel.send(musicbot.note('fail', `Não foi possível obter nenhum vídeo dessa lista de reprodução.`));
if (playlist.total_items >= musicbot.maxQueueSize && musicbot.maxQueueSize != 0) return msg.channel.send(musicbot.note('fail', `Muitos vídeos para enfileirar. No máximo ` + musicbot.maxQueueSize + ` é permitido.`));
var index = 0;
var ran = 0;
var queue = musicbot.getQueue(msg.guild.id);
playlist.items.forEach(async (video) => {
ran++;
if (queue.songs.length == (musicbot.maxQueueSize + 1) && musicbot.maxQueueSize !== 0 || !video) return;
video.url = video.url_simple ? video.url_simple : `https://www.youtube.com/watch?v=` + video.id;
musicbot.playFunction(msg, video.url, [], true);
index++;
if (ran >= playlist.items.length) {
console.log(queue);
if (queue.songs.length >= 1) musicbot.executeQueue(msg, queue);
if (index == 0) msg.channel.send(musicbot.note('fail', `Você não pode obter nenhuma música dessa lista de reprodução!`))
else if (index == 1) msg.channel.send(musicbot.note('note', `Em fila uma música.`));
else if (index > 1) msg.channel.send(musicbot.note('note', `Músicas em fila ${index}.`));
}
});
});
} else {
if (!ignore) msg.channel.send(musicbot.note("search", `\`Procurando: ${searchstring}\`~`));
new Promise(async (resolve, reject) => {
let result = await musicbot.searcher.search(searchstring, { type: 'video' }).catch((err) => {
var errorMsg = err.message;
if (errorMsg.includes('\"reason\": \"dailyLimitExceeded\",')) {
errorMsg = errorMsg.slice(errorMsg.indexOf('Limite diário excedido. '));
errorMsg = errorMsg.slice(0, errorMsg.indexOf('\",'));
if (!ignore) msg.channel.send(musicbot.note("fail", "**Não foi possível concluir a reprodução:**\n" + errorMsg));
return;
} else if (errorMsg.includes('\"reason\": \"quotaExceeded\",')) {
if (!ignore) msg.channel.send(musicbot.note("fail", "Não foi possível concluir a reprodução! Cota da API do Google excedida!"));
return;
} else {
if (!ignore) msg.channel.send(musicbot.note("fail", "Ocorreu um erro desconhecido! Não foi possível concluir a reprodução. Verifique os registros para obter mais detalhes."));
return console.log(err);
}
});
if (result === undefined) return;
resolve(result.first)
}).then((res) => {
if (!res) return msg.channel.send(musicbot.note("fail", "Algo deu errado. Tente novamente!"));
res.requester = msg.author.id;
if (searchstring.startsWith("https://www.youtube.com/") || searchstring.startsWith("https://youtu.be/")) res.url = searchstring;
res.channelURL = `https://www.youtube.com/channel/${res.channelId}`;
res.queuedOn = new Date().toLocaleDateString(musicbot.dateLocal, { day: 'numeric', month: 'numeric', year: 'numeric', hour: 'numeric', minute: 'numeric' });
if (musicbot.requesterName) res.requesterAvatarURL = msg.author.displayAvatarURL;
const queue = musicbot.getQueue(msg.guild.id)
res.position = queue.songs.length ? queue.songs.length : 0;
queue.songs.push(res);
if (!ignore) {
if (msg.channel.permissionsFor(msg.guild.me).has('EMBED_LINKS')) {
const embed = new Discord.RichEmbed();
try {
embed.setAuthor('Adicionando à fila', client.user.avatarURL);
var songTitle = res.title.replace(/\\/g, '\\\\')
.replace(/\`/g, '\\`')
.replace(/\*/g, '\\*')
.replace(/_/g, '\\_')
.replace(/~/g, '\\~')
.replace(/`/g, '\\`');
embed.setColor(musicbot.embedColor);
embed.addField(res.channelTitle, `[${songTitle}](${res.url})`, musicbot.inlineEmbeds);
embed.addField("Adicionada no", res.queuedOn, musicbot.inlineEmbeds);
if (!musicbot.bigPicture) embed.setThumbnail(`https://img.youtube.com/vi/${res.id}/maxresdefault.jpg`);
if (musicbot.bigPicture) embed.setImage(`https://img.youtube.com/vi/${res.id}/maxresdefault.jpg`);
const resMem = client.users.get(res.requester);
if (musicbot.requesterName && resMem) embed.setFooter(`Requerido por ${client.users.get(res.requester).username}`, res.requesterAvatarURL);
if (musicbot.requesterName && !resMem) embed.setFooter(`Requerido por \`UnknownUser (ID: ${res.requester})\``, res.requesterAvatarURL);
msg.channel.send({
embed
});
} catch (e) {
console.error(`[${msg.guild.name}] [playCmd] ` + e.stack);
};
} else {
try {
var songTitle = res.title.replace(/\\/g, '\\\\')
.replace(/\`/g, '\\`')
.replace(/\*/g, '\\*')
.replace(/_/g, '\\_')
.replace(/~/g, '\\~')
.replace(/`/g, '\\`');
msg.channel.send(`Em reprodução: **${songTitle}**\nRequerido por:${client.users.get(res.requester).username}\nAdicionada no: ${res.queuedOn}`)
} catch (e) {
console.error(`[${msg.guild.name}] [npCmd] ` + e.stack);
};
};
};
if (queue.songs.length === 1 || !client.voiceConnections.find(val => val.channel.guild.id == msg.guild.id)) musicbot.executeQueue(msg, queue);
}).catch((res) => {
console.log(new Error(res));
});
};
};
musicbot.helpFunction = (msg, suffix, args) => {
const prefix = typeof musicbot.botPrefix == "object" ? (musicbot.botPrefix.has(msg.guild.id) ? musicbot.botPrefix.get(msg.guild.id).prefix : musicbot.defaultPrefix) : musicbot.botPrefix;
let command = suffix.trim();
if (!suffix) {
if (msg.channel.permissionsFor(msg.guild.me)
.has('EMBED_LINKS')) {
const embed = new Discord.RichEmbed();
embed.setAuthor("Comandos", client.user.avatarURL);
embed.setDescription(`Use \`${prefix}${musicbot.help.name} nome do comando para obter ajuda sobre o uso. Qualquer pessoa com uma função chamada \`${musicbot.djRole}\` pode usar qualquer comando.`);
// embed.addField(musicbot.helpCmd, musicbot.helpHelp);
const newCmds = Array.from(musicbot.commands);
let index = 0;
let max = musicbot.commandsArray.length;
embed.setColor(musicbot.embedColor);
for (var i = 0; i < musicbot.commandsArray.length; i++) {
if (!musicbot.commandsArray[i].exclude) embed.addField(musicbot.commandsArray[i].name, musicbot.commandsArray[i].help);
index++;
if (index == max) {
if (musicbot.messageHelp) {
let sent = false;
msg.author.send({
embed
})
.then(() => {
sent = true;
});
setTimeout(() => {
if (!sent) return msg.channel.send({
embed
});
}, 1200);
} else {
return msg.channel.send({
embed
});
};
}
};
} else {
var cmdmsg = `= Comandos de música =\nUse ${prefix}${musicbot.help.name} [comando] para obter ajuda sobre um comando. Qualquer pessoa com uma função chamada \`${musicbot.djRole}\` pode usar qualquer comando.\n`;
let index = 0;
let max = musicbot.commandsArray.length;
for (var i = 0; i < musicbot.commandsArray.length; i++) {
if (!musicbot.commandsArray[i].disabled || !musicbot.commandsArray[i].exclude) {
cmdmsg = cmdmsg + `\n• ${musicbot.commandsArray[i].name}: ${musicbot.commandsArray[i].help}`;
index++;
if (index == musicbot.commandsArray.length) {
if (musicbot.messageHelp) {
let sent = false;
msg.author.send(cmdmsg, {
code: 'asciidoc'
})
.then(() => {
sent = true;
});
setTimeout(() => {
if (!sent) return msg.channel.send(cmdmsg, {
code: 'asciidoc'
});
}, 500);
} else {
return msg.channel.send(cmdmsg, {
code: 'asciidoc'
});
};
}
};
};
};
} else if (musicbot.commands.has(command) || musicbot.aliases.has(command)) {
if (msg.channel.permissionsFor(msg.guild.me)
.has('EMBED_LINKS')) {
const embed = new Discord.RichEmbed();
command = musicbot.commands.get(command) || musicbot.aliases.get(command);
if (command.exclude) return msg.channel.send(musicbot.note('fail', `${suffix} não é um comando válido!`));
embed.setAuthor(command.name, msg.client.user.avatarURL);
embed.setDescription(command.help);
if (command.alt.length > 0) embed.addField(`Aliases`, command.alt.join(", "), musicbot.inlineEmbeds);
if (command.usage && typeof command.usage == "string") embed.addField(`Uso`, command.usage.replace(/{{prefix}}/g, prefix), musicbot.inlineEmbeds);
embed.setColor(musicbot.embedColor);
msg.channel.send({
embed
});
} else {
command = musicbot.commands.get(command) || musicbot.aliases.get(command);
if (command.exclude) return msg.channel.send(musicbot.note('fail', `${suffix} is not a valid command!`));
var cmdhelp = `= ${command.name} =\n`;
cmdhelp = cmdhelp + `\n${command.help}`;
if (command.usage !== null) cmdhelp = cmdhelp + `\nComo usar: ${command.usage.replace(/{{prefix}}/g, prefix)}`;
if (command.alt.length > 0) cmdhelp = cmdhelp + `\nAliases: ${command.alt.join(", ")}`;
msg.channel.send(cmdhelp, {
code: 'asciidoc'
});
};
} else {
msg.channel.send(musicbot.note('fail', `${suffix} não é um comando válido!`));
};
};
musicbot.skipFunction = (msg, suffix, args) => {
if (!msg.member.voiceChannel) return msg.channel.send(musicbot.note('fail', `Você não está em um canal de voz.`));
const voiceConnection = client.voiceConnections.find(val => val.channel.guild.id == msg.guild.id);
if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'Nenhuma música sendo tocada.'));
if (voiceConnection && voiceConnection.channel.id != msg.member.voiceChannel.id) return msg.channel.send(musicbot.note('fail', `Você deve estar no mesmo canal de voz que eu.`));
const queue = musicbot.getQueue(msg.guild.id);
if (!musicbot.canSkip(msg.member, queue)) return msg.channel.send(musicbot.note('fail', `Você não pode pular isso porque não o colocou na fila.`));
if (musicbot.queues.get(msg.guild.id).loop == "song") return msg.channel.send(musicbot.note("fail", "Não é possível pular enquanto o loop está definido como único."));
const dispatcher = voiceConnection.player.dispatcher;
if (!dispatcher || dispatcher === null) {
if (musicbot.logging) return console.log(new Error(`dispatcher null on skip cmd [${msg.guild.name}] [${msg.author.username}]`));
return msg.channel.send(musicbot.note("fail", "Ocorreu um erro ao pular."));
};
if (voiceConnection.paused) dispatcher.end();
dispatcher.end();
msg.channel.send(musicbot.note("note", "Música pulada."));
};
musicbot.pauseFunction = (msg, suffix, args) => {
if (!msg.member.voiceChannel) return msg.channel.send(musicbot.note('fail', `Você não está em um canal de voz.`));
const voiceConnection = client.voiceConnections.find(val => val.channel.guild.id == msg.guild.id);
if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'Nenhuma música sendo tocada.'));
if (voiceConnection && voiceConnection.channel.id != msg.member.voiceChannel.id) return msg.channel.send(musicbot.note('fail', `Você deve estar no mesmo canal de voz que eu.`));
if (!musicbot.isAdmin(msg.member) && !musicbot.anyoneCanPause) return msg.channel.send(musicbot.note('fail', 'Você não pode pausar filas.'));
const dispatcher = voiceConnection.player.dispatcher;
if (dispatcher.paused) return msg.channel.send(musicbot.note(`fail`, `Música já pausada!`))
else dispatcher.pause();
msg.channel.send(musicbot.note('note', 'Reprodução pausada.'));
};
musicbot.resumeFunction = (msg, suffix, args) => {
if (!msg.member.voiceChannel) return msg.channel.send(musicbot.note('fail', `Você não está em um canal de voz.`));
const voiceConnection = client.voiceConnections.find(val => val.channel.guild.id == msg.guild.id);
if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'Nenhuma música sendo tocada.'));
if (voiceConnection && voiceConnection.channel.id != msg.member.voiceChannel.id) return msg.channel.send(musicbot.note('fail', `Você deve estar no mesmo canal de voz que eu.`));
if (!musicbot.isAdmin(msg.member) && !musicbot.anyoneCanPause) return msg.channel.send(musicbot.note('fail', `Você não pode retomar filas.`));
const dispatcher = voiceConnection.player.dispatcher;
if (!dispatcher.paused) return msg.channel.send(musicbot.note('fail', `Música já tocando.`))
else dispatcher.resume();
msg.channel.send(musicbot.note('note', 'A reprodução foi retomada.'));
};
musicbot.leaveFunction = (msg, suffix) => {
if (musicbot.isAdmin(msg.member) || musicbot.anyoneCanLeave === true) {
if (!msg.member.voiceChannel) return msg.channel.send(musicbot.note('fail', `Você não está em um canal de voz.`));
const voiceConnection = client.voiceConnections.find(val => val.channel.guild.id == msg.guild.id);
if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'Não estou em um canal de voz.'));
if (voiceConnection && voiceConnection.channel.id != msg.member.voiceChannel.id) return msg.channel.send(musicbot.note('fail', `Você deve estar no mesmo canal de voz que eu.`));
musicbot.emptyQueue(msg.guild.id).then(() => {
if (!voiceConnection.player.dispatcher) return;
voiceConnection.player.dispatcher.end();
voiceConnection.disconnect();
msg.channel.send(musicbot.note('note', 'Saiu do canal de voz com sucesso.'));
}).catch((res) => {
console.log("[" + msg.guild.id + "] " + res);
musicbot.queues.delete(msg.guild.id);
musicbot.queues.set(msg.guild.id, { songs: [], last: null, loop: "none", id: msg.guild.id, volume: musicbot.defVolume, oldSongs: [], working: false, needsRefresh: false });
})
} else {
const chance = Math.floor((Math.random() * 100) + 1);
if (chance <= 10) return msg.channel.send(musicbot.note('fail', `Receio não poder deixar você fazer isso, ${msg.author.username}.`))
else return msg.channel.send(musicbot.note('fail', 'Desculpe, você não tem permissão para fazer isso.'));
}
}
musicbot.npFunction = (msg, suffix, args) => {
const voiceConnection = client.voiceConnections.find(val => val.channel.guild.id == msg.guild.id);
if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'Nenhuma música está sendo tocada.'));
const queue = musicbot.getQueue(msg.guild.id, true);
const dispatcher = voiceConnection.player.dispatcher;
if (musicbot.queues.get(msg.guild.id).songs.length <= 0) return msg.channel.send(musicbot.note('note', 'Fila vazia.'));
if (msg.channel.permissionsFor(msg.guild.me)
.has('EMBED_LINKS')) {
const embed = new Discord.RichEmbed();
try {
embed.setAuthor('Tocando agora', client.user.avatarURL);
var songTitle = queue.last.title.replace(/\\/g, '\\\\')
.replace(/\`/g, '\\`')
.replace(/\*/g, '\\*')
.replace(/_/g, '\\_')
.replace(/~/g, '\\~')
.replace(/`/g, '\\`');
embed.setColor(musicbot.embedColor);
embed.addField(queue.last.channelTitle, `[${songTitle}](${queue.last.url})`, musicbot.inlineEmbeds);
embed.addField("Adicionada no", queue.last.queuedOn, musicbot.inlineEmbeds);
if (!musicbot.bigPicture) embed.setThumbnail(`https://img.youtube.com/vi/${queue.last.id}/maxresdefault.jpg`);
if (musicbot.bigPicture) embed.setImage(`https://img.youtube.com/vi/${queue.last.id}/maxresdefault.jpg`);
const resMem = client.users.get(queue.last.requester);
if (musicbot.requesterName && resMem) embed.setFooter(`Requerido por ${client.users.get(queue.last.requester).username}`, queue.last.requesterAvatarURL);
if (musicbot.requesterName && !resMem) embed.setFooter(`Requerido por \`UnknownUser (ID: ${queue.last.requester})\``, queue.last.requesterAvatarURL);
msg.channel.send({
embed
});
} catch (e) {
console.error(`[${msg.guild.name}] [npCmd] ` + e.stack);
};
} else {
try {
var songTitle = queue.last.title.replace(/\\/g, '\\\\')
.replace(/\`/g, '\\`')
.replace(/\*/g, '\\*')
.replace(/_/g, '\\_')
.replace(/~/g, '\\~')
.replace(/`/g, '\\`');
msg.channel.send(`Em reprodução: **${songTitle}**\nRequerido por:${client.users.get(queue.last.requester).username}\nAdicionada no: ${queue.last.queuedOn}`)
} catch (e) {
console.error(`[${msg.guild.name}] [npCmd] ` + e.stack);
};
}
};
musicbot.deleteQueueFunction = async (msg, suffix, args) => {
if (!musicbot.isAdmin(msg.member)) return msg.channel.send(musicbot.note("fail", "Somente Admin e podem fazer isso."));
const voiceConnection = client.voiceConnections.find(val => val.channel.guild.id == msg.guild.id);
musicbot.emptyQueue(msg.guild.id).then(() => {
if (voiceConnection !== null) {
const dispatcher = voiceConnection.player.dispatcher;
dispatcher.end()
}
return msg.channel.send(musicbot.note("note", "A fila agora deve ser esvaziada."))
}).catch(async (res) => {
console.log("[" + msg.guild.id + "] " + e);
// force the queue delete
musicbot.queues.delete(msg.guild.id);
musicbot.queues.set(msg.guild.id, { songs: [], last: null, loop: "none", id: msg.guild.id, volume: musicbot.defVolume, oldSongs: [], working: false, needsRefresh: false });
if (voiceConnection !== null) {
const dispatcher = voiceConnection.player.dispatcher;
dispatcher.end()
}
msg.channel.send(musicbot.note("note", "A fila agora deve ser excluída."))
})
}
musicbot.queueFunction = (msg, suffix, args) => {
if (!msg.member.voiceChannel) return msg.channel.send(musicbot.note('fail', `Você não está em um canal de voz.`));
const voiceConnection = client.voiceConnections.find(val => val.channel.guild.id == msg.guild.id);
if (voiceConnection === null) return msg.channel.send(musicbot.note('fail', 'Nenhuma música sendo tocada.'));
if (voiceConnection && voiceConnection.channel.id != msg.member.voiceChannel.id) return msg.channel.send(musicbot.note('fail', `Você deve estar no mesmo canal de voz que eu.`));
if (!musicbot.queues.has(msg.guild.id)) return msg.channel.send(musicbot.note("fail", "Não foi possível encontrar uma fila para este servidor."));
else if (musicbot.queues.get(msg.guild.id).songs.length <= 0) return msg.channel.send(musicbot.note("fail", "A fila está vazia."));
const queue = musicbot.queues.get(msg.guild.id);
if (suffix) {
let video = queue.songs.find(s => s.position == parseInt(suffix) - 1);
if (!video) return msg.channel.send(musicbot.note("fail", "Não foi possível encontrar o vídeo."));
const embed = new Discord.RichEmbed()
.setAuthor('Queued Song', client.user.avatarURL)
.setColor(musicbot.embedColor)
.addField(video.channelTitle, `[${video.title.replace(/\\/g, '\\\\').replace(/\`/g, '\\`').replace(/\*/g, '\\*').replace(/_/g, '\\_').replace(/~/g, '\\~').replace(/`/g, '\\`')}](${video.url})`, musicbot.inlineEmbeds)
.addField("Adicionada no", video.queuedOn, musicbot.inlineEmbeds)
.addField("Position", video.position + 1, musicbot.inlineEmbeds);
if (!musicbot.bigPicture) embed.setThumbnail(`https://img.youtube.com/vi/${video.id}/maxresdefault.jpg`);
if (musicbot.bigPicture) embed.setImage(`https://img.youtube.com/vi/${video.id}/maxresdefault.jpg`);
const resMem = client.users.get(video.requester);
if (musicbot.requesterName && resMem) embed.setFooter(`Requerido por ${client.users.get(video.requester).username}`, video.requesterAvatarURL);
if (musicbot.requesterName && !resMem) embed.setFooter(`Requerido por \`UnknownUser (ID: ${video.requester})\``, video.requesterAvatarURL);
msg.channel.send({ embed });
} else {
if (queue.songs.length > 11) {
let pages = [];
let page = 1;
const newSongs = queue.songs.musicArraySort(10);
newSongs.forEach(s => {
var i = s.map((video, index) => (