diff --git a/lib/services/deezer/index.js b/lib/services/deezer/index.js index 948785a..a2dea0a 100644 --- a/lib/services/deezer/index.js +++ b/lib/services/deezer/index.js @@ -75,15 +75,22 @@ export function* lookupId(id, type) { } }; -export function* search(data) { +export function* search(data, original={}) { let cleanParam = function(str) { return str.replace(/[\:\?\&]+/, ''); }; let query, album; let {type} = data; + const various = data.artist.name === 'Various Artists' || data.artist.name === 'Various'; + if (type === 'album') { - query = cleanParam(data.artist.name) + ' ' + cleanParam(data.name); + // Deezer is shitty about artists with these names, strip them instead + if (various) { + query = cleanParam(data.name); + } else { + query = cleanParam(data.artist.name) + ' ' + cleanParam(data.name); + } album = data.name; } else if (type === 'track') { query = cleanParam(data.artist.name) + ' ' + cleanParam(data.albumName) + ' ' + cleanParam(data.name); @@ -91,8 +98,17 @@ export function* search(data) { } var path = '/search/' + type + '?q=' + encodeURIComponent(query); + let response = yield request.get(apiRoot + path); - if (response.body.data[0]) { + + const name = original.name || data.name; + + if (response.body.data.length > 0) { + let match; + if (!(match = exactMatch(name, response.body.data, data.type, various))) { + match = looseMatch(name, response.body.data, data.type, various); + } + return yield module.exports.lookupId(response.body.data[0].id, type); } else { var matches = album.match(/^[^\(\[]+/); @@ -103,9 +119,35 @@ export function* search(data) { } else if (type === 'track') { cleanedData.albumName = matches[0].trim(); } - return yield module.exports.search(cleanedData); + return yield module.exports.search(cleanedData, data); } else { return Promise.resolve({service: 'deezer'}); } } }; + +function exactMatch(needle, haystack, type, various) { + // try to find exact match + return haystack.find(function(entry) { + if (!entry[type] || (various && (entry.artist.name !== 'Various' || entry.artist.name !== 'Various Artists'))) { + return false; + } + entry = entry[type]; + if (entry.title === needle) { + return entry; + } + }); +} + +function looseMatch(needle, haystack, type, various) { + // try to find exact match + return haystack.find(function(entry) { + if (!entry[type] || (various && (entry.artist.name !== 'Various' || entry.artist.name !== 'Various Artists'))) { + return false; + } + const name = entry[type].title || entry[type].name; + if (name.indexOf(needle) >= 0) { + return entry[type]; + } + }); +} diff --git a/test/services/deezer.js b/test/services/deezer.js index 91d3734..f86d326 100644 --- a/test/services/deezer.js +++ b/test/services/deezer.js @@ -20,6 +20,11 @@ describe('Deezer', function(){ result.name.should.startWith('In Colour'); }); + it('should find album with various artists by search', function* (){ + const result = yield deezer.search({type: 'album', artist: {name: 'Various Artists'}, name: 'The Trevor Nelson Collection'}); + result.name.should.equal('The Trevor Nelson Collection'); + }); + it('should find track by search', function* (){ const result = yield deezer.search({type: 'track', artist: {name: 'Deftones'}, albumName: 'Deftones', name: 'Hexagram'}); result.name.should.equal('Hexagram'); diff --git a/test/services/spotify.js b/test/services/spotify.js index ed229fc..60c7bad 100644 --- a/test/services/spotify.js +++ b/test/services/spotify.js @@ -20,7 +20,7 @@ describe('Spotify', function(){ result.name.should.equal('Listen (Deluxe)'); }); - it('should find album with colon in name by search', function* (){ + it('should find album by various artists by search', function* (){ const result = yield spotify.search({type: 'album', artist: {name: 'Various Artists'}, name: 'The Get Down Part II: Original Soundtrack From The Netflix Original Series'}); result.name.should.equal('The Get Down Part II: Original Soundtrack From The Netflix Original Series'); });