|
|
|
@ -22,7 +22,16 @@ class DJ {
|
|
|
|
|
this.voiceChannel = voiceChannel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Connects to the given voice channel. Disconnects from the previous one if it exists.
|
|
|
|
|
* When the bot was moved and connect is executed again, it connects to the initial VoiceChannel because the
|
|
|
|
|
* VoiceChannel is saved as object variable.
|
|
|
|
|
* @returns {Promise<T | never>}
|
|
|
|
|
*/
|
|
|
|
|
connect() {
|
|
|
|
|
if (this.conn) {
|
|
|
|
|
this.stop();
|
|
|
|
|
}
|
|
|
|
|
logger.verbose(`Connecting to voiceChannel ${this.voiceChannel.name}`);
|
|
|
|
|
return this.voiceChannel.join().then(connection => {
|
|
|
|
|
logger.info(`Connected to Voicechannel ${this.voiceChannel.name}`);
|
|
|
|
@ -30,6 +39,11 @@ class DJ {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Plays a file for the given filename.
|
|
|
|
|
* TODO: Implement queue
|
|
|
|
|
* @param filename
|
|
|
|
|
*/
|
|
|
|
|
playFile(filename) {
|
|
|
|
|
if (this.conn !== null) {
|
|
|
|
|
this.disp = this.conn.playFile(filename);
|
|
|
|
@ -42,6 +56,12 @@ class DJ {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Plays the url of the current song if there is no song playing or puts it in the queue.
|
|
|
|
|
* If the url is a playlist (regex match), the videos of the playlist are fetched and put
|
|
|
|
|
* in the queue. For each song the title is saved in the queue too.
|
|
|
|
|
* @param url
|
|
|
|
|
*/
|
|
|
|
|
playYouTube(url) {
|
|
|
|
|
if (!this.conn) this.connect(this.voiceChannel).then(this.playYouTube(url));
|
|
|
|
|
let plist = url.match(/(?<=\?list=)[\w\-]+/g);
|
|
|
|
@ -55,13 +75,19 @@ class DJ {
|
|
|
|
|
if (err) {
|
|
|
|
|
logger.error(err);
|
|
|
|
|
} else {
|
|
|
|
|
this.queue.find((el) => {
|
|
|
|
|
return (el.url === vurl);
|
|
|
|
|
}).title = title;
|
|
|
|
|
try {
|
|
|
|
|
logger.debug(`Found title: ${title} for ${vurl}`);
|
|
|
|
|
this.queue.find((el) => {
|
|
|
|
|
return (el.url === vurl);
|
|
|
|
|
}).title = title;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.error(JSON.stringify(error));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
this.playYouTube(this.queue.shift().url);
|
|
|
|
|
this.current = this.queue.shift();
|
|
|
|
|
this.playYouTube(this.current.url);
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -74,7 +100,7 @@ class DJ {
|
|
|
|
|
this.playing = false;
|
|
|
|
|
this.current = null;
|
|
|
|
|
if (this.queue.length > 0) {
|
|
|
|
|
this.current = this.queue.shift()
|
|
|
|
|
this.current = this.queue.shift();
|
|
|
|
|
this.playYouTube(this.current.url);
|
|
|
|
|
} else {
|
|
|
|
|
this.stop();
|
|
|
|
@ -83,19 +109,41 @@ class DJ {
|
|
|
|
|
this.playing = true;
|
|
|
|
|
} else {
|
|
|
|
|
logger.debug(`Added ${url} to the queue`);
|
|
|
|
|
this.queue.push(url);
|
|
|
|
|
this.queue.push({'url': url, 'title': null});
|
|
|
|
|
yttl(url.replace(/http(s)?:\/\/(www.)?youtube.com\/watch\?v=/g, ''), (err, title) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
logger.error(err);
|
|
|
|
|
} else {
|
|
|
|
|
try {
|
|
|
|
|
logger.debug(`Found title: ${title} for ${url}`);
|
|
|
|
|
this.queue.find((el) => {
|
|
|
|
|
return (el.url === url);
|
|
|
|
|
}).title = title;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(JSON.stringify(error));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the volume of the dispatcher to the given value
|
|
|
|
|
* @param percentage
|
|
|
|
|
*/
|
|
|
|
|
setVolume(percentage) {
|
|
|
|
|
logger.verbose(`Setting volume to ${percentage}`);
|
|
|
|
|
if (this.disp !== null) {
|
|
|
|
|
this.volume = percentage;
|
|
|
|
|
this.disp.setVolume(percentage);
|
|
|
|
|
} else {
|
|
|
|
|
logger.warn("No dispatcher found.")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Pauses if a dispatcher exists
|
|
|
|
|
*/
|
|
|
|
|
pause() {
|
|
|
|
|
logger.verbose("Pausing music...");
|
|
|
|
|
if (this.disp !== null) {
|
|
|
|
@ -105,6 +153,9 @@ class DJ {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Resumes if a dispatcher exists
|
|
|
|
|
*/
|
|
|
|
|
resume() {
|
|
|
|
|
logger.verbose("Resuming music...");
|
|
|
|
|
if (this.disp !== null) {
|
|
|
|
@ -114,7 +165,11 @@ class DJ {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stops playing music by ending the Dispatcher and disconnecting
|
|
|
|
|
*/
|
|
|
|
|
stop() {
|
|
|
|
|
this.queue = [];
|
|
|
|
|
logger.verbose("Stopping music...");
|
|
|
|
|
if (this.disp !== null) {
|
|
|
|
|
this.disp.end();
|
|
|
|
@ -126,6 +181,10 @@ class DJ {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Skips to the next song by ending the current StreamDispatcher and thereby triggering the
|
|
|
|
|
* end event of the dispatcher that automatically plays the next song.
|
|
|
|
|
*/
|
|
|
|
|
skip () {
|
|
|
|
|
logger.debug("Skipping song");
|
|
|
|
|
if (this.disp !== null) {
|
|
|
|
@ -133,18 +192,30 @@ class DJ {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the title for each song saved in the queue
|
|
|
|
|
* @returns {Array}
|
|
|
|
|
*/
|
|
|
|
|
get playlist() {
|
|
|
|
|
let songs = [];
|
|
|
|
|
logger.debug(`Playlist: ${JSON.stringify(this.queue)}`);
|
|
|
|
|
this.queue.forEach((entry) => {
|
|
|
|
|
songs.push(entry.title);
|
|
|
|
|
});
|
|
|
|
|
return songs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the song saved in the private variable 'current'
|
|
|
|
|
* @returns {null|*}
|
|
|
|
|
*/
|
|
|
|
|
get song() {
|
|
|
|
|
return this.current.title;
|
|
|
|
|
return this.current;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Shuffles the queue
|
|
|
|
|
*/
|
|
|
|
|
shuffle() {
|
|
|
|
|
this.queue = shuffleArray(this.queue);
|
|
|
|
|
}
|
|
|
|
|