Support for Spotify playlists and albums (#226)

This commit is contained in:
Thaddeus Kuah 2021-01-10 23:38:28 +08:00 committed by GitHub
parent 6d53e02e74
commit 15e223a50e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 1 deletions

View file

@ -141,6 +141,8 @@ class Player extends EventEmitter {
return 'youtube-video'
} else if (this.util.isSoundcloudLink(query)) {
return 'soundcloud-song'
} else if (this.util.isSpotifyPLLink(query)) {
return 'spotify-playlist'
} else {
return 'youtube-video-keywords'
}
@ -331,7 +333,63 @@ class Player extends EventEmitter {
this._addTracksToQueue(message, playlist.tracks)
}
}
async _handleSpotifyPlaylist (message, query) {
const playlist = await spotify.getData(query)
if (!playlist) return this.emit('noResults', message, query)
let tracks = []
let s;
for (var i = 0; i < playlist.tracks.items.length; i++) {
let query = `${playlist.tracks.items[i].track.artists[0].name} - ${playlist.tracks.items[i].track.name}`
let results = await ytsr.search(query, { type: 'video' })
if (results.length < 1) {
s++ // could be used later for skipped tracks due to result not being found
continue;
}
tracks.push(results[0])
}
playlist.tracks = tracks.map((item) => new Track(item, message.author))
playlist.duration = playlist.tracks.reduce((prev, next) => prev + next.duration, 0)
playlist.thumbnail = playlist.images[0].url
playlist.requestedBy = message.author
if (this.isPlaying(message)) {
const queue = this._addTracksToQueue(message, playlist.tracks)
this.emit('playlistAdd', message, queue, playlist)
} else {
const track = playlist.tracks.shift()
const queue = await this._createQueue(message, track).catch((e) => this.emit('error', e, message))
this.emit('trackStart', message, queue.tracks[0])
this._addTracksToQueue(message, playlist.tracks)
}
}
async _handleSpotifyAlbum (message, query) {
const album = await spotify.getData(query)
if (!album) return this.emit('noResults', message, query)
let tracks = []
let s;
for (var i = 0; i < album.tracks.items.length; i++) {
let query = `${album.tracks.items[i].artists[0].name} - ${album.tracks.items[i].name}`
let results = await ytsr.search(query, { type: 'video' })
if (results.length < 1) {
s++ // could be used later for skipped tracks due to result not being found
continue;
}
tracks.push(results[0])
}
album.tracks = tracks.map((item) => new Track(item, message.author))
album.duration = album.tracks.reduce((prev, next) => prev + next.duration, 0)
album.thumbnail = album.images[0].url
album.requestedBy = message.author
if (this.isPlaying(message)) {
const queue = this._addTracksToQueue(message, album.tracks)
this.emit('playlistAdd', message, queue, album)
} else {
const track = album.tracks.shift()
const queue = await this._createQueue(message, track).catch((e) => this.emit('error', e, message))
this.emit('trackStart', message, queue.tracks[0])
this._addTracksToQueue(message, album.tracks)
}
}
/**
* 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 Discord `message`
@ -346,6 +404,12 @@ class Player extends EventEmitter {
if (this.util.isYTPlaylistLink(query)) {
return this._handlePlaylist(message, query)
}
if (this.util.isSpotifyPLLink(query)) {
return this._handleSpotifyPlaylist(message, query)
}
if (this.util.isSpotifyAlbumLink(query)) {
return this._handleSpotifyAlbum(message, query)
}
let trackToPlay
if (query instanceof Track) {
trackToPlay = query

View file

@ -2,6 +2,8 @@ const ytsr = require('youtube-sr')
const soundcloud = require('soundcloud-scraper')
const spotifySongRegex = (/https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:track\/|\?uri=spotify:track:)((\w|-){22})/)
const spotifyPlaylistRegex = (/https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:playlist\/|\?uri=spotify:playlist:)((\w|-){22})/)
const spotifyAlbumRegex = (/https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:album\/|\?uri=spotify:album:)((\w|-){22})/)
module.exports = class Util {
constructor () {
@ -20,6 +22,14 @@ module.exports = class Util {
return spotifySongRegex.test(query)
}
static isSpotifyPLLink (query) {
return spotifyPlaylistRegex.test(query)
}
static isSpotifyAlbumLink(query) {
return spotifyAlbumRegex.test(query)
}
static isYTPlaylistLink (query) {
return ytsr.validate(query, 'PLAYLIST')
}