diff --git a/lib/services/itunes/index.js b/lib/services/itunes/index.js index 966ac6d..d78004a 100644 --- a/lib/services/itunes/index.js +++ b/lib/services/itunes/index.js @@ -76,6 +76,7 @@ export function* lookupId(id, type, cc) { }; export function* search(data) { + const markets = ['us', 'gb', 'jp', 'br', 'de', 'es']; let query, album, entity; const type = data.type; @@ -89,47 +90,48 @@ export function* search(data) { entity = 'musicTrack'; } - const path = '/search?term=' + encodeURIComponent(query) + '&media=music&entity=' + entity; - const response = yield request.get(apiRoot + path); - let result = JSON.parse(response.text); + for (let market of markets) { + const path = '/' + market + '/search?term=' + encodeURIComponent(query) + '&media=music&entity=' + entity; + const response = yield request.get(apiRoot + path); - if (!result.results[0]) { - const matches = album.match(/^[^\(\[]+/); - if (matches && matches[0] && matches[0] !== album) { - const cleanedData = JSON.parse(JSON.stringify(data)); - if (type === 'album') { - cleanedData.name = matches[0].trim(); - } else if (type === 'track') { - cleanedData.albumName = matches[0].trim(); + let result = JSON.parse(response.text); + if (!result.results[0]) { + const matches = album.match(/^[^\(\[]+/); + if (matches && matches[0] && matches[0] !== album) { + const cleanedData = JSON.parse(JSON.stringify(data)); + if (type === 'album') { + cleanedData.name = matches[0].trim(); + } else if (type === 'track') { + cleanedData.albumName = matches[0].trim(); + } + return yield search(cleanedData); } - return yield search(cleanedData); } else { - return {service: 'itunes'}; - } - } else { - result = result.results[0]; + result = result.results[0]; - const item = { - service: 'itunes', - type: type, - id: 'us' + result.collectionId, - name: result.trackName ? result.trackName : result.collectionName, - streamUrl: null, - purchaseUrl: result.collectionViewUrl, - artwork: { - small: 'https://match.audio/itunes/' + result.artworkUrl100.replace('100x100', '200x200').replace('http://', ''), - large: 'https://match.audio/itunes/' + result.artworkUrl100.replace('100x100', '600x600').replace('http://', '') - }, - artist: { - name: result.artistName - } - }; - - if (type === 'track') { - item.album = { - name: result.collectionName + const item = { + service: 'itunes', + type: type, + id: 'us' + result.collectionId, + name: result.trackName ? result.trackName : result.collectionName, + streamUrl: null, + purchaseUrl: result.collectionViewUrl, + artwork: { + small: 'https://match.audio/itunes/' + result.artworkUrl100.replace('100x100', '200x200').replace('http://', ''), + large: 'https://match.audio/itunes/' + result.artworkUrl100.replace('100x100', '600x600').replace('http://', '') + }, + artist: { + name: result.artistName + } }; + + if (type === 'track') { + item.album = { + name: result.collectionName + }; + } + return item; } - return item; } + return {service: 'itunes'}; }; diff --git a/lib/services/spotify/index.js b/lib/services/spotify/index.js index 2af1d5d..009dc7b 100644 --- a/lib/services/spotify/index.js +++ b/lib/services/spotify/index.js @@ -1,6 +1,8 @@ import { parse } from 'url'; import bluebird from 'bluebird'; import spotifyCB from 'spotify'; +import request from 'superagent'; +import 'superagent-bluebird-promise'; const spotify = bluebird.promisifyAll(spotifyCB); import { match as urlMatch } from './url'; @@ -64,8 +66,9 @@ export function* lookupId(id, type) { } } -export function* search(data) { - var cleanParam = function(str) { +export function* search(data, original={}) { + const markets = ['US', 'GB', 'JP', 'BR', 'DE', 'ES']; + const cleanParam = function(str) { var chopChars = ['&', '[', '(']; chopChars.forEach(function(chr) { if (data.artist.name.indexOf('&') > 0) { @@ -74,8 +77,8 @@ export function* search(data) { }) return str.replace(/[\:\?]+/, ""); } - var query, album; - var type = data.type; + let query, album; + const type = data.type; if (type == "album") { query = "artist:" + cleanParam(data.artist.name) + " album:" + cleanParam(data.name); @@ -85,27 +88,50 @@ export function* search(data) { album = data.albumName; } - const results = yield spotify.searchAsync({query: query, type: type}); + for (let market of markets) { + const response = yield request.get('https://api.spotify.com/v1/search?type=' + type + '&q=' + encodeURI(query) + '&market=' + market); + const items = response.body[type + 's'].items; - if (!results[type + "s"].items[0]) { - return {service: "spotify"}; - } else { - let found; - const choppedAlbum = data.type == "album" ? cleanParam(data.name) : cleanParam(data.albumName); - if (!choppedAlbum.length) { - return yield lookupId(results[type + "s"].items[0].id, type); + const name = original.name || data.name; + + let match; + if (!(match = exactMatch(name, items, type))) { + match = looseMatch(name, items, type); } - results[type + "s"].items.forEach(function(item) { - const albumName = data.type == "album" ? item.name : item.album.name; - const matches = cleanParam(albumName).match(/^[^\(\[]+/); - if(choppedAlbum.indexOf(matches[0]) >= 0) { - found = item; + if (match) { + if (type === 'album') { + return yield lookupId(match.id, type); + } else if (type === 'track') { + return yield lookupId(match.id, type); } - }); - if (!found) { - return {service: "spotify"}; } - return yield lookupId(results[type + "s"].items[0].id, type); } + return {service: "spotify"}; +} + +function exactMatch(needle, haystack, type) { + // try to find exact match + return haystack.find(function(entry) { + if (entry.type !== type) { + return false; + } + + if (entry.name === needle) { + return entry; + } + }); +} + +function looseMatch(needle, haystack, type) { + // try to find exact match + return haystack.find(function(entry) { + if (entry.type !== type) { + return false; + } + + if (entry.name.indexOf(needle) >= 0) { + return entry + } + }); } diff --git a/test/services/itunes.js b/test/services/itunes.js index 277a465..cf7719e 100644 --- a/test/services/itunes.js +++ b/test/services/itunes.js @@ -20,6 +20,11 @@ describe('iTunes Music', function(){ result.name.should.equal('White Pony'); }); + it('should find awkward album by search', function* (){ + const result = yield itunes.search({type: 'album', artist: {name: 'Anavitória'}, name: 'Fica'}); + result.name.should.equal('Fica (feat. Matheus & Kauan) - Single'); + }); + it('should find track by search', function* (){ const result = yield itunes.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 60c7bad..bca91ab 100644 --- a/test/services/spotify.js +++ b/test/services/spotify.js @@ -20,6 +20,11 @@ describe('Spotify', function(){ result.name.should.equal('Listen (Deluxe)'); }); + it('should find br album by search', function* (){ + const result = yield spotify.search({type: 'album', artist: {name: 'Anavitória'}, name: 'Fica'}); + result.name.should.equal('Fica'); + }); + 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');