|
|
|
@ -4,6 +4,7 @@ const Discord = require("discord.js"),
|
|
|
|
|
yttl = require('get-youtube-title'),
|
|
|
|
|
args = require('args-parser')(process.argv),
|
|
|
|
|
config = require('../config.json'),
|
|
|
|
|
utils = require('./utils.js'),
|
|
|
|
|
ytapiKey = args.ytapi || config.ytapikey;
|
|
|
|
|
/* Variable Definition */
|
|
|
|
|
let logger = require('winston');
|
|
|
|
@ -46,6 +47,17 @@ exports.DJ = class {
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Defining setter for listenOnRepeat to include the current song into the repeating loop.
|
|
|
|
|
* @param value
|
|
|
|
|
*/
|
|
|
|
|
set listenOnRepeat(value) {
|
|
|
|
|
this.repeat = value;
|
|
|
|
|
if (this.current) {
|
|
|
|
|
this.queue.push(this.current);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns if a connection exists
|
|
|
|
|
* @returns {boolean}
|
|
|
|
@ -100,84 +112,83 @@ exports.DJ = class {
|
|
|
|
|
* @param playnext
|
|
|
|
|
*/
|
|
|
|
|
playYouTube(url, playnext) {
|
|
|
|
|
/** Commented because it causes an connection overflow error.
|
|
|
|
|
* TODO: Decide to either fix this with promises or ignore it because connection checks are performed by the guild handler.**/
|
|
|
|
|
/*
|
|
|
|
|
if (!this.connected) {
|
|
|
|
|
this.connect().then(this.playYouTube(url));
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
let plist = url.match(/(?<=\?list=)[\w\-]+/);
|
|
|
|
|
let plist = utils.YouTube.getPlaylistIdFromUrl(url);
|
|
|
|
|
if (plist) {
|
|
|
|
|
logger.debug(`Adding playlist ${plist} to queue`);
|
|
|
|
|
ypi(ytapiKey, plist).then(items => {
|
|
|
|
|
for (let i = 0; i < items.length; i++) {
|
|
|
|
|
let vurl = `https://www.youtube.com/watch?v=${items[i].resourceId.videoId}`;
|
|
|
|
|
this.queue.push({'url': vurl, 'title': null});
|
|
|
|
|
yttl(vurl.replace(/http(s)?:\/\/(www.)?youtube.com\/watch\?v=/g, ''), (err, title) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
logger.debug(JSON.stringify(err));
|
|
|
|
|
} else {
|
|
|
|
|
try {
|
|
|
|
|
logger.debug(`Found title: ${title} for ${vurl}`);
|
|
|
|
|
this.queue.find((el) => {
|
|
|
|
|
return (el.url === vurl);
|
|
|
|
|
}).title = title;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.verbose(JSON.stringify(error));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
let firstSong = utils.YouTube.getVideoUrlFromId(items.shift().resourceId.videoId);
|
|
|
|
|
|
|
|
|
|
this.getVideoName(firstSong).then((title) => { // getting the first song to start playing music
|
|
|
|
|
if (this.repeat) // listen on repeat
|
|
|
|
|
this.queue.push({'url': firstSong, 'title': title}); // put the current song back at the end of the queue
|
|
|
|
|
this.playYouTube(firstSong); // call with single url that gets queued if a song is already playing
|
|
|
|
|
}).catch((err) => logger.error(err.message));
|
|
|
|
|
for (let item of items) {
|
|
|
|
|
let vurl = utils.YouTube.getVideoUrlFromId(item.resourceId.videoId);
|
|
|
|
|
this.getVideoName(vurl).then((title) => {
|
|
|
|
|
this.queue.push({'url': vurl, 'title': title});
|
|
|
|
|
}).catch((err) => logger.error(err.message));
|
|
|
|
|
}
|
|
|
|
|
this.current = this.queue.shift();
|
|
|
|
|
if (this.repeat) this.queue.push(this.current);
|
|
|
|
|
this.playYouTube(this.current.url);
|
|
|
|
|
logger.debug(`Added ${items.length} songs to the queue`);
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!this.playing || !this.disp) {
|
|
|
|
|
logger.debug(`Playing ${url}`);
|
|
|
|
|
this.disp = this.conn.playStream(ytdl(url, {
|
|
|
|
|
filter: 'audioonly',
|
|
|
|
|
quality: this.quality,
|
|
|
|
|
liveBuffer: 40000
|
|
|
|
|
}), {volume: this.volume});
|
|
|
|
|
this.disp.on('end', (reason) => {
|
|
|
|
|
if (reason !== 'stop') {
|
|
|
|
|
this.playing = false;
|
|
|
|
|
this.current = null;
|
|
|
|
|
if (this.queue.length > 0) {
|
|
|
|
|
this.current = this.queue.shift();
|
|
|
|
|
if (this.repeat) this.queue.push(this.current);
|
|
|
|
|
this.playYouTube(this.current.url);
|
|
|
|
|
} else {
|
|
|
|
|
this.stop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.playing = true;
|
|
|
|
|
} else {
|
|
|
|
|
logger.debug(`Added ${url} to the queue`);
|
|
|
|
|
if (playnext) {
|
|
|
|
|
this.queue.unshift({'url': url, 'title': null});
|
|
|
|
|
if (!this.playing || !this.disp) {
|
|
|
|
|
logger.debug(`Playing ${url}`);
|
|
|
|
|
|
|
|
|
|
this.getVideoName(url).then((title) => {
|
|
|
|
|
this.current = ({'url': url, 'title': title});
|
|
|
|
|
|
|
|
|
|
this.disp = this.conn.playStream(ytdl(url, {
|
|
|
|
|
filter: 'audioonly', quality: this.quality, liveBuffer: 40000
|
|
|
|
|
}), {volume: this.volume});
|
|
|
|
|
|
|
|
|
|
this.disp.on('end', (reason) => { // end event triggers the next song to play when the reason is not stop
|
|
|
|
|
if (reason !== 'stop') {
|
|
|
|
|
this.playing = false;
|
|
|
|
|
this.current = null;
|
|
|
|
|
if (this.queue.length > 0) {
|
|
|
|
|
this.current = this.queue.shift();
|
|
|
|
|
if (this.repeat) // listen on repeat
|
|
|
|
|
this.queue.push(this.current);
|
|
|
|
|
this.playYouTube(this.current.url);
|
|
|
|
|
} else {
|
|
|
|
|
this.stop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.playing = true;
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
this.queue.push({'url': url, 'title': null});
|
|
|
|
|
logger.debug(`Added ${url} to the queue`);
|
|
|
|
|
if (playnext) {
|
|
|
|
|
this.getVideoName(url).then((title) => {
|
|
|
|
|
this.queue.unshift({'url': url, 'title': title});
|
|
|
|
|
}).catch((err) => logger.error(err.message));
|
|
|
|
|
} else {
|
|
|
|
|
this.getVideoName(url).then((title) => {
|
|
|
|
|
this.queue.push({'url': url, 'title': title});
|
|
|
|
|
}).catch((err) => logger.error(err.message));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
yttl(url.replace(/http(s)?:\/\/(www.)?youtube.com\/watch\?v=/g, ''), (err, title) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets the name of the YouTube Video at url
|
|
|
|
|
* @param url
|
|
|
|
|
* @returns {Promise<>}
|
|
|
|
|
*/
|
|
|
|
|
getVideoName(url) {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
yttl(utils.YouTube.getVideoIdFromUrl(url), (err, title) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
logger.debug(JSON.stringify(err));
|
|
|
|
|
reject(err);
|
|
|
|
|
} else {
|
|
|
|
|
try {
|
|
|
|
|
logger.debug(`Found title: ${title} for ${url}`);
|
|
|
|
|
this.queue.find((el) => {
|
|
|
|
|
return (el.url === url);
|
|
|
|
|
}).title = title;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.verbose(JSON.stringify(error));
|
|
|
|
|
}
|
|
|
|
|
resolve(title);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|