diff --git a/lib/services/deezer/index.js b/lib/services/deezer/index.js index 5df14b5..948785a 100644 --- a/lib/services/deezer/index.js +++ b/lib/services/deezer/index.js @@ -86,8 +86,8 @@ export function* search(data) { query = cleanParam(data.artist.name) + ' ' + cleanParam(data.name); album = data.name; } else if (type === 'track') { - query = cleanParam(data.artist.name) + ' ' + cleanParam(data.album.name) + ' ' + cleanParam(data.name); - album = data.album.name; + query = cleanParam(data.artist.name) + ' ' + cleanParam(data.albumName) + ' ' + cleanParam(data.name); + album = data.albumName; } var path = '/search/' + type + '?q=' + encodeURIComponent(query); @@ -101,7 +101,7 @@ export function* search(data) { if (type === 'album') { cleanedData.name = matches[0].trim(); } else if (type === 'track') { - cleanedData.album.name = matches[0].trim(); + cleanedData.albumName = matches[0].trim(); } return yield module.exports.search(cleanedData); } else { diff --git a/lib/services/google/index.js b/lib/services/google/index.js index 16be600..3832aab 100644 --- a/lib/services/google/index.js +++ b/lib/services/google/index.js @@ -88,7 +88,7 @@ export function* lookupId(id, type) { } }; -export function* search(data) { +export function* search(data, original={}) { yield ready; let query, album; const type = data.type; @@ -97,39 +97,68 @@ export function* search(data) { query = data.artist.name + ' ' + data.name; album = data.name; } else if (type === 'track') { - query = data.artist.name + ' ' + data.album.name + ' ' + data.name; - album = data.album.name; + query = data.artist.name + ' ' + data.albumName + ' ' + data.name; + album = data.albumName; } let result = yield pm.searchAsync(query, 5) if (!result.entries) { const matches = album.match(/^[^\(\[]+/); - if (matches && matches[0] && matches[0] !== album) { + if (matches && matches[0]) { const cleanedData = JSON.parse(JSON.stringify(data)); if (type === 'album') { - cleanedData.name = matches[0].trim(); + cleanedData.name = data.name.match(/^[^\(\[]+/)[0].trim(); } else if (type === 'track') { - cleanedData.album.name = matches[0].trim(); + cleanedData.albumName = data.albumName.match(/^[^\(\[]+/)[0].trim(); + cleanedData.name = data.name.match(/^[^\(\[]+/)[0].trim(); } - return yield search(cleanedData); + return yield search(cleanedData, data); } else { return {service: 'google'}; } } - result = result.entries.filter(function(entry) { - return entry[type]; - }).sort(function(a, b) { // sort by match score - return a.score < b.score; - }).shift(); - if (!result) { + const name = original.name || data.name; + + let match; + if (!(match = exactMatch(name, result.entries, data.type))) { + match = looseMatch(name, result.entries, data.type); + } + + if (!match) { return {service: 'google'}; } else { if (type === 'album') { - return yield lookupId(result.album.albumId, type); + return yield lookupId(match.album.albumId, type); } else if (type === 'track') { - return yield lookupId(result.track.nid, type); + return yield lookupId(match.track.storeId, type); } } }; + +function exactMatch(needle, haystack, type) { + // try to find exact match + return haystack.find(function(entry) { + if (!entry[type]) { + return false; + } + entry = entry[type]; + if (entry.title === needle) { + return entry; + } + }); +} + +function looseMatch(needle, haystack, type) { + // try to find exact match + return haystack.find(function(entry) { + if (!entry[type]) { + return false; + } + const name = entry[type].title || entry[type].name; + if (name.indexOf(needle) >= 0) { + return entry[type]; + } + }); +} diff --git a/lib/services/itunes/index.js b/lib/services/itunes/index.js index 9de52c0..966ac6d 100644 --- a/lib/services/itunes/index.js +++ b/lib/services/itunes/index.js @@ -84,8 +84,8 @@ export function* search(data) { album = data.name; entity = 'album'; } else if (type === 'track') { - query = data.artist.name + ' ' + data.album.name + ' ' + data.name; - album = data.album.name; + query = data.artist.name + ' ' + data.albumName + ' ' + data.name; + album = data.albumName; entity = 'musicTrack'; } @@ -100,7 +100,7 @@ export function* search(data) { if (type === 'album') { cleanedData.name = matches[0].trim(); } else if (type === 'track') { - cleanedData.album.name = matches[0].trim(); + cleanedData.albumName = matches[0].trim(); } return yield search(cleanedData); } else { diff --git a/lib/services/spotify/index.js b/lib/services/spotify/index.js index da15d18..f3dd065 100644 --- a/lib/services/spotify/index.js +++ b/lib/services/spotify/index.js @@ -81,8 +81,8 @@ export function* search(data) { query = "artist:" + cleanParam(data.artist.name) + " album:" + cleanParam(data.name); album = data.name; } else if (type == "track") { - query = "artist:" + cleanParam(data.artist.name) + " track:" + cleanParam(data.name) + ( cleanParam(data.album.name).length > 0 ? " album:" + cleanParam(data.album.name): ""); - album = data.album.name; + query = "artist:" + cleanParam(data.artist.name) + " track:" + cleanParam(data.name) + ( cleanParam(data.albumName).length > 0 ? " album:" + cleanParam(data.albumName): ""); + album = data.albumName; } const results = yield spotify.searchAsync({query: query, type: type}); @@ -90,7 +90,7 @@ export function* search(data) { return {service: "spotify"}; } else { let found; - const choppedAlbum = data.type == "album" ? cleanParam(data.name) : cleanParam(data.album.name); + const choppedAlbum = data.type == "album" ? cleanParam(data.name) : cleanParam(data.albumName); if (!choppedAlbum.length) { return yield lookupId(results[type + "s"].items[0].id, type); } diff --git a/lib/services/xbox/index.js b/lib/services/xbox/index.js index 11eba43..491880b 100644 --- a/lib/services/xbox/index.js +++ b/lib/services/xbox/index.js @@ -107,7 +107,7 @@ export function* search(data) { album = data.name; } else if (type == 'track') { query = cleanParam(data.artist.name.substring(0, data.artist.name.indexOf('&'))) + ' ' + cleanParam(data.name); - album = data.album.name + album = data.albumName } const path = '/music/search?q=' + encodeURIComponent(query) + '&filters=' + type + 's'; try { diff --git a/lib/services/youtube/index.js b/lib/services/youtube/index.js index 2aa93c2..2b00e65 100644 --- a/lib/services/youtube/index.js +++ b/lib/services/youtube/index.js @@ -80,7 +80,7 @@ export function* lookupId(id, type) { match.name = topic.property['/type/object/name'].values[0].text; if (topic.property['/music/recording/releases']) { match.type = 'album'; - match.album.name = topic.property['/music/recording/releases'].values[0].text; + match.albumName = topic.property['/music/recording/releases'].values[0].text; } } else if (musicalAlbum) { match.name = topic.property['/type/object/name'].values[0].text; @@ -103,7 +103,7 @@ export function* search(data) { album = data.name; } else if (type == 'track') { query = data.artist.name + ' ' + data.name; - album = data.album.name + album = data.albumName } const path = '/search?part=snippet&q=' + encodeURIComponent(query) + '&type=video&videoCaption=any&videoCategoryId=10&key=' + credentials.key; diff --git a/test/services/deezer.js b/test/services/deezer.js index 9f2002e..91d3734 100644 --- a/test/services/deezer.js +++ b/test/services/deezer.js @@ -21,7 +21,7 @@ describe('Deezer', function(){ }); it('should find track by search', function* (){ - const result = yield deezer.search({type: 'track', artist: {name: 'Deftones'}, album: {name: 'Deftones'}, name: 'Hexagram'}); + const result = yield deezer.search({type: 'track', artist: {name: 'Deftones'}, albumName: 'Deftones', name: 'Hexagram'}); result.name.should.equal('Hexagram'); }); }); diff --git a/test/services/google.js b/test/services/google.js index 150a517..249b8f0 100644 --- a/test/services/google.js +++ b/test/services/google.js @@ -19,6 +19,16 @@ describe('Google Play Music', function(){ const result = yield google.search({type: 'album', artist: {name: 'Jamie xx'}, name: 'In Colour'}); result.name.should.equal('In Colour'); }); + + it('should find track by search', function* (){ + const result = yield google.search({type: 'track', artist: {name: 'Jamie xx'}, albumName: 'In Colour', name: 'Loud Places'}); + result.name.should.equal('Loud Places'); + }); + + it('should find awkward track by search', function* (){ + const result = yield google.search({type: 'track', artist: {name: 'Jamie xx'}, albumName: 'In Colour (Remixes)', name: 'Loud Places [Tessela Remix]'}); + result.name.should.equal('Loud Places [Tessela Remix]'); + }); }); describe('lookupUrl', function(){ diff --git a/test/services/itunes.js b/test/services/itunes.js index 05af3c7..277a465 100644 --- a/test/services/itunes.js +++ b/test/services/itunes.js @@ -21,7 +21,7 @@ describe('iTunes Music', function(){ }); it('should find track by search', function* (){ - const result = yield itunes.search({type: 'track', artist: {name: 'Deftones'}, album: {name: 'Deftones'}, name: 'Hexagram'}); + const result = yield itunes.search({type: 'track', artist: {name: 'Deftones'}, albumName: 'Deftones', name: 'Hexagram'}); result.name.should.equal('Hexagram'); }); });