2022-03-06 23:32:04 +01:00
const axios = require ( 'axios' )
const Logger = require ( '../Logger' )
2022-03-07 00:26:35 +01:00
const { stripHtml } = require ( 'string-strip-html' )
2022-03-06 23:32:04 +01:00
class iTunes {
constructor ( ) { }
// https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/iTuneSearchAPI/Searching.html
search ( options ) {
if ( ! options . term ) {
Logger . error ( '[iTunes] Invalid search options - no term' )
return [ ]
}
var query = {
term : options . term ,
media : options . media ,
entity : options . entity ,
lang : options . lang ,
limit : options . limit ,
country : options . country
}
return axios . get ( 'https://itunes.apple.com/search' , { params : query } ) . then ( ( response ) => {
2022-03-07 00:26:35 +01:00
return response . data . results || [ ]
2022-03-06 23:32:04 +01:00
} ) . catch ( ( error ) => {
Logger . error ( ` [iTunes] search request error ` , error )
return [ ]
} )
}
2022-03-07 00:26:35 +01:00
2022-03-07 02:02:06 +01:00
// Example cover art: https://is1-ssl.mzstatic.com/image/thumb/Music118/v4/cb/ea/73/cbea739b-ff3b-11c4-fb93-7889fbec7390/9781598874983_cover.jpg/100x100bb.jpg
// 100x100bb can be replaced by other values https://github.com/bendodson/itunes-artwork-finder
// Target size 600 or larger
getCoverArtwork ( data ) {
if ( data . artworkUrl600 ) {
return data . artworkUrl600
}
// Should already be sorted from small to large
var artworkSizes = Object . keys ( data ) . filter ( key => key . startsWith ( 'artworkUrl' ) ) . map ( key => {
return {
url : data [ key ] ,
size : Number ( key . replace ( 'artworkUrl' , '' ) )
}
} )
if ( ! artworkSizes . length ) return null
// Return next biggest size > 600
var nextBestSize = artworkSizes . find ( size => size . size > 600 )
if ( nextBestSize ) return nextBestSize . url
// Find square artwork
var squareArtwork = artworkSizes . find ( size => size . url . includes ( ` ${ size . size } x ${ size . size } bb ` ) )
// Square cover replace with 600x600bb
if ( squareArtwork ) {
return squareArtwork . url . replace ( ` ${ squareArtwork . size } x ${ squareArtwork . size } bb ` , '600x600bb' )
}
// Last resort just return biggest size
return artworkSizes [ artworkSizes . length - 1 ] . url
}
2022-03-07 00:26:35 +01:00
cleanAudiobook ( data ) {
return {
id : data . collectionId ,
artistId : data . artistId ,
title : data . collectionName ,
author : data . artistName ,
description : stripHtml ( data . description || '' ) . result ,
2022-03-14 01:34:31 +01:00
publishedYear : data . releaseDate ? data . releaseDate . split ( '-' ) [ 0 ] : null ,
2022-03-07 00:26:35 +01:00
genres : data . primaryGenreName ? [ data . primaryGenreName ] : [ ] ,
2022-03-07 02:02:06 +01:00
cover : this . getCoverArtwork ( data )
2022-03-07 00:26:35 +01:00
}
}
searchAudiobooks ( term ) {
return this . search ( { term , entity : 'audiobook' , media : 'audiobook' } ) . then ( ( results ) => {
2022-03-07 02:02:06 +01:00
return results . map ( this . cleanAudiobook . bind ( this ) )
} )
}
cleanPodcast ( data ) {
return {
id : data . collectionId ,
2022-04-14 01:13:39 +02:00
artistId : data . artistId || null ,
2022-03-07 02:02:06 +01:00
title : data . collectionName ,
artistName : data . artistName ,
description : stripHtml ( data . description || '' ) . result ,
releaseDate : data . releaseDate ,
genres : data . genres || [ ] ,
cover : this . getCoverArtwork ( data ) ,
trackCount : data . trackCount ,
feedUrl : data . feedUrl ,
pageUrl : data . collectionViewUrl
}
}
searchPodcasts ( term , options = { } ) {
return this . search ( { term , entity : 'podcast' , media : 'podcast' , ... options } ) . then ( ( results ) => {
return results . map ( this . cleanPodcast . bind ( this ) )
2022-03-07 00:26:35 +01:00
} )
}
2022-03-06 23:32:04 +01:00
}
module . exports = iTunes