diff --git a/commands/Music/play.js b/commands/Music/play.js index 7a9ac18..ddcbb9a 100644 --- a/commands/Music/play.js +++ b/commands/Music/play.js @@ -1,4 +1,6 @@ +const Youtube = require("simple-youtube-api"); const ytdl = require("ytdl-core"); +const youtube = new Youtube(process.env.YOUTUBEAPI); exports.run = async (client, message, args, level) => { /* @@ -17,8 +19,10 @@ exports.run = async (client, message, args, level) => { play(connection, message); }) */ - const queue = message.client.queue; - const serverQueue = message.client.queue.get(message.guild.id); + + /* + const queue = client.queue; + const serverQueue = client.queue.get(message.guild.id); const voiceChannel = message.member.voiceChannel; if(!voiceChannel) return message.reply("you need to be in a voice channel to use this command!"); @@ -50,13 +54,171 @@ exports.run = async (client, message, args, level) => { queueConstruct.connection = connection; this.play(message, queueConstruct.songs[0]); } catch(err) { - client.Logger.error(err); + client.logger.error(err); queue.delete(message.guild.id); - return message.channel.send(`Uh oh! Looks like I hit a snag. Here's the error that Node picked up: ${err}`); + return message.channel.send(`Uh oh! Looks like I hit a snag. Here's the error that Node picked up: \`${err}\``); } } else { serverQueue.songs.push(song); - return message.channel.send(`${song.title} has been added to the queue!`); + return message.channel.send(`**${song.title}** has been added to the queue!`); + } + */ + + const query = args[0]; + + var voiceChannel = message.author.voiceChannel; + if (!voiceChannel) return message.reply("you need to be in a voice channel to use this command!"); + + if(query.match(/^(?!.*\?.*\bv=)https:\/\/www\.youtube\.com\/.*\?.*\blist=.*%/)) { + try { + const playlist = await youtube.getPlaylist(query); + const videosObj = await playlist.getVideos(); + + for (let i = 0; i < videosObj.length; i++) { + const video = await videosObj[i].fetch(); + + const url = `https://www.youtube.com/watch?v=${video.raw.id}`; + const title = video.raw.snippet.title; + let duration = this.formatDuration(video.duration); + const thumbnail = video.thumbnails.high.url; + if (duration == "00:00") duration = "Live Stream"; + + const song = { + url, + title, + duration, + thumbnail, + voiceChannel + }; + + message.guild.musicData.push(song); + } + if(message.guild.musicData.isPlaying == false) { + message.guild.musicData.isPlaying == true; + return this.playSong(message.guild.musicData.queue, message); + } else if (message.guild.musicData.isPlaying == true) { + return message.channel.send(`Playlist - :musical_note: ${playlist.title} :musical_note: has been added to the queue.`); + } + } catch (err) { + client.logger.error(err); + return message.reply("that playlist is either private or doesn't exist!"); + } + } + if(query.match(/^(http(s)?:\/\/)?((w){3}.)?youtu(be|.be)?(\.com)?\/.+/)) { + const url = query; + try { + query = query.replace(/(>|<)/gi, "").split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/); + + const id = query[2].split(/[^0-9a-z_\-]/i)[0]; + const video = await youtube.getVideoByID(id); + const title = video.title; + let duration = this.formatDuration(video.duration); + const thumbnail = video.thumbnails.high.url; + if(duration == "00:00") duration = "Live Stream"; + const song = { + url, + title, + duration, + thumbnail, + voiceChannel + }; + message.guild.musicData.queue.push(song); + if(message.guild.musicData.isPlaying == false || typeof message.guild.musicData.isPlaying == "undefined") { + message.guild.musicData.isPlaying = true; + return this.playSong(message.guild.musicData.queue, message); + } else if(message.guild.musicData.isPlaying == true) { + return message.channel.send(`${song.title} has been added to the queue.`); + } + } catch (err) { + client.logger.error(err); + return message.channel.send("Uh oh! Looks like I hit a snag. Ask a bot administrator to check the console."); + } + } + try { + const videos = await youtube.searchVideos(query, 5); + if(videos.length < 5) { + return message.reply("it seems I had some trouble finding what you requested. Please try again or be more specific."); + } + const vidNameArr = []; + for(let i = 0; i < videos.length; i++) { + vidNameArr.push(`${i + 1}: ${videos[i].title}`); + } + vidNameArr.push("exit"); + + const embed = new client.embed("Top 5 songs found", "Please select a song from the list below.", [ + { + name: "**__Song 1__**", + value: vidNameArr[0] + } + { + name: "**__Song 2__**", + value: vidNameArr[1] + } + { + name: "**__Song 3__**", + value: vidNameArr[2] + } + { + name: "**__Song 4__**", + value: vidNameArr[3] + } + { + name: "**__Song 5__**", + value: vidNameArr[4] + } + ], + { + author: message.author.tag, + authorIcon: message.author.avatarURL + }); + var songEmbed = await message.channel.send({ embed }); + + try { + var response = await message.channel.awaitMessages( + msg => (msg.content > 0 && msg.content < 6) || msg.content === "exit", + { + max: 1, + maxProcessed: 1, + time: 20000, + errors: ["time"] + } + ); + + var videoIndex = parseInt(response.first().content) + } catch (err) { + client.logger.error(err); + songEmbed.delete(); + return message.reply("Please try again, and enter a valid number from 1 to 5.\n*(Hint: you can exit this menu by responding with \`exit\`)*"); + } + const url = `https://www.youtube.com/watch?v=${video.raw.id}`; + const title = video.title; + let duration = this.formatDuration(video.duration); + const thumbnail = video.thumbnails.high.url; + if(duration == "00:00") duration = "Live Stream"; + const song = { + url, + title, + duration, + thumbnail, + voiceChannel + }; + + message.guild.musicData.queue.push(song); + + if(message.guild.musicData.isPlaying == false) { + message.guild.musicData.isPlaying = true; + songEmbed.delete(); + this.playSong(message.guild.musicData.queue, message); + } else if(message.guild.musicData.isPlaying == true) { + songEmbed.delete(); + return message.channel.send(`${song.title} has been added to queue.`); + } + } catch (err) { + console.error(err); + if (songEmbed) { + songEmbed.delete(); + } + return message.channel.send("Something went wrong playing one of the songs, is its source private?"); } }; @@ -74,6 +236,7 @@ exports.help = { usage: "play [url]" }; +/* function play(message, song) { const queue = client.queue; const guild = message.guild; @@ -97,3 +260,70 @@ function play(message, song) { }); dispatcher.setVolumeLogarithmic(serverQueue.volume / 5); }; +*/ + +function playSong(queue, message) { + let voiceChannel; + queue[0].voiceChannel + .join() + .then(connection => { + const dispatcher = connection + .play( + ytdl(queue[0].url, { + quality: "highestaudio", + highWaterMark: 1024 * 1024 * 10 + }) + ) + .on("start", () => { + message.guild.musicData.songDispatcher = dispatcher; + voiceChannel = queue[0].voiceChannel; + + const videoEmbed = client.embed("", "", [ + { + name: "**__Now Playing__**", + value: queue[0].title + }, + { + name: "**__Duration__**", + value: queue[0].duration + } + ], + { + thumbnail: queue[0].thumbnail + }); + if (queue[1]) videoEmbed.addField("Next Up:", queue[1].title); + message.channel.send(videoEmbed); + return queue.shift(); + }) + .on("finish", () => { + if (queue.length >= 1) { + return this.playSong(queue, message); + } else { + message.guild.musicData.isPlaying = false; + return voiceChannel.leave(); + } + }) + .on("error", e => { + message.channel.send("I couldn't play that song!"); + console.error(e); + return voiceChannel.leave(); + }); + }) + .catch(e => { + console.error(e); + return voiceChannel.leave(); + }); +} + +function formatDuration(durationObj) { + const duration = `${durationObj.hours ? durationObj.hours + ":" : ""}${ + durationObj.minutes ? durationObj.minutes : "00" + }:${ + durationObj.seconds < 10 + ? "0" + durationObj.seconds + : durationObj.seconds + ? durationObj.seconds + : "00" + }`; + return duration; +} diff --git a/commands/Music/stop.js b/commands/Music/stop.js index 161c887..aeeca48 100644 --- a/commands/Music/stop.js +++ b/commands/Music/stop.js @@ -1,5 +1,4 @@ exports.run = async (client, message, args, level) => { - /* var server = client.servers[message.guild.id]; if(message.guild.voiceConnection) { for(var i = server.queue.length -1; i >= 0; i--) { @@ -7,17 +6,23 @@ exports.run = async (client, message, args, level) => { } if(server.dispatcher) server.dispatcher.end(); - message.channel.send(`${message.author.mention} has stopped the music.`); + message.channel.send(`${message.author} has stopped the music.`); } if(message.guild.voiceConnection) message.guild.voiceConnection.disconnect(); - */ - const serverQueue = message.client.queue.get(message.guild.id); + + /* + const serverQueue = client.queue.get(message.guild.id); if (!message.member.voiceChannel) return message.channel.send('You have to be in a voice channel to stop the music!'); serverQueue.songs = []; - serverQueue.connection.dispatcher.end(); - message.channel.send(`${message.author.mention} has stopped the music.`); + if(serverQueue.connection.dispatcher) serverQueue.connection.dispatcher.end(); + message.channel.send(`${message.author} has stopped the music.`); + + if(message.guild.voiceConnection) message.guild.voiceConnection.disconnect(); + */ + + }; exports.conf = { diff --git a/commands/test.js b/commands/test.js index 95d3fbf..d408a6a 100644 --- a/commands/test.js +++ b/commands/test.js @@ -3,20 +3,20 @@ const got = require("got"); exports.run = async (client, message, args, level) => { const pgAmount = args[0] || 2; const out = await got(`https://loripsum.net/api/${pgAmount}/decorate/code`); - + let final = out.body; - final = final.then( - .replace("", "**")).then( - .replace("", "**")).then( - .replace("

", "")).then( - .replace("

", "")).then( - .replace("", "_")).then( - .replace("", "_")).then( - .replace("", "||").then( - .replace("", "||").then( - .replace("
","```").then(
+  final = final
+  	.replace("", "**")
+  	.replace("", "**")
+  	.replace("

", "") + .replace("

", "") + .replace("", "_") + .replace("", "_") + .replace("", "||") + .replace("", "||") + .replace("
","```")
   	.replace("
","```"); - + message.channel.send(final); }; @@ -32,4 +32,4 @@ exports.help = { category: "", description: "Sends randomly-generated Lorem Ipsum demo text.", usage: "test [paragraphCount:2]" -}; \ No newline at end of file +}; diff --git a/index.js b/index.js index af647e3..892235e 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ if (Number(process.version.slice(1).split(".")[0]) < 8) throw new Error("Node 8.0.0 or higher is required. Update Node on your system."); const Discord = require("discord.js"); +const { Structures } = require("discord.js"); const { promisify } = require("util"); const readdir = promisify(require("fs").readdir); @@ -14,9 +15,25 @@ client.logger = require("./modules/Logger"); require("./modules/functions.js")(client); client.commands = new Enmap(); client.aliases = new Enmap(); -client.queue = new Enmap(); +client.queue = new Map(); client.settings = new Enmap({name: "settings"}); +/* +Structures.extend("Guild", Guild => { + class MusicGuild extends Guild { + constructor(client, data) { + super(client, data); + this.musicData = { + queue: [], + isPlaying: false, + songDispatcher: null + }; + } + } + return MusicGuild; +}); +*/ + async function crawl(directory, filesArray) { const dirs = await readdir(directory, { withFileTypes: true