mirror of
https://gitlab.com/RemixDev/deemix-js.git
synced 2024-12-29 10:56:18 +00:00
Started working on spotify plugin implementation
This commit is contained in:
parent
1371e5aeb4
commit
fe47f6f60b
|
@ -49,7 +49,17 @@ async function generateDownloadObject(dz, link, bitrate, plugins={}, listener){
|
||||||
let link_type, link_id
|
let link_type, link_id
|
||||||
[link, link_type, link_id] = await parseLink(link)
|
[link, link_type, link_id] = await parseLink(link)
|
||||||
|
|
||||||
if (link_type == null || link_id == null) return null
|
if (link_type == null || link_id == null){
|
||||||
|
const pluginNames = Object.keys(plugins)
|
||||||
|
let currentPlugin
|
||||||
|
let item = null
|
||||||
|
for (let i = 0; i < pluginNames.length; i++){
|
||||||
|
currentPlugin = plugins[pluginNames[i]]
|
||||||
|
item = await currentPlugin.generateDownloadObject(dz, link, bitrate, listener)
|
||||||
|
if (item) break
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
switch (link_type) {
|
switch (link_type) {
|
||||||
case 'track':
|
case 'track':
|
||||||
|
@ -65,7 +75,6 @@ async function generateDownloadObject(dz, link, bitrate, plugins={}, listener){
|
||||||
case 'artist_top':
|
case 'artist_top':
|
||||||
return generateArtistTopItem(dz, link_id, bitrate)
|
return generateArtistTopItem(dz, link_id, bitrate)
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -99,5 +108,8 @@ module.exports = {
|
||||||
localpaths: require('./utils/localpaths.js'),
|
localpaths: require('./utils/localpaths.js'),
|
||||||
pathtemplates: require('./utils/pathtemplates.js'),
|
pathtemplates: require('./utils/pathtemplates.js'),
|
||||||
deezer: require('./utils/deezer.js')
|
deezer: require('./utils/deezer.js')
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
spotify: require('./plugins/spotify.js')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,6 +307,20 @@ class NotYourPrivatePlaylist extends GenerationError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TrackNotOnDeezer extends GenerationError {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = "TrackNotOnDeezer";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AlbumNotOnDeezer extends GenerationError {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = "AlbumNotOnDeezer";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
generateTrackItem,
|
generateTrackItem,
|
||||||
generateAlbumItem,
|
generateAlbumItem,
|
||||||
|
@ -317,5 +331,7 @@ module.exports = {
|
||||||
|
|
||||||
GenerationError,
|
GenerationError,
|
||||||
ISRCnotOnDeezer,
|
ISRCnotOnDeezer,
|
||||||
NotYourPrivatePlaylist
|
NotYourPrivatePlaylist,
|
||||||
|
TrackNotOnDeezer,
|
||||||
|
AlbumNotOnDeezer
|
||||||
}
|
}
|
||||||
|
|
15
deemix/plugins/plugin.js
Normal file
15
deemix/plugins/plugin.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class Plugin {
|
||||||
|
constructor(){}
|
||||||
|
async setup(){}
|
||||||
|
|
||||||
|
async parseLink(link){
|
||||||
|
return [link, undefined, undefined]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*eslint no-unused-vars: ["error", { "args": "none" }]*/
|
||||||
|
async generateDownloadObject(dz, link, bitrate, listener){
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Plugin
|
203
deemix/plugins/spotify.js
Normal file
203
deemix/plugins/spotify.js
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
const Plugin = require('./plugin.js')
|
||||||
|
const { getConfigFolder } = require('../utils/localpaths.js')
|
||||||
|
const {
|
||||||
|
generateTrackItem,
|
||||||
|
generateAlbumItem,
|
||||||
|
TrackNotOnDeezer,
|
||||||
|
AlbumNotOnDeezer
|
||||||
|
} = require('../itemgen.js')
|
||||||
|
const { sep } = require('path')
|
||||||
|
const fs = require('fs')
|
||||||
|
const SpotifyWebApi = require('spotify-web-api-node')
|
||||||
|
const got = require('got')
|
||||||
|
|
||||||
|
class Spotify extends Plugin {
|
||||||
|
constructor(configFolder = undefined){
|
||||||
|
super()
|
||||||
|
this.credentials = {clientId: "", clientSecret: ""}
|
||||||
|
this.enabled = false
|
||||||
|
this.sp
|
||||||
|
this.configFolder = configFolder || getConfigFolder()
|
||||||
|
this.configFolder += `spotify${sep}`
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
async setup(){
|
||||||
|
fs.mkdirSync(this.configFolder, { recursive: true })
|
||||||
|
|
||||||
|
if (! fs.existsSync(this.configFolder+'credentials.json')) fs.writeFileSync(this.configFolder+'credentials.json', JSON.stringify(this.credentials))
|
||||||
|
this.credentials = JSON.parse(fs.readFileSync(this.configFolder+'credentials.json'))
|
||||||
|
await this.checkCredentials()
|
||||||
|
}
|
||||||
|
|
||||||
|
async parseLink(link){
|
||||||
|
if (link.includes('link.tospotify.com')){
|
||||||
|
link = await got.get(link) // Resolve URL shortner
|
||||||
|
link = link.url
|
||||||
|
}
|
||||||
|
// Remove extra stuff
|
||||||
|
if (link.includes('?')) link = link.slice(0, link.indexOf('?'))
|
||||||
|
if (link.includes('&')) link = link.slice(0, link.indexOf('&'))
|
||||||
|
if (link.endsWith('/')) link = link.slice(0, -1) // Remove last slash if present
|
||||||
|
|
||||||
|
let link_type, link_id
|
||||||
|
|
||||||
|
if (!link.includes('spotify')) return [link, link_type, link_id] // return if not a spotify link
|
||||||
|
|
||||||
|
if (link.search(/[/:]track[/:](.+)/g) != -1){
|
||||||
|
link_type = 'track'
|
||||||
|
link_id = /[/:]track[/:](.+)/g.exec(link)[1]
|
||||||
|
}else if (link.search(/[/:]album[/:](.+)/g) != -1){
|
||||||
|
link_type = 'album'
|
||||||
|
link_id = /[/:]album[/:](.+)/g.exec(link)[1]
|
||||||
|
}else if (link.search(/[/:]playlist[/:](\d+)/g) != -1){
|
||||||
|
link_type = 'playlist'
|
||||||
|
link_id = /[/:]playlist[/:](.+)/g.exec(link)[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return [link, link_type, link_id]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*eslint no-unused-vars: ["error", { "args": "none" }]*/
|
||||||
|
async generateDownloadObject(dz, link, bitrate, _){
|
||||||
|
let link_type, link_id
|
||||||
|
[link, link_type, link_id] = await this.parseLink(link)
|
||||||
|
|
||||||
|
if (link_type == null || link_id == null) return null
|
||||||
|
|
||||||
|
switch (link_type) {
|
||||||
|
case 'track':
|
||||||
|
return this.generateTrackItem(dz, link_id, bitrate)
|
||||||
|
case 'album':
|
||||||
|
return this.generateAlbumItem(dz, link_id, bitrate)
|
||||||
|
case 'playlist':
|
||||||
|
return this.generatePlaylistItem(dz, link_id, bitrate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateTrackItem(dz, link_id, bitrate){
|
||||||
|
let [track_id, trackAPI, _] = await this.convertTrack(dz, link_id)
|
||||||
|
|
||||||
|
if (track_id !== "0"){
|
||||||
|
return generateTrackItem(dz, track_id, bitrate, trackAPI)
|
||||||
|
} else {
|
||||||
|
throw new TrackNotOnDeezer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateAlbumItem(dz, link_id, bitrate){
|
||||||
|
let album_id = await this.convertAlbum(dz, link_id)
|
||||||
|
|
||||||
|
if (album_id !== "0"){
|
||||||
|
return generateAlbumItem(dz, album_id, bitrate)
|
||||||
|
} else {
|
||||||
|
throw new AlbumNotOnDeezer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async generatePlaylistItem(dz, link_id, bitrate){
|
||||||
|
throw new Error("Not implemented yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
async convertTrack(dz, track_id, fallbackSearch = false, cachedTrack = null){
|
||||||
|
if (!this.enabled) throw new Error("Spotify plugin not enabled")
|
||||||
|
let shouldSaveCache = false
|
||||||
|
let cache
|
||||||
|
if (!cachedTrack){
|
||||||
|
// Read spotify cache
|
||||||
|
cache = {tracks: {}, albums: {}}
|
||||||
|
shouldSaveCache = true
|
||||||
|
cachedTrack = await this.sp.getTrack(track_id)
|
||||||
|
cachedTrack = cachedTrack.body
|
||||||
|
}
|
||||||
|
|
||||||
|
let dz_id = "0"
|
||||||
|
let dz_track = null
|
||||||
|
let isrc = null
|
||||||
|
if (cachedTrack.external_ids && cachedTrack.external_ids.isrc){
|
||||||
|
isrc = cachedTrack.external_ids.isrc
|
||||||
|
dz_track = await dz.api.get_track_by_ISRC(isrc)
|
||||||
|
if (dz_track.title && dz_track.id) dz_id = dz_track.id
|
||||||
|
}
|
||||||
|
if (dz_id === "0" && fallbackSearch){
|
||||||
|
dz_id = dz.api.get_track_id_from_metadata(
|
||||||
|
cachedTrack.artists[0].name,
|
||||||
|
cachedTrack.name,
|
||||||
|
cachedTrack.album.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldSaveCache){
|
||||||
|
cache.tracks[track_id] = {id: dz_id, isrc: isrc}
|
||||||
|
// Save edited cache
|
||||||
|
}
|
||||||
|
return [dz_id, dz_track, isrc]
|
||||||
|
}
|
||||||
|
|
||||||
|
async convertAlbum(dz, album_id){
|
||||||
|
if (!this.enabled) throw new Error("Spotify plugin not enabled")
|
||||||
|
let cachedAlbum
|
||||||
|
let cache
|
||||||
|
// Read spotify cache
|
||||||
|
cache = {tracks: {}, albums: {}}
|
||||||
|
if (!cachedAlbum){
|
||||||
|
cachedAlbum = await this.sp.getAlbum(album_id)
|
||||||
|
cachedAlbum = cachedAlbum.body
|
||||||
|
}
|
||||||
|
let dz_id = "0"
|
||||||
|
let dz_album = null
|
||||||
|
let upc = null
|
||||||
|
if (cachedAlbum.external_ids && cachedAlbum.external_ids.upc){
|
||||||
|
upc = cachedAlbum.external_ids.upc
|
||||||
|
try {
|
||||||
|
dz_album = await dz.api.get_album_by_UPC(upc)
|
||||||
|
} catch (e){
|
||||||
|
dz_album = null
|
||||||
|
}
|
||||||
|
if (!dz_album){
|
||||||
|
upc = ""+parseInt(upc)
|
||||||
|
try {
|
||||||
|
dz_album = await dz.api.get_album_by_UPC(upc)
|
||||||
|
} catch (e) {
|
||||||
|
dz_album = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dz_album && dz_album.title && dz_album.id) dz_id = dz_album.id
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.tracks[album_id] = {id: dz_id, upc: upc}
|
||||||
|
// Save cache
|
||||||
|
return dz_id
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkCredentials(){
|
||||||
|
if (this.credentials.clientId === "" || this.credentials.clientSecret === ""){
|
||||||
|
this.enabled = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.sp = new SpotifyWebApi(this.credentials)
|
||||||
|
try {
|
||||||
|
const creds = await this.sp.clientCredentialsGrant()
|
||||||
|
this.sp.setAccessToken(creds.body.access_token)
|
||||||
|
this.enabled = true
|
||||||
|
} catch (e){
|
||||||
|
this.enabled = false
|
||||||
|
this.sp = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getCredentials(){
|
||||||
|
return this.credentials
|
||||||
|
}
|
||||||
|
|
||||||
|
async setCredentials(newCredentials){
|
||||||
|
newCredentials.clientId = newCredentials.clientId.trim()
|
||||||
|
newCredentials.clientSecret = newCredentials.clientSecret.trim()
|
||||||
|
|
||||||
|
this.credentials = newCredentials
|
||||||
|
fs.writeFileSync(this.configFolder+'credentials.json', JSON.stringify(this.credentials))
|
||||||
|
await this.checkCredentials()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Spotify
|
|
@ -14,7 +14,8 @@
|
||||||
"crypto": "^1.0.1",
|
"crypto": "^1.0.1",
|
||||||
"deezer-js": "^0.0.8",
|
"deezer-js": "^0.0.8",
|
||||||
"got": "^11.8.2",
|
"got": "^11.8.2",
|
||||||
"metaflac-js2": "^1.0.7"
|
"metaflac-js2": "^1.0.7",
|
||||||
|
"spotify-web-api-node": "^5.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^7.23.0"
|
"eslint": "^7.23.0"
|
||||||
|
|
145
yarn.lock
145
yarn.lock
|
@ -225,6 +225,14 @@ cacheable-request@^7.0.1:
|
||||||
normalize-url "^4.1.0"
|
normalize-url "^4.1.0"
|
||||||
responselike "^2.0.0"
|
responselike "^2.0.0"
|
||||||
|
|
||||||
|
call-bind@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||||
|
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
get-intrinsic "^1.0.2"
|
||||||
|
|
||||||
callsites@^3.0.0:
|
callsites@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
|
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
|
||||||
|
@ -283,7 +291,7 @@ color-name@~1.1.4:
|
||||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
||||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
|
resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
|
||||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||||
|
@ -295,11 +303,21 @@ commander@^3.0.1:
|
||||||
resolved "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz"
|
resolved "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz"
|
||||||
integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==
|
integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==
|
||||||
|
|
||||||
|
component-emitter@^1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
||||||
|
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
|
||||||
|
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
||||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||||
|
|
||||||
|
cookiejar@^2.1.2:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c"
|
||||||
|
integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==
|
||||||
|
|
||||||
core-util-is@1.0.2:
|
core-util-is@1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
|
||||||
|
@ -555,6 +573,11 @@ fast-levenshtein@^2.0.6:
|
||||||
resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz"
|
resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz"
|
||||||
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
|
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
|
||||||
|
|
||||||
|
fast-safe-stringify@^2.0.7:
|
||||||
|
version "2.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
|
||||||
|
integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
|
||||||
|
|
||||||
file-entry-cache@^6.0.1:
|
file-entry-cache@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz"
|
resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz"
|
||||||
|
@ -580,6 +603,15 @@ forever-agent@~0.6.1:
|
||||||
resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz"
|
resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz"
|
||||||
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
|
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
|
||||||
|
|
||||||
|
form-data@^3.0.0:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
|
||||||
|
integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
|
||||||
|
dependencies:
|
||||||
|
asynckit "^0.4.0"
|
||||||
|
combined-stream "^1.0.8"
|
||||||
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
form-data@~2.3.2:
|
form-data@~2.3.2:
|
||||||
version "2.3.3"
|
version "2.3.3"
|
||||||
resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz"
|
resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz"
|
||||||
|
@ -589,16 +621,35 @@ form-data@~2.3.2:
|
||||||
combined-stream "^1.0.6"
|
combined-stream "^1.0.6"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
|
formidable@^1.2.2:
|
||||||
|
version "1.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9"
|
||||||
|
integrity sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==
|
||||||
|
|
||||||
fs.realpath@^1.0.0:
|
fs.realpath@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||||
|
|
||||||
|
function-bind@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||||
|
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||||
|
|
||||||
functional-red-black-tree@^1.0.1:
|
functional-red-black-tree@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz"
|
||||||
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
|
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
|
||||||
|
|
||||||
|
get-intrinsic@^1.0.2:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
|
||||||
|
integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
has "^1.0.3"
|
||||||
|
has-symbols "^1.0.1"
|
||||||
|
|
||||||
get-stream@^5.1.0:
|
get-stream@^5.1.0:
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz"
|
resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz"
|
||||||
|
@ -686,6 +737,18 @@ has-flag@^4.0.0:
|
||||||
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
|
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
|
||||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||||
|
|
||||||
|
has-symbols@^1.0.1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
|
||||||
|
integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
|
||||||
|
|
||||||
|
has@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||||
|
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
|
||||||
http-cache-semantics@^4.0.0:
|
http-cache-semantics@^4.0.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz"
|
resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz"
|
||||||
|
@ -884,6 +947,11 @@ metaflac-js2@^1.0.7:
|
||||||
commander "^3.0.1"
|
commander "^3.0.1"
|
||||||
probe-image-size "^5.0.0"
|
probe-image-size "^5.0.0"
|
||||||
|
|
||||||
|
methods@^1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||||
|
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
|
||||||
|
|
||||||
mime-db@1.47.0:
|
mime-db@1.47.0:
|
||||||
version "1.47.0"
|
version "1.47.0"
|
||||||
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz"
|
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz"
|
||||||
|
@ -896,6 +964,11 @@ mime-types@^2.1.12, mime-types@~2.1.19:
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-db "1.47.0"
|
mime-db "1.47.0"
|
||||||
|
|
||||||
|
mime@^2.4.6:
|
||||||
|
version "2.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
|
||||||
|
integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
|
||||||
|
|
||||||
mimic-response@^1.0.0:
|
mimic-response@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz"
|
||||||
|
@ -943,6 +1016,11 @@ oauth-sign@~0.9.0:
|
||||||
resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz"
|
resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz"
|
||||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||||
|
|
||||||
|
object-inspect@^1.9.0:
|
||||||
|
version "1.10.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369"
|
||||||
|
integrity sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==
|
||||||
|
|
||||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
|
resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
|
||||||
|
@ -1028,6 +1106,13 @@ punycode@^2.1.0, punycode@^2.1.1:
|
||||||
resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz"
|
resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz"
|
||||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||||
|
|
||||||
|
qs@^6.9.4:
|
||||||
|
version "6.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a"
|
||||||
|
integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==
|
||||||
|
dependencies:
|
||||||
|
side-channel "^1.0.4"
|
||||||
|
|
||||||
qs@~6.5.2:
|
qs@~6.5.2:
|
||||||
version "6.5.2"
|
version "6.5.2"
|
||||||
resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz"
|
resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz"
|
||||||
|
@ -1038,6 +1123,15 @@ quick-lru@^5.1.1:
|
||||||
resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz"
|
resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz"
|
||||||
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
|
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
|
||||||
|
|
||||||
|
readable-stream@^3.6.0:
|
||||||
|
version "3.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||||
|
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||||
|
dependencies:
|
||||||
|
inherits "^2.0.3"
|
||||||
|
string_decoder "^1.1.1"
|
||||||
|
util-deprecate "^1.0.1"
|
||||||
|
|
||||||
regexpp@^3.1.0:
|
regexpp@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz"
|
resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz"
|
||||||
|
@ -1098,7 +1192,7 @@ rimraf@^3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
|
|
||||||
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
|
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
|
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
|
||||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
@ -1108,7 +1202,7 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||||
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
|
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
|
||||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||||
|
|
||||||
semver@^7.2.1:
|
semver@^7.2.1, semver@^7.3.2:
|
||||||
version "7.3.5"
|
version "7.3.5"
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz"
|
resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz"
|
||||||
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
|
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
|
||||||
|
@ -1127,6 +1221,15 @@ shebang-regex@^3.0.0:
|
||||||
resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
|
resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
|
||||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||||
|
|
||||||
|
side-channel@^1.0.4:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
||||||
|
integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
|
||||||
|
dependencies:
|
||||||
|
call-bind "^1.0.0"
|
||||||
|
get-intrinsic "^1.0.2"
|
||||||
|
object-inspect "^1.9.0"
|
||||||
|
|
||||||
slice-ansi@^4.0.0:
|
slice-ansi@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz"
|
resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz"
|
||||||
|
@ -1136,6 +1239,13 @@ slice-ansi@^4.0.0:
|
||||||
astral-regex "^2.0.0"
|
astral-regex "^2.0.0"
|
||||||
is-fullwidth-code-point "^3.0.0"
|
is-fullwidth-code-point "^3.0.0"
|
||||||
|
|
||||||
|
spotify-web-api-node@^5.0.2:
|
||||||
|
version "5.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/spotify-web-api-node/-/spotify-web-api-node-5.0.2.tgz#683669b3ccc046a5a357300f151df93a2b3539fe"
|
||||||
|
integrity sha512-r82dRWU9PMimHvHEzL0DwEJrzFk+SMCVfq249SLt3I7EFez7R+jeoKQd+M1//QcnjqlXPs2am4DFsGk8/GCsrA==
|
||||||
|
dependencies:
|
||||||
|
superagent "^6.1.0"
|
||||||
|
|
||||||
sprintf-js@~1.0.2:
|
sprintf-js@~1.0.2:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
|
resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
|
||||||
|
@ -1172,6 +1282,13 @@ string-width@^4.2.0:
|
||||||
is-fullwidth-code-point "^3.0.0"
|
is-fullwidth-code-point "^3.0.0"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
|
string_decoder@^1.1.1:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
|
||||||
|
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "~5.2.0"
|
||||||
|
|
||||||
strip-ansi@^6.0.0:
|
strip-ansi@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz"
|
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz"
|
||||||
|
@ -1184,6 +1301,23 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
|
||||||
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
|
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
|
||||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||||
|
|
||||||
|
superagent@^6.1.0:
|
||||||
|
version "6.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/superagent/-/superagent-6.1.0.tgz#09f08807bc41108ef164cfb4be293cebd480f4a6"
|
||||||
|
integrity sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==
|
||||||
|
dependencies:
|
||||||
|
component-emitter "^1.3.0"
|
||||||
|
cookiejar "^2.1.2"
|
||||||
|
debug "^4.1.1"
|
||||||
|
fast-safe-stringify "^2.0.7"
|
||||||
|
form-data "^3.0.0"
|
||||||
|
formidable "^1.2.2"
|
||||||
|
methods "^1.1.2"
|
||||||
|
mime "^2.4.6"
|
||||||
|
qs "^6.9.4"
|
||||||
|
readable-stream "^3.6.0"
|
||||||
|
semver "^7.3.2"
|
||||||
|
|
||||||
supports-color@^5.3.0:
|
supports-color@^5.3.0:
|
||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
|
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
|
||||||
|
@ -1274,6 +1408,11 @@ uri-js@^4.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
|
util-deprecate@^1.0.1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
|
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||||
|
|
||||||
uuid@^3.3.2:
|
uuid@^3.3.2:
|
||||||
version "3.4.0"
|
version "3.4.0"
|
||||||
resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz"
|
resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz"
|
||||||
|
|
Loading…
Reference in a new issue