📝 Update documentation

This commit is contained in:
Androz2091 2020-08-14 20:52:34 +02:00
parent f88e77170d
commit 5c784991ca
2 changed files with 302 additions and 170 deletions

View file

@ -114,6 +114,10 @@ class Player extends EventEmitter {
client.on('voiceStateUpdate', (oldState, newState) => this._handleVoiceStateUpdate(oldState, newState)) client.on('voiceStateUpdate', (oldState, newState) => this._handleVoiceStateUpdate(oldState, newState))
} }
/**
* @ignore
* @param {String} query
*/
resolveQueryType (query) { resolveQueryType (query) {
if (this.util.isSpotifyLink(query)) { if (this.util.isSpotifyLink(query)) {
return 'spotify-song' return 'spotify-song'
@ -129,9 +133,11 @@ class Player extends EventEmitter {
} }
/** /**
* * Search tracks
* @ignore
* @param {Discord.Message} message * @param {Discord.Message} message
* @param {string} query * @param {string} query
* @returns {Promise<Track>}
*/ */
_searchTracks (message, query) { _searchTracks (message, query) {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
@ -192,6 +198,15 @@ class Player extends EventEmitter {
}) })
} }
/**
* Change the filters.
* @param {Discord.Message} message
* @param {Partial<Filters>} newFilters The filters to update and their new status.
* @example
* client.player.setFilters(message, {
* bassboost: true
* });
*/
setFilters (message, newFilters) { setFilters (message, newFilters) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Get guild queue // Get guild queue
@ -204,10 +219,21 @@ class Player extends EventEmitter {
}) })
} }
/**
* Check whether there is a music played in the server
* @param {Discord.Message} message
*/
isPlaying (message) { isPlaying (message) {
return this.queues.some((g) => g.guildID === message.guild.id) return this.queues.some((g) => g.guildID === message.guild.id)
} }
/**
* Add a track to the queue
* @ignore
* @param {Discord.Message} message
* @param {Track} track
* @returns {Queue}
*/
_addTrackToQueue (message, track) { _addTrackToQueue (message, track) {
const queue = this.getQueue(message) const queue = this.getQueue(message)
if (!queue) throw new Error('NotPlaying') if (!queue) throw new Error('NotPlaying')
@ -216,6 +242,13 @@ class Player extends EventEmitter {
return queue return queue
} }
/**
* Add multiple tracks to the queue
* @ignore
* @param {Discord.Message} message
* @param {Track[]} tracks
* @returns {Queue}
*/
_addTracksToQueue (message, tracks) { _addTracksToQueue (message, tracks) {
const queue = this.getQueue(message) const queue = this.getQueue(message)
if (!queue) throw new Error('Cannot add tracks to queue because no song is currently played on the server.') if (!queue) throw new Error('Cannot add tracks to queue because no song is currently played on the server.')
@ -223,6 +256,13 @@ class Player extends EventEmitter {
return queue return queue
} }
/**
* Create a new queue and play the first track
* @ignore
* @param {Discord.Message} message
* @param {Track} track
* @returns {Promise<Queue>}
*/
_createQueue (message, track) { _createQueue (message, track) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const channel = message.member.voice ? message.member.voice.channel : null const channel = message.member.voice ? message.member.voice.channel : null
@ -243,6 +283,12 @@ class Player extends EventEmitter {
}) })
} }
/**
* Handle playlist by fetching the tracks and adding them to the queue
* @ignore
* @param {Discord.Message} message
* @param {String} query
*/
async _handlePlaylist (message, query) { async _handlePlaylist (message, query) {
const playlist = await ytpl(query).catch(() => {}) const playlist = await ytpl(query).catch(() => {})
if (!playlist) return this.emit('noResults', message, query) if (!playlist) return this.emit('noResults', message, query)
@ -261,14 +307,15 @@ class Player extends EventEmitter {
} }
} }
async _resolveSong (message, query) { /**
* Play a track in the server. Supported query types are `keywords`, YouTube video links`, `YouTube playlists links`, Spotify track link` or `SoundCloud song link`.
} * @param {Discord.Message} message
* @param {String} query
async _handleSong (message, query) { * @returns {Promise<void>}
*
} * @example
* client.player.play(message, "Despacito");
*/
async play (message, query) { async play (message, query) {
const isPlaying = this.isPlaying(message) const isPlaying = this.isPlaying(message)
if (this.util.isYTPlaylistLink(query)) { if (this.util.isYTPlaylistLink(query)) {
@ -294,6 +341,12 @@ class Player extends EventEmitter {
} }
} }
/**
* Pause the music in the server.
* @param {Discord.Message} message
* @example
* client.player.pause(message);
*/
pause (message) { pause (message) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Get guild queue // Get guild queue
@ -307,141 +360,186 @@ class Player extends EventEmitter {
}) })
} }
/**
* Resume the music in the server.
* @param {Discord.Message} message
* @returns {Queue}
* @example
* client.player.resume(message);
*/
resume (message) { resume (message) {
return new Promise((resolve, reject) => { // Get guild queue
// Get guild queue const queue = this.queues.find((g) => g.guildID === message.guild.id)
const queue = this.queues.find((g) => g.guildID === message.guild.id) if (!queue) return this.emit('error', 'NotPlaying')
if (!queue) return reject(new Error('Not playing')) // Pause the dispatcher
// Pause the dispatcher queue.voiceConnection.dispatcher.resume()
queue.voiceConnection.dispatcher.resume() queue.paused = false
queue.paused = false // Resolve the guild queue
// Resolve the guild queue return queue
resolve(queue.playing)
})
} }
/**
* Stop the music in the server.
* @param {Discord.Message} message
* @example
* client.player.stop(message);
*/
stop (message) { stop (message) {
return new Promise((resolve, reject) => { // Get guild queue
// Get guild queue const queue = this.queues.find((g) => g.guildID === message.guild.id)
const queue = this.queues.find((g) => g.guildID === message.guild.id) if (!queue) return this.emit('error', 'NotPlaying')
if (!queue) return reject(new Error('Not playing')) // Stop the dispatcher
// Stop the dispatcher queue.stopped = true
queue.stopped = true queue.tracks = []
queue.tracks = [] if (queue.stream) queue.stream.destroy()
if (queue.stream) queue.stream.destroy() queue.voiceConnection.dispatcher.end()
queue.voiceConnection.dispatcher.end() if (this.options.leaveOnStop) queue.voiceConnection.channel.leave()
if (this.options.leaveOnStop) queue.voiceConnection.channel.leave() this.queues.delete(message.guild.id)
this.queues.delete(message.guild.id)
// Resolve
resolve()
})
} }
/**
* Change the server volume.
* @param {Discord.Message} message
* @param {number} percent
* @returns {Queue}
* @example
* client.player.setVolume(message, 90);
*/
setVolume (message, percent) { setVolume (message, percent) {
return new Promise((resolve, reject) => { // Get guild queue
// Get guild queue const queue = this.queues.get(message.guild.id)
const queue = this.queues.get(message.guild.id) if (!queue) return this.emit('error', 'NotPlaying')
if (!queue) return reject(new Error('Not playing')) // Update volume
// Update volume queue.volume = percent
queue.volume = percent queue.voiceConnection.dispatcher.setVolumeLogarithmic(queue.calculatedVolume / 200)
queue.voiceConnection.dispatcher.setVolumeLogarithmic(queue.calculatedVolume / 200) // Return the queue
// Resolve guild queue return queue
resolve()
})
} }
/**
* Get the server queue.
* @param {Discord.Message} message
* @returns {Queue}
*/
getQueue (message) { getQueue (message) {
// Gets guild queue // Gets guild queue
const queue = this.queues.get(message.guild.id) const queue = this.queues.get(message.guild.id)
return queue return queue
} }
/**
* Clears the server queue.
* @param {Discord.Message} message
* @returns {Queue}
*/
clearQueue (message) { clearQueue (message) {
return new Promise((resolve, reject) => { // Get guild queue
// Get guild queue const queue = this.queues.get(message.guild.id)
const queue = this.queues.get(message.guild.id) if (!queue) return this.emit('error', 'NotPlaying')
if (!queue) return reject(new Error('Not playing')) // Clear queue
// Clear queue queue.tracks = []
queue.tracks = [] // Return the queue
// Resolve guild queue return queue
resolve(queue)
})
} }
/**
* Skips to the next song.
* @param {Discord.Message} message
* @returns {Queue}
*/
skip (message) { skip (message) {
return new Promise((resolve, reject) => { // Get guild queue
// Get guild queue const queue = this.queues.get(message.guild.id)
const queue = this.queues.get(message.guild.id) if (!queue) return this.emit('error', 'NotPlaying')
if (!queue) return reject(new Error('Not playing')) const currentTrack = queue.playing
const currentTrack = queue.playing // End the dispatcher
// End the dispatcher queue.voiceConnection.dispatcher.end()
queue.voiceConnection.dispatcher.end() queue.lastSkipped = true
queue.lastSkipped = true // Return the queue
// Resolve the current track return queue
resolve(currentTrack)
})
} }
/**
* Get the played song in the server.
* @param {Discord.Message} message
* @returns {Track}
*/
nowPlaying (message) { nowPlaying (message) {
return new Promise((resolve, reject) => { // Get guild queue
// Get guild queue const queue = this.queues.get(message.guild.id)
const queue = this.queues.get(message.guild.id) if (!queue) return this.emit('error', 'NotPlaying')
if (!queue) return reject(new Error('Not playing')) const currentTrack = queue.tracks[0]
const currentTrack = queue.tracks[0] // Return the current track
// Resolve the current track return currentTrack
resolve(currentTrack)
})
} }
/**
* Enable or disable repeat mode in the server.
* @param {Discord.Message} message
* @param {boolean} enabled
* @returns {boolean} whether the repeat mode is now enabled.
*/
setRepeatMode (message, enabled) { setRepeatMode (message, enabled) {
return new Promise((resolve, reject) => { // Get guild queue
// Get guild queue const queue = this.queues.get(message.guild.id)
const queue = this.queues.get(message.guild.id) if (!queue) return this.emit('error', 'NotPlaying')
if (!queue) return reject(new Error('Not playing')) // Enable/Disable repeat mode
// Enable/Disable repeat mode queue.repeatMode = enabled
queue.repeatMode = enabled // Return the repeat mode
// Resolve return queue.repeatMode
resolve()
})
} }
/**
* Shuffle the queue of the server.
* @param {Discord.Message} message
* @returns {}
*/
shuffle (message) { shuffle (message) {
return new Promise((resolve, reject) => { // Get guild queue
// Get guild queue const queue = this.queues.get(message.guild.id)
const queue = this.queues.get(message.guild.id) if (!queue) return this.emit('error', 'NotPlaying')
if (!queue) return reject(new Error('Not playing')) // Shuffle the queue (except the first track)
// Shuffle the queue (except the first track) const currentTrack = queue.tracks.shift()
const currentTrack = queue.tracks.shift() queue.tracks = queue.tracks.sort(() => Math.random() - 0.5)
queue.tracks = queue.tracks.sort(() => Math.random() - 0.5) queue.tracks.unshift(currentTrack)
queue.tracks.unshift(currentTrack) // Return the queue
// Resolve return queue
resolve(queue)
})
} }
/**
* Remove a track from the queue of the server
* @param {Discord.Message} message
* @param {Track|number} track
* @returns {Track} the removed track
*/
remove (message, track) { remove (message, track) {
return new Promise((resolve, reject) => { // Get guild queue
// Gets guild queue const queue = this.queues.get(message.guild.id)
const queue = this.queues.get(message.guild.id) if (!queue) return this.emit('error', 'NotPlaying')
if (!queue) return reject(new Error('Not playing')) // Remove the track from the queue
// Remove the track from the queue let trackFound = null
let trackFound = null if (typeof track === 'number') {
if (typeof track === 'number') { trackFound = queue.tracks[track]
trackFound = queue.tracks[track] if (trackFound) {
if (trackFound) { queue.tracks = queue.tracks.filter((t) => t !== trackFound)
queue.tracks = queue.tracks.filter((t) => t !== trackFound)
}
} else {
trackFound = queue.tracks.find((s) => s === track)
if (trackFound) {
queue.tracks = queue.tracks.filter((s) => s !== trackFound)
}
} }
// Resolve } else {
resolve(trackFound) trackFound = queue.tracks.find((s) => s === track)
}) if (trackFound) {
queue.tracks = queue.tracks.filter((s) => s !== trackFound)
}
}
// Resolve
return trackFound
} }
/**
* Create a progress bar for the queue of the server.
* @param {Discord.Message} message
* @param {Object} options
* @param {boolean} options.timecodes
* @returns {string}
*/
createProgressBar (message, options) { createProgressBar (message, options) {
// Gets guild queue // Gets guild queue
const queue = this.queues.get(message.guild.id) const queue = this.queues.get(message.guild.id)
@ -489,7 +587,7 @@ class Player extends EventEmitter {
if (newState.member.id === this.client.user.id && !newState.channelID) { if (newState.member.id === this.client.user.id && !newState.channelID) {
queue.stream.destroy() queue.stream.destroy()
this.queues.delete(newState.guild.id) this.queues.delete(newState.guild.id)
this.emit('botDisconnect') this.emit('botDisconnect', queue.firstMessage)
} }
// process leaveOnEmpty checks // process leaveOnEmpty checks
@ -580,7 +678,7 @@ class Player extends EventEmitter {
return queue.emit('musicStopp') return queue.emit('musicStopp')
} }
// Emit end event // Emit end event
return queue.emit('queueEnd') return queue.emit('queueEnd', queue.firstMessage, queue)
} }
// if the track needs to be the next one // if the track needs to be the next one
if (!queue.repeatMode && !firstPlay) queue.tracks.shift() if (!queue.repeatMode && !firstPlay) queue.tracks.shift()
@ -594,3 +692,95 @@ class Player extends EventEmitter {
}; };
module.exports = Player module.exports = Player
/**
* Emitted when a track starts
* @event Player#trackStart
* @param {Discord.Message} message
* @param {Queue} queue
* @param {Track} track
*/
/**
* Emitted when a playlist is started
* @event Player#queueCreate
* @param {Discord.Message} message
* @param {Queue} queue
* @param {Object} playlist
* @param {Track} track
*/
/**
* Emitted when the bot is awaiting search results
* @event Player#searchResults
* @param {Discord.Message} message
* @param {string} query
* @param {Track[]} tracks
*/
/**
* Emitted when the user has sent an invalid response for search results
* @event Player#searchInvalidResponse
* @param {Discord.Message} message
* @param {string} query
* @param {Track[]} tracks
* @param {string} invalidResponse
*/
/**
* Emitted when the bot has stopped awaiting search results (timeout)
* @event Player#searchCancel
* @param {Discord.Message} message
* @param {string} query
* @param {Track[]} tracks
*/
/**
* Emitted when the bot can't find related results to the query
* @event Player#noResults
* @param {Discord.Message} message
* @param {string} query
*/
/**
* Emitted when the bot is disconnected from the channel
* @event Player#botDisconnect
* @param {Discord.Message} message
*/
/**
* Emitted when the channel of the bot is empty
* @event Player#channelEmpty
* @param {Discord.Message} message
* @param {Queue} queue
*/
/**
* Emitted when the queue of the server is ended
* @event Player#queueEnd
* @param {Discord.Message} message
* @param {Queue} queue
*/
/**
* Emitted when a track is added to the queue
* @event Player#trackAdd
* @param {Discord.Message} message
* @param {Queue} queue
* @param {Track} track
*/
/**
* Emitted when a playlist is added to the queue
* @event Player#playlistAdd
* @param {Discord.Message} message
* @param {Queue} queue
* @param {Object} playlist
*/
/**
* Emitted when an error is triggered
* @event Player#error
* @param {Discord.Message} message
* @param {string} error It can be `NotConnected`, `UnableToJoin` or `NotPlaying`.
*/

View file

@ -90,61 +90,3 @@ class Queue extends EventEmitter {
} }
module.exports = Queue module.exports = Queue
/**
* Emitted when the queue is empty.
* @event Queue#end
*
* @example
* client.on('message', (message) => {
*
* const args = message.content.slice(settings.prefix.length).trim().split(/ +/g);
* const command = args.shift().toLowerCase();
*
* if(command === 'play'){
*
* let track = await client.player.play(message.member.voice.channel, args[0]);
*
* track.queue.on('end', () => {
* message.channel.send('The queue is empty, please add new tracks!');
* });
*
* }
*
* });
*/
/**
* Emitted when the voice channel is empty.
* @event Queue#channelEmpty
*/
/**
* Emitted when the track changes.
* @event Queue#trackChanged
* @param {Track} oldTrack The old track (playing before)
* @param {Track} newTrack The new track (currently playing)
* @param {Boolean} skipped Whether the change is due to the skip() function
*
* @example
* client.on('message', (message) => {
*
* const args = message.content.slice(settings.prefix.length).trim().split(/ +/g);
* const command = args.shift().toLowerCase();
*
* if(command === 'play'){
*
* let track = await client.player.play(message.member.voice.channel, args[0]);
*
* track.queue.on('trackChanged', (oldTrack, newTrack, skipped, repeatMode) => {
* if(repeatMode){
* message.channel.send(`Playing ${newTrack} again...`);
* } else {
* message.channel.send(`Now playing ${newTrack}...`);
* }
* });
*
* }
*
* });
*/