diff --git a/app.js b/app.js index de4ec6c..a559657 100644 --- a/app.js +++ b/app.js @@ -1,92 +1,93 @@ "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'); +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"); -var index = require('./routes/index'); -var search = require('./routes/search'); -var share = require('./routes/share'); -var itunesProxy = require('./routes/itunes-proxy'); +var index = require("./routes/index"); +var search = require("./routes/search"); +var share = require("./routes/share"); +var itunesProxy = require("./routes/itunes-proxy"); -var React = require('react'); -var nodejsx = require('node-jsx').install({extension: '.jsx'}); -var ErrorView = React.createFactory(require('./views/error.jsx')); +var React = require("react"); +require("node-jsx").install({extension: ".jsx"}); -var browserify = require('connect-browserify'); +var ErrorView = React.createFactory(require("./views/error.jsx")); + +var browserify = require("connect-browserify"); var app = express(); -var development = process.env.NODE_ENV !== 'production'; +var development = process.env.NODE_ENV !== "production"; // view engine setup -app.set('views', path.join(__dirname, 'views')); -app.set('view engine', 'ejs'); +app.set("views", path.join(__dirname, "views")); +app.set("view engine", "ejs"); app.use(compress()); -app.use(favicon(__dirname + '/public/images/favicon.png')); +app.use(favicon(path.join(__dirname, "/public/images/favicon.png"))); app.use(helmet()); -app.use(logger('dev')); +app.use(logger("dev")); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(session({ - secret: 'keyboard catz', + secret: "keyboard catz", resave: false, saveUninitialized: true })); app.use(flash()); -app.use(express.static(path.join(__dirname, 'public'))); +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']); + req.db = res.db = pmongo(dbUrl, ["matches"]); next(); }); if (development) { - app.get('/javascript/bundle.js', - browserify('./views/app.jsx', { + app.get("/javascript/bundle.js", + browserify("./views/app.jsx", { debug: true, watch: true })); } -app.get('*', function(req,res,next) { +app.get("*", function(req, res, next) { // force SSL - if (req.headers['cf-visitor'] && req.headers['cf-visitor'] != '{"scheme":"https"}') { + 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']) { + } else if (req.headers["cf-visitor"]) { req.userProtocol = "https"; } else { req.userProtocol = "http"; } // redirect www if (req.headers.host.match(/^www/) !== null ) { - return res.redirect(req.userProtocol + '://' + req.headers.host.replace(/^www\./, '') + req.url); + return res.redirect(req.userProtocol + "://" + req.headers.host.replace(/^www\./, "") + req.url); } else { 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){ +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]]); + recents.push(doc.services[doc._id.split("$$")[0]]); // eslint-disable-line no-underscore-dangle }); - res.json({recents:recents}); + res.json({recents: recents}); }).catch(function (error) { return next(error); }); @@ -94,7 +95,7 @@ app.get('/recent', function(req, res, next) { // catch 404 and forward to error handler app.use(function(req, res, next) { - var err = new Error('Not Found'); + var err = new Error("Not Found"); err.status = 404; next(err); }); @@ -103,23 +104,23 @@ app.use(function(req, res, next) { // development error handler // will print stacktrace -if (app.get('env') === 'development') { - app.use(function(err, req, res, next) { +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('\n' + content); + res.send("\n" + content); }); } // production error handler // no stacktraces leaked to user -app.use(function(err, req, res, next) { +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('\n' + content); + res.send("\n" + content); }); diff --git a/bin/www b/bin/www index 1a8743a..b446065 100755 --- a/bin/www +++ b/bin/www @@ -1,6 +1,6 @@ #!/usr/bin/env node "use strict"; -var debug = require('debug')('unify.audio'); +var debug = require('debug')('match.audio'); var app = require('../app'); app.set('port', process.env.PORT || 3000); diff --git a/lib/lookup.js b/lib/lookup.js index 06ed6dc..25dc68d 100644 --- a/lib/lookup.js +++ b/lib/lookup.js @@ -1,5 +1,5 @@ "use strict"; -var path = require('path'); +var path = require("path"); var services = []; @@ -17,7 +17,7 @@ module.exports = function(url) { matchedService = service.match(url) ? service : null; return matchedService; }); - + if (matchedService) { return matchedService.parseUrl(url).timeout(10000).then(function(result) { return matchedService.lookupId(result.id, result.type).then(function(item) { diff --git a/lib/services.js b/lib/services.js index 4f30c9d..e8e6110 100644 --- a/lib/services.js +++ b/lib/services.js @@ -1,6 +1,5 @@ "use strict"; -var path = require('path'); -var Promise = require("bluebird"); +var path = require("path"); module.exports = []; diff --git a/lib/services/beats/index.js b/lib/services/beats/index.js index 338339e..385012c 100644 --- a/lib/services/beats/index.js +++ b/lib/services/beats/index.js @@ -1,8 +1,7 @@ "use strict"; -var parse = require('url').parse; -var Promise = require('bluebird'); -var request = require('superagent'); -require('superagent-bluebird-promise'); +var parse = require("url").parse; +var request = require("superagent"); +require("superagent-bluebird-promise"); module.exports.id = "beats"; @@ -29,10 +28,10 @@ module.exports.parseUrl = function(url) { } else { throw new Error("Url does not match"); } -} +}; module.exports.lookupId = function(id, type) { - if (type == "album") { + 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) { @@ -59,7 +58,7 @@ module.exports.lookupId = function(id, type) { }); }); }); - } else if (type == "track") { + } 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"); @@ -99,16 +98,20 @@ module.exports.lookupId = function(id, type) { 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) + '"'; + 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) + '"'; - album = data.album.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; @@ -118,20 +121,20 @@ module.exports.search = function(data) { return {service: "beats"}; } else { var found; - var choppedAlbum = data.type == "album" ? cleanParam(data.name) : cleanParam(data.album.name); + 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) { diff --git a/lib/services/beats/url.js b/lib/services/beats/url.js index 026f540..a8fda32 100644 --- a/lib/services/beats/url.js +++ b/lib/services/beats/url.js @@ -1,5 +1,5 @@ "use strict"; -var parse = require('url').parse; +var parse = require("url").parse; module.exports.match = function(url) { var parsed = parse(url); diff --git a/routes/index.js b/routes/index.js index 0ee415e..c6daff8 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,18 +1,18 @@ "use strict"; -var React = require('react'); -var nodejsx = require('node-jsx').install({extension: '.jsx'}); -var Router = require('react-router'); -var routes = require('../views/app.jsx').routes; +var React = require("react"); +var Router = require("react-router"); +require("node-jsx").install({extension: ".jsx"}); +var routes = require("../views/app.jsx").routes; module.exports = function(req, res, next) { - req.db.matches.find().sort({created_at:-1}).limit(6).toArray().then(function(docs){ + 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]}); + var shares = Object.keys(doc.services).map(function (key) {return doc.services[key]; }); shares.some(function(item) { - if (item.service == doc._id.split("$$")[0]) { + if (item.service === doc._id.split("$$")[0]) { // eslint-disable-line no-underscore-dangle recents.push(item); return false; } @@ -22,9 +22,9 @@ module.exports = function(req, res, next) { Router.run(routes, req.url, function (Handler) { var App = React.createFactory(Handler); var content = React.renderToString(new App({recents: recents})); - res.send('\n' + content.replace("", "")); + res.send("\n" + content.replace("", "")); }); }).catch(function(error) { next(error); }); -} \ No newline at end of file +}; diff --git a/routes/itunes-proxy.js b/routes/itunes-proxy.js index 7073b4b..1c5225c 100644 --- a/routes/itunes-proxy.js +++ b/routes/itunes-proxy.js @@ -1,6 +1,6 @@ "use strict"; -var parse = require('url').parse; -var request = require('superagent'); +var parse = require("url").parse; +var request = require("superagent"); module.exports = function(req, res) { var url = "http://" + req.url.substr(8); diff --git a/routes/search.js b/routes/search.js index 8f1a5e5..69bb64d 100644 --- a/routes/search.js +++ b/routes/search.js @@ -1,41 +1,40 @@ "use strict"; -var parse = require('url').parse; -var path = require('path'); -var lookup = require('../lib/lookup'); -var services = require('../lib/services'); +var parse = require("url").parse; +var lookup = require("../lib/lookup"); +var services = require("../lib/services"); -module.exports = function(req, res, next) { +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."}}); + return res.json({error: {message: "You need to submit a url."}}); } - + var promise = lookup(req.body.url); - + if (!promise) { return res.json({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(); + item.matched_at = new Date(); // eslint-disable-line camelcase var matches = {}; matches[item.service] = item; services.forEach(function(service) { - if (service.id == item.service) { + if (service.id === item.service) { return; } matches[service.id] = {service: service.id}; service.search(item).then(function(match) { - match.matched_at = new Date(); + 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() { + return req.db.matches.save({_id: item.service + "$$" + item.id, "created_at": new Date(), services: matches}).then(function() { res.json(item); }); }, function(error) { diff --git a/routes/share.js b/routes/share.js index 162bffc..f50655d 100644 --- a/routes/share.js +++ b/routes/share.js @@ -1,25 +1,21 @@ "use strict"; -var path = require('path'); -var Promise = require('bluebird'); -var util = require('util'); -var browserify = require('connect-browserify'); -var React = require('react'); -var Router = require('react-router'); -var nodejsx = require('node-jsx').install(); -var routes = require('../views/app.jsx').routes; +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 services = require("../lib/services"); var formatAndSort = function(matches, serviceId) { - matches = Object.keys(matches).map(function (key) {return matches[key]}); + matches = Object.keys(matches).map(function (key) {return matches[key]; }); matches.sort(function(a, b) { return a.id && !b.id; - }).sort(function(a, b) { - return a.service != serviceId; + }).sort(function(a) { + return a.service !== serviceId; }); return matches; -} +}; module.exports = function(req, res, next) { var serviceId = req.params.service; @@ -28,50 +24,50 @@ module.exports = function(req, res, next) { var matchedService; services.some(function(service) { - matchedService = serviceId == service.id ? service : null; + matchedService = serviceId === service.id ? service : null; return matchedService; }); - if (!matchedService || (type != "album" && type != "track")) { + if (!matchedService || (type !== "album" && type !== "track")) { return next(); } - return req.db.matches.findOne({_id:serviceId + "$$" + itemId}).then(function(doc) { + 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(); + item.matched_at = new Date(); // eslint-disable-line camelcase matches[item.service] = item; services.forEach(function(service) { - if (service.id == item.service) { + if (service.id === item.service) { return; } matches[service.id] = {service: service.id}; service.search(item).then(function(match) { - match.matched_at = new Date(); + 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 shares = formatAndSort(matches, serviceId); + 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: shares})); - res.send('\n' + content.replace("", "")); + var content = React.renderToString(new App({shares: newShares})); + res.send("\n" + content.replace("", "")); }); }); - }) + }); } var shares = formatAndSort(doc.services, serviceId); - if (req.params.format == "json") { - return res.json({shares:shares}); + 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('\n' + content.replace("", "")); + res.send("\n" + content.replace("", "")); }); }).catch(function (error) { return next(error); diff --git a/views/.eslintrc b/views/.eslintrc new file mode 100644 index 0000000..9c66146 --- /dev/null +++ b/views/.eslintrc @@ -0,0 +1,11 @@ +{ + "ecmaFeatures": { + "jsx": true + }, + "plugins": [ + "react" + ], + "env": { + "browser": true + } +} \ No newline at end of file diff --git a/views/app.jsx b/views/app.jsx index 68f911d..1f811bf 100644 --- a/views/app.jsx +++ b/views/app.jsx @@ -1,23 +1,19 @@ -'use strict'; +"use strict"; -var request = require('superagent'); -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 Error = require('./error.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({ - render: function () { - return ( @@ -47,16 +43,16 @@ var routes = ( module.exports.routes = routes; -if (typeof window !== 'undefined') { +if (typeof window !== "undefined") { window.onload = function() { Router.run(routes, Router.HistoryLocation, function (Handler) { - if (typeof recents !== "undefined") { - React.render(, document); + if (typeof window.recents !== "undefined") { + React.render(, document); } else if (typeof shares !== "undefined") { - React.render(, document); + React.render(, document); } }); - ga('create', 'UA-66209-8', 'auto'); - ga('send', 'pageview'); - } -} \ No newline at end of file + ga("create", "UA-66209-8", "auto"); + ga("send", "pageview"); + }; +} diff --git a/views/error.jsx b/views/error.jsx index 4e9fa12..5105c84 100644 --- a/views/error.jsx +++ b/views/error.jsx @@ -1,8 +1,8 @@ -'use strict'; +"use strict"; -var React = require('react'); -var Head = require('./head.jsx'); -var Foot = require('./foot.jsx'); +var React = require("react"); +var Head = require("./head.jsx"); +var Foot = require("./foot.jsx"); module.exports = React.createClass({ diff --git a/views/faq.jsx b/views/faq.jsx index 955a28d..543d464 100644 --- a/views/faq.jsx +++ b/views/faq.jsx @@ -1,6 +1,6 @@ -'use strict'; +"use strict"; -var React = require('react'); +var React = require("react"); module.exports = React.createClass({ diff --git a/views/foot.jsx b/views/foot.jsx index 3bc832e..6dcdf10 100644 --- a/views/foot.jsx +++ b/views/foot.jsx @@ -1,6 +1,6 @@ -'use strict'; +"use strict"; -var React = require('react'); +var React = require("react"); module.exports = React.createClass({ @@ -9,7 +9,7 @@ module.exports = React.createClass({