diff --git a/README.md b/README.md index 05623be..d884662 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,4 @@ On the immediate todo list: * Add support for tracks, and maybe artists * Use album release year for additional sanity check on matches * Do some kind of a design, particularly for the share page +* Handle expected and unexpected errors better than the current crash-fest diff --git a/lib/googleplaymusic.js b/lib/googleplaymusic.js index 235f76c..eabda90 100644 --- a/lib/googleplaymusic.js +++ b/lib/googleplaymusic.js @@ -14,33 +14,47 @@ module.exports.lookupId = function(id, type, next) { if (type == "album") { pm.getAlbum(id, true, function(album) { next({ + service: "googleplaymusic", + type: "album", id: album.albumId, name: album.name, url: "https://play.google.com/music/listen#/album/" + album.albumId, artwork: album.albumArtRef.replace("http:", ""), artist: { name: album.artist - }, - type: type + } }); }); } else if (type == "track") { pm.getAllAccessTrack(id, function(track) { next({ + service: "googleplaymusic", + type: "track", id: track.nid, name: track.title, url: "https://play.google.com/music/listen#/track/" + track.nid + "/" + track.albumId, artwork: track.albumArtRef[0].url.replace("http:", ""), + album: { + name: track.album + }, artist: { name: track.artist - }, - type: type + } }); }); } } -module.exports.search = function(query, type, next) { +module.exports.search = function(data, next) { + var query = ""; + var type = data.type; + + if (type == "album") { + query = data.artist.name + " " + data.name; + } else if (type == "track") { + query = data.artist.name + " " + data.album.name + " " + data.name; + } + pm.search(query, 5, function(data) { // max 5 results var result = data.entries.filter(function(result) { return result[type]; @@ -49,9 +63,9 @@ module.exports.search = function(query, type, next) { }).shift(); var id; - if (result.album) { + if (type == "album") { id = result.album.albumId; - } else if (result.track) { + } else if (type == "track") { id = result.track.nid; } @@ -73,9 +87,7 @@ module.exports.parseUrl = function(url, next) { if (id.length > 0) { return next({id: id, type: type}); } else { - module.exports.search(artist + " " + album, "album", function(googleAlbum) { - next(googleAlbum); - }); + module.exports.search({type: type, name:album, artist: {name: artist}}, next); } } else if(path) { var matches = path.match(/\/music\/m\/([\w]+)/); diff --git a/lib/rdio.js b/lib/rdio.js index 95a6d0f..cfa62cb 100644 --- a/lib/rdio.js +++ b/lib/rdio.js @@ -21,14 +21,15 @@ module.exports.lookupId = function(id, next) { var id = parsed.path.replace("/x/", "").replace("/", ""); var type = result.album ? "track" : "album"; next({ + service: "rdio", + type: type, id: id, name: result.name, url: result.shortUrl, - artwork: result.icon.replace("http:", ""), + artwork: result.icon.replace("http:", "").replace("square-200", "square-500"), artist: { name: result.artist - }, - type: type + } }); }); }; @@ -58,19 +59,29 @@ module.exports.lookupUrl = function(url, next) { var id = parsed.path.replace("/x/", "").replace("/", ""); var type = result.album ? "track" : "album"; next({ + service: "rdio", + type: type, id: id, name: result.name, url: result.shortUrl, - artwork: result.icon.replace("http:", ""), + artwork: result.icon.replace("http:", "").replace("square-200", "square-500"), artist: { name: result.artist - }, - type: type + } }); }); }; -module.exports.search = function(query, type, next) { +module.exports.search = function(data, next) { + var query; + var type = data.type; + + if (type == "album") { + query = data.artist.name + " " + data.name; + } else if (type == "track") { + query = data.artist.name + " " + data.album.name + " " + data.name; + } + console.log(query) rdio.api("", "", { query: query, method: 'search', @@ -83,14 +94,15 @@ module.exports.search = function(query, type, next) { var parsed = parse(result.shortUrl) var id = parsed.path.replace("/x/", "").replace("/", ""); next({ + service: "rdio", + type: type, id: id, name: result.name, url: result.shortUrl, - artwork: result.icon.replace("http:", ""), + artwork: result.icon.replace("http:", "").replace("square-200", "square-500"), artist: { name: result.artist - }, - type: type + } }); }); }; diff --git a/lib/spotify.js b/lib/spotify.js index 7b838a9..8359f76 100644 --- a/lib/spotify.js +++ b/lib/spotify.js @@ -11,19 +11,49 @@ module.exports.lookupId = function(id, type, next) { var artist = data.artists[0]; - next({ - id: data.id, - name: data.name, - url: "https://play.spotify.com/" + type + "/" + data.id, - artwork: data.images ? data.images[0].url.replace("http:", "") : data.album.images[0].url.replace("http:", ""), - artist: { - name: artist.name - } - }) + if (type == "album") { + next({ + service: "spotify", + type: type, + id: data.id, + name: data.name, + url: "https://play.spotify.com/" + type + "/" + data.id, + artwork: data.images ? data.images[0].url.replace("http:", "") : data.album.images[0].url.replace("http:", ""), + artist: { + name: artist.name + } + }); + } else if (type == "track") { + next({ + service: "spotify", + type: type, + id: data.id, + name: data.name, + url: "https://play.spotify.com/" + type + "/" + data.id, + artwork: data.images ? data.images[0].url.replace("http:", "") : data.album.images[0].url.replace("http:", ""), + artist: { + name: artist.name + }, + album: { + name: data.album.name + } + }) + } }); } -module.exports.search = function(query, type, next) { +module.exports.search = function(data, next) { + var query = ""; + var type = data.type; + + if (type == "album") { + query = data.artist.name + " " + data.name; + } else if (type == "track") { + query = data.artist.name + " " + data.album.name + " " + data.name; + } + + query = query.replace(":", ""); + spotify.search({query: query, type: type}, function(err, data) { if ( err ) { console.log('Error occurred: ' + err); @@ -40,6 +70,6 @@ module.exports.parseUrl = function(url, next) { var matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/); if (matches && matches[2]) { - next({id:matches[2], type: matches[1]}) + module.exports.lookupId(matches[2], matches[1], next); } } diff --git a/public/images/googleplaymusic.png b/public/images/googleplaymusic.png new file mode 100644 index 0000000..9d27f90 Binary files /dev/null and b/public/images/googleplaymusic.png differ diff --git a/public/images/rdio.png b/public/images/rdio.png new file mode 100644 index 0000000..c3684bd Binary files /dev/null and b/public/images/rdio.png differ diff --git a/public/images/spotify.png b/public/images/spotify.png new file mode 100644 index 0000000..735c71c Binary files /dev/null and b/public/images/spotify.png differ diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 30e047d..3c62a06 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -1,8 +1,73 @@ body { - padding: 50px; - font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; + font-family: "Open Sans"; } -a { - color: #00B7FF; -} \ No newline at end of file +header { + background: #e6832e; +} + +header h1 { + margin: 0; + text-align: center; + font-weight: 300; + font-size: 2em; + padding: 20px 0; +} + +header h1 a { + color: #fff; +} + +header h1 a:hover { + color: #f2c4ad; + text-decoration: none; +} + +.share header h1 { + text-align: left; + font-size: 1.5em; + padding: 10px 0; +} + +.audio-lighten { + color:#f2c4ad; +} + +h2 { + font-size: 1.5em; + font-weight: 700; + margin: 40px 0; +} + +.share-form { + margin: 50px 0; + text-align: center; +} + +.service { + padding: 40px 10px 10px 10px; +} +.matching-from { + position: absolute; + top: 10px; + left: 25px; +} +.source-service { + background: #eee; +} +.album-artwork { + margin-bottom: 10px; +} +.service-link { + text-align: center; +} +.service-link a { + font-size: 1.8em; + color: #444; +} +.service-link a:hover { + text-decoration: none; +} +.service-link img { + margin-bottom: 7px; +} diff --git a/routes/index.js b/routes/index.js index 7d4b5a1..cd3f81c 100644 --- a/routes/index.js +++ b/routes/index.js @@ -7,35 +7,47 @@ var googleplaymusic = require('../lib/googleplaymusic'); var spotify = require('../lib/spotify'); var rdio = require('../lib/rdio'); +var cache = {googleplaymusic:{}, spotify:{},rdio:{}}; + router.get('/:service/:type/:id', function(req, res) { var service = req.params.service; var type = req.params.type; var id = req.params.id; + var items = []; switch(service) { case "spotify": - spotify.lookupId(id, type, function(spotifyAlbum) { - googleplaymusic.search(spotifyAlbum.artist.name + " " + spotifyAlbum.name, type, function(googleAlbum) { - rdio.search(googleAlbum.artist.name + " " + googleAlbum.name, type, function(rdioAlbum) { - res.render('album', {rdioAlbum: rdioAlbum, googleAlbum: googleAlbum, spotifyAlbum: spotifyAlbum}); + spotify.lookupId(id, type, function(result) { + items.push(result); + googleplaymusic.search(result, function(item) { + items.push(item); + rdio.search(result, function(item) { + items.push(item); + res.render(result.type, {items: items}); }); }); }); break; case "google": - googleplaymusic.lookupId(id, type, function(googleAlbum) { - spotify.search(googleAlbum.artist.name + " " + googleAlbum.name, type, function(spotifyAlbum) { - rdio.search(googleAlbum.artist.name + " " + googleAlbum.name, type, function(rdioAlbum) { - res.render('album', {rdioAlbum: rdioAlbum, googleAlbum: googleAlbum, spotifyAlbum: spotifyAlbum}); + googleplaymusic.lookupId(id, type, function(result) { + items.push(result); + spotify.search(result, function(item) { + items.push(item); + rdio.search(result, function(item) { + items.push(item); + res.render(result.type, {items: items}); }); }); }); break; case "rdio": - rdio.lookupId(id, function(rdioAlbum) { - googleplaymusic.search(rdioAlbum.artist.name + " " + rdioAlbum.name, type, function(googleAlbum) { - spotify.search(rdioAlbum.artist.name + " " + rdioAlbum.name, type, function(spotifyAlbum) { - res.render('album', {rdioAlbum: rdioAlbum, googleAlbum: googleAlbum, spotifyAlbum: spotifyAlbum}); + rdio.lookupId(id, type, function(result) { + items.push(result); + googleplaymusic.search(result, function(item) { + items.push(item); + spotify.search(result, function(item) { + items.push(item); + res.render(result.type, {items: items}); }); }); }); @@ -65,11 +77,12 @@ router.post('/search', function(req, res) { }); } else if (url.host.match(/play\.google\.com$/)) { googleplaymusic.parseUrl(url.href, function(result) { - if (!result.id) { + if (!result) { req.flash('search-error', 'No match found for this link'); res.redirect('/'); + } else { + res.redirect("/google/" + result.type + "/" + result.id); } - res.redirect("/google/" + result.type + "/" + result.id); }); } else { req.flash('search-error', 'No match found for this link'); diff --git a/test/test.js b/test/test.js index da3267e..3eebf08 100644 --- a/test/test.js +++ b/test/test.js @@ -17,7 +17,7 @@ describe('Spotify', function(){ describe('search', function(){ it('should find album by search', function(done){ - spotify.search("David Guetta Listen (Deluxe)", "album", function(result) { + spotify.search({type: "album", artist: {name: "David Guetta"}, name: "Listen (Deluxe)"}, function(result) { result.name.should.equal("Listen (Deluxe)"); done(); }); @@ -46,7 +46,7 @@ describe('Rdio', function(){ describe('search', function(){ it('should find album by search', function(done){ - rdio.search("David Guetta Listen (Deluxe)", "album", function(result) { + rdio.search({type: "album", artist: {name: "David Guetta"}, name: "Listen (Deluxe)"}, function(result) { result.name.should.equal("Listen (Deluxe)"); done(); }); @@ -82,7 +82,7 @@ describe('Google Play Music', function(){ describe('search', function(){ it('should find album by search', function(done){ - googleplaymusic.search("David Guetta Listen (Deluxe)", "album", function(result) { + googleplaymusic.search({type: "album", artist: {name: "David Guetta"}, name: "Listen (Deluxe)"}, function(result) { result.name.should.equal("Listen (Deluxe)"); done(); }); diff --git a/views/album.ejs b/views/album.ejs index e4889eb..1d767b3 100644 --- a/views/album.ejs +++ b/views/album.ejs @@ -7,23 +7,41 @@ + - + - + +
+
+
+ +
+
+
- <%= spotifyAlbum.id %> Play on Spotify +
+

<%= items[0].artist.name %> - <%= items[0].name %>

+
- <%= googleAlbum.id %> Play on Google Music + <% for (var i=0;i < items.length;i++) { var album = items[i]; %> +
+
"> +
<%= i==0 ? "Found matches for this album" : "" %>
+ + +
+
+ <% } %>
-
- <%= rdioAlbum.id %> Play on Rdio +
diff --git a/views/index.ejs b/views/index.ejs index 1b56d2c..46f67b1 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -7,32 +7,31 @@ + - + - + +
+

match.audio

+
-
-
+
-
-

Make sharing music from subscription services better. Give us one link (Rdio, Spotify or Google Music) and we'll match it with other services and give you back a link with all of them. Here's an example.

+
+

Make sharing music from subscription services better. + We match links from Rdio, Spotify and Google Music and give you back a link with all of them. + Here's an example.

diff --git a/views/track.ejs b/views/track.ejs new file mode 100644 index 0000000..33aa3bb --- /dev/null +++ b/views/track.ejs @@ -0,0 +1,40 @@ + + + + + + Match Audio + + + + + + + + +
+
+
+

match.audio

+

<%= items[0].artist.name %> - <%= items[0].name %>

+
+
+
+ <% for (var i=0;i < items.length;i++) { var track = items[i]; %> +
+
"> +
<%= i==0 ? "Matching track from this album" : "" %>
+ + +
+
+ <% } %> +
+ +
+ +