Files
emacs/lisp/emacs-application-framework/app/music-player/node_modules/album-art/index.js
2022-01-04 15:21:47 +01:00

194 lines
3.6 KiB
JavaScript

'use strict';
( ( root, cx ) => {
if ( typeof define === 'function' && define.amd ) {
// AMD
define( ['isomorphic-fetch'], cx )
} else if ( typeof exports === 'object' ) {
// Node, CommonJS-like
module.exports = cx( require( 'isomorphic-fetch' ) )
} else {
// Browser globals (root is window)
root.albumArt = cx( root.fetch )
}
} )( this, fetch => {
const albumArt = async ( artist, options, cb ) => {
// Massage inputs
if ( typeof artist !== 'string' ) {
throw new TypeError( 'Expected search query to be a string' )
}
if ( typeof options === 'function' ) {
cb = options
options = null
}
if ( typeof cb !== 'function' ) {
cb = null
}
// Default options
artist = artist.replace( '&', 'and' )
const opts = Object.assign( {
album: null,
size: null
}, options )
// Image size options
const SIZES = {
SMALL: 'small',
MEDIUM: 'medium',
LARGE: 'large'
}
// Public Key on purpose - don't make me regret this
const apiEndpoint = 'https://api.spotify.com/v1'
const authEndpoint = 'https://accounts.spotify.com/api/token'
const clientId = '3f974573800a4ff5b325de9795b8e603'
const clientSecret = 'ff188d2860ff44baa57acc79c121a3b9'
// Create request URL
const method = ( opts.album === null ) ? 'artist' : 'album'
const queryParams = `?q=${encodeURIComponent( artist )}${method === 'album' ? '%20' + opts.album : ''}&type=${method}&limit=1`
const searchUrl = `${apiEndpoint}/search${queryParams}`
const authString = `${clientId}:${clientSecret}`
let authorization
if ( typeof btoa !== 'undefined' ) {
authorization = btoa( authString )
} else if ( Buffer ) {
authorization = Buffer.from( authString ).toString( 'base64' )
} else {
throw new Error( 'No suitable environment found' )
}
// Start by authorizing a session
const authToken = await fetch( authEndpoint, {
method: 'post',
body: 'grant_type=client_credentials',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Basic ${authorization}`
}
} )
.then(
res => res.json()
)
.then(
json => json.access_token
)
// Perform image search
let error = null
const response = await fetch( searchUrl, {
method: 'get',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: `Bearer ${authToken}`
}
} )
.then(
res => res.json()
)
.then(
json => {
if ( typeof ( json.error ) !== 'undefined' ) {
// Error
return Promise.reject( new Error( `JSON - ${json.error} ${json.message}` ) )
}
if ( !json[method + 's'] || json[method + 's'].items.length === 0 ) {
// Error
return Promise.reject( new Error( 'No results found' ) )
}
// Select image size
const images = json[method + 's'].items[0].images
let smallest = images[0]
let largest = images[0]
for ( const element of images ) {
if ( parseInt( element.width ) < parseInt( smallest.width ) ) {
smallest = element
}
if ( parseInt( element.width ) > parseInt( largest.width ) ) {
largest = element
}
}
if ( opts.size === SIZES.SMALL ) {
return smallest.url
}
if ( opts.size === SIZES.MEDIUM && images.length > 1 ) {
return images[1].url
}
// Large by default
return largest.url
}
)
.catch( error_ => {
error = error_
return error_
} )
// Callback
if ( cb ) {
return cb( error, response )
}
// Promise
return response
}
// Exposed public method
return albumArt
} )