import _ from 'lodash' ; import MetaProvider from '../metaProvider' ; import * as Discogs from '../../rest/Discogs' ; import LastFmApi from '../../rest/Lastfm' ; import Track from '../../structs/Track' ; import { SearchResultsArtist , SearchResultsAlbum , SearchResultsTrack , SearchResultsSource , ArtistDetails , AlbumDetails , AlbumType } from '../plugins.types' ; import { DiscogsReleaseSearchResponse , DiscogsArtistSearchResponse , DiscogsArtistReleasesSearchResponse , DiscogsArtistInfo , DiscogsArtistSearchResult , DiscogsReleaseSearchResult , DiscogsArtistReleaseSearchResult , DiscogsReleaseInfo , DiscogsTrack } from '../../rest/Discogs.types' ; import { LastFmArtistInfo , LastfmTopTracks , LastfmTrack } from '../../rest/Lastfm.types' ; import { cleanName } from '../../structs/Artist' ; class DiscogsMetaProvider extends MetaProvider { lastfm : LastFmApi ; constructor ( ) { super ( ) ; this . name = 'Discogs Meta Provider' ; this . searchName = 'Discogs' ; this . sourceName = 'Discogs Metadata Provider' ; this . description = 'Metadata provider that uses Discogs as a source.' ; this . image = null ; this . isDefault = true ; this . lastfm = new LastFmApi ( process . env . LAST_FM_API_KEY , process . env . LASTFM_API_SECRET ) ; } getCoverImage ( entity ) { return _ . get ( _ . find ( entity . images , { type : 'primary' } ) , 'resource_url' , _ . get ( _ . find ( entity . images , { type : 'secondary' } ) , 'resource_url' ) ) ; } discogsReleaseSearchResultToGeneric ( release ) { const albumNameRegex = /(?<artist>.*) - (?<album>.*)/g ; const match = albumNameRegex . exec ( release . title ) ; return { id : `${ release . id }` , coverImage : release . cover_image , thumb : release . cover_image , title : match . groups . album , artist : match . groups . artist , resourceUrl : release . resource_url , source : SearchResultsSource . Discogs } ; } discogsArtistReleaseSearchResultToGeneric ( release ) { return { id : `${ release . id }` , coverImage : release . thumb , thumb : release . thumb , title : release . title , artist : release . artist , resourceUrl : release . resource_url , type : release . type , source : SearchResultsSource . Discogs } ; } discogsReleaseInfoToGeneric ( release , releaseType ) { const artist = _ . head ( release . artists ) . name ; const coverImage = this . getCoverImage ( release ) ; const tracklist = [ ] ; release . tracklist . forEach ( track => { if ( track . sub_tracks ) { track . sub_tracks . forEach ( subTrack => tracklist . push ( this . discogsTrackToGeneric ( subTrack , artist ) ) ) ; } else { tracklist . push ( this . discogsTrackToGeneric ( track , artist ) ) ; } } ) ; return { id : `${ release . id }` , artist : _ . head ( release . artists ) . name , title : release . title , thumb : coverImage , coverImage , images : _ . map ( release . images , 'resource_url' ) , genres : [ ... _ . map ( release . genres ) , ... _ . map ( release . styles ) ] , year : `${ release . year }` , type : releaseType , tracklist , resourceUrl : release . resource_url } ; } discogsTrackToGeneric ( discogsTrack , artist ) { const track = new Track ( ) ; track . artist = artist ; track . title = discogsTrack . title ; track . duration = discogsTrack . duration ; track . position = discogsTrack . position ; track . extraArtists = _ . map ( discogsTrack . extraartists , 'name' ) ; track . type = discogsTrack . type_ ; return track ; } discogsArtistSearchResultToGeneric ( artist ) { return { id : `${ artist . id }` , coverImage : artist . cover_image , thumb : artist . thumb , name : artist . title , resourceUrl : artist . resource_url , source : SearchResultsSource . Discogs } ; } searchForArtists ( query ) { return Discogs . search ( query , 'artist' ) . then ( response => response . json ( ) ) . then ( ( json ) => json . results . map ( this . discogsArtistSearchResultToGeneric ) ) ; } searchForReleases ( query ) { return Discogs . search ( query , 'master' ) . then ( response => response . json ( ) ) . then ( ( json ) => json . results . map ( this . discogsReleaseSearchResultToGeneric ) ) ; } searchForTracks ( ) { return Promise . resolve ( [ ] ) ; } searchAll ( query ) { return Discogs . search ( query ) . then ( response => response . json ( ) ) . then ( json => { if ( json . results ) { const artists = json . results . flatMap ( item => ( item . type === 'artist' ) ? [ this . discogsArtistSearchResultToGeneric ( item ) ] : [ ] ) ; const releases = json . results . flatMap ( item => ( item . type === 'master' || item . type === 'release' ) ? [ this . discogsReleaseSearchResultToGeneric ( item ) ] : [ ] ) ; return Promise . resolve ( { artists , releases , tracks : [ ] } ) ; } return Promise . resolve ( { artists : [ ] , releases : [ ] , tracks : [ ] } ) ; } ) ; } async fetchArtistDetails ( artistId ) { const discogsInfo = await ( await Discogs . artistInfo ( artistId ) ) . json ( ) ; discogsInfo . name = cleanName ( discogsInfo . name ) ; const lastFmInfo = ( await ( await this . lastfm . getArtistInfo ( discogsInfo . name ) ) . json ( ) ) . artist ; const lastFmTopTracks = ( await ( await this . lastfm . getArtistTopTracks ( discogsInfo . name ) ) . json ( ) ) . toptracks ; const coverImage = this . getCoverImage ( discogsInfo ) ; return Promise . resolve ( { id : discogsInfo . id , name : discogsInfo . name , description : _ . get ( lastFmInfo , 'bio.summary' ) , tags : _ . map ( _ . get ( lastFmInfo , 'tags.tag' ) , 'name' ) , onTour : lastFmInfo . ontour === '1' , coverImage , thumb : coverImage , images : _ . map ( discogsInfo . images , 'resource_url' ) , topTracks : _ . map ( lastFmTopTracks . track , ( track ) => ( { name : track . name , title : track . name , thumb : coverImage , playcount : track . playcount , listeners : track . listeners , artist : track . artist } ) ) , similar : _ . map ( lastFmInfo . similar . artist , artist => ( { name : artist . name , thumbnail : _ . get ( _ . find ( artist . image , { size : 'large' } ) , '#text' ) } ) ) , source : SearchResultsSource . Discogs } ) ; } async fetchArtistDetailsByName ( artistName ) { const artistSearch = await ( await Discogs . search ( artistName , 'artist' ) ) . json ( ) ; const artist = _ . head ( artistSearch . results ) ; return this . fetchArtistDetails ( `${ artist . id }` ) ; } async fetchArtistAlbums ( artistId ) { const releases = await ( await Discogs . artistReleases ( artistId ) ) . json ( ) ; return Promise . resolve ( releases . releases . map ( this . discogsArtistReleaseSearchResultToGeneric ) ) ; } async fetchAlbumDetails ( albumId , albumType = 'master' , resourceUrl ) { const albumData = await ( await Discogs . releaseInfo ( albumId , albumType , { resource_url : resourceUrl } ) ) . json ( ) ; return Promise . resolve ( this . discogsReleaseInfoToGeneric ( albumData , albumType as AlbumType ) ) ; } async fetchAlbumDetailsByName ( albumName , albumType = 'master' ) { const albumSearch = await ( await Discogs . search ( albumName , albumType ) ) . json ( ) ; const matchingAlbum = _ . head ( albumSearch . results ) ; const albumData = await ( await Discogs . releaseInfo ( `${ matchingAlbum . id }` , albumType , { resource_url : matchingAlbum . resource_url } ) ) . json ( ) ; return Promise . resolve ( this . discogsReleaseInfoToGeneric ( albumData , albumType === 'master' ? AlbumType . master : AlbumType . release ) ) ; } } export default DiscogsMetaProvider ;