Add suppport for tracks, basic design, minor refactor
This commit is contained in:
parent
e20b3b86c4
commit
acb129899d
13 changed files with 267 additions and 77 deletions
|
@ -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
|
||||
|
|
|
@ -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]+)/);
|
||||
|
|
32
lib/rdio.js
32
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
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -11,7 +11,10 @@ module.exports.lookupId = function(id, type, next) {
|
|||
|
||||
var artist = data.artists[0];
|
||||
|
||||
if (type == "album") {
|
||||
next({
|
||||
service: "spotify",
|
||||
type: type,
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
url: "https://play.spotify.com/" + type + "/" + data.id,
|
||||
|
@ -19,11 +22,38 @@ module.exports.lookupId = function(id, type, next) {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
BIN
public/images/googleplaymusic.png
Normal file
BIN
public/images/googleplaymusic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.5 KiB |
BIN
public/images/rdio.png
Normal file
BIN
public/images/rdio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4 KiB |
BIN
public/images/spotify.png
Normal file
BIN
public/images/spotify.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
|
@ -1,8 +1,73 @@
|
|||
body {
|
||||
padding: 50px;
|
||||
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
||||
font-family: "Open Sans";
|
||||
}
|
||||
|
||||
a {
|
||||
color: #00B7FF;
|
||||
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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
req.flash('search-error', 'No match found for this link');
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -7,23 +7,41 @@
|
|||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
<style>
|
||||
.container {
|
||||
padding-top: 100px;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/stylesheets/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<body class="album share">
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<img src="<%= spotifyAlbum.artwork %>" height=200 class="img-rounded" /> <%= spotifyAlbum.id %> <a href="<%= spotifyAlbum.url %>">Play on Spotify</a>
|
||||
<div class="col-md-12">
|
||||
<h1><a href="/">match<span class="audio-lighten">.audio</span></a></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2><%= items[0].artist.name %> - <%= items[0].name %></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<img src="<%= googleAlbum.artwork %>" height=200 class="img-rounded" /> <%= googleAlbum.id %> <a href="<%= googleAlbum.url %>">Play on Google Music</a>
|
||||
<% for (var i=0;i < items.length;i++) { var album = items[i]; %>
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<div class="service <%= i==0 ? "source-service" : "" %>">
|
||||
<div class="matching-from"><%= i==0 ? "Found matches for this album" : "" %></div>
|
||||
<img src="<%= album.artwork %>" class="img-rounded album-artwork" width="100%">
|
||||
<div class="service-link">
|
||||
<a href="<%= album.url %>">Listen on <img src="/images/<%= album.service %>.png" class="img-rounded"></a>
|
||||
</div>
|
||||
<div class="row">
|
||||
<img src="<%= rdioAlbum.artwork %>" height=200 class="img-rounded" /> <%= rdioAlbum.id %> <a href="<%= rdioAlbum.url %>">Play on Rdio</a>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<div class="row share">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -7,32 +7,31 @@
|
|||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
<style>
|
||||
.container {
|
||||
padding-top: 100px;
|
||||
}
|
||||
.form-inline {
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/stylesheets/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<body class="home">
|
||||
<header>
|
||||
<h1><a href="/">match<span class="audio-lighten">.audio</span></a></h1>
|
||||
</header>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-sm-offset-3">
|
||||
<div class="row share-form">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<%= error %>
|
||||
<form role="form" method="post" action="/search" class="form-inline">
|
||||
<div class="form-group form-group-lg">
|
||||
<input type="text" name="url" placeholder="Paste link here" class="form-control">
|
||||
<input type="submit" class="btn btn-default btn-lg" value="Share Music">
|
||||
</div>
|
||||
<input type="submit" class="btn btn-default btn-lg" value="Share Music">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-sm-offset-3">
|
||||
<p>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. <a href="/google/album/B3qrtsvk5s3piwyla76sk6qyxny">Here's an example</a>.</p>
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<p>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.
|
||||
<a href="/google/album/B3qrtsvk5s3piwyla76sk6qyxny">Here's an example</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
40
views/track.ejs
Normal file
40
views/track.ejs
Normal file
|
@ -0,0 +1,40 @@
|
|||
<!doctype html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Match Audio</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/stylesheets/style.css">
|
||||
</head>
|
||||
<body class="track share">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2><a href="/">match.audio</a></h2>
|
||||
<h1><%= items[0].artist.name %> - <%= items[0].name %></h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<% for (var i=0;i < items.length;i++) { var track = items[i]; %>
|
||||
<div class="col-md-3 col-xs-6">
|
||||
<div class="service <%= i==0 ? "source-service" : "" %>">
|
||||
<div class="matching-from"><%= i==0 ? "Matching track from this album" : "" %></div>
|
||||
<img src="<%= track.artwork %>" class="img-rounded album-artwork" width="100%">
|
||||
<div class="service-link">
|
||||
<a href="<%= track.url %>">Listen on <img src="/images/<%= track.service %>.png" class="img-rounded"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<div class="row share">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue