UNPKG

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
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) => (