Switch to Koa, more es6
This commit is contained in:
parent
1090affc9c
commit
b3abff99ae
36 changed files with 25573 additions and 928 deletions
|
@ -1,4 +1,10 @@
|
|||
{
|
||||
"ecmaFeatures": {
|
||||
"modules": true
|
||||
},
|
||||
"rules": {
|
||||
"quotes": [2, "single", "avoid-escape"]
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
|
|
189
app.js
189
app.js
|
@ -1,127 +1,102 @@
|
|||
"use strict";
|
||||
var express = require("express");
|
||||
var helmet = require("helmet");
|
||||
var path = require("path");
|
||||
var favicon = require("serve-favicon");
|
||||
var logger = require("morgan");
|
||||
var session = require("express-session");
|
||||
var cookieParser = require("cookie-parser");
|
||||
var flash = require("connect-flash");
|
||||
var compress = require("compression");
|
||||
var bodyParser = require("body-parser");
|
||||
var pmongo = require("promised-mongo");
|
||||
import path from 'path';
|
||||
import koa from 'koa';
|
||||
import route from 'koa-route';
|
||||
import logger from 'koa-logger';
|
||||
import favicon from 'koa-favicon';
|
||||
import compress from 'koa-compress';
|
||||
import staticHandler from 'koa-static';
|
||||
import bodyparser from 'koa-bodyparser';
|
||||
import React from 'react';
|
||||
import co from 'co';
|
||||
import db from './config/db';
|
||||
import index from './routes/index';
|
||||
import search from './routes/search';
|
||||
import share from './routes/share';
|
||||
import itunesProxy from './routes/itunes-proxy';
|
||||
import {routes} from './views/app.jsx';
|
||||
import zlib from 'zlib';
|
||||
import createHandler from './lib/react-handler';
|
||||
|
||||
var index = require("./routes/index");
|
||||
var search = require("./routes/search");
|
||||
var share = require("./routes/share");
|
||||
var itunesProxy = require("./routes/itunes-proxy");
|
||||
import debuglog from 'debug';
|
||||
const debug = debuglog('match.audio');
|
||||
|
||||
var React = require("react");
|
||||
require("node-jsx").install({extension: ".jsx"});
|
||||
const app = koa();
|
||||
|
||||
var ErrorView = React.createFactory(require("./views/error.jsx"));
|
||||
app.use(function* (next) {
|
||||
this.set('Server', 'Nintendo 64');
|
||||
try {
|
||||
yield next;
|
||||
} catch (err) {
|
||||
if (!err.status) {
|
||||
console.error(err.stack);
|
||||
} else if (err.status === 404) {
|
||||
let Handler = yield createHandler(routes, this.request.url);
|
||||
|
||||
var browserify = require("connect-browserify");
|
||||
let App = React.createFactory(Handler);
|
||||
let content = React.renderToString(new App());
|
||||
|
||||
var app = express();
|
||||
|
||||
var development = process.env.NODE_ENV !== "production";
|
||||
|
||||
// view engine setup
|
||||
app.set("views", path.join(__dirname, "views"));
|
||||
app.set("view engine", "ejs");
|
||||
|
||||
app.use(compress());
|
||||
app.use(favicon(path.join(__dirname, "/public/images/favicon.png")));
|
||||
app.use(helmet());
|
||||
app.use(logger("dev"));
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(cookieParser());
|
||||
app.use(session({
|
||||
secret: "keyboard catz",
|
||||
resave: false,
|
||||
saveUninitialized: true
|
||||
}));
|
||||
app.use(flash());
|
||||
app.use(express.static(path.join(__dirname, "public")));
|
||||
|
||||
var dbUrl = process.env.MONGOHQ_URL || "mongodb://localhost/match-audio";
|
||||
app.use(function(req, res, next) {
|
||||
req.db = res.db = pmongo(dbUrl, ["matches"]);
|
||||
next();
|
||||
this.body = '<!doctype html>\n' + content;
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (development) {
|
||||
app.get("/javascript/bundle.js",
|
||||
browserify("./views/app.jsx", {
|
||||
debug: true,
|
||||
watch: true
|
||||
}));
|
||||
}
|
||||
app.use(bodyparser());
|
||||
app.use(compress({flush: zlib.Z_SYNC_FLUSH }));
|
||||
app.use(favicon(path.join(__dirname, '/public/images/favicon.png')));
|
||||
app.use(logger());
|
||||
app.use(staticHandler(path.join(__dirname, 'public')));
|
||||
|
||||
app.get("*", function(req, res, next) {
|
||||
let mongo = {};
|
||||
|
||||
co(function*() {
|
||||
mongo = yield db();
|
||||
});
|
||||
|
||||
app.use(function* (next){
|
||||
this.db = mongo;
|
||||
yield next;
|
||||
});
|
||||
|
||||
app.use(function* (next) {
|
||||
// force SSL
|
||||
if (req.headers["cf-visitor"] && req.headers["cf-visitor"] !== "{\"scheme\":\"https\"}") {
|
||||
return res.redirect("https://" + req.headers.host + req.url);
|
||||
} else if (req.headers["cf-visitor"]) {
|
||||
req.userProtocol = "https";
|
||||
if (this.headers['cf-visitor'] && this.headers['cf-visitor'] !== '{"scheme":"https"}') {
|
||||
return this.redirect('https://' + this.headers.host + this.url);
|
||||
} else if (this.headers['cf-visitor']) {
|
||||
this.userProtocol = 'https';
|
||||
} else {
|
||||
req.userProtocol = "http";
|
||||
this.userProtocol = 'http';
|
||||
}
|
||||
// redirect www
|
||||
if (req.headers.host.match(/^www/) !== null ) {
|
||||
return res.redirect(req.userProtocol + "://" + req.headers.host.replace(/^www\./, "") + req.url);
|
||||
if (this.headers.host.match(/^www/) !== null ) {
|
||||
return this.redirect(this.userProtocol + '://' + this.headers.host.replace(/^www\./, '') + this.url);
|
||||
} else {
|
||||
next();
|
||||
yield next;
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/", index);
|
||||
app.post("/search", search);
|
||||
app.get("/:service/:type/:id.:format?", share);
|
||||
app.get("/itunes/*", itunesProxy);
|
||||
app.get("/recent", function(req, res, next) {
|
||||
req.db.matches.find().sort({"created_at": -1}).limit(6).toArray().then(function(docs){
|
||||
var recents = [];
|
||||
docs.forEach(function(doc) {
|
||||
recents.push(doc.services[doc._id.split("$$")[0]]); // eslint-disable-line no-underscore-dangle
|
||||
});
|
||||
res.json({recents: recents});
|
||||
}).catch(function (error) {
|
||||
return next(error);
|
||||
app.use(route.get('/', index));
|
||||
app.use(route.post('/search', search));
|
||||
app.use(route.get('/itunes/(.*)', itunesProxy));
|
||||
app.use(route.get('/:service/:type/:id.:format?', share));
|
||||
app.use(route.get('/recent', function* () {
|
||||
let recents = [];
|
||||
let docs = yield this.db.matches.find().sort({'created_at': -1}).limit(6).toArray();
|
||||
docs.forEach(function(doc) {
|
||||
recents.push(doc.services[doc._id.split('$$')[0]]); // eslint-disable-line no-underscore-dangle
|
||||
});
|
||||
});
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use(function(req, res, next) {
|
||||
var err = new Error("Not Found");
|
||||
err.status = 404;
|
||||
next(err);
|
||||
});
|
||||
|
||||
// error handlers
|
||||
|
||||
// development error handler
|
||||
// will print stacktrace
|
||||
if (app.get("env") === "development") {
|
||||
app.use(function(err, req, res) {
|
||||
console.log(err.stack);
|
||||
res.status(err.status || 500);
|
||||
|
||||
var content = React.renderToString(new ErrorView({status: err.status || 500, message: err.message, error: err}));
|
||||
res.send("<!doctype html>\n" + content);
|
||||
});
|
||||
}
|
||||
|
||||
// production error handler
|
||||
// no stacktraces leaked to user
|
||||
app.use(function(err, req, res) {
|
||||
res.status(err.status || 500);
|
||||
|
||||
var content = React.renderToString(new ErrorView({status: err.status || 500, message: err.message, error: {status: err.status || 500}}));
|
||||
res.send("<!doctype html>\n" + content);
|
||||
});
|
||||
this.body = {recents: recents};
|
||||
}));
|
||||
|
||||
app.use(route.get('*', function* () {
|
||||
this.throw(404);
|
||||
}));
|
||||
|
||||
module.exports = app;
|
||||
|
||||
if (!module.parent) {
|
||||
app.listen(process.env.PORT || 3000, function() {
|
||||
debug('Koa server listening on port ' + (process.env.PORT || 3000));
|
||||
});
|
||||
}
|
||||
|
|
10
bin/www
10
bin/www
|
@ -1,10 +1,10 @@
|
|||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
var debug = require('debug')('match.audio');
|
||||
var app = require('../app');
|
||||
var debug = require("debug")("match.audio");
|
||||
var app = require("../app");
|
||||
|
||||
app.set('port', process.env.PORT || 3000);
|
||||
app.set("port", process.env.PORT || 3000);
|
||||
|
||||
var server = app.listen(app.get('port'), function() {
|
||||
debug('Express server listening on port ' + server.address().port);
|
||||
var server = app.listen(app.get("port"), function() {
|
||||
debug("Express server listening on port " + server.address().port);
|
||||
});
|
||||
|
|
17
config/db.js
Normal file
17
config/db.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
'use strict';
|
||||
const debug = require('debug')('match.audio');
|
||||
|
||||
// Shut mongodb-promisified up.
|
||||
const dir = console.dir;
|
||||
console.dir = function() {};
|
||||
const MongoClient = require('mongodb-promisified')().MongoClient;
|
||||
console.dir = dir;
|
||||
|
||||
const uristring = process.env.MONGOLAB_URI || process.env.MONGOHQ_URL || 'mongodb://localhost:27017/match-audio';
|
||||
|
||||
module.exports = function*() {
|
||||
const client = yield MongoClient.connect(uristring);
|
||||
debug('Successfully connected to Mongodb');
|
||||
client.matches = client.collection('matches');
|
||||
return client;
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
"use strict";
|
||||
var path = require("path");
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
var services = [];
|
||||
|
||||
require("fs").readdirSync(path.join(__dirname, "services")).forEach(function(file) {
|
||||
var service = require(path.join(__dirname, "services", file));
|
||||
fs.readdirSync(path.join(__dirname, 'services')).forEach(function(file) {
|
||||
var service = require(path.join(__dirname, 'services', file));
|
||||
if (service.search) {
|
||||
services.push(service);
|
||||
}
|
||||
|
|
19
lib/react-handler.js
vendored
Normal file
19
lib/react-handler.js
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
var Router = require('react-router');
|
||||
|
||||
export default function* (routes, url) {
|
||||
let router = Router.create({
|
||||
location: url,
|
||||
routes: routes,
|
||||
onAbort(aborted) {
|
||||
let { to, params, query } = aborted;
|
||||
|
||||
this.redirect(Router.makePath(to, params, query));
|
||||
}
|
||||
});
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
router.run((Handler) => {
|
||||
resolve(Handler);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
"use strict";
|
||||
var path = require("path");
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
module.exports = [];
|
||||
|
||||
require("fs").readdirSync(path.join(__dirname, "services")).forEach(function(file) {
|
||||
var service = require(path.join(__dirname, "services", file));
|
||||
fs.readdirSync(path.join(__dirname, 'services')).forEach(function(file) {
|
||||
var service = require(path.join(__dirname, 'services', file));
|
||||
if (service.search) {
|
||||
module.exports.push(service);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
"use strict";
|
||||
var parse = require("url").parse;
|
||||
var request = require("superagent");
|
||||
require("superagent-bluebird-promise");
|
||||
|
||||
module.exports.id = "beats";
|
||||
|
||||
if (!process.env.BEATS_KEY || !process.env.BEATS_SECRET) {
|
||||
console.warn("BEATS_KEY or BEATS_SECRET environment variables not found, deactivating Beats.");
|
||||
return;
|
||||
}
|
||||
|
||||
var credentials = {
|
||||
key: process.env.BEATS_KEY,
|
||||
secret: process.env.BEATS_SECRET
|
||||
};
|
||||
|
||||
var apiRoot = "https://partner.api.beatsmusic.com/v1/api";
|
||||
|
||||
module.exports.match = require("./url").match;
|
||||
|
||||
module.exports.parseUrl = function(url) {
|
||||
var matches = parse(url).path.match(/\/albums[\/]+([^\/]+)(\/tracks\/)?([^\/]+)?/);
|
||||
if (matches && matches[3]) {
|
||||
return module.exports.lookupId(matches[3], "track");
|
||||
} else if (matches && matches[1]) {
|
||||
return module.exports.lookupId(matches[1], "album");
|
||||
} else {
|
||||
throw new Error("Url does not match");
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.lookupId = function(id, type) {
|
||||
if (type === "album") {
|
||||
return request.get(apiRoot + "/albums/" + id + "/images/default?size=large&client_id=" + credentials.key).redirects(0).promise().then(function(res) {
|
||||
var artwork = {large: res.headers.location.replace("http:", "https:")};
|
||||
return request.get(apiRoot + "/albums/" + id + "/images/default?client_id=" + credentials.key).redirects(0).promise().then(function(res) {
|
||||
artwork.small = res.headers.location.replace("http:", "https:");
|
||||
return request.get(apiRoot + "/albums/" + id + "?client_id=" + credentials.key).promise().then(function(res) {
|
||||
if (!res.body.data) {
|
||||
var error = new Error("Not Found");
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
var result = res.body.data;
|
||||
return {
|
||||
service: "beats",
|
||||
type: "album",
|
||||
id: result.id,
|
||||
name: result.title,
|
||||
streamUrl: "https://listen.beatsmusic.com/albums/" + result.id,
|
||||
purchaseUrl: null,
|
||||
artwork: artwork,
|
||||
artist: {
|
||||
name: result.artist_display_name
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
} else if (type === "track") {
|
||||
return request.get(apiRoot + "/tracks/" + id + "?client_id=" + credentials.key).promise().then(function(res) {
|
||||
if (!res.body.data) {
|
||||
var error = new Error("Not Found");
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
var result = res.body.data;
|
||||
return request.get(apiRoot + "/albums/" + result.refs.album.id + "/images/default?size=large&client_id=" + credentials.key).redirects(0).promise().then(function(res) {
|
||||
var artwork = {large: res.headers.location.replace("http:", "https:")};
|
||||
return request.get(apiRoot + "/albums/" + result.refs.album.id + "/images/default?client_id=" + credentials.key).redirects(0).promise().then(function(res) {
|
||||
artwork.small = res.headers.location.replace("http:", "https:");
|
||||
return {
|
||||
service: "beats",
|
||||
type: "track",
|
||||
id: result.id,
|
||||
name: result.title,
|
||||
streamUrl: "https://listen.beatsmusic.com/albums/" + result.refs.album.id + "/tracks/" + result.id,
|
||||
purchaseUrl: null,
|
||||
artwork: artwork,
|
||||
artist: {
|
||||
name: result.artist_display_name
|
||||
},
|
||||
album: {
|
||||
name: result.refs.album.display
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
var error = new Error("Not Found");
|
||||
error.status = 404;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.search = function(data) {
|
||||
var cleanParam = function(str) {
|
||||
return str.replace(/[\:\?\&]+/, "");
|
||||
};
|
||||
var query, album;
|
||||
var type = data.type;
|
||||
|
||||
if (type === "album") {
|
||||
query = "'" + cleanParam(data.artist.name) + "' '" + cleanParam(data.name) + "'";
|
||||
album = data.name;
|
||||
} else if (type === "track") {
|
||||
query = "'" + cleanParam(data.artist.name) + "' '" + cleanParam(data.name) + "'";
|
||||
if (data.album) {
|
||||
album = data.album.name;
|
||||
} else {
|
||||
album = "";
|
||||
}
|
||||
}
|
||||
|
||||
var path = "/search?q=" + encodeURIComponent(query) + "&type=" + type + "&client_id=" + credentials.key;
|
||||
|
||||
return request.get(apiRoot + path).promise().then(function(res) {
|
||||
if (!res.body.data[0]) {
|
||||
return {service: "beats"};
|
||||
} else {
|
||||
var found;
|
||||
var choppedAlbum = data.type === "album" ? cleanParam(data.name) : cleanParam(data.album.name);
|
||||
var choppedArtist = cleanParam(data.artist.name);
|
||||
|
||||
res.body.data.forEach(function(item) {
|
||||
var matches = item.detail.match(/^[^\(\[]+/);
|
||||
if(choppedArtist.indexOf(matches[0]) >= 0) {
|
||||
found = item;
|
||||
}
|
||||
});
|
||||
|
||||
if (!found && !choppedAlbum.length) {
|
||||
return module.exports.lookupId(res.body.data[0].id, type);
|
||||
}
|
||||
|
||||
res.body.data.forEach(function(item) {
|
||||
var matches = item.related.display.match(/^[^\(\[]+/);
|
||||
if(choppedAlbum.indexOf(matches[0]) >= 0) {
|
||||
found = item;
|
||||
}
|
||||
});
|
||||
if (!found) {
|
||||
return {service: "beats"};
|
||||
}
|
||||
return module.exports.lookupId(found.id, type);
|
||||
}
|
||||
});
|
||||
};
|
|
@ -1,11 +0,0 @@
|
|||
"use strict";
|
||||
var parse = require("url").parse;
|
||||
|
||||
module.exports.match = function(url) {
|
||||
var parsed = parse(url);
|
||||
if (!parsed.host.match(/beatsmusic\.com$/)) {
|
||||
return false;
|
||||
}
|
||||
var matches = parsed.path.match(/\/albums[\/]+([^\/]+)(\/tracks\/)?([^\/]+)?/);
|
||||
return matches.length > 1;
|
||||
};
|
|
@ -1,109 +1,110 @@
|
|||
"use strict";
|
||||
var parse = require('url').parse;
|
||||
var Promise = require('bluebird');
|
||||
var request = require('superagent');
|
||||
require('superagent-bluebird-promise');
|
||||
import {parse} from 'url';
|
||||
import request from 'superagent';
|
||||
import 'superagent-bluebird-promise';
|
||||
|
||||
module.exports.id = "deezer";
|
||||
module.exports.id = 'deezer';
|
||||
|
||||
var apiRoot = "https://api.deezer.com";
|
||||
const apiRoot = 'https://api.deezer.com';
|
||||
|
||||
module.exports.match = require('./url').match;
|
||||
|
||||
module.exports.parseUrl = function(url) {
|
||||
var matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
|
||||
let matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
|
||||
|
||||
if (matches && matches[2]) {
|
||||
return module.exports.lookupId(matches[2], matches[1]);
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.lookupId = function(id, type) {
|
||||
var path = "/" + type + "/" + id;
|
||||
|
||||
return request.get(apiRoot + path).promise().then(function(res) {
|
||||
var result = res.body;
|
||||
if (res.body.error) {
|
||||
var error = new Error("Not Found");
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
var cover = result.cover || result.album.cover;
|
||||
return request.get(cover).redirects(0).promise().then(function(res) {
|
||||
var artwork = {
|
||||
small: res.headers.location.replace("120x120", "200x200"),
|
||||
large: res.headers.location.replace("120x120", "800x800")
|
||||
};
|
||||
if (type == "album") {
|
||||
return {
|
||||
service: "deezer",
|
||||
type: type,
|
||||
id: result.id,
|
||||
name: result.title,
|
||||
streamUrl: result.link,
|
||||
purchaseUrl: null,
|
||||
artwork: artwork,
|
||||
artist: {
|
||||
name: result.artist.name
|
||||
},
|
||||
};
|
||||
} else if (type == "track") {
|
||||
return {
|
||||
service: "deezer",
|
||||
type: type,
|
||||
id: result.id,
|
||||
name: result.title,
|
||||
streamUrl: result.album.link,
|
||||
purchaseUrl: null,
|
||||
artwork: artwork,
|
||||
artist: {
|
||||
name: result.artist.name
|
||||
},
|
||||
album: {
|
||||
name: result.album.title
|
||||
}
|
||||
};
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.search = function(data) {
|
||||
var cleanParam = function(str) {
|
||||
return str.replace(/[\:\?\&]+/, "");
|
||||
}
|
||||
var query, album;
|
||||
var type = data.type;
|
||||
module.exports.lookupId = function* (id, type) {
|
||||
let path = '/' + type + '/' + id;
|
||||
|
||||
if (type == "album") {
|
||||
query = cleanParam(data.artist.name) + " " + cleanParam(data.name);
|
||||
let {body} = yield request.get(apiRoot + path).promise();
|
||||
if (!body || body.error) {
|
||||
let error = new Error('Not Found');
|
||||
error.status = 404;
|
||||
return Promise.reject(error);
|
||||
}
|
||||
let item = body;
|
||||
let coverUrl = item.cover || item.album.cover;
|
||||
let cover = 'test';
|
||||
// nasty hacks for superagent-bluebird-promise
|
||||
try {
|
||||
cover = yield request.get(coverUrl).redirects(0);
|
||||
} catch(err) {
|
||||
cover = err.message.response.res;
|
||||
}
|
||||
let artwork = {
|
||||
small: cover.headers.location.replace('120x120', '200x200'),
|
||||
large: cover.headers.location.replace('120x120', '800x800')
|
||||
};
|
||||
if (type === 'album') {
|
||||
return Promise.resolve({
|
||||
service: 'deezer',
|
||||
type: type,
|
||||
id: item.id,
|
||||
name: item.title,
|
||||
streamUrl: item.link,
|
||||
purchaseUrl: null,
|
||||
artwork: artwork,
|
||||
artist: {
|
||||
name: item.artist.name
|
||||
}
|
||||
});
|
||||
} else if (type === 'track') {
|
||||
return Promise.resolve({
|
||||
service: 'deezer',
|
||||
type: type,
|
||||
id: item.id,
|
||||
name: item.title,
|
||||
streamUrl: item.album.link,
|
||||
purchaseUrl: null,
|
||||
artwork: artwork,
|
||||
artist: {
|
||||
name: item.artist.name
|
||||
},
|
||||
album: {
|
||||
name: item.album.title
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return Promise.reject(new Error());
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.search = function* (data) {
|
||||
let cleanParam = function(str) {
|
||||
return str.replace(/[\:\?\&]+/, '');
|
||||
};
|
||||
let query, album;
|
||||
let {type} = data;
|
||||
|
||||
if (type === 'album') {
|
||||
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);
|
||||
} else if (type === 'track') {
|
||||
query = cleanParam(data.artist.name) + ' ' + cleanParam(data.album.name) + ' ' + cleanParam(data.name);
|
||||
album = data.album.name;
|
||||
}
|
||||
|
||||
var path = "/search/" + type + "?q=" + encodeURIComponent(query);
|
||||
return request.get(apiRoot + path).promise().then(function(res) {
|
||||
if (!res.body.data[0]) {
|
||||
var matches = album.match(/^[^\(\[]+/);
|
||||
if (matches && matches[0] && matches[0] != album) {
|
||||
var cleanedData = JSON.parse(JSON.stringify(data));
|
||||
if (type == "album") {
|
||||
cleanedData.name = matches[0].trim();
|
||||
} else if (type == "track") {
|
||||
cleanedData.album.name = matches[0].trim();
|
||||
}
|
||||
return module.exports.search(cleanedData);
|
||||
} else {
|
||||
return {service: "deezer"};
|
||||
var path = '/search/' + type + '?q=' + encodeURIComponent(query);
|
||||
let response = yield request.get(apiRoot + path);
|
||||
if (response.body.data[0]) {
|
||||
return yield module.exports.lookupId(response.body.data[0].id, type);
|
||||
} else {
|
||||
var matches = album.match(/^[^\(\[]+/);
|
||||
if (matches && matches[0] && matches[0] !== album) {
|
||||
var cleanedData = JSON.parse(JSON.stringify(data));
|
||||
if (type === 'album') {
|
||||
cleanedData.name = matches[0].trim();
|
||||
} else if (type === 'track') {
|
||||
cleanedData.album.name = matches[0].trim();
|
||||
}
|
||||
return yield module.exports.search(cleanedData);
|
||||
} else {
|
||||
return module.exports.lookupId(res.body.data[0].id, type);
|
||||
return Promise.resolve({service: 'deezer'});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,138 +1,134 @@
|
|||
"use strict";
|
||||
var parse = require("url").parse;
|
||||
var Promise = require('bluebird');
|
||||
var querystring = require('querystring');
|
||||
var request = require('superagent');
|
||||
require('superagent-bluebird-promise');
|
||||
import {parse} from 'url';
|
||||
import querystring from 'querystring';
|
||||
import request from 'superagent';
|
||||
import 'superagent-bluebird-promise';
|
||||
|
||||
module.exports.id = "itunes";
|
||||
module.exports.id = 'itunes';
|
||||
|
||||
var apiRoot = "https://itunes.apple.com";
|
||||
const apiRoot = 'https://itunes.apple.com';
|
||||
|
||||
module.exports.match = require('./url').match;
|
||||
|
||||
module.exports.parseUrl = function(url) {
|
||||
var parsed = parse(url);
|
||||
var matches = parsed.path.match(/[\/]?([\/]?[a-z]{2}?)?[\/]+album[\/]+([^\/]+)[\/]+([^\?]+)/);
|
||||
var query = querystring.parse(parsed.query);
|
||||
module.exports.parseUrl = function* (url) {
|
||||
let parsed = parse(url);
|
||||
let matches = parsed.path.match(/[\/]?([\/]?[a-z]{2}?)?[\/]+album[\/]+([^\/]+)[\/]+([^\?]+)/);
|
||||
let query = querystring.parse(parsed.query);
|
||||
|
||||
if (matches) {
|
||||
var type = "album";
|
||||
var id = matches[3].substr(2);
|
||||
let type = 'album';
|
||||
let id = matches[3].substr(2);
|
||||
if (query.i) {
|
||||
type = "track";
|
||||
type = 'track';
|
||||
id = query.i;
|
||||
}
|
||||
return module.exports.lookupId(id, type, matches[1] || "us");
|
||||
return yield module.exports.lookupId(id, type, matches[1] || 'us');
|
||||
} else {
|
||||
throw new Error();
|
||||
return Promise.reject(new Error());
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.lookupId = function(id, type, cc) {
|
||||
module.exports.lookupId = function* (id, type, cc) {
|
||||
if (String(id).match(/^[a-z]{2}/)) {
|
||||
cc = id.substr(0,2);
|
||||
cc = id.substr(0, 2);
|
||||
id = id.substr(2);
|
||||
}
|
||||
|
||||
var path = "/lookup?id=" + id;
|
||||
let path = '/lookup?id=' + id;
|
||||
if (cc) {
|
||||
path = "/" + cc + path;
|
||||
path = '/' + cc + path;
|
||||
}
|
||||
|
||||
return request.get(apiRoot + path).promise().then(function(res) {
|
||||
var data = JSON.parse(res.text);
|
||||
let response = yield request.get(apiRoot + path);
|
||||
let result = JSON.parse(response.text);
|
||||
|
||||
if (!data.results || data.resultCount == 0 || !data.results[0].collectionId) {
|
||||
var error = new Error("Not Found");
|
||||
error.status = 404;
|
||||
throw error;
|
||||
} else {
|
||||
var result = data.results[0];
|
||||
if (!result.results || result.resultCount === 0 || !result.results[0].collectionId) {
|
||||
let error = new Error('Not Found');
|
||||
error.status = 404;
|
||||
return Promise.reject(error);
|
||||
} else {
|
||||
result = result.results[0];
|
||||
|
||||
var item = {
|
||||
service: "itunes",
|
||||
type: type,
|
||||
id: cc + id,
|
||||
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
|
||||
};
|
||||
let item = {
|
||||
service: 'itunes',
|
||||
type: type,
|
||||
id: cc + id,
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
return item;
|
||||
if (type === 'track') {
|
||||
item.album = {
|
||||
name: result.collectionName
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.resolve(item);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.search = function(data) {
|
||||
var query, album, entity;
|
||||
var type = data.type;
|
||||
module.exports.search = function* (data) {
|
||||
let query, album, entity;
|
||||
let type = data.type;
|
||||
|
||||
if (type == "album") {
|
||||
query = data.artist.name + " " + data.name;
|
||||
if (type === 'album') {
|
||||
query = data.artist.name + ' ' + data.name;
|
||||
album = data.name;
|
||||
entity = "album";
|
||||
} else if (type == "track") {
|
||||
query = data.artist.name + " " + data.album.name + " " + data.name;
|
||||
entity = 'album';
|
||||
} else if (type === 'track') {
|
||||
query = data.artist.name + ' ' + data.album.name + ' ' + data.name;
|
||||
album = data.album.name;
|
||||
entity = "musicTrack";
|
||||
entity = 'musicTrack';
|
||||
}
|
||||
|
||||
var path = "/search?term=" + encodeURIComponent(query) + "&media=music&entity=" + entity;
|
||||
return request.get(apiRoot + path).promise().then(function(res) {
|
||||
var result = JSON.parse(res.text);
|
||||
let path = '/search?term=' + encodeURIComponent(query) + '&media=music&entity=' + entity;
|
||||
let response = yield request.get(apiRoot + path);
|
||||
let result = JSON.parse(response.text);
|
||||
|
||||
if (!result.results[0]) {
|
||||
var matches = album.match(/^[^\(\[]+/);
|
||||
if (matches && matches[0] && matches[0] != album) {
|
||||
var cleanedData = JSON.parse(JSON.stringify(data));
|
||||
if (type == "album") {
|
||||
cleanedData.name = matches[0].trim();
|
||||
} else if (type == "track") {
|
||||
cleanedData.album.name = matches[0].trim();
|
||||
}
|
||||
return module.exports.search(cleanedData);
|
||||
} else {
|
||||
return {service: "itunes"};
|
||||
if (!result.results[0]) {
|
||||
let matches = album.match(/^[^\(\[]+/);
|
||||
if (matches && matches[0] && matches[0] !== album) {
|
||||
let cleanedData = JSON.parse(JSON.stringify(data));
|
||||
if (type === 'album') {
|
||||
cleanedData.name = matches[0].trim();
|
||||
} else if (type === 'track') {
|
||||
cleanedData.album.name = matches[0].trim();
|
||||
}
|
||||
return yield module.exports.search(cleanedData);
|
||||
} else {
|
||||
var result = result.results[0];
|
||||
|
||||
var 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 Promise.resolve({service: 'itunes'});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result = result.results[0];
|
||||
|
||||
let 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 Promise.resolve(item);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -6,8 +6,7 @@ module.exports.id = "rdio";
|
|||
|
||||
if (!process.env.RDIO_API_KEY || !process.env.RDIO_API_SHARED) {
|
||||
console.warn("RDIO_API_KEY or RDIO_API_SHARED environment variables not found, deactivating Rdio.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
var rdio = require('rdio')({
|
||||
rdio_api_key: process.env.RDIO_API_KEY,
|
||||
|
@ -178,3 +177,5 @@ module.exports.search = function(data) {
|
|||
}
|
||||
});
|
||||
};
|
||||
|
||||
}
|
|
@ -8,8 +8,7 @@ module.exports.id = "xbox";
|
|||
|
||||
if (!process.env.XBOX_CLIENT_ID || !process.env.XBOX_CLIENT_SECRET) {
|
||||
console.warn("XBOX_CLIENT_ID and XBOX_CLIENT_SECRET environment variables not found, deactivating Xbox Music.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
var credentials = {
|
||||
clientId: process.env.XBOX_CLIENT_ID,
|
||||
|
@ -104,3 +103,5 @@ module.exports.search = function(data) {
|
|||
});
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -11,8 +11,7 @@ module.exports.id = "youtube";
|
|||
|
||||
if (!process.env.YOUTUBE_KEY) {
|
||||
console.warn("YOUTUBE_KEY environment variable not found, deactivating Youtube.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
var credentials = {
|
||||
key: process.env.YOUTUBE_KEY,
|
||||
|
@ -136,3 +135,5 @@ module.exports.search = function(data) {
|
|||
return {service: "youtube"};
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
|
|
63
package.json
63
package.json
|
@ -3,13 +3,13 @@
|
|||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node ./bin/www",
|
||||
"test": "./node_modules/mocha/bin/mocha test/**/*.js --timeout=10000",
|
||||
"build": "browserify ./views/app.jsx | uglifyjs -cm 2>/dev/null > ./public/javascript/bundle.js",
|
||||
"start": "babel-node app.js",
|
||||
"test": "mocha --require co-mocha --compilers js:babel/register test/**/*.js --timeout=10000",
|
||||
"build": "browserify -t babelify ./views/app.jsx > ./public/javascript/bundle.js",
|
||||
"clean": "rm -f ./public/javascript/bundle.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "0.12.x"
|
||||
"iojs": "2.2.1"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
|
@ -22,38 +22,39 @@
|
|||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"bluebird": "^2.4.2",
|
||||
"body-parser": "~1.10.0",
|
||||
"browserify": "^7.0.0",
|
||||
"compression": "^1.2.2",
|
||||
"connect-browserify": "^3.2.1",
|
||||
"connect-flash": "^0.1.1",
|
||||
"cookie-parser": "~1.3.3",
|
||||
"crypto-js": "^3.1.2-5",
|
||||
"debug": "~2.1.0",
|
||||
"envify": "^3.2.0",
|
||||
"express": "~4.10.6",
|
||||
"express-session": "^1.9.2",
|
||||
"helmet": "^0.5.2",
|
||||
"moment": "^2.9.0",
|
||||
"morgan": "~1.5.0",
|
||||
"node-jsx": "^0.12.4",
|
||||
"babel": "^5.2.17",
|
||||
"babelify": "^6.0.2",
|
||||
"bluebird": "^2.9.25",
|
||||
"browserify": "^10.1.3",
|
||||
"co": "^4.5.4",
|
||||
"debug": "^2.1.1",
|
||||
"koa": "^0.21.0",
|
||||
"koa-bodyparser": "^2.0.0",
|
||||
"koa-compress": "^1.0.8",
|
||||
"koa-favicon": "^1.2.0",
|
||||
"koa-logger": "^1.2.2",
|
||||
"koa-route": "^2.4.0",
|
||||
"koa-static": "^1.4.9",
|
||||
"moment": "^2.10.3",
|
||||
"mongodb-promisified": "^1.0.2",
|
||||
"node-uuid": "^1.4.2",
|
||||
"playmusic": "^2.0.2",
|
||||
"promised-mongo": "^0.11.1",
|
||||
"playmusic": "^2.0.0",
|
||||
"rdio": "^1.5.2",
|
||||
"react": "^0.12.1",
|
||||
"react": "^0.13.3",
|
||||
"react-google-analytics": "^0.2.0",
|
||||
"react-router": "^0.11.6",
|
||||
"reactify": "^0.17.1",
|
||||
"serve-favicon": "~2.2.0",
|
||||
"react-router": "^0.13.3",
|
||||
"reactify": "^1.1.1",
|
||||
"spotify": "^0.3.0",
|
||||
"superagent": "^0.21.0",
|
||||
"superagent-bluebird-promise": "^0.5.1",
|
||||
"uglify-js": "^2.4.16"
|
||||
"superagent": "^1.2.0",
|
||||
"superagent-bluebird-promise": "^2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"should": "^4.4.1",
|
||||
"mocha": "^2.0.1"
|
||||
"co-mocha": "^1.1.0",
|
||||
"eslint": "^0.22.1",
|
||||
"eslint-plugin-react": "^2.5.0",
|
||||
"mocha": "^2.1.0",
|
||||
"nodemon": "^1.3.7",
|
||||
"parallelshell": "^1.1.1",
|
||||
"should": "^6.0.3"
|
||||
}
|
||||
}
|
||||
|
|
BIN
public/images/logo-inverse.png
Normal file
BIN
public/images/logo-inverse.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
24968
public/javascript/bundle.js
Normal file
24968
public/javascript/bundle.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,30 +1,28 @@
|
|||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var React = require("react");
|
||||
var Router = require("react-router");
|
||||
require("node-jsx").install({extension: ".jsx"});
|
||||
var routes = require("../views/app.jsx").routes;
|
||||
import React from 'react';
|
||||
import createHandler from '../lib/react-handler';
|
||||
import {routes} from '../views/app.jsx';
|
||||
|
||||
module.exports = function(req, res, next) {
|
||||
|
||||
req.db.matches.find().sort({"created_at": -1}).limit(6).toArray().then(function(docs){
|
||||
var recents = [];
|
||||
docs.forEach(function(doc) {
|
||||
var shares = Object.keys(doc.services).map(function (key) {return doc.services[key]; });
|
||||
shares.some(function(item) {
|
||||
if (item.service === doc._id.split("$$")[0]) { // eslint-disable-line no-underscore-dangle
|
||||
recents.push(item);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
module.exports = function* () {
|
||||
let recents = [];
|
||||
let docs = yield this.db.matches.find().sort({'created_at': -1}).limit(6).toArray();
|
||||
docs.forEach(function(doc) {
|
||||
let shares = Object.keys(doc.services).map(function (key) {return doc.services[key]; });
|
||||
shares.some(function(item) {
|
||||
if (item.service === doc._id.split('$$')[0]) { // eslint-disable-line no-underscore-dangle
|
||||
recents.push(item);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
Router.run(routes, req.url, function (Handler) {
|
||||
var App = React.createFactory(Handler);
|
||||
var content = React.renderToString(new App({recents: recents}));
|
||||
res.send("<!doctype html>\n" + content.replace("</body></html>", "<script>var recents = " + JSON.stringify(recents) + "</script></body></html>"));
|
||||
});
|
||||
}).catch(function(error) {
|
||||
next(error);
|
||||
});
|
||||
|
||||
let Handler = yield createHandler(routes, this.request.url);
|
||||
|
||||
let App = React.createFactory(Handler);
|
||||
let content = React.renderToString(new App({recents: recents}));
|
||||
|
||||
content = content.replace('</body></html>', '<script>var recents = ' + JSON.stringify(recents) + '</script></body></html>');
|
||||
|
||||
this.body = '<!doctype html>\n' + content;
|
||||
};
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
"use strict";
|
||||
var parse = require("url").parse;
|
||||
var request = require("superagent");
|
||||
import {parse} from 'url';
|
||||
import request from 'superagent';
|
||||
|
||||
module.exports = function(req, res) {
|
||||
var url = "http://" + req.url.substr(8);
|
||||
var parsed = parse(url);
|
||||
module.exports = function* (next) {
|
||||
let url = 'http://' + this.request.url.substr(8);
|
||||
let parsed = parse(url);
|
||||
if (parsed.host.match(/mzstatic\.com/)) {
|
||||
request.get(url, function(response){
|
||||
res.set(response.headers);
|
||||
res.send(response.body);
|
||||
});
|
||||
let proxyResponse = yield request.get(url);
|
||||
this.set(proxyResponse.headers);
|
||||
this.body = proxyResponse.body;
|
||||
} else {
|
||||
yield next;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,44 +1,42 @@
|
|||
"use strict";
|
||||
var parse = require("url").parse;
|
||||
var lookup = require("../lib/lookup");
|
||||
var services = require("../lib/services");
|
||||
import {parse} from 'url';
|
||||
import co from 'co';
|
||||
import lookup from '../lib/lookup';
|
||||
import services from '../lib/services';
|
||||
|
||||
module.exports = function(req, res) {
|
||||
var url = parse(req.body.url);
|
||||
if (!url.host) {
|
||||
return res.json({error: {message: "You need to submit a url."}});
|
||||
}
|
||||
module.exports = function* () {
|
||||
let url = parse(this.request.body.url);
|
||||
this.assert(url.host, 400, {error: {message: 'You need to submit a url.'}});
|
||||
|
||||
var promise = lookup(req.body.url);
|
||||
let item = yield lookup(this.request.body.url);
|
||||
|
||||
if (!promise) {
|
||||
return res.json({error: {message: "No supported music found at that link :("}});
|
||||
}
|
||||
this.assert(item, 400, {error: {message: 'No supported music found at that link :('}});
|
||||
|
||||
promise.then(function(item) {
|
||||
if (!item) {
|
||||
return res.json({error: {message: "No supported music found at that link :("}});
|
||||
item.matched_at = new Date(); // eslint-disable-line camelcase
|
||||
let matches = {};
|
||||
matches[item.service] = item;
|
||||
|
||||
|
||||
for (let service of services) {
|
||||
if (service.id === item.service) {
|
||||
continue;
|
||||
}
|
||||
item.matched_at = new Date(); // eslint-disable-line camelcase
|
||||
var matches = {};
|
||||
matches[item.service] = item;
|
||||
services.forEach(function(service) {
|
||||
matches[service.id] = {service: service.id};
|
||||
}
|
||||
|
||||
yield this.db.matches.save({_id: item.service + '$$' + item.id, 'created_at': new Date(), services: matches});
|
||||
this.body = item;
|
||||
|
||||
process.nextTick(co.wrap(function* (){
|
||||
for (let service of services) {
|
||||
if (service.id === item.service) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
matches[service.id] = {service: service.id};
|
||||
service.search(item).then(function(match) {
|
||||
match.matched_at = new Date(); // eslint-disable-line camelcase
|
||||
var update = {};
|
||||
update["services." + match.service] = match;
|
||||
req.db.matches.update({_id: item.service + "$$" + item.id}, {"$set": update});
|
||||
});
|
||||
});
|
||||
return req.db.matches.save({_id: item.service + "$$" + item.id, "created_at": new Date(), services: matches}).then(function() {
|
||||
res.json(item);
|
||||
});
|
||||
}, function(error) {
|
||||
console.log(error.stack);
|
||||
res.json({error: {message: "No matches found for this link, sorry :("}});
|
||||
});
|
||||
let match = yield service.search(item);
|
||||
match.matched_at = new Date(); // eslint-disable-line camelcase
|
||||
let update = {};
|
||||
update['services.' + match.service] = match;
|
||||
yield this.db.matches.updateOne({_id: item.service + '$$' + item.id}, {'$set': update});
|
||||
}
|
||||
}.bind(this)));
|
||||
};
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
"use strict";
|
||||
import React from 'react';
|
||||
import createHandler from '../lib/react-handler';
|
||||
import {routes} from '../views/app.jsx';
|
||||
import services from '../lib/services';
|
||||
|
||||
var React = require("react");
|
||||
var Router = require("react-router");
|
||||
require("node-jsx").install();
|
||||
var routes = require("../views/app.jsx").routes;
|
||||
|
||||
var services = require("../lib/services");
|
||||
|
||||
var formatAndSort = function(matches, serviceId) {
|
||||
let formatAndSort = function(matches, serviceId) {
|
||||
matches = Object.keys(matches).map(function (key) {return matches[key]; });
|
||||
matches.sort(function(a, b) {
|
||||
return a.id && !b.id;
|
||||
|
@ -17,60 +13,34 @@ var formatAndSort = function(matches, serviceId) {
|
|||
return matches;
|
||||
};
|
||||
|
||||
module.exports = function(req, res, next) {
|
||||
var serviceId = req.params.service;
|
||||
var type = req.params.type;
|
||||
var itemId = req.params.id;
|
||||
|
||||
var matchedService;
|
||||
module.exports = function* (serviceId, type, itemId, format, next) {
|
||||
let matchedService;
|
||||
services.some(function(service) {
|
||||
matchedService = serviceId === service.id ? service : null;
|
||||
return matchedService;
|
||||
});
|
||||
|
||||
if (!matchedService || (type !== "album" && type !== "track")) {
|
||||
return next();
|
||||
if (!matchedService || (type !== 'album' && type !== 'track')) {
|
||||
return yield next;
|
||||
}
|
||||
|
||||
return req.db.matches.findOne({_id: serviceId + "$$" + itemId}).then(function(doc) {
|
||||
if (!doc) {
|
||||
return matchedService.lookupId(itemId, type).then(function(item) {
|
||||
var matches = {};
|
||||
item.matched_at = new Date(); // eslint-disable-line camelcase
|
||||
matches[item.service] = item;
|
||||
services.forEach(function(service) {
|
||||
if (service.id === item.service) {
|
||||
return;
|
||||
}
|
||||
matches[service.id] = {service: service.id};
|
||||
service.search(item).then(function(match) {
|
||||
match.matched_at = new Date(); // eslint-disable-line camelcase
|
||||
var update = {};
|
||||
update["services." + match.service] = match;
|
||||
req.db.matches.update({_id: item.service + "$$" + item.id}, {"$set": update});
|
||||
});
|
||||
});
|
||||
return req.db.matches.save({_id: item.service + "$$" + item.id, "created_at": new Date(), services: matches}).then(function() {
|
||||
var newShares = formatAndSort(matches, serviceId);
|
||||
Router.run(routes, req.url, function (Handler) {
|
||||
var App = React.createFactory(Handler);
|
||||
var content = React.renderToString(new App({shares: newShares}));
|
||||
res.send("<!doctype html>\n" + content.replace("</body></html>", "<script>var shares = " + JSON.stringify(newShares) + "</script></body></html>"));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
var shares = formatAndSort(doc.services, serviceId);
|
||||
if (req.params.format === "json") {
|
||||
return res.json({shares: shares});
|
||||
}
|
||||
Router.run(routes, req.url, function (Handler) {
|
||||
var App = React.createFactory(Handler);
|
||||
var content = React.renderToString(new App({shares: shares}));
|
||||
res.send("<!doctype html>\n" + content.replace("</body></html>", "<script>var shares = " + JSON.stringify(shares) + "</script></body></html>"));
|
||||
});
|
||||
}).catch(function (error) {
|
||||
return next(error);
|
||||
});
|
||||
let shares = [];
|
||||
let doc = yield this.db.matches.findOne({_id: serviceId + '$$' + itemId});
|
||||
|
||||
this.assert(doc, 404, 'Not Found');
|
||||
|
||||
shares = formatAndSort(doc.services, serviceId);
|
||||
|
||||
if (format === 'json') {
|
||||
this.body = {shares: shares};
|
||||
} else {
|
||||
let Handler = yield createHandler(routes, this.request.url);
|
||||
|
||||
let App = React.createFactory(Handler);
|
||||
let content = React.renderToString(new App({shares: shares}));
|
||||
|
||||
content = content.replace('</body></html>', '<script>var shares = ' + JSON.stringify(shares) + '</script></body></html>');
|
||||
|
||||
this.body = '<!doctype html>\n' + content;
|
||||
}
|
||||
};
|
||||
|
|
6
test/.eslintrc
Normal file
6
test/.eslintrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"mocha": true
|
||||
}
|
||||
}
|
|
@ -1,15 +1,9 @@
|
|||
"use strict";
|
||||
require('should');
|
||||
|
||||
var lookup = require("../lib/lookup");
|
||||
import 'should';
|
||||
import lookup from '../lib/lookup';
|
||||
|
||||
describe('Search with url', function(){
|
||||
|
||||
it('should find album by url', function(done){
|
||||
lookup("https://play.google.com/music/listen#/album/Bz6wrjczddcj5hurijsv6ohdoay").then(function(result) {
|
||||
result.name.should.equal("Phase 5");
|
||||
done();
|
||||
});
|
||||
it('should find album by url', function* (){
|
||||
let result = yield lookup('https://play.google.com/music/listen#/album/Bz6wrjczddcj5hurijsv6ohdoay');
|
||||
result.name.should.equal('Phase 5');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
"use strict";
|
||||
var assert = require("assert");
|
||||
var should = require('should');
|
||||
|
||||
var beats = require("../../lib/services/beats");
|
||||
|
||||
describe('Beats Music', function(){
|
||||
describe('lookupId', function(){
|
||||
it('should find album by ID', function(done){
|
||||
beats.lookupId("al920431", "album").then(function(result) {
|
||||
result.name.should.equal("Deftones");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should find track by ID', function(done){
|
||||
beats.lookupId("tr6910289", "track").then(function(result) {
|
||||
result.name.should.equal("Californication");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('search', function(){
|
||||
it('should find album by search', function(done){
|
||||
beats.search({type: "album", artist: {name: "Deftones"}, name: "Deftones"}).then(function(result) {
|
||||
result.name.should.equal("Deftones");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should find track by search', function(done){
|
||||
beats.search({type: "track", artist: {name: "Deftones"}, album: {name: "Deftones"}, name: "Hexagram"}).then(function(result) {
|
||||
result.name.should.equal("Hexagram");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('lookupUrl', function(){
|
||||
describe('parseUrl', function(){
|
||||
it('should parse album url into ID', function(done){
|
||||
beats.parseUrl("https://listen.beatsmusic.com/albums/al920431").then(function(result) {
|
||||
result.id.should.equal("al920431");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse track url into ID', function(done){
|
||||
beats.parseUrl("https://listen.beatsmusic.com/albums/al6910269/tracks/tr6910289").then(function(result) {
|
||||
result.id.should.equal("tr6910289");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,56 +1,41 @@
|
|||
"use strict";
|
||||
var assert = require("assert");
|
||||
var should = require('should');
|
||||
|
||||
var deezer = require("../../lib/services/deezer");
|
||||
import 'should';
|
||||
import deezer from '../../lib/services/deezer';
|
||||
|
||||
describe('Deezer', function(){
|
||||
describe('lookupId', function(){
|
||||
it('should find album by ID', function(done){
|
||||
deezer.lookupId("302127", "album").then(function(result) {
|
||||
result.name.should.equal("Discovery");
|
||||
done();
|
||||
});
|
||||
it('should find album by ID', function* (){
|
||||
let result = yield deezer.lookupId('302127', 'album');
|
||||
result.name.should.equal('Discovery');
|
||||
});
|
||||
|
||||
it('should find track by ID', function(done){
|
||||
deezer.lookupId("3135554", "track").then(function(result) {
|
||||
result.name.should.equal("Aerodynamic");
|
||||
done();
|
||||
});
|
||||
it('should find track by ID', function* (){
|
||||
let result = yield deezer.lookupId('3135554', 'track');
|
||||
result.name.should.equal('Aerodynamic');
|
||||
});
|
||||
});
|
||||
|
||||
describe('search', function(){
|
||||
it('should find album by search', function(done){
|
||||
deezer.search({type: "album", artist: {name: "David Guetta"}, name: "Listen (Deluxe)"}).then(function(result) {
|
||||
result.name.should.startWith("Listen");
|
||||
done();
|
||||
});
|
||||
it('should find album by search', function* (){
|
||||
let result = yield deezer.search({type: 'album', artist: {name: 'David Guetta'}, name: 'Listen (Deluxe)'});
|
||||
result.name.should.startWith('Listen');
|
||||
});
|
||||
|
||||
it('should find track by search', function(done){
|
||||
deezer.search({type: "track", artist: {name: "Deftones"}, album: {name: "Deftones"}, name: "Hexagram"}).then(function(result) {
|
||||
result.name.should.equal("Hexagram");
|
||||
done();
|
||||
});
|
||||
it('should find track by search', function* (){
|
||||
let result = yield deezer.search({type: 'track', artist: {name: 'Deftones'}, album: {name: 'Deftones'}, name: 'Hexagram'});
|
||||
result.name.should.equal('Hexagram');
|
||||
});
|
||||
});
|
||||
|
||||
describe('lookupUrl', function(){
|
||||
describe('parseUrl', function(){
|
||||
it('should parse album url into ID', function(done){
|
||||
deezer.parseUrl("http://www.deezer.com/album/302127").then(function(result) {
|
||||
result.id.should.equal(302127);
|
||||
done();
|
||||
});
|
||||
it('should parse album url into ID', function* (){
|
||||
let result = yield deezer.parseUrl('http://www.deezer.com/album/302127');
|
||||
result.id.should.equal(302127);
|
||||
});
|
||||
|
||||
it('should parse track url into ID', function(done){
|
||||
deezer.parseUrl("http://www.deezer.com/track/3135554").then(function(result) {
|
||||
result.id.should.equal(3135554);
|
||||
done();
|
||||
});
|
||||
it('should parse track url into ID', function* (){
|
||||
let result = yield deezer.parseUrl('http://www.deezer.com/track/3135554');
|
||||
result.id.should.equal(3135554);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,55 +1,40 @@
|
|||
"use strict";
|
||||
var assert = require("assert");
|
||||
var should = require('should');
|
||||
|
||||
var google = require("../../lib/services/google");
|
||||
import 'should';
|
||||
import google from '../../lib/services/google';
|
||||
|
||||
describe('Google Play Music', function(){
|
||||
describe('lookupId', function(){
|
||||
it('should find album by ID', function(done){
|
||||
google.lookupId("Byp6lvzimyf74wxi5634ul4tgam", "album").then(function(result) {
|
||||
result.name.should.equal("Listen (Deluxe)");
|
||||
done();
|
||||
});
|
||||
it('should find album by ID', function* (){
|
||||
let result = yield google.lookupId('Byp6lvzimyf74wxi5634ul4tgam', 'album');
|
||||
result.name.should.equal('Listen (Deluxe)');
|
||||
});
|
||||
|
||||
it('should find track by ID', function(done){
|
||||
google.lookupId("Tjosptub24g2dft37lforqnudpe", "track").then(function(result) {
|
||||
result.name.should.equal("Cherub Rock");
|
||||
done();
|
||||
});
|
||||
it('should find track by ID', function* (){
|
||||
let result = yield google.lookupId('Tjosptub24g2dft37lforqnudpe', 'track');
|
||||
result.name.should.equal('Cherub Rock');
|
||||
});
|
||||
});
|
||||
|
||||
describe('search', function(){
|
||||
it('should find album by search', function(done){
|
||||
google.search({type: "album", artist: {name: "David Guetta"}, name: "Listen (Deluxe)"}).then(function(result) {
|
||||
result.name.should.equal("Listen (Deluxe)");
|
||||
done();
|
||||
});
|
||||
it('should find album by search', function* (){
|
||||
let result = yield google.search({type: 'album', artist: {name: 'David Guetta'}, name: 'Listen (Deluxe)'});
|
||||
result.name.should.equal('Listen (Deluxe)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('lookupUrl', function(){
|
||||
it('should parse regular url into album ID', function(done){
|
||||
google.parseUrl("https://play.google.com/music/listen#/album/Byp6lvzimyf74wxi5634ul4tgam/David+Guetta/Listen+(Deluxe)").then(function(result) {
|
||||
result.id.should.equal("Byp6lvzimyf74wxi5634ul4tgam");
|
||||
done();
|
||||
});
|
||||
it('should parse regular url into album ID', function* (){
|
||||
let result = yield google.parseUrl('https://play.google.com/music/listen#/album/Byp6lvzimyf74wxi5634ul4tgam/David+Guetta/Listen+(Deluxe)');
|
||||
result.id.should.equal('Byp6lvzimyf74wxi5634ul4tgam');
|
||||
});
|
||||
|
||||
it('should parse url without ID into album ID', function(done){
|
||||
google.parseUrl("https://play.google.com/music/listen#/album//David+Guetta/Listen+(Deluxe)").then(function(result) {
|
||||
result.id.should.equal("Byp6lvzimyf74wxi5634ul4tgam");
|
||||
done();
|
||||
});
|
||||
it('should parse url without ID into album ID', function* (){
|
||||
let result = yield google.parseUrl('https://play.google.com/music/listen#/album//David+Guetta/Listen+(Deluxe)');
|
||||
result.id.should.equal('Byp6lvzimyf74wxi5634ul4tgam');
|
||||
});
|
||||
|
||||
it('should parse share url into album ID', function(done){
|
||||
google.parseUrl("https://play.google.com/music/m/Byp6lvzimyf74wxi5634ul4tgam").then(function(result) {
|
||||
result.id.should.equal("Byp6lvzimyf74wxi5634ul4tgam");
|
||||
done();
|
||||
});
|
||||
it('should parse share url into album ID', function* (){
|
||||
let result = yield google.parseUrl('https://play.google.com/music/m/Byp6lvzimyf74wxi5634ul4tgam');
|
||||
result.id.should.equal('Byp6lvzimyf74wxi5634ul4tgam');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,56 +1,41 @@
|
|||
"use strict";
|
||||
var assert = require("assert");
|
||||
var should = require('should');
|
||||
|
||||
var itunes = require("../../lib/services/itunes");
|
||||
import 'should';
|
||||
import itunes from '../../lib/services/itunes';
|
||||
|
||||
describe('iTunes Music', function(){
|
||||
describe('lookupId', function(){
|
||||
it('should find album by ID', function(done){
|
||||
itunes.lookupId("id215206912", "album").then(function(result) {
|
||||
result.name.should.equal("Peace Orchestra");
|
||||
done();
|
||||
});
|
||||
it('should find album by ID', function* (){
|
||||
let result = yield itunes.lookupId('id215206912', 'album');
|
||||
result.name.should.equal('Peace Orchestra');
|
||||
});
|
||||
|
||||
it('should find track by ID', function(done){
|
||||
itunes.lookupId("id215206958", "track").then(function(result) {
|
||||
result.name.should.equal("Double Drums");
|
||||
done();
|
||||
});
|
||||
it('should find track by ID', function* (){
|
||||
let result = yield itunes.lookupId('id215206958', 'track');
|
||||
result.name.should.equal('Double Drums');
|
||||
});
|
||||
});
|
||||
|
||||
describe('search', function(){
|
||||
it('should find album by search', function(done){
|
||||
itunes.search({type: "album", artist: {name: "Deftones"}, name: "Deftones"}).then(function(result) {
|
||||
result.name.should.equal("Deftones");
|
||||
done();
|
||||
});
|
||||
it('should find album by search', function* (){
|
||||
let result = yield itunes.search({type: 'album', artist: {name: 'Deftones'}, name: 'Deftones'});
|
||||
result.name.should.equal('Deftones');
|
||||
});
|
||||
|
||||
it('should find track by search', function(done){
|
||||
itunes.search({type: "track", artist: {name: "Deftones"}, album: {name: "Deftones"}, name: "Hexagram"}).then(function(result) {
|
||||
result.name.should.equal("Hexagram");
|
||||
done();
|
||||
});
|
||||
it('should find track by search', function* (){
|
||||
let result = yield itunes.search({type: 'track', artist: {name: 'Deftones'}, album: {name: 'Deftones'}, name: 'Hexagram'});
|
||||
result.name.should.equal('Hexagram');
|
||||
});
|
||||
});
|
||||
|
||||
describe('lookupUrl', function(){
|
||||
describe('parseUrl', function(){
|
||||
it('should parse album url into ID', function(done){
|
||||
itunes.parseUrl("https://itunes.apple.com/us/album/double-drums/id215206912").then(function(result) {
|
||||
result.id.should.equal("us215206912");
|
||||
done();
|
||||
});
|
||||
it('should parse album url into ID', function* (){
|
||||
let result = yield itunes.parseUrl('https://itunes.apple.com/us/album/double-drums/id215206912');
|
||||
result.id.should.equal('us215206912');
|
||||
});
|
||||
|
||||
it('should parse track url into ID', function(done){
|
||||
itunes.parseUrl("https://itunes.apple.com/us/album/double-drums/id215206912?i=215206958&uo=4").then(function(result) {
|
||||
result.id.should.equal("us215206958");
|
||||
done();
|
||||
});
|
||||
it('should parse track url into ID', function* (){
|
||||
let result = yield itunes.parseUrl('https://itunes.apple.com/us/album/double-drums/id215206912?i=215206958&uo=4');
|
||||
result.id.should.equal('us215206958');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,41 +1,30 @@
|
|||
"use strict";
|
||||
var assert = require("assert");
|
||||
var should = require('should');
|
||||
|
||||
var rdio = require("../../lib/services/rdio");
|
||||
import 'should';
|
||||
import rdio from '../../lib/services/rdio';
|
||||
|
||||
describe('Rdio', function(){
|
||||
describe('lookupId', function(){
|
||||
it('should find album by ID', function(done){
|
||||
rdio.lookupId("Qj4NXr0").then(function(result) {
|
||||
result.name.should.equal("Listen (Deluxe)");
|
||||
done();
|
||||
});
|
||||
it('should find album by ID', function* (){
|
||||
let result = yield rdio.lookupId('Qj4NXr0');
|
||||
result.name.should.equal('Listen (Deluxe)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('search', function(){
|
||||
it('should find album by search', function(done){
|
||||
rdio.search({type: "album", artist: {name: "David Guetta"}, name: "Listen (Deluxe)"}).then(function(result) {
|
||||
result.name.should.equal("Listen (Deluxe)");
|
||||
done();
|
||||
});
|
||||
it('should find album by search', function* (){
|
||||
let result = yield rdio.search({type: 'album', artist: {name: 'David Guetta'}, name: 'Listen (Deluxe)'});
|
||||
result.name.should.equal('Listen (Deluxe)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseUrl', function(){
|
||||
it('should parse regular url into album object', function(done){
|
||||
rdio.parseUrl("https://www.rdio.com/artist/David_Guetta/album/Listen_(Deluxe)/").then(function(result) {
|
||||
result.name.should.equal("Listen (Deluxe)");
|
||||
done();
|
||||
});
|
||||
it('should parse regular url into album object', function* (){
|
||||
let result = yield rdio.parseUrl('https://www.rdio.com/artist/David_Guetta/album/Listen_(Deluxe)/');
|
||||
result.name.should.equal('Listen (Deluxe)');
|
||||
});
|
||||
|
||||
it('should parse short url into album object', function(done){
|
||||
rdio.parseUrl("http://rd.io/x/Qj4NXr0/").then(function(result) {
|
||||
result.name.should.equal("Listen (Deluxe)");
|
||||
done();
|
||||
});
|
||||
it('should parse short url into album object', function* (){
|
||||
let result = yield rdio.parseUrl('http://rd.io/x/Qj4NXr0/');
|
||||
result.name.should.equal('Listen (Deluxe)');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,41 +1,30 @@
|
|||
"use strict";
|
||||
var assert = require("assert");
|
||||
var should = require('should');
|
||||
|
||||
var spotify = require("../../lib/services/spotify");
|
||||
import 'should';
|
||||
import spotify from '../../lib/services/spotify';
|
||||
|
||||
describe('Spotify', function(){
|
||||
describe('lookupId', function(){
|
||||
it('should find album by ID', function(done){
|
||||
spotify.lookupId("77UW17CZFyCaRLHdHeofZu", "album").then(function(result) {
|
||||
result.name.should.equal("Listen (Deluxe)");
|
||||
done();
|
||||
});
|
||||
it('should find album by ID', function* (){
|
||||
let result = yield spotify.lookupId('77UW17CZFyCaRLHdHeofZu', 'album');
|
||||
result.name.should.equal('Listen (Deluxe)');
|
||||
});
|
||||
|
||||
it('should find track by ID', function(done){
|
||||
spotify.lookupId("7dS5EaCoMnN7DzlpT6aRn2", "track").then(function(result) {
|
||||
result.name.should.equal("Take Me To Church");
|
||||
done();
|
||||
});
|
||||
it('should find track by ID', function* (){
|
||||
let result = yield spotify.lookupId('7dS5EaCoMnN7DzlpT6aRn2', 'track');
|
||||
result.name.should.equal('Take Me To Church');
|
||||
});
|
||||
});
|
||||
|
||||
describe('search', function(){
|
||||
it('should find album by search', function(done){
|
||||
spotify.search({type: "album", artist: {name: "David Guetta"}, name: "Listen (Deluxe)"}).then(function(result) {
|
||||
result.name.should.equal("Listen (Deluxe)");
|
||||
done();
|
||||
});
|
||||
it('should find album by search', function* (){
|
||||
let result = yield spotify.search({type: 'album', artist: {name: 'David Guetta'}, name: 'Listen (Deluxe)'});
|
||||
result.name.should.equal('Listen (Deluxe)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseUrl', function(){
|
||||
it('should parse url into ID', function(done){
|
||||
spotify.parseUrl("https://play.spotify.com/album/77UW17CZFyCaRLHdHeofZu").then(function(result) {
|
||||
result.id.should.equal("77UW17CZFyCaRLHdHeofZu");
|
||||
done();
|
||||
});
|
||||
it('should parse url into ID', function* (){
|
||||
let result = yield spotify.parseUrl('https://play.spotify.com/album/77UW17CZFyCaRLHdHeofZu');
|
||||
result.id.should.equal('77UW17CZFyCaRLHdHeofZu');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,41 +1,30 @@
|
|||
"use strict";
|
||||
var assert = require("assert");
|
||||
var should = require('should');
|
||||
|
||||
var google = require("../../lib/services/xbox");
|
||||
import 'should';
|
||||
import xbox from '../../lib/services/xbox';
|
||||
|
||||
describe('Xbox Music', function(){
|
||||
describe('lookupId', function(){
|
||||
it('should find album by ID', function(done){
|
||||
google.lookupId("music.8b558d00-0100-11db-89ca-0019b92a3933", "album").then(function(result) {
|
||||
result.name.should.equal("Muchas Gracias: The Best Of Kyuss");
|
||||
done();
|
||||
});
|
||||
it('should find album by ID', function* (){
|
||||
let result = yield xbox.lookupId('music.8b558d00-0100-11db-89ca-0019b92a3933', 'album');
|
||||
result.name.should.equal('Muchas Gracias: The Best Of Kyuss');
|
||||
});
|
||||
|
||||
it('should find track by ID', function(done){
|
||||
google.lookupId("music.8f558d00-0100-11db-89ca-0019b92a3933", "track").then(function(result) {
|
||||
result.name.should.equal("Shine");
|
||||
done();
|
||||
});
|
||||
it('should find track by ID', function* (){
|
||||
let result = yield xbox.lookupId('music.8f558d00-0100-11db-89ca-0019b92a3933', 'track');
|
||||
result.name.should.equal('Shine');
|
||||
});
|
||||
});
|
||||
|
||||
describe('search', function(){
|
||||
it('should find album by search', function(done){
|
||||
google.search({type: "album", artist: {name: "Kyuss"}, name: "Muchas Gracias: The Best Of Kyuss"}).then(function(result) {
|
||||
result.name.should.equal("Muchas Gracias: The Best Of Kyuss");
|
||||
done();
|
||||
});
|
||||
it('should find album by search', function* (){
|
||||
let result = yield xbox.search({type: 'album', artist: {name: 'Kyuss'}, name: 'Muchas Gracias: The Best Of Kyuss'});
|
||||
result.name.should.equal('Muchas Gracias: The Best Of Kyuss');
|
||||
});
|
||||
});
|
||||
|
||||
describe('lookupUrl', function(){
|
||||
it('should parse regular url into album ID', function(done){
|
||||
google.parseUrl("https://music.xbox.com/album/kyuss/muchas-gracias-the-best-of-kyuss/8b558d00-0100-11db-89ca-0019b92a3933").then(function(result) {
|
||||
result.id.should.equal("music.8B558D00-0100-11DB-89CA-0019B92A3933");
|
||||
done();
|
||||
});
|
||||
it('should parse regular url into album ID', function* (){
|
||||
let result = yield xbox.parseUrl('https://music.xbox.com/album/kyuss/muchas-gracias-the-best-of-kyuss/8b558d00-0100-11db-89ca-0019b92a3933');
|
||||
result.id.should.equal('music.8B558D00-0100-11DB-89CA-0019B92A3933');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
"use strict";
|
||||
var assert = require("assert");
|
||||
var should = require('should');
|
||||
|
||||
var youtube = require("../../lib/services/youtube");
|
||||
import 'should';
|
||||
import youtube from '../../lib/services/youtube';
|
||||
|
||||
describe('Youtube', function(){
|
||||
describe('search', function(){
|
||||
it('should find album by search', function(done){
|
||||
youtube.search({type: "track", artist: {name: "Aesop Rock"}, album: {name: "Skelethon"}, name: "Zero Dark Thirty"}).then(function(result) {
|
||||
result.name.should.equal("Aesop Rock - Zero Dark Thirty");
|
||||
done();
|
||||
});
|
||||
it('should find album by search', function* (){
|
||||
let result = yield youtube.search({type: 'track', artist: {name: 'Aesop Rock'}, album: {name: 'Skelethon'}, name: 'Zero Dark Thirty'});
|
||||
result.name.should.equal('Aesop Rock - Zero Dark Thirty');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"react"
|
||||
],
|
||||
"env": {
|
||||
"browser": true
|
||||
"browser": true,
|
||||
"es6": true
|
||||
}
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var React = require("react");
|
||||
var Router = require("react-router");
|
||||
var Route = require("react-router").Route;
|
||||
var DefaultRoute = require("react-router").DefaultRoute;
|
||||
var NotFoundRoute = require("react-router").NotFoundRoute;
|
||||
var RouteHandler = require("react-router").RouteHandler;
|
||||
var Home = require("./home.jsx");
|
||||
var Share = require("./share.jsx");
|
||||
var Head = require("./head.jsx");
|
||||
var ga = require("react-google-analytics");
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var Route = require('react-router').Route;
|
||||
var DefaultRoute = require('react-router').DefaultRoute;
|
||||
var NotFoundRoute = require('react-router').NotFoundRoute;
|
||||
var RouteHandler = require('react-router').RouteHandler;
|
||||
var Home = require('./home.jsx');
|
||||
var Share = require('./share.jsx');
|
||||
var Head = require('./head.jsx');
|
||||
var ga = require('react-google-analytics');
|
||||
var GAInitiailizer = ga.Initializer;
|
||||
|
||||
var App = React.createClass({
|
||||
|
@ -17,42 +17,36 @@ var App = React.createClass({
|
|||
return (
|
||||
<html>
|
||||
<Head {...this.props} />
|
||||
<body className="home">
|
||||
<body className='home'>
|
||||
<RouteHandler {...this.props} />
|
||||
<GAInitiailizer />
|
||||
<script src="/javascript/bundle.js" />
|
||||
<script src='/javascript/bundle.js' />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var NotFound = React.createClass({
|
||||
render: function () {
|
||||
return <h2>Not found</h2>;
|
||||
}
|
||||
});
|
||||
|
||||
var routes = (
|
||||
<Route name="home" handler={App} path="/">
|
||||
<Route name='home' handler={App} path='/'>
|
||||
<DefaultRoute handler={Home} />
|
||||
<Route name="share" path=":service/:type/:id" handler={Share}/>
|
||||
<NotFoundRoute handler={NotFound}/>
|
||||
<Route name='share' path=':service/:type/:id' handler={Share}/>
|
||||
<NotFoundRoute handler={Error}/>
|
||||
</Route>
|
||||
);
|
||||
|
||||
module.exports.routes = routes;
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.onload = function() {
|
||||
Router.run(routes, Router.HistoryLocation, function (Handler) {
|
||||
if (typeof window.recents !== "undefined") {
|
||||
if (typeof window.recents !== 'undefined') {
|
||||
React.render(<Handler recents={window.recents} />, document);
|
||||
} else if (typeof shares !== "undefined") {
|
||||
} else if (typeof shares !== 'undefined') {
|
||||
React.render(<Handler shares={window.shares} />, document);
|
||||
}
|
||||
});
|
||||
ga("create", "UA-66209-8", "auto");
|
||||
ga("send", "pageview");
|
||||
ga('create', 'UA-66209-8', 'auto');
|
||||
ga('send', 'pageview');
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var React = require("react");
|
||||
var React = require('react');
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="row faq">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<div className='row faq'>
|
||||
<div className='col-md-6 col-md-offset-3'>
|
||||
<h2>Questions?</h2>
|
||||
<ul>
|
||||
<li>
|
||||
|
@ -20,11 +20,11 @@ module.exports = React.createClass({
|
|||
</li>
|
||||
<li>
|
||||
<h3>Where do I find a link to paste in the box?</h3>
|
||||
<p>Most music services have a "share" dialog for albums and tracks in their interface. If you have them open in a web browser instead of an app, you can simply copy and paste the address bar and we'll work out the rest.</p>
|
||||
<p>Most music services have a 'share' dialog for albums and tracks in their interface. If you have them open in a web browser instead of an app, you can simply copy and paste the address bar and we'll work out the rest.</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>Why don't you guys support Bandcamp, Amazon Music, Sony Music Unlimited… ?</h3>
|
||||
<p>Let me stop you there. <a href="https://github.com/kudos/match.audio">Match Audio is open source</a>, that means any capable programmer who wants to add other music services can look at our code and submit changes. If you're not a programmer, you can always <a href="https://github.com/kudos/match.audio/issues">submit a request</a> and maybe we'll do it for you.</p>
|
||||
<p>Let me stop you there. <a href='https://github.com/kudos/match.audio'>Match Audio is open source</a>, that means any capable programmer who wants to add other music services can look at our code and submit changes. If you're not a programmer, you can always <a href='https://github.com/kudos/match.audio/issues'>submit a request</a> and maybe we'll do it for you.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -65,7 +65,7 @@ var SearchForm = React.createClass({
|
|||
});
|
||||
return;
|
||||
}
|
||||
request.post("/search").send({url: url}).end(function(res) {
|
||||
request.post("/search").send({url: url}).end(function(req, res) {
|
||||
that.setState({
|
||||
submitting: false
|
||||
});
|
||||
|
@ -118,7 +118,7 @@ module.exports = React.createClass({
|
|||
|
||||
componentDidMount: function () {
|
||||
if (!this.props.recents) {
|
||||
request.get("/recent").set("Accept", "application/json").end(function(res) {
|
||||
request.get("/recent").set("Accept", "application/json").end(function(err, res) {
|
||||
this.setState({
|
||||
recents: res.body.recents
|
||||
});
|
||||
|
|
|
@ -100,7 +100,7 @@ module.exports = React.createClass({
|
|||
});
|
||||
|
||||
var getShares = function() {
|
||||
request.get(this.getPathname() + ".json").end(function(res) {
|
||||
request.get(this.getPathname() + ".json").end(function(err, res) {
|
||||
var shares = res.body.shares;
|
||||
complete = true;
|
||||
shares.forEach(function(share) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue