Finally finished giant ES6 refactor
This commit is contained in:
parent
c6d48cc424
commit
03e2666958
39 changed files with 553 additions and 635 deletions
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
(The MIT License)
|
(The MIT License)
|
||||||
|
|
||||||
Copyright (c) 20014 Jonathan Cremin <jonathan@crem.in>
|
Copyright (c) 2014 Jonathan Cremin <jonathan@crem.in>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
|
2
Procfile
2
Procfile
|
@ -1 +1 @@
|
||||||
web: npm start
|
web: npm run build && npm start
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#match.audio [](https://circleci.com/gh/kudos/match.audio)
|
#match.audio [](https://circleci.com/gh/kudos/match.audio)
|
||||||
|
|
||||||
Make sharing from music services better. We match links from Rdio, Spotify, Deezer, Beats Music, Google Music and iTunes and give you back a link with all of them.
|
Make sharing from music services better. We match links from Rdio, Spotify, Deezer, Google Music and iTunes and give you back a link with all of them.
|
||||||
|
|
||||||
## Supported Services
|
## Supported Services
|
||||||
|
|
||||||
|
@ -32,4 +32,4 @@ So there's no surprises for contributors later, I plan on using referral tags wh
|
||||||
|
|
||||||
## Licence
|
## Licence
|
||||||
|
|
||||||
The code is MIT licenced, the brand is not. This applies to the logo, name and magenta colour scheme. I'll probably pull the branding out of the app itself at some point to make that distinction more clear.
|
The code is MIT licenced, the brand is not. This applies to the logo, name and magenta colour scheme. I'll probably pull the branding out of the app itself at some point to make that distinction more clear.
|
||||||
|
|
25
app.js
25
app.js
|
@ -1,4 +1,5 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import zlib from 'zlib';
|
||||||
import koa from 'koa';
|
import koa from 'koa';
|
||||||
import route from 'koa-route';
|
import route from 'koa-route';
|
||||||
import logger from 'koa-logger';
|
import logger from 'koa-logger';
|
||||||
|
@ -13,8 +14,7 @@ import index from './routes/index';
|
||||||
import search from './routes/search';
|
import search from './routes/search';
|
||||||
import share from './routes/share';
|
import share from './routes/share';
|
||||||
import itunesProxy from './routes/itunes-proxy';
|
import itunesProxy from './routes/itunes-proxy';
|
||||||
import {routes} from './views/app';
|
import { routes } from './views/app';
|
||||||
import zlib from 'zlib';
|
|
||||||
import createHandler from './lib/react-handler';
|
import createHandler from './lib/react-handler';
|
||||||
|
|
||||||
import debuglog from 'debug';
|
import debuglog from 'debug';
|
||||||
|
@ -29,6 +29,7 @@ app.use(function* (next) {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!err.status) {
|
if (!err.status) {
|
||||||
debug('Error: %o', err);
|
debug('Error: %o', err);
|
||||||
|
throw err;
|
||||||
} else if (err.status === 404) {
|
} else if (err.status === 404) {
|
||||||
let Handler = yield createHandler(routes, this.request.url);
|
let Handler = yield createHandler(routes, this.request.url);
|
||||||
|
|
||||||
|
@ -90,20 +91,10 @@ app.use(route.get('/recent', function* () {
|
||||||
this.body = {recents: recents};
|
this.body = {recents: recents};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
module.exports = app;
|
|
||||||
|
|
||||||
if (!module.parent) {
|
if (!module.parent) {
|
||||||
if (process.env.LOCALHOST_KEY) {
|
app.listen(process.env.PORT || 3000, function() {
|
||||||
require('spdy').createServer({
|
debug('Koa HTTP server listening on port ' + (process.env.PORT || 3000));
|
||||||
key: process.env.LOCALHOST_KEY,
|
});
|
||||||
cert: process.env.LOCALHOST_CRT
|
|
||||||
}, app.callback()).listen(3000, function() {
|
|
||||||
debug('Koa SPDY server listening on port ' + (process.env.PORT || 3000));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
app.listen(process.env.PORT || 3000, function() {
|
|
||||||
debug('Koa HTTP server listening on port ' + (process.env.PORT || 3000));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default app;
|
||||||
|
|
10
bin/www
10
bin/www
|
@ -1,10 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
"use strict";
|
|
||||||
var debug = require("debug")("match.audio");
|
|
||||||
var app = require("../app");
|
|
||||||
|
|
||||||
app.set("port", process.env.PORT || 3000);
|
|
||||||
|
|
||||||
var server = app.listen(app.get("port"), function() {
|
|
||||||
debug("Express server listening on port " + server.address().port);
|
|
||||||
});
|
|
14
config/db.js
14
config/db.js
|
@ -1,15 +1,11 @@
|
||||||
'use strict';
|
import mongodb from 'mongodb-promisified';
|
||||||
const debug = require('debug')('match.audio');
|
const MongoClient = mongodb().MongoClient;
|
||||||
|
import debuglog from 'debug';
|
||||||
// Shut mongodb-promisified up.
|
const debug = debuglog('match.audio');
|
||||||
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';
|
const uristring = process.env.MONGOLAB_URI || process.env.MONGOHQ_URL || 'mongodb://localhost:27017/match-audio';
|
||||||
|
|
||||||
module.exports = function*() {
|
export default function*() {
|
||||||
const client = yield MongoClient.connect(uristring);
|
const client = yield MongoClient.connect(uristring);
|
||||||
debug('Successfully connected to Mongodb');
|
debug('Successfully connected to Mongodb');
|
||||||
client.matches = client.collection('matches');
|
client.matches = client.collection('matches');
|
||||||
|
|
|
@ -4,25 +4,19 @@ import fs from 'fs';
|
||||||
var services = [];
|
var services = [];
|
||||||
|
|
||||||
fs.readdirSync(path.join(__dirname, 'services')).forEach(function(file) {
|
fs.readdirSync(path.join(__dirname, 'services')).forEach(function(file) {
|
||||||
var service = require(path.join(__dirname, 'services', file));
|
const service = require(path.join(__dirname, 'services', file));
|
||||||
if (service.search) {
|
if (service.search) {
|
||||||
services.push(service);
|
services.push(service);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = function(url) {
|
export default function* (url) {
|
||||||
|
let matchedService;
|
||||||
var matchedService;
|
for (let service of services) {
|
||||||
services.some(function(service) {
|
matchedService = yield service.match(url);
|
||||||
matchedService = service.match(url) ? service : null;
|
if (matchedService) {
|
||||||
return matchedService;
|
const result = yield service.parseUrl(url);
|
||||||
});
|
return yield service.lookupId(result.id, result.type);
|
||||||
|
}
|
||||||
if (matchedService) {
|
|
||||||
return matchedService.parseUrl(url).timeout(10000).then(function(result) {
|
|
||||||
return matchedService.lookupId(result.id, result.type).then(function(item) {
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
module.exports = [];
|
const services = [];
|
||||||
|
|
||||||
fs.readdirSync(path.join(__dirname, 'services')).forEach(function(file) {
|
fs.readdirSync(path.join(__dirname, 'services')).forEach(function(file) {
|
||||||
var service = require(path.join(__dirname, 'services', file));
|
var service = require(path.join(__dirname, 'services', file));
|
||||||
if (service.search) {
|
if (service.search) {
|
||||||
module.exports.push(service);
|
services.push(service);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default services;
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import {parse} from 'url';
|
import { parse } from 'url';
|
||||||
import request from 'superagent';
|
import request from 'superagent';
|
||||||
import 'superagent-bluebird-promise';
|
import 'superagent-bluebird-promise';
|
||||||
|
import { match as urlMatch } from './url';
|
||||||
|
|
||||||
module.exports.id = 'deezer';
|
export let id = 'deezer';
|
||||||
|
|
||||||
const apiRoot = 'https://api.deezer.com';
|
const apiRoot = 'https://api.deezer.com';
|
||||||
|
|
||||||
module.exports.match = require('./url').match;
|
export const match = urlMatch;
|
||||||
|
|
||||||
module.exports.parseUrl = function(url) {
|
export function parseUrl(url) {
|
||||||
let matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
|
let matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
|
||||||
|
|
||||||
if (matches && matches[2]) {
|
if (matches && matches[2]) {
|
||||||
|
@ -18,7 +19,7 @@ module.exports.parseUrl = function(url) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.lookupId = function* (id, type) {
|
export function* lookupId(id, type) {
|
||||||
let path = '/' + type + '/' + id;
|
let path = '/' + type + '/' + id;
|
||||||
|
|
||||||
let {body} = yield request.get(apiRoot + path).promise();
|
let {body} = yield request.get(apiRoot + path).promise();
|
||||||
|
@ -74,7 +75,7 @@ module.exports.lookupId = function* (id, type) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.search = function* (data) {
|
export function* search(data) {
|
||||||
let cleanParam = function(str) {
|
let cleanParam = function(str) {
|
||||||
return str.replace(/[\:\?\&]+/, '');
|
return str.replace(/[\:\?\&]+/, '');
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
var parse = require('url').parse;
|
|
||||||
|
|
||||||
module.exports.match = function(url) {
|
export function* match(url) {
|
||||||
var parsed = parse(url);
|
const parsed = parse(url);
|
||||||
if (!parsed.host.match(/deezer\.com$/)) {
|
if (!parsed.host.match(/deezer\.com$/)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var matches = parsed.path.match(/\/(album|track)[\/]+([^\/]+)/);
|
const matches = parsed.path.match(/\/(album|track)[\/]+([^\/]+)/);
|
||||||
return matches.length > 1;
|
return matches.length > 1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,148 +1,135 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
|
import bluebird from 'bluebird';
|
||||||
|
import PlayMusic from 'playmusic';
|
||||||
|
import { match as urlMatch } from './url';
|
||||||
|
|
||||||
var parse = require("url").parse;
|
const pm = bluebird.promisifyAll(new PlayMusic());
|
||||||
var Promise = require("bluebird");
|
|
||||||
var PlayMusic = require("playmusic");
|
|
||||||
var pm = Promise.promisifyAll(new PlayMusic());
|
|
||||||
|
|
||||||
module.exports.id = "google";
|
export let id = 'google';
|
||||||
|
|
||||||
if (!process.env.GOOGLE_EMAIL || !process.env.GOOGLE_PASSWORD) {
|
if (!process.env.GOOGLE_EMAIL || !process.env.GOOGLE_PASSWORD) {
|
||||||
console.warn("GOOGLE_EMAIL or GOOGLE_PASSWORD environment variables not found, deactivating Google Play Music.");
|
console.warn('GOOGLE_EMAIL or GOOGLE_PASSWORD environment variables not found, deactivating Google Play Music.');
|
||||||
}
|
}
|
||||||
|
|
||||||
var ready = pm.initAsync({email: process.env.GOOGLE_EMAIL, password: process.env.GOOGLE_PASSWORD}).catch(function(err) {
|
let ready = pm.initAsync({email: process.env.GOOGLE_EMAIL, password: process.env.GOOGLE_PASSWORD}).catch(function(err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports.match = require("./url").match;
|
export const match = urlMatch;
|
||||||
|
|
||||||
module.exports.parseUrl = function(url) {
|
export function* parseUrl(url) {
|
||||||
return ready.then(function() {
|
yield ready;
|
||||||
var parsed = parse(url.replace(/\+/g, "%20"));
|
const parsed = parse(url.replace(/\+/g, '%20'));
|
||||||
var path = parsed.path;
|
const path = parsed.path;
|
||||||
var hash = parsed.hash;
|
const hash = parsed.hash;
|
||||||
if (hash) {
|
if (hash) {
|
||||||
var parts = hash.split("/");
|
const parts = hash.split('/');
|
||||||
var type = parts[1];
|
const type = parts[1];
|
||||||
var id = parts[2];
|
const id = parts[2];
|
||||||
var artist = decodeURIComponent(parts[3]);
|
const artist = decodeURIComponent(parts[3]);
|
||||||
var album = decodeURIComponent(parts[4]);
|
const album = decodeURIComponent(parts[4]);
|
||||||
|
|
||||||
if (type !== "album" && type !== "track") {
|
if (type !== 'album' && type !== 'track') {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (id.length > 0) {
|
|
||||||
return {id: id, type: type};
|
|
||||||
} else {
|
|
||||||
return module.exports.search({type: type, name: album, artist: {name: artist}});
|
|
||||||
}
|
|
||||||
} else if(path) {
|
|
||||||
var matches = path.match(/\/music\/m\/([\w]+)/);
|
|
||||||
type = matches[1][0] === "T" ? "track" : "album";
|
|
||||||
return module.exports.lookupId(matches[1], type);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.lookupId = function(id, type) {
|
|
||||||
return ready.then(function() {
|
|
||||||
if (type === "album") {
|
|
||||||
return pm.getAlbumAsync(id, false).then(function(album) {
|
|
||||||
return {
|
|
||||||
service: "google",
|
|
||||||
type: "album",
|
|
||||||
id: album.albumId,
|
|
||||||
name: album.name,
|
|
||||||
streamUrl: "https://play.google.com/music/m/" + album.albumId + "?signup_if_needed=1",
|
|
||||||
purchaseUrl: "https://play.google.com/store/music/album?id=" + album.albumId,
|
|
||||||
artwork: {
|
|
||||||
small: album.albumArtRef.replace("http:", "https:"),
|
|
||||||
large: album.albumArtRef.replace("http:", "https:")
|
|
||||||
},
|
|
||||||
artist: {
|
|
||||||
name: album.artist
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, function(error) {
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
} else if (type === "track") {
|
|
||||||
return pm.getAllAccessTrackAsync(id).then(function(track) {
|
|
||||||
return {
|
|
||||||
service: "google",
|
|
||||||
type: "track",
|
|
||||||
id: track.nid,
|
|
||||||
name: track.title,
|
|
||||||
streamUrl: "https://play.google.com/music/m/" + track.nid + "?signup_if_needed=1",
|
|
||||||
purchaseUrl: "https://play.google.com/store/music/album?id=" + track.albumId,
|
|
||||||
artwork: {
|
|
||||||
small: track.albumArtRef[0].url.replace("http:", "https:"),
|
|
||||||
large: track.albumArtRef[0].url.replace("http:", "https:")
|
|
||||||
},
|
|
||||||
album: {
|
|
||||||
name: track.album
|
|
||||||
},
|
|
||||||
artist: {
|
|
||||||
name: track.artist
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, function(error) {
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.search = function(data) {
|
|
||||||
return ready.then(function() {
|
|
||||||
var query, album;
|
|
||||||
var type = data.type;
|
|
||||||
|
|
||||||
if (type === "album") {
|
|
||||||
query = data.artist.name + " " + data.name;
|
|
||||||
album = data.name;
|
|
||||||
} else if (type === "track") {
|
|
||||||
query = data.artist.name + " " + data.album.name + " " + data.name;
|
|
||||||
album = data.album.name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pm.searchAsync(query, 5).then(function(result) {
|
if (id.length > 0) {
|
||||||
|
return {id: id, type: type};
|
||||||
if (!result.entries) {
|
} else {
|
||||||
var matches = album.match(/^[^\(\[]+/);
|
return yield search({type: type, name: album, artist: {name: artist}});
|
||||||
if (matches && matches[0] && matches[0] !== album) {
|
}
|
||||||
var cleanedData = JSON.parse(JSON.stringify(data));
|
} else if(path) {
|
||||||
if (type === "album") {
|
const matches = path.match(/\/music\/m\/([\w]+)/);
|
||||||
cleanedData.name = matches[0].trim();
|
const type = matches[1][0] === 'T' ? 'track' : 'album';
|
||||||
} else if (type === "track") {
|
return yield lookupId(matches[1], type);
|
||||||
cleanedData.album.name = matches[0].trim();
|
}
|
||||||
}
|
return false;
|
||||||
return module.exports.search(cleanedData);
|
};
|
||||||
} else {
|
|
||||||
return {service: "google"};
|
export function* lookupId(id, type) {
|
||||||
}
|
yield ready;
|
||||||
}
|
if (type === 'album') {
|
||||||
result = result.entries.filter(function(entry) {
|
const album = yield pm.getAlbumAsync(id, false);
|
||||||
return entry[type];
|
return {
|
||||||
}).sort(function(a, b) { // sort by match score
|
service: 'google',
|
||||||
return a.score < b.score;
|
type: 'album',
|
||||||
}).shift();
|
id: album.albumId,
|
||||||
|
name: album.name,
|
||||||
if (!result) {
|
streamUrl: 'https://play.google.com/music/m/' + album.albumId + '?signup_if_needed=1',
|
||||||
return {service: "google"};
|
purchaseUrl: 'https://play.google.com/store/music/album?id=' + album.albumId,
|
||||||
} else {
|
artwork: {
|
||||||
var id;
|
small: album.albumArtRef.replace('http:', 'https:'),
|
||||||
if (type === "album") {
|
large: album.albumArtRef.replace('http:', 'https:')
|
||||||
id = result.album.albumId;
|
},
|
||||||
} else if (type === "track") {
|
artist: {
|
||||||
id = result.track.nid;
|
name: album.artist
|
||||||
}
|
}
|
||||||
|
};
|
||||||
return module.exports.lookupId(id, type);
|
} else if (type === 'track') {
|
||||||
}
|
const track = yield pm.getAllAccessTrackAsync(id);
|
||||||
});
|
return {
|
||||||
});
|
service: 'google',
|
||||||
|
type: 'track',
|
||||||
|
id: track.nid,
|
||||||
|
name: track.title,
|
||||||
|
streamUrl: 'https://play.google.com/music/m/' + track.nid + '?signup_if_needed=1',
|
||||||
|
purchaseUrl: 'https://play.google.com/store/music/album?id=' + track.albumId,
|
||||||
|
artwork: {
|
||||||
|
small: track.albumArtRef[0].url.replace('http:', 'https:'),
|
||||||
|
large: track.albumArtRef[0].url.replace('http:', 'https:')
|
||||||
|
},
|
||||||
|
album: {
|
||||||
|
name: track.album
|
||||||
|
},
|
||||||
|
artist: {
|
||||||
|
name: track.artist
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function* search(data) {
|
||||||
|
yield ready;
|
||||||
|
let query, album;
|
||||||
|
const type = data.type;
|
||||||
|
|
||||||
|
if (type === 'album') {
|
||||||
|
query = data.artist.name + ' ' + data.name;
|
||||||
|
album = data.name;
|
||||||
|
} else if (type === 'track') {
|
||||||
|
query = data.artist.name + ' ' + data.album.name + ' ' + data.name;
|
||||||
|
album = data.album.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = yield pm.searchAsync(query, 5)
|
||||||
|
|
||||||
|
if (!result.entries) {
|
||||||
|
const matches = album.match(/^[^\(\[]+/);
|
||||||
|
if (matches && matches[0] && matches[0] !== album) {
|
||||||
|
const cleanedData = JSON.parse(JSON.stringify(data));
|
||||||
|
if (type === 'album') {
|
||||||
|
cleanedData.name = matches[0].trim();
|
||||||
|
} else if (type === 'track') {
|
||||||
|
cleanedData.album.name = matches[0].trim();
|
||||||
|
}
|
||||||
|
return yield search(cleanedData);
|
||||||
|
} else {
|
||||||
|
return {service: 'google'};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = result.entries.filter(function(entry) {
|
||||||
|
return entry[type];
|
||||||
|
}).sort(function(a, b) { // sort by match score
|
||||||
|
return a.score < b.score;
|
||||||
|
}).shift();
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return {service: 'google'};
|
||||||
|
} else {
|
||||||
|
if (type === 'album') {
|
||||||
|
return yield lookupId(result.album.albumId, type);
|
||||||
|
} else if (type === 'track') {
|
||||||
|
return yield lookupId(result.track.nid, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
var parse = require('url').parse;
|
|
||||||
|
|
||||||
module.exports.match = function(url) {
|
export function* match(url) {
|
||||||
var parsed = parse(url.replace(/\+/g, "%20"));
|
var parsed = parse(url.replace(/\+/g, "%20"));
|
||||||
if (!parsed.host.match(/play\.google\.com$/)) {
|
if (!parsed.host.match(/play\.google\.com$/)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var path = parsed.path;
|
const path = parsed.path;
|
||||||
var hash = parsed.hash;
|
const hash = parsed.hash;
|
||||||
|
|
||||||
if (hash) {
|
if (hash) {
|
||||||
var parts = hash.split("/");
|
const parts = hash.split("/");
|
||||||
var id = parts[2];
|
const id = parts[2];
|
||||||
var artist = parts[3];
|
const artist = parts[3];
|
||||||
|
|
||||||
if (id.length > 0) {
|
if (id.length > 0) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -21,7 +20,7 @@ module.exports.match = function(url) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if(path) {
|
} else if(path) {
|
||||||
var matches = path.match(/\/music\/m\/([\w]+)/);
|
const matches = path.match(/\/music\/m\/([\w]+)/);
|
||||||
if (matches[1]) {
|
if (matches[1]) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
import {parse} from 'url';
|
import { parse } from 'url';
|
||||||
import querystring from 'querystring';
|
import querystring from 'querystring';
|
||||||
import request from 'superagent';
|
import request from 'superagent';
|
||||||
import 'superagent-bluebird-promise';
|
import 'superagent-bluebird-promise';
|
||||||
|
import { match as urlMatch } from './url';
|
||||||
|
|
||||||
module.exports.id = 'itunes';
|
export let id = 'itunes';
|
||||||
|
|
||||||
const apiRoot = 'https://itunes.apple.com';
|
const apiRoot = 'https://itunes.apple.com';
|
||||||
|
|
||||||
module.exports.match = require('./url').match;
|
export const match = urlMatch;
|
||||||
|
|
||||||
module.exports.parseUrl = function* (url) {
|
export function* parseUrl(url) {
|
||||||
let parsed = parse(url);
|
const parsed = parse(url);
|
||||||
let matches = parsed.path.match(/[\/]?([\/]?[a-z]{2}?)?[\/]+album[\/]+([^\/]+)[\/]+([^\?]+)/);
|
const matches = parsed.path.match(/[\/]?([\/]?[a-z]{2}?)?[\/]+album[\/]+([^\/]+)[\/]+([^\?]+)/);
|
||||||
let query = querystring.parse(parsed.query);
|
const query = querystring.parse(parsed.query);
|
||||||
|
|
||||||
if (matches) {
|
if (matches) {
|
||||||
let type = 'album';
|
let type = 'album';
|
||||||
|
@ -23,11 +24,11 @@ module.exports.parseUrl = function* (url) {
|
||||||
}
|
}
|
||||||
return yield module.exports.lookupId(id, type, matches[1] || 'us');
|
return yield module.exports.lookupId(id, type, matches[1] || 'us');
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject(new Error());
|
throw new Error();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.lookupId = function* (id, type, cc) {
|
export function* lookupId(id, type, cc) {
|
||||||
if (String(id).match(/^[a-z]{2}/)) {
|
if (String(id).match(/^[a-z]{2}/)) {
|
||||||
cc = id.substr(0, 2);
|
cc = id.substr(0, 2);
|
||||||
id = id.substr(2);
|
id = id.substr(2);
|
||||||
|
@ -38,13 +39,13 @@ module.exports.lookupId = function* (id, type, cc) {
|
||||||
path = '/' + cc + path;
|
path = '/' + cc + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = yield request.get(apiRoot + path);
|
const response = yield request.get(apiRoot + path);
|
||||||
let result = JSON.parse(response.text);
|
let result = JSON.parse(response.text);
|
||||||
|
|
||||||
if (!result.results || result.resultCount === 0 || !result.results[0].collectionId) {
|
if (!result.results || result.resultCount === 0 || !result.results[0].collectionId) {
|
||||||
let error = new Error('Not Found');
|
const error = new Error('Not Found');
|
||||||
error.status = 404;
|
error.status = 404;
|
||||||
return Promise.reject(error);
|
throw error;
|
||||||
} else {
|
} else {
|
||||||
result = result.results[0];
|
result = result.results[0];
|
||||||
|
|
||||||
|
@ -70,13 +71,13 @@ module.exports.lookupId = function* (id, type, cc) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve(item);
|
return item;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.search = function* (data) {
|
export function* search(data) {
|
||||||
let query, album, entity;
|
let query, album, entity;
|
||||||
let type = data.type;
|
const type = data.type;
|
||||||
|
|
||||||
if (type === 'album') {
|
if (type === 'album') {
|
||||||
query = data.artist.name + ' ' + data.name;
|
query = data.artist.name + ' ' + data.name;
|
||||||
|
@ -88,27 +89,27 @@ module.exports.search = function* (data) {
|
||||||
entity = 'musicTrack';
|
entity = 'musicTrack';
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = '/search?term=' + encodeURIComponent(query) + '&media=music&entity=' + entity;
|
const path = '/search?term=' + encodeURIComponent(query) + '&media=music&entity=' + entity;
|
||||||
let response = yield request.get(apiRoot + path);
|
const response = yield request.get(apiRoot + path);
|
||||||
let result = JSON.parse(response.text);
|
let result = JSON.parse(response.text);
|
||||||
|
|
||||||
if (!result.results[0]) {
|
if (!result.results[0]) {
|
||||||
let matches = album.match(/^[^\(\[]+/);
|
const matches = album.match(/^[^\(\[]+/);
|
||||||
if (matches && matches[0] && matches[0] !== album) {
|
if (matches && matches[0] && matches[0] !== album) {
|
||||||
let cleanedData = JSON.parse(JSON.stringify(data));
|
const cleanedData = JSON.parse(JSON.stringify(data));
|
||||||
if (type === 'album') {
|
if (type === 'album') {
|
||||||
cleanedData.name = matches[0].trim();
|
cleanedData.name = matches[0].trim();
|
||||||
} else if (type === 'track') {
|
} else if (type === 'track') {
|
||||||
cleanedData.album.name = matches[0].trim();
|
cleanedData.album.name = matches[0].trim();
|
||||||
}
|
}
|
||||||
return yield module.exports.search(cleanedData);
|
return yield search(cleanedData);
|
||||||
} else {
|
} else {
|
||||||
return Promise.resolve({service: 'itunes'});
|
return {service: 'itunes'};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = result.results[0];
|
result = result.results[0];
|
||||||
|
|
||||||
let item = {
|
const item = {
|
||||||
service: 'itunes',
|
service: 'itunes',
|
||||||
type: type,
|
type: type,
|
||||||
id: 'us' + result.collectionId,
|
id: 'us' + result.collectionId,
|
||||||
|
@ -129,6 +130,6 @@ module.exports.search = function* (data) {
|
||||||
name: result.collectionName
|
name: result.collectionName
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return Promise.resolve(item);
|
return item;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
var parse = require('url').parse;
|
import querystring from 'querystring';
|
||||||
var querystring = require('querystring');
|
|
||||||
|
|
||||||
module.exports.match = function(url, type) {
|
export function* match(url, type) {
|
||||||
var parsed = parse(url);
|
const parsed = parse(url);
|
||||||
|
|
||||||
if (!parsed.host.match(/itunes.apple\.com$/)) {
|
if (!parsed.host.match(/itunes.apple\.com$/)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var matches = parsed.path.match(/[\/]?([\/]?[a-z]{2}?)?[\/]+album[\/]+([^\/]+)[\/]+([^\?]+)/);
|
const matches = parsed.path.match(/[\/]?([\/]?[a-z]{2}?)?[\/]+album[\/]+([^\/]+)[\/]+([^\?]+)/);
|
||||||
var query = querystring.parse(parsed.query);
|
const query = querystring.parse(parsed.query);
|
||||||
|
|
||||||
return !!matches[3];
|
return !!matches[3];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { parse } from 'url';
|
import { parse } from 'url';
|
||||||
|
|
||||||
export function match(url) {
|
export function* match(url) {
|
||||||
var parsed = parse(url);
|
const parsed = parse(url);
|
||||||
if (!parsed.host.match(/rd\.io$/) && !parsed.host.match(/rdio\.com$/)) {
|
if (!parsed.host.match(/rd\.io$/) && !parsed.host.match(/rdio\.com$/)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var regular = parsed.path.match(/[\/]*artist[\/]*([^\/]*)[\/]*album[\/]*([^\/]*)[\/]*([track]*)?[\/]*([^\/]*)/);
|
const regular = parsed.path.match(/[\/]*artist[\/]*([^\/]*)[\/]*album[\/]*([^\/]*)[\/]*([track]*)?[\/]*([^\/]*)/);
|
||||||
var short = parsed.path.match(/[\/]*x[\/]*([^\/]*)/);
|
const short = parsed.path.match(/[\/]*x[\/]*([^\/]*)/);
|
||||||
return (regular && !!regular[2]) || (short && !!short[1]);
|
return (regular && !!regular[2]) || (short && !!short[1]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,70 +1,70 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
var parse = require('url').parse;
|
import bluebird from 'bluebird';
|
||||||
var Promise = require('bluebird');
|
import spotifyCB from 'spotify';
|
||||||
var spotify = Promise.promisifyAll(require('spotify'));
|
const spotify = bluebird.promisifyAll(spotifyCB);
|
||||||
|
import { match as urlMatch } from './url';
|
||||||
|
|
||||||
module.exports.id = "spotify";
|
export let id = "spotify";
|
||||||
|
|
||||||
module.exports.match = require('./url').match;
|
export const match = urlMatch;
|
||||||
|
|
||||||
module.exports.parseUrl = function(url) {
|
export function* parseUrl(url) {
|
||||||
var matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
|
var matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
|
||||||
|
|
||||||
if (matches && matches[2]) {
|
if (matches && matches[2]) {
|
||||||
return module.exports.lookupId(matches[2], matches[1]);
|
return yield lookupId(matches[2], matches[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.lookupId = function(id, type) {
|
export function* lookupId(id, type) {
|
||||||
return spotify.lookupAsync({id: id, type: type}).then(function(data) {
|
const data = yield spotify.lookupAsync({id: id, type: type});
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
var error = new Error("Not Found");
|
var error = new Error("Not Found");
|
||||||
error.status = 404;
|
error.status = 404;
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
var artist = data.artists[0];
|
var artist = data.artists[0];
|
||||||
|
|
||||||
if (type == "album") {
|
if (type == "album") {
|
||||||
return {
|
return {
|
||||||
service: "spotify",
|
service: "spotify",
|
||||||
type: type,
|
type: type,
|
||||||
id: data.id,
|
id: data.id,
|
||||||
name: data.name,
|
name: data.name,
|
||||||
streamUrl: "https://play.spotify.com/" + type + "/" + data.id,
|
streamUrl: "https://play.spotify.com/" + type + "/" + data.id,
|
||||||
purchaseUrl: null,
|
purchaseUrl: null,
|
||||||
artwork: {
|
artwork: {
|
||||||
small: data.images[1].url.replace("http:", "https:"),
|
small: data.images[1].url.replace("http:", "https:"),
|
||||||
large: data.images[0].url.replace("http:", "https:"),
|
large: data.images[0].url.replace("http:", "https:"),
|
||||||
},
|
},
|
||||||
artist: {
|
artist: {
|
||||||
name: artist.name
|
name: artist.name
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (type == "track") {
|
} else if (type == "track") {
|
||||||
return {
|
return {
|
||||||
service: "spotify",
|
service: "spotify",
|
||||||
type: type,
|
type: type,
|
||||||
id: data.id,
|
id: data.id,
|
||||||
name: data.name,
|
name: data.name,
|
||||||
streamUrl: "https://play.spotify.com/" + type + "/" + data.id,
|
streamUrl: "https://play.spotify.com/" + type + "/" + data.id,
|
||||||
purchaseUrl: null,
|
purchaseUrl: null,
|
||||||
artwork: {
|
artwork: {
|
||||||
small: data.album.images[1].url.replace("http:", "https:"),
|
small: data.album.images[1].url.replace("http:", "https:"),
|
||||||
large: data.album.images[0].url.replace("http:", "https:"),
|
large: data.album.images[0].url.replace("http:", "https:"),
|
||||||
},
|
},
|
||||||
artist: {
|
artist: {
|
||||||
name: artist.name
|
name: artist.name
|
||||||
},
|
},
|
||||||
album: {
|
album: {
|
||||||
name: data.album.name
|
name: data.album.name
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.search = function(data) {
|
export function* search(data) {
|
||||||
var cleanParam = function(str) {
|
var cleanParam = function(str) {
|
||||||
var chopChars = ['&', '[', '('];
|
var chopChars = ['&', '[', '('];
|
||||||
chopChars.forEach(function(chr) {
|
chopChars.forEach(function(chr) {
|
||||||
|
@ -85,28 +85,26 @@ module.exports.search = function(data) {
|
||||||
album = data.album.name;
|
album = data.album.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return spotify.searchAsync({query: query, type: type}).then(function(results) {
|
const results = yield spotify.searchAsync({query: query, type: type});
|
||||||
if (!results[type + "s"].items[0]) {
|
if (!results[type + "s"].items[0]) {
|
||||||
return {service: "spotify"};
|
return {service: "spotify"};
|
||||||
} else {
|
} else {
|
||||||
var found;
|
let found;
|
||||||
var choppedAlbum = data.type == "album" ? cleanParam(data.name) : cleanParam(data.album.name);
|
const choppedAlbum = data.type == "album" ? cleanParam(data.name) : cleanParam(data.album.name);
|
||||||
if (!choppedAlbum.length) {
|
if (!choppedAlbum.length) {
|
||||||
return module.exports.lookupId(results[type + "s"].items[0].id, type);
|
return yield lookupId(results[type + "s"].items[0].id, type);
|
||||||
}
|
|
||||||
|
|
||||||
results[type + "s"].items.forEach(function(item) {
|
|
||||||
var albumName = data.type == "album" ? item.name : item.album.name;
|
|
||||||
var matches = albumName.match(/^[^\(\[]+/);
|
|
||||||
if(choppedAlbum.indexOf(matches[0]) >= 0) {
|
|
||||||
found = item;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!found) {
|
|
||||||
return {service: "spotify"};
|
|
||||||
}
|
|
||||||
return module.exports.lookupId(results[type + "s"].items[0].id, type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
results[type + "s"].items.forEach(function(item) {
|
||||||
|
const albumName = data.type == "album" ? item.name : item.album.name;
|
||||||
|
const matches = albumName.match(/^[^\(\[]+/);
|
||||||
|
if(choppedAlbum.indexOf(matches[0]) >= 0) {
|
||||||
|
found = item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!found) {
|
||||||
|
return {service: "spotify"};
|
||||||
|
}
|
||||||
|
return yield lookupId(results[type + "s"].items[0].id, type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
var parse = require('url').parse;
|
|
||||||
|
|
||||||
module.exports.match = function(url, type) {
|
export function* match(url, type) {
|
||||||
var parsed = parse(url);
|
const parsed = parse(url);
|
||||||
if (!parsed.host.match(/spotify\.com$/)) {
|
if (!parsed.host.match(/spotify\.com$/)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
|
const matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
|
||||||
return matches && !!matches[2];
|
return matches && !!matches[2];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,40 +1,45 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
var parse = require('url').parse;
|
import querystring from 'querystring';
|
||||||
var Promise = require('bluebird');
|
import request from 'superagent';
|
||||||
var request = require('superagent');
|
import 'superagent-bluebird-promise';
|
||||||
require('superagent-bluebird-promise');
|
import { match as urlMatch } from './url';
|
||||||
|
|
||||||
module.exports.id = "xbox";
|
export let id = "xbox";
|
||||||
|
|
||||||
if (!process.env.XBOX_CLIENT_ID || !process.env.XBOX_CLIENT_SECRET) {
|
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.");
|
console.warn("XBOX_CLIENT_ID and XBOX_CLIENT_SECRET environment variables not found, deactivating Xbox Music.");
|
||||||
} else {
|
}
|
||||||
|
|
||||||
var credentials = {
|
const credentials = {
|
||||||
clientId: process.env.XBOX_CLIENT_ID,
|
clientId: process.env.XBOX_CLIENT_ID,
|
||||||
clientSecret: process.env.XBOX_CLIENT_SECRET
|
clientSecret: process.env.XBOX_CLIENT_SECRET
|
||||||
};
|
};
|
||||||
|
|
||||||
var apiRoot = "https://music.xboxlive.com/1/content";
|
const apiRoot = "https://music.xboxlive.com/1/content";
|
||||||
|
|
||||||
var getAccessToken = function() {
|
function* getAccessToken() {
|
||||||
var authUrl = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
|
const authUrl = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
|
||||||
var scope = "http://music.xboxlive.com";
|
const scope = "http://music.xboxlive.com";
|
||||||
var grantType = "client_credentials";
|
const grantType = "client_credentials";
|
||||||
|
|
||||||
var data = {client_id: credentials.clientId, client_secret: credentials.clientSecret, scope: scope, grant_type: grantType};
|
const data = {
|
||||||
return request.post(authUrl).send(data).set('Content-type', 'application/x-www-form-urlencoded').promise().then(function(res) {
|
client_id: credentials.clientId,
|
||||||
return res.body.access_token;
|
client_secret: credentials.clientSecret,
|
||||||
});
|
scope: scope,
|
||||||
|
grant_type: grantType
|
||||||
|
};
|
||||||
|
const result = yield request.post(authUrl).send(data).set('Content-type', 'application/x-www-form-urlencoded').promise();
|
||||||
|
return result.body.access_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
var formatResponse = function(res) {
|
function formatResponse(res) {
|
||||||
|
let result;
|
||||||
if (res.body.Tracks) {
|
if (res.body.Tracks) {
|
||||||
var result = res.body.Tracks.Items[0];
|
result = res.body.Tracks.Items[0];
|
||||||
} else {
|
} else {
|
||||||
var result = res.body.Albums.Items[0];
|
result = res.body.Albums.Items[0];
|
||||||
}
|
}
|
||||||
var item = {
|
let item = {
|
||||||
service: "xbox",
|
service: "xbox",
|
||||||
type: res.body.Tracks ? "track" : "album",
|
type: res.body.Tracks ? "track" : "album",
|
||||||
id: result.Id,
|
id: result.Id,
|
||||||
|
@ -55,37 +60,33 @@ var formatResponse = function(res) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.match = require('./url').match;
|
export const match = urlMatch;
|
||||||
|
|
||||||
module.exports.parseUrl = function(url) {
|
export function* parseUrl(url) {
|
||||||
var parsed = parse(url);
|
const parsed = parse(url);
|
||||||
var parts = parsed.path.split("/");
|
const parts = parsed.path.split("/");
|
||||||
var type = parts[1];
|
const type = parts[1];
|
||||||
var idMatches = parts[4].match(/[\w\-]+/);
|
const idMatches = parts[4].match(/[\w\-]+/);
|
||||||
var id = idMatches[0];
|
const id = idMatches[0];
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return module.exports.lookupId("music." + id, type);
|
return yield lookupId("music." + id, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.lookupId = function(id, type) {
|
export function* lookupId(id, type) {
|
||||||
return getAccessToken().then(function(access_token){
|
const access_token = yield getAccessToken();
|
||||||
var path = "/" + id + "/lookup";
|
const path = "/" + id + "/lookup";
|
||||||
return request.get(apiRoot + path).set("Authorization", "Bearer " + access_token).promise().then(function(res) {
|
const result = yield request.get(apiRoot + path).set("Authorization", "Bearer " + access_token).promise();
|
||||||
return formatResponse(res);
|
return result ? formatResponse(result) : {service: "xbox"};
|
||||||
}, function(res) {
|
|
||||||
return {service: "xbox"};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.search = function(data) {
|
export function* search(data) {
|
||||||
var cleanParam = function(str) {
|
var cleanParam = function(str) {
|
||||||
return str.replace(/[\:\?\&]+/, "");
|
return str.replace(/[\:\?\&]+/, "");
|
||||||
}
|
}
|
||||||
var query, album;
|
let query, album;
|
||||||
var type = data.type;
|
const type = data.type;
|
||||||
|
|
||||||
if (type == "album") {
|
if (type == "album") {
|
||||||
query = cleanParam(data.artist.name.substring(0, data.artist.name.indexOf('&'))) + " " + cleanParam(data.name);
|
query = cleanParam(data.artist.name.substring(0, data.artist.name.indexOf('&'))) + " " + cleanParam(data.name);
|
||||||
|
@ -94,14 +95,8 @@ module.exports.search = function(data) {
|
||||||
query = cleanParam(data.artist.name.substring(0, data.artist.name.indexOf('&'))) + " " + cleanParam(data.name);
|
query = cleanParam(data.artist.name.substring(0, data.artist.name.indexOf('&'))) + " " + cleanParam(data.name);
|
||||||
album = data.album.name
|
album = data.album.name
|
||||||
}
|
}
|
||||||
return getAccessToken().then(function(access_token){
|
const access_token = yield getAccessToken();
|
||||||
var path = "/music/search?q=" + encodeURIComponent(query) + "&filters=" + type + "s";
|
const path = "/music/search?q=" + encodeURIComponent(query) + "&filters=" + type + "s";
|
||||||
return request.get(apiRoot + path).set("Authorization", "Bearer " + access_token).promise().then(function(res) {
|
const result = yield request.get(apiRoot + path).set("Authorization", "Bearer " + access_token).promise()
|
||||||
return formatResponse(res);
|
return result ? formatResponse(result) : {service: "xbox"};
|
||||||
}, function(res) {
|
|
||||||
return {service: "xbox"};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
var parse = require('url').parse;
|
|
||||||
|
|
||||||
module.exports.match = function(url, type) {
|
|
||||||
var parsed = parse(url);
|
|
||||||
|
|
||||||
|
export function* match(url, type) {
|
||||||
|
const parsed = parse(url);
|
||||||
if (!parsed.host.match(/music.xbox.com$/)) {
|
if (!parsed.host.match(/music.xbox.com$/)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var parts = parsed.path.split("/");
|
const parts = parsed.path.split("/");
|
||||||
|
|
||||||
return (parts[1] == "album" || parts[1] == "track") && parts[4];
|
return (parts[1] == "album" || parts[1] == "track") && parts[4];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
var parse = require('url').parse;
|
import querystring from 'querystring';
|
||||||
var Promise = require('bluebird');
|
import request from 'superagent';
|
||||||
var request = require('superagent');
|
import 'superagent-bluebird-promise';
|
||||||
require('superagent-bluebird-promise');
|
|
||||||
|
|
||||||
var credentials = {
|
const credentials = {
|
||||||
key: process.env.YOUTUBE_KEY,
|
key: process.env.YOUTUBE_KEY,
|
||||||
};
|
};
|
||||||
|
|
||||||
var apiRoot = "https://www.googleapis.com/freebase/v1/topic";
|
const apiRoot = "https://www.googleapis.com/freebase/v1/topic";
|
||||||
|
|
||||||
module.exports.get = function(topic) {
|
export function* get(topic) {
|
||||||
return request.get(apiRoot + topic + "?key=" + credentials.key).promise().then(function(res) {
|
const result = yield request.get(apiRoot + topic + "?key=" + credentials.key).promise();
|
||||||
return res.body;
|
return result.body;
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports.get("/m/0dwcrm_");
|
|
|
@ -1,139 +1,124 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
var parse = require('url').parse;
|
import querystring from 'querystring';
|
||||||
var freebase = require('./freebase');
|
import moment from 'moment';
|
||||||
var querystring = require('querystring');
|
import request from 'superagent';
|
||||||
var moment = require('moment');
|
import 'superagent-bluebird-promise';
|
||||||
var Promise = require('bluebird');
|
import { match as urlMatch } from './url';
|
||||||
var request = require('superagent');
|
import freebase from './freebase';
|
||||||
require('superagent-bluebird-promise');
|
|
||||||
|
|
||||||
module.exports.id = "youtube";
|
module.exports.id = 'youtube';
|
||||||
|
|
||||||
if (!process.env.YOUTUBE_KEY) {
|
if (!process.env.YOUTUBE_KEY) {
|
||||||
console.warn("YOUTUBE_KEY environment variable not found, deactivating Youtube.");
|
console.warn('YOUTUBE_KEY environment variable not found, deactivating Youtube.');
|
||||||
} else {
|
}
|
||||||
|
|
||||||
var credentials = {
|
const credentials = {
|
||||||
key: process.env.YOUTUBE_KEY,
|
key: process.env.YOUTUBE_KEY,
|
||||||
};
|
};
|
||||||
|
|
||||||
var apiRoot = "https://www.googleapis.com/youtube/v3";
|
const apiRoot = 'https://www.googleapis.com/youtube/v3';
|
||||||
|
|
||||||
module.exports.match = require('./url').match;
|
export const match = urlMatch;
|
||||||
|
|
||||||
|
export function parseUrl(url) {
|
||||||
|
const parsed = parse(url);
|
||||||
|
const query = querystring.parse(parsed.query);
|
||||||
|
let id = query.v;
|
||||||
|
|
||||||
module.exports.parseUrl = function(url) {
|
|
||||||
var parsed = parse(url);
|
|
||||||
var query = querystring.parse(parsed.query);
|
|
||||||
var id = query.v;
|
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
id = parsed.path.substr(1);
|
id = parsed.path.substr(1);
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return module.exports.lookupId(id, "track");
|
return lookupId(id, 'track');
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.lookupId = function(id, type) {
|
export function* lookupId(id, type) {
|
||||||
|
|
||||||
var path = "/videos?part=snippet%2CtopicDetails%2CcontentDetails&id=" + id + "&key=" + credentials.key;
|
const path = '/videos?part=snippet%2CtopicDetails%2CcontentDetails&id=' + id + '&key=' + credentials.key;
|
||||||
|
|
||||||
return request.get(apiRoot + path).promise().then(function(res) {
|
const result = yield request.get(apiRoot + path).promise();
|
||||||
var item = res.body.items[0];
|
const item = res.body.items[0];
|
||||||
if (item.topicDetails.topicIds) {
|
if (!item.topicDetails.topicIds) {
|
||||||
var promises = [];
|
return {service: 'youtube'};
|
||||||
var match = {
|
}
|
||||||
id: id,
|
|
||||||
service: "youtube",
|
const promises = [];
|
||||||
name: item.snippet.title,
|
const match = {
|
||||||
type: "track",
|
id: id,
|
||||||
album: {name: ""},
|
service: 'youtube',
|
||||||
streamUrl: "https://youtu.be/" + id,
|
name: item.snippet.title,
|
||||||
purchaseUrl: null,
|
type: 'track',
|
||||||
artwork: {
|
album: {name: ''},
|
||||||
small: item.snippet.thumbnails.medium.url,
|
streamUrl: 'https://youtu.be/' + id,
|
||||||
large: item.snippet.thumbnails.high.url,
|
purchaseUrl: null,
|
||||||
}
|
artwork: {
|
||||||
};
|
small: item.snippet.thumbnails.medium.url,
|
||||||
item.topicDetails.topicIds.forEach(function(topicId) {
|
large: item.snippet.thumbnails.high.url,
|
||||||
promises.push(freebase.get(topicId).then(function(topic) {
|
|
||||||
if (topic.property["/type/object/type"].values.some(function(value) {
|
|
||||||
return value.text == "Musical Artist";
|
|
||||||
})) {
|
|
||||||
match.artist = {name: topic.property["/type/object/name"].values[0].text};
|
|
||||||
} else if (topic.property["/type/object/type"].values.some(function(value) {
|
|
||||||
return value.text == "Musical Recording";
|
|
||||||
})) {
|
|
||||||
//if (moment.duration(item.contentDetails.duration).asSeconds() < 900) {
|
|
||||||
match.name = topic.property["/type/object/name"].values[0].text;
|
|
||||||
if (topic.property["/music/recording/releases"]) {
|
|
||||||
match.type = "album";
|
|
||||||
match.album.name = topic.property["/music/recording/releases"].values[0].text;
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
} else if (topic.property["/type/object/type"].values.some(function(value) {
|
|
||||||
return value.text == "Musical Album";
|
|
||||||
})) {
|
|
||||||
match.name = topic.property["/type/object/name"].values[0].text;
|
|
||||||
match.type = "album";
|
|
||||||
}
|
|
||||||
}, function(err) {
|
|
||||||
console.log(err)
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
return Promise.all(promises).then(function() {
|
|
||||||
return match;
|
|
||||||
}, function(err) {
|
|
||||||
console.log(err)
|
|
||||||
return {service: "youtube"};
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return {service: "youtube"};
|
|
||||||
}
|
}
|
||||||
}, function(err) {
|
};
|
||||||
console.log(err)
|
|
||||||
return {service: "youtube"};
|
for (let topic of yield freebase.get(topicId)) {
|
||||||
});
|
const musicalArtist = topic.property['/type/object/type'].values.some((value) => {
|
||||||
|
return value.text == 'Musical Artist';
|
||||||
|
});
|
||||||
|
|
||||||
|
const musicalRecording = topic.property['/type/object/type'].values.some(function(value) {
|
||||||
|
return value.text == 'Musical Recording';
|
||||||
|
});
|
||||||
|
|
||||||
|
const musicalAlbum = topic.property['/type/object/type'].values.some(function(value) {
|
||||||
|
return value.text == 'Musical Album';
|
||||||
|
})
|
||||||
|
|
||||||
|
if (musicalArtist) {
|
||||||
|
match.artist = {name: topic.property['/type/object/name'].values[0].text};
|
||||||
|
} else if (musicalRecording) {
|
||||||
|
match.name = topic.property['/type/object/name'].values[0].text;
|
||||||
|
if (topic.property['/music/recording/releases']) {
|
||||||
|
match.type = 'album';
|
||||||
|
match.album.name = topic.property['/music/recording/releases'].values[0].text;
|
||||||
|
}
|
||||||
|
} else if (musicalAlbum) {
|
||||||
|
match.name = topic.property['/type/object/name'].values[0].text;
|
||||||
|
match.type = 'album';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.search = function(data) {
|
export function* search(data) {
|
||||||
var query, album;
|
let query, album;
|
||||||
var type = data.type;
|
const type = data.type;
|
||||||
|
|
||||||
if (type == "album") {
|
if (type == 'album') {
|
||||||
query = data.artist.name + " " + data.name;
|
query = data.artist.name + ' ' + data.name;
|
||||||
album = data.name;
|
album = data.name;
|
||||||
} else if (type == "track") {
|
} else if (type == 'track') {
|
||||||
query = data.artist.name + " " + data.name;
|
query = data.artist.name + ' ' + data.name;
|
||||||
album = data.album.name
|
album = data.album.name
|
||||||
}
|
}
|
||||||
|
|
||||||
var path = "/search?part=snippet&q=" + encodeURIComponent(query) + "&type=video&videoCaption=any&videoCategoryId=10&key=" + credentials.key;
|
const path = '/search?part=snippet&q=' + encodeURIComponent(query) + '&type=video&videoCaption=any&videoCategoryId=10&key=' + credentials.key;
|
||||||
|
|
||||||
return request.get(apiRoot + path).promise().then(function(res) {
|
const result = yield request.get(apiRoot + path).promise();
|
||||||
var result = res.body.items[0];
|
const item = result.body.items[0];
|
||||||
|
|
||||||
if (!result) {
|
if (!item) {
|
||||||
return {service:"youtube", type: "video"};
|
return {service:'youtube', type: 'video'};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
service: "youtube",
|
service: 'youtube',
|
||||||
type: "video",
|
type: 'video',
|
||||||
id: result.id.videoId,
|
id: item.id.videoId,
|
||||||
name: result.snippet.title,
|
name: item.snippet.title,
|
||||||
streamUrl: "https://www.youtube.com/watch?v=" + result.id.videoId,
|
streamUrl: 'https://www.youtube.com/watch?v=' + item.id.videoId,
|
||||||
purchaseUrl: null,
|
purchaseUrl: null,
|
||||||
artwork: {
|
artwork: {
|
||||||
small: result.snippet.thumbnails.medium.url,
|
small: item.snippet.thumbnails.medium.url,
|
||||||
large: result.snippet.thumbnails.high.url,
|
large: item.snippet.thumbnails.high.url,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, function(err) {
|
|
||||||
console.log(err)
|
|
||||||
return {service: "youtube"};
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
"use strict";
|
import { parse } from 'url';
|
||||||
var parse = require("url").parse;
|
import querystring from 'querystring';
|
||||||
var querystring = require('querystring');
|
|
||||||
|
|
||||||
module.exports.match = function(url, type) {
|
export function* match(url, type) {
|
||||||
var parsed = parse(url);
|
const parsed = parse(url);
|
||||||
|
|
||||||
if (parsed.host.match(/youtu\.be$/)) {
|
if (parsed.host.match(/youtu\.be$/)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (parsed.host.match(/youtube\.com$/)) {
|
} else if (parsed.host.match(/youtube\.com$/)) {
|
||||||
var query = querystring.parse(parsed.query);
|
const query = querystring.parse(parsed.query);
|
||||||
return !!query.v;
|
return !!query.v;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
12
package.json
12
package.json
|
@ -1,26 +1,24 @@
|
||||||
{
|
{
|
||||||
"name": "match.audio",
|
"name": "match.audio",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"repository": "https://github.com/kudos/match.audio",
|
||||||
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "babel -d public/views views",
|
"build": "babel -d public/views views",
|
||||||
"cover": "istanbul cover _mocha -- --require babel/register --require co-mocha test/**/*.js",
|
"cover": "istanbul cover _mocha -- --require babel/register --require co-mocha test/**/*.js",
|
||||||
"start": "babel-node app.js",
|
"start": "babel-node app.js",
|
||||||
"postinstall": "npm run build",
|
|
||||||
"test": "mocha --require co-mocha --compilers js:babel/register test/**/*.js --timeout=10000",
|
"test": "mocha --require co-mocha --compilers js:babel/register test/**/*.js --timeout=10000",
|
||||||
"watch": "parallelshell \"npm run watch-js\" \"npm run watch-server\"",
|
"watch": "parallelshell \"npm run watch-js\" \"npm run watch-server\"",
|
||||||
"watch-js": "babel --modules system -wd public/views views",
|
"watch-js": "babel --modules system -wd public/views views",
|
||||||
"watch-server": "nodemon -x \"babel-node\" -e js,jsx -i public/ app.js"
|
"watch-server": "nodemon -x \"babel-node\" -e js,jsx -i public/ app.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"iojs": "^2.5.0",
|
"iojs": "^3.1.0",
|
||||||
"npm": "^3.3.0"
|
"npm": "^3.3.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel": "~5.8.3",
|
"babel": "~5.8.3",
|
||||||
"babelify": "~6.1.3",
|
|
||||||
"bluebird": "~2.9.34",
|
"bluebird": "~2.9.34",
|
||||||
"browserify": "~11.0.0",
|
|
||||||
"co": "~4.6.0",
|
"co": "~4.6.0",
|
||||||
"debug": "~2.2.0",
|
"debug": "~2.2.0",
|
||||||
"jspm": "~0.16.0",
|
"jspm": "~0.16.0",
|
||||||
|
@ -39,7 +37,6 @@
|
||||||
"react": "~0.13.3",
|
"react": "~0.13.3",
|
||||||
"react-google-analytics": "~0.2.0",
|
"react-google-analytics": "~0.2.0",
|
||||||
"react-router": "~0.13.3",
|
"react-router": "~0.13.3",
|
||||||
"reactify": "~1.1.1",
|
|
||||||
"spotify": "~0.3.0",
|
"spotify": "~0.3.0",
|
||||||
"superagent": "~1.3.0",
|
"superagent": "~1.3.0",
|
||||||
"superagent-bluebird-promise": "~2.0.2"
|
"superagent-bluebird-promise": "~2.0.2"
|
||||||
|
@ -52,8 +49,7 @@
|
||||||
"mocha": "~2.2.5",
|
"mocha": "~2.2.5",
|
||||||
"nodemon": "~1.4.1",
|
"nodemon": "~1.4.1",
|
||||||
"parallelshell": "~2.0.0",
|
"parallelshell": "~2.0.0",
|
||||||
"should": "~7.0.1",
|
"should": "~7.0.1"
|
||||||
"spdy": "~2.0.4"
|
|
||||||
},
|
},
|
||||||
"jspm": {
|
"jspm": {
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import createHandler from '../lib/react-handler';
|
import createHandler from '../lib/react-handler';
|
||||||
import {routes} from '../views/app';
|
import { routes } from '../views/app';
|
||||||
|
|
||||||
module.exports = function* () {
|
export default function* () {
|
||||||
let recents = [];
|
const recents = [];
|
||||||
let docs = yield this.db.matches.find().sort({'created_at': -1}).limit(6).toArray();
|
const docs = yield this.db.matches.find().sort({'created_at': -1}).limit(6).toArray();
|
||||||
docs.forEach(function(doc) {
|
docs.forEach(function(doc) {
|
||||||
let shares = Object.keys(doc.services).map(function (key) {return doc.services[key]; });
|
let shares = Object.keys(doc.services).map(function (key) {return doc.services[key]; });
|
||||||
shares.some(function(item) {
|
shares.some(function(item) {
|
||||||
|
@ -17,9 +15,9 @@ module.exports = function* () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let Handler = yield createHandler(routes, this.request.url);
|
const Handler = yield createHandler(routes, this.request.url);
|
||||||
|
|
||||||
let App = React.createFactory(Handler);
|
const App = React.createFactory(Handler);
|
||||||
let content = React.renderToString(new App({recents: recents}));
|
let content = React.renderToString(new App({recents: recents}));
|
||||||
|
|
||||||
content = content.replace('</body></html>', '<script>var recents = ' + JSON.stringify(recents) + '</script></body></html>');
|
content = content.replace('</body></html>', '<script>var recents = ' + JSON.stringify(recents) + '</script></body></html>');
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import {parse} from 'url';
|
import { parse } from 'url';
|
||||||
import request from 'superagent';
|
import request from 'superagent';
|
||||||
|
|
||||||
module.exports = function* (next) {
|
export default function* (next) {
|
||||||
let url = 'http://' + this.request.url.substr(8);
|
const url = 'http://' + this.request.url.substr(8);
|
||||||
let parsed = parse(url);
|
const parsed = parse(url);
|
||||||
if (parsed.host.match(/mzstatic\.com/)) {
|
if (parsed.host.match(/mzstatic\.com/)) {
|
||||||
let proxyResponse = yield request.get(url);
|
const proxyResponse = yield request.get(url);
|
||||||
this.set(proxyResponse.headers);
|
this.set(proxyResponse.headers);
|
||||||
this.body = proxyResponse.body;
|
this.body = proxyResponse.body;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import {parse} from 'url';
|
import { parse } from 'url';
|
||||||
import co from 'co';
|
import co from 'co';
|
||||||
import lookup from '../lib/lookup';
|
import lookup from '../lib/lookup';
|
||||||
import services from '../lib/services';
|
import services from '../lib/services';
|
||||||
|
|
||||||
module.exports = function* () {
|
module.exports = function* () {
|
||||||
let url = parse(this.request.body.url);
|
const url = parse(this.request.body.url);
|
||||||
this.assert(url.host, 400, {error: {message: 'You need to submit a url.'}});
|
this.assert(url.host, 400, {error: {message: 'You need to submit a url.'}});
|
||||||
|
|
||||||
let item = yield lookup(this.request.body.url);
|
const item = yield lookup(this.request.body.url);
|
||||||
|
|
||||||
this.assert(item, 400, {error: {message: 'No supported music found at that link :('}});
|
this.assert(item, 400, {error: {message: 'No supported music found at that link :('}});
|
||||||
|
|
||||||
item.matched_at = new Date(); // eslint-disable-line camelcase
|
item.matched_at = new Date(); // eslint-disable-line camelcase
|
||||||
let matches = {};
|
const matches = {};
|
||||||
matches[item.service] = item;
|
matches[item.service] = item;
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,9 +32,9 @@ module.exports = function* () {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
matches[service.id] = {service: service.id};
|
matches[service.id] = {service: service.id};
|
||||||
let match = yield service.search(item);
|
const match = yield service.search(item);
|
||||||
match.matched_at = new Date(); // eslint-disable-line camelcase
|
match.matched_at = new Date(); // eslint-disable-line camelcase
|
||||||
let update = {};
|
const update = {};
|
||||||
update['services.' + match.service] = match;
|
update['services.' + match.service] = match;
|
||||||
yield this.db.matches.updateOne({_id: item.service + '$$' + item.id}, {'$set': update});
|
yield this.db.matches.updateOne({_id: item.service + '$$' + item.id}, {'$set': update});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import createHandler from '../lib/react-handler';
|
import createHandler from '../lib/react-handler';
|
||||||
import {routes} from '../views/app';
|
import { routes } from '../views/app';
|
||||||
import services from '../lib/services';
|
import services from '../lib/services';
|
||||||
|
|
||||||
let formatAndSort = function(matches, serviceId) {
|
function formatAndSort(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) {
|
matches.sort(function(a, b) {
|
||||||
return a.id && !b.id;
|
return a.id && !b.id;
|
||||||
|
@ -13,7 +13,7 @@ let formatAndSort = function(matches, serviceId) {
|
||||||
return matches;
|
return matches;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = function* (serviceId, type, itemId, format, next) {
|
export default function* (serviceId, type, itemId, format, next) {
|
||||||
let matchedService;
|
let matchedService;
|
||||||
services.some(function(service) {
|
services.some(function(service) {
|
||||||
matchedService = serviceId === service.id ? service : null;
|
matchedService = serviceId === service.id ? service : null;
|
||||||
|
@ -24,19 +24,18 @@ module.exports = function* (serviceId, type, itemId, format, next) {
|
||||||
return yield next;
|
return yield next;
|
||||||
}
|
}
|
||||||
|
|
||||||
let shares = [];
|
const doc = yield this.db.matches.findOne({_id: serviceId + '$$' + itemId});
|
||||||
let doc = yield this.db.matches.findOne({_id: serviceId + '$$' + itemId});
|
|
||||||
|
|
||||||
this.assert(doc, 404, 'Not Found');
|
this.assert(doc, 404, 'Not Found');
|
||||||
|
|
||||||
shares = formatAndSort(doc.services, serviceId);
|
const shares = formatAndSort(doc.services, serviceId);
|
||||||
|
|
||||||
if (format === 'json') {
|
if (format === 'json') {
|
||||||
this.body = {shares: shares};
|
this.body = {shares: shares};
|
||||||
} else {
|
} else {
|
||||||
let Handler = yield createHandler(routes, this.request.url);
|
const Handler = yield createHandler(routes, this.request.url);
|
||||||
|
|
||||||
let App = React.createFactory(Handler);
|
const App = React.createFactory(Handler);
|
||||||
let content = React.renderToString(new App({shares: shares}));
|
let content = React.renderToString(new App({shares: shares}));
|
||||||
|
|
||||||
content = content.replace('</body></html>', '<script>var shares = ' + JSON.stringify(shares) + '</script></body></html>');
|
content = content.replace('</body></html>', '<script>var shares = ' + JSON.stringify(shares) + '</script></body></html>');
|
||||||
|
|
|
@ -3,7 +3,7 @@ import lookup from '../lib/lookup';
|
||||||
|
|
||||||
describe('Search with url', function(){
|
describe('Search with url', function(){
|
||||||
it('should find album by url', function* (){
|
it('should find album by url', function* (){
|
||||||
let result = yield lookup('https://play.google.com/music/listen#/album/Bz6wrjczddcj5hurijsv6ohdoay');
|
const result = yield lookup('https://play.google.com/music/listen#/album/Bz6wrjczddcj5hurijsv6ohdoay');
|
||||||
result.name.should.equal('Phase 5');
|
result.name.should.equal('Phase 5');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
import 'should';
|
import 'should';
|
||||||
import deezer from '../../lib/services/deezer';
|
import * as deezer from '../../lib/services/deezer';
|
||||||
|
|
||||||
describe('Deezer', function(){
|
describe('Deezer', function(){
|
||||||
describe('lookupId', function(){
|
describe('lookupId', function(){
|
||||||
it('should find album by ID', function* (){
|
it('should find album by ID', function* (){
|
||||||
let result = yield deezer.lookupId('302127', 'album');
|
const result = yield deezer.lookupId('302127', 'album');
|
||||||
result.name.should.equal('Discovery');
|
result.name.should.equal('Discovery');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find track by ID', function* (){
|
it('should find track by ID', function* (){
|
||||||
let result = yield deezer.lookupId('3135554', 'track');
|
const result = yield deezer.lookupId('3135554', 'track');
|
||||||
result.name.should.equal('Aerodynamic');
|
result.name.should.equal('Aerodynamic');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('search', function(){
|
describe('search', function(){
|
||||||
it('should find album by search', function* (){
|
it('should find album by search', function* (){
|
||||||
let result = yield deezer.search({type: 'album', artist: {name: 'David Guetta'}, name: 'Listen (Deluxe)'});
|
const result = yield deezer.search({type: 'album', artist: {name: 'David Guetta'}, name: 'Listen (Deluxe)'});
|
||||||
result.name.should.startWith('Listen');
|
result.name.should.startWith('Listen');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find track by search', function* (){
|
it('should find track by search', function* (){
|
||||||
let result = yield deezer.search({type: 'track', artist: {name: 'Deftones'}, album: {name: 'Deftones'}, name: 'Hexagram'});
|
const result = yield deezer.search({type: 'track', artist: {name: 'Deftones'}, album: {name: 'Deftones'}, name: 'Hexagram'});
|
||||||
result.name.should.equal('Hexagram');
|
result.name.should.equal('Hexagram');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -29,12 +29,12 @@ describe('Deezer', function(){
|
||||||
describe('lookupUrl', function(){
|
describe('lookupUrl', function(){
|
||||||
describe('parseUrl', function(){
|
describe('parseUrl', function(){
|
||||||
it('should parse album url into ID', function* (){
|
it('should parse album url into ID', function* (){
|
||||||
let result = yield deezer.parseUrl('http://www.deezer.com/album/302127');
|
const result = yield deezer.parseUrl('http://www.deezer.com/album/302127');
|
||||||
result.id.should.equal(302127);
|
result.id.should.equal(302127);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse track url into ID', function* (){
|
it('should parse track url into ID', function* (){
|
||||||
let result = yield deezer.parseUrl('http://www.deezer.com/track/3135554');
|
const result = yield deezer.parseUrl('http://www.deezer.com/track/3135554');
|
||||||
result.id.should.equal(3135554);
|
result.id.should.equal(3135554);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,39 +1,39 @@
|
||||||
import 'should';
|
import 'should';
|
||||||
import google from '../../lib/services/google';
|
import * as google from '../../lib/services/google';
|
||||||
|
|
||||||
describe('Google Play Music', function(){
|
describe('Google Play Music', function(){
|
||||||
describe('lookupId', function(){
|
describe('lookupId', function(){
|
||||||
it('should find album by ID', function* (){
|
it('should find album by ID', function* (){
|
||||||
let result = yield google.lookupId('Byp6lvzimyf74wxi5634ul4tgam', 'album');
|
const result = yield google.lookupId('Byp6lvzimyf74wxi5634ul4tgam', 'album');
|
||||||
result.name.should.equal('Listen (Deluxe)');
|
result.name.should.equal('Listen (Deluxe)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find track by ID', function* (){
|
it('should find track by ID', function* (){
|
||||||
let result = yield google.lookupId('Tjosptub24g2dft37lforqnudpe', 'track');
|
const result = yield google.lookupId('Tjosptub24g2dft37lforqnudpe', 'track');
|
||||||
result.name.should.equal('Cherub Rock');
|
result.name.should.equal('Cherub Rock');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('search', function(){
|
describe('search', function(){
|
||||||
it('should find album by search', function* (){
|
it('should find album by search', function* (){
|
||||||
let result = yield google.search({type: 'album', artist: {name: 'Jamie xx'}, name: 'In Colour'});
|
const result = yield google.search({type: 'album', artist: {name: 'Jamie xx'}, name: 'In Colour'});
|
||||||
result.name.should.equal('In Colour');
|
result.name.should.equal('In Colour');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('lookupUrl', function(){
|
describe('lookupUrl', function(){
|
||||||
it('should parse regular url into album ID', function* (){
|
it('should parse regular url into album ID', function* (){
|
||||||
let result = yield google.parseUrl('https://play.google.com/music/listen#/album/Byp6lvzimyf74wxi5634ul4tgam/Jamie+xx/In+Colour');
|
const result = yield google.parseUrl('https://play.google.com/music/listen#/album/Byp6lvzimyf74wxi5634ul4tgam/Jamie+xx/In+Colour');
|
||||||
result.id.should.equal('Byp6lvzimyf74wxi5634ul4tgam');
|
result.id.should.equal('Byp6lvzimyf74wxi5634ul4tgam');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse url without ID into album ID', function* (){
|
it('should parse url without ID into album ID', function* (){
|
||||||
let result = yield google.parseUrl('https://play.google.com/music/listen#/album//Jamie+xx/In+Colour');
|
const result = yield google.parseUrl('https://play.google.com/music/listen#/album//Jamie+xx/In+Colour');
|
||||||
result.id.should.equal('Bvfmezcj3n42lo4xeuslpclbyrm');
|
result.id.should.equal('Bvfmezcj3n42lo4xeuslpclbyrm');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse share url into album ID', function* (){
|
it('should parse share url into album ID', function* (){
|
||||||
let result = yield google.parseUrl('https://play.google.com/music/m/Byp6lvzimyf74wxi5634ul4tgam');
|
const result = yield google.parseUrl('https://play.google.com/music/m/Byp6lvzimyf74wxi5634ul4tgam');
|
||||||
result.id.should.equal('Byp6lvzimyf74wxi5634ul4tgam');
|
result.id.should.equal('Byp6lvzimyf74wxi5634ul4tgam');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
import 'should';
|
import 'should';
|
||||||
import itunes from '../../lib/services/itunes';
|
import * as itunes from '../../lib/services/itunes';
|
||||||
|
|
||||||
describe('iTunes Music', function(){
|
describe('iTunes Music', function(){
|
||||||
describe('lookupId', function(){
|
describe('lookupId', function(){
|
||||||
it('should find album by ID', function* (){
|
it('should find album by ID', function* (){
|
||||||
let result = yield itunes.lookupId('id215206912', 'album');
|
const result = yield itunes.lookupId('id215206912', 'album');
|
||||||
result.name.should.equal('Peace Orchestra');
|
result.name.should.equal('Peace Orchestra');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find track by ID', function* (){
|
it('should find track by ID', function* (){
|
||||||
let result = yield itunes.lookupId('id215206958', 'track');
|
const result = yield itunes.lookupId('id215206958', 'track');
|
||||||
result.name.should.equal('Double Drums');
|
result.name.should.equal('Double Drums');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('search', function(){
|
describe('search', function(){
|
||||||
it('should find album by search', function* (){
|
it('should find album by search', function* (){
|
||||||
let result = yield itunes.search({type: 'album', artist: {name: 'Deftones'}, name: 'Deftones'});
|
const result = yield itunes.search({type: 'album', artist: {name: 'Deftones'}, name: 'Deftones'});
|
||||||
result.name.should.equal('Deftones');
|
result.name.should.equal('Deftones');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find track by search', function* (){
|
it('should find track by search', function* (){
|
||||||
let result = yield itunes.search({type: 'track', artist: {name: 'Deftones'}, album: {name: 'Deftones'}, name: 'Hexagram'});
|
const result = yield itunes.search({type: 'track', artist: {name: 'Deftones'}, album: {name: 'Deftones'}, name: 'Hexagram'});
|
||||||
result.name.should.equal('Hexagram');
|
result.name.should.equal('Hexagram');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -29,12 +29,12 @@ describe('iTunes Music', function(){
|
||||||
describe('lookupUrl', function(){
|
describe('lookupUrl', function(){
|
||||||
describe('parseUrl', function(){
|
describe('parseUrl', function(){
|
||||||
it('should parse album url into ID', function* (){
|
it('should parse album url into ID', function* (){
|
||||||
let result = yield itunes.parseUrl('https://itunes.apple.com/us/album/double-drums/id215206912');
|
const result = yield itunes.parseUrl('https://itunes.apple.com/us/album/double-drums/id215206912');
|
||||||
result.id.should.equal('us215206912');
|
result.id.should.equal('us215206912');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse track url into ID', function* (){
|
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');
|
const result = yield itunes.parseUrl('https://itunes.apple.com/us/album/double-drums/id215206912?i=215206958&uo=4');
|
||||||
result.id.should.equal('us215206958');
|
result.id.should.equal('us215206958');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,26 +4,26 @@ import * as rdio from '../../lib/services/rdio';
|
||||||
describe('Rdio', function(){
|
describe('Rdio', function(){
|
||||||
describe('lookupId', function(){
|
describe('lookupId', function(){
|
||||||
it('should find album by ID', function* (){
|
it('should find album by ID', function* (){
|
||||||
let result = yield rdio.lookupId('Qj4NXr0');
|
const result = yield rdio.lookupId('Qj4NXr0');
|
||||||
result.name.should.equal('Listen (Deluxe)');
|
result.name.should.equal('Listen (Deluxe)');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('search', function(){
|
describe('search', function(){
|
||||||
it('should find album by search', function* (){
|
it('should find album by search', function* (){
|
||||||
let result = yield rdio.search({type: 'album', artist: {name: 'David Guetta'}, name: 'Listen (Deluxe)'});
|
const result = yield rdio.search({type: 'album', artist: {name: 'David Guetta'}, name: 'Listen (Deluxe)'});
|
||||||
result.name.should.equal('Listen (Deluxe)');
|
result.name.should.equal('Listen (Deluxe)');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('parseUrl', function(){
|
describe('parseUrl', function(){
|
||||||
it('should parse regular url into album object', function* (){
|
it('should parse regular url into album object', function* (){
|
||||||
let result = yield rdio.parseUrl('https://www.rdio.com/artist/David_Guetta/album/Listen_(Deluxe)/');
|
const result = yield rdio.parseUrl('https://www.rdio.com/artist/David_Guetta/album/Listen_(Deluxe)/');
|
||||||
result.name.should.equal('Listen (Deluxe)');
|
result.name.should.equal('Listen (Deluxe)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse short url into album object', function* (){
|
it('should parse short url into album object', function* (){
|
||||||
let result = yield rdio.parseUrl('http://rd.io/x/Qj4NXr0/');
|
const result = yield rdio.parseUrl('http://rd.io/x/Qj4NXr0/');
|
||||||
result.name.should.equal('Listen (Deluxe)');
|
result.name.should.equal('Listen (Deluxe)');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
import 'should';
|
import 'should';
|
||||||
import spotify from '../../lib/services/spotify';
|
import * as spotify from '../../lib/services/spotify';
|
||||||
|
|
||||||
describe('Spotify', function(){
|
describe('Spotify', function(){
|
||||||
describe('lookupId', function(){
|
describe('lookupId', function(){
|
||||||
it('should find album by ID', function* (){
|
it('should find album by ID', function* (){
|
||||||
let result = yield spotify.lookupId('77UW17CZFyCaRLHdHeofZu', 'album');
|
const result = yield spotify.lookupId('77UW17CZFyCaRLHdHeofZu', 'album');
|
||||||
result.name.should.equal('Listen (Deluxe)');
|
result.name.should.equal('Listen (Deluxe)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find track by ID', function* (){
|
it('should find track by ID', function* (){
|
||||||
let result = yield spotify.lookupId('7dS5EaCoMnN7DzlpT6aRn2', 'track');
|
const result = yield spotify.lookupId('7dS5EaCoMnN7DzlpT6aRn2', 'track');
|
||||||
result.name.should.equal('Take Me To Church');
|
result.name.should.equal('Take Me To Church');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('search', function(){
|
describe('search', function(){
|
||||||
it('should find album by search', function* (){
|
it('should find album by search', function* (){
|
||||||
let result = yield spotify.search({type: 'album', artist: {name: 'David Guetta'}, name: 'Listen (Deluxe)'});
|
const result = yield spotify.search({type: 'album', artist: {name: 'David Guetta'}, name: 'Listen (Deluxe)'});
|
||||||
result.name.should.equal('Listen (Deluxe)');
|
result.name.should.equal('Listen (Deluxe)');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('parseUrl', function(){
|
describe('parseUrl', function(){
|
||||||
it('should parse url into ID', function* (){
|
it('should parse url into ID', function* (){
|
||||||
let result = yield spotify.parseUrl('https://play.spotify.com/album/77UW17CZFyCaRLHdHeofZu');
|
const result = yield spotify.parseUrl('https://play.spotify.com/album/77UW17CZFyCaRLHdHeofZu');
|
||||||
result.id.should.equal('77UW17CZFyCaRLHdHeofZu');
|
result.id.should.equal('77UW17CZFyCaRLHdHeofZu');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
import 'should';
|
import 'should';
|
||||||
import xbox from '../../lib/services/xbox';
|
import * as xbox from '../../lib/services/xbox';
|
||||||
|
|
||||||
describe('Xbox Music', function(){
|
describe('Xbox Music', function(){
|
||||||
describe('lookupId', function(){
|
describe('lookupId', function(){
|
||||||
it('should find album by ID', function* (){
|
it('should find album by ID', function* (){
|
||||||
let result = yield xbox.lookupId('music.8b558d00-0100-11db-89ca-0019b92a3933', 'album');
|
const result = yield xbox.lookupId('music.8b558d00-0100-11db-89ca-0019b92a3933', 'album');
|
||||||
result.name.should.equal('Muchas Gracias: The Best Of Kyuss');
|
result.name.should.equal('Muchas Gracias: The Best Of Kyuss');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find track by ID', function* (){
|
it('should find track by ID', function* (){
|
||||||
let result = yield xbox.lookupId('music.8f558d00-0100-11db-89ca-0019b92a3933', 'track');
|
const result = yield xbox.lookupId('music.8f558d00-0100-11db-89ca-0019b92a3933', 'track');
|
||||||
result.name.should.equal('Shine');
|
result.name.should.equal('Shine');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('search', function(){
|
describe('search', function(){
|
||||||
it('should find album by search', function* (){
|
it('should find album by search', function* (){
|
||||||
let result = yield xbox.search({type: 'album', artist: {name: 'Kyuss'}, name: 'Muchas Gracias: The Best Of Kyuss'});
|
const 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');
|
result.name.should.equal('Muchas Gracias: The Best Of Kyuss');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('lookupUrl', function(){
|
describe('lookupUrl', function(){
|
||||||
it('should parse regular url into album ID', function* (){
|
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');
|
const 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');
|
result.id.should.equal('music.8B558D00-0100-11DB-89CA-0019B92A3933');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import 'should';
|
import 'should';
|
||||||
import youtube from '../../lib/services/youtube';
|
import * as youtube from '../../lib/services/youtube';
|
||||||
|
|
||||||
describe('Youtube', function(){
|
describe('Youtube', function(){
|
||||||
describe('search', function(){
|
describe('search', function(){
|
||||||
it('should find album by search', function* (){
|
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'});
|
const result = yield youtube.search({type: 'track', artist: {name: 'Aesop Rock'}, album: {name: 'Skeconsthon'}, name: 'Zero Dark Thirty'});
|
||||||
result.name.should.equal('Aesop Rock - Zero Dark Thirty');
|
result.name.should.equal('Aesop Rock - Zero Dark Thirty');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
10
views/app.js
10
views/app.js
|
@ -1,12 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Router, {Route, DefaultRoute, NotFoundRoute, RouteHandler} from 'react-router';
|
import Router, { Route, DefaultRoute, NotFoundRoute, RouteHandler } from 'react-router';
|
||||||
import ga, {Initializer as GAInitiailizer} from 'react-google-analytics';
|
import ga, { Initializer as GAInitiailizer } from 'react-google-analytics';
|
||||||
import Home from './home';
|
import Home from './home';
|
||||||
import Share from './share';
|
import Share from './share';
|
||||||
import Head from './head';
|
import Head from './head';
|
||||||
import ErrorView from './error';
|
import ErrorView from './error';
|
||||||
|
|
||||||
let App = React.createClass({
|
const App = React.createClass({
|
||||||
render: function () {
|
render: function () {
|
||||||
return (
|
return (
|
||||||
<html>
|
<html>
|
||||||
|
@ -24,7 +24,7 @@ let App = React.createClass({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let routes = (
|
const routes = (
|
||||||
<Route name='home' handler={App} path='/'>
|
<Route name='home' handler={App} path='/'>
|
||||||
<DefaultRoute handler={Home} />
|
<DefaultRoute handler={Home} />
|
||||||
<Route name='share' path=':service/:type/:id' handler={Share}/>
|
<Route name='share' path=':service/:type/:id' handler={Share}/>
|
||||||
|
@ -45,4 +45,4 @@ if (typeof window !== 'undefined') {
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
}
|
}
|
||||||
|
|
||||||
export {routes};
|
export { routes };
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {State} from 'react-router';
|
import { State } from 'react-router';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@ export default React.createClass({
|
||||||
router: React.PropTypes.func.isRequired
|
router: React.PropTypes.func.isRequired
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var image = this.props.shares ? this.props.shares[0].artwork.large : 'https://match.audio/images/logo-512.png';
|
const image = this.props.shares ? this.props.shares[0].artwork.large : 'https://match.audio/images/logo-512.png';
|
||||||
var title = this.props.shares ? this.props.shares[0].name + ' by ' + this.props.shares[0].artist.name : 'Match Audio';
|
const title = this.props.shares ? this.props.shares[0].name + ' by ' + this.props.shares[0].artist.name : 'Match Audio';
|
||||||
var shareUrl = 'https://match.audio/' + this.getParams().service + '/' + this.getParams().type + '/' + this.getParams().id;
|
const shareUrl = 'https://match.audio/' + this.getParams().service + '/' + this.getParams().type + '/' + this.getParams().id;
|
||||||
return (
|
return (
|
||||||
<head>
|
<head>
|
||||||
<script dangerouslySetInnerHTML={{__html: 'var timerStart = Date.now();'}}></script>
|
<script dangerouslySetInnerHTML={{__html: 'var timerStart = Date.now();'}}></script>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import request from 'superagent';
|
import request from 'superagent';
|
||||||
import {Navigation, State, Link} from 'react-router';
|
import { Navigation, State, Link } from 'react-router';
|
||||||
import Faq from './faq';
|
import Faq from './faq';
|
||||||
import Foot from './foot';
|
import Foot from './foot';
|
||||||
|
|
||||||
var Recent = React.createClass({
|
const Recent = React.createClass({
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
return (<div className='row'>
|
return (<div className='row'>
|
||||||
|
@ -21,7 +21,7 @@ var Recent = React.createClass({
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var RecentItem = React.createClass({
|
const RecentItem = React.createClass({
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
if (!this.props.item.artwork) {
|
if (!this.props.item.artwork) {
|
||||||
|
@ -38,7 +38,7 @@ var RecentItem = React.createClass({
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var SearchForm = React.createClass({
|
const SearchForm = React.createClass({
|
||||||
|
|
||||||
mixins: [ Navigation, State ],
|
mixins: [ Navigation, State ],
|
||||||
|
|
||||||
|
@ -50,26 +50,25 @@ var SearchForm = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSubmit: function(e) {
|
handleSubmit: function(e) {
|
||||||
|
e.preventDefault();
|
||||||
this.setState({
|
this.setState({
|
||||||
submitting: true
|
submitting: true
|
||||||
});
|
});
|
||||||
var that = this;
|
const url = this.refs.url.getDOMNode().value.trim();
|
||||||
e.preventDefault();
|
|
||||||
var url = this.refs.url.getDOMNode().value.trim();
|
|
||||||
if (!url) {
|
if (!url) {
|
||||||
that.setState({
|
this.setState({
|
||||||
submitting: false
|
submitting: false
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
request.post('/search').send({url: url}).end(function(req, res) {
|
request.post('/search').send({url: url}).end((req, res) => {
|
||||||
that.setState({
|
this.setState({
|
||||||
submitting: false
|
submitting: false
|
||||||
});
|
});
|
||||||
if (res.body.error) {
|
if (res.body.error) {
|
||||||
that.setState({error: res.body.error.message});
|
this.setState({error: res.body.error.message});
|
||||||
}
|
}
|
||||||
that.transitionTo('share', res.body);
|
this.transitionTo('share', res.body);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -102,7 +101,7 @@ export default React.createClass({
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
// Use this only on first page load, refresh whenever we navigate back.
|
// Use this only on first page load, refresh whenever we navigate back.
|
||||||
if (this.props.recents) {
|
if (this.props.recents) {
|
||||||
var recents = this.props.recents;
|
const recents = this.props.recents;
|
||||||
delete this.props.recents;
|
delete this.props.recents;
|
||||||
return {
|
return {
|
||||||
recents: recents
|
recents: recents
|
||||||
|
@ -115,11 +114,11 @@ export default React.createClass({
|
||||||
|
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
if (!this.props.recents) {
|
if (!this.props.recents) {
|
||||||
request.get('/recent').set('Accept', 'application/json').end(function(err, res) {
|
request.get('/recent').set('Accept', 'application/json').end((err, res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
recents: res.body.recents
|
recents: res.body.recents
|
||||||
});
|
});
|
||||||
}.bind(this));
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import request from 'superagent';
|
import request from 'superagent';
|
||||||
import {State, Link} from 'react-router';
|
import { State, Link } from 'react-router';
|
||||||
import Foot from './foot';
|
import Foot from './foot';
|
||||||
|
|
||||||
var MusicItem = React.createClass({
|
const MusicItem = React.createClass({
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
if (!this.props.item.matched_at) {
|
if (!this.props.item.matched_at) {
|
||||||
|
@ -88,7 +88,7 @@ export default React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
var complete = this.state.shares.length > 0;
|
let complete = this.state.shares.length > 0;
|
||||||
|
|
||||||
this.state.shares.forEach(function(share) {
|
this.state.shares.forEach(function(share) {
|
||||||
if (typeof share.matched_at === 'undefined') {
|
if (typeof share.matched_at === 'undefined') {
|
||||||
|
@ -96,9 +96,9 @@ export default React.createClass({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var getShares = function() {
|
const getShares = () => {
|
||||||
request.get(this.getPathname() + '.json').end(function(err, res) {
|
request.get(this.getPathname() + '.json').end((err, res) => {
|
||||||
var shares = res.body.shares;
|
const shares = res.body.shares;
|
||||||
complete = true;
|
complete = true;
|
||||||
shares.forEach(function(share) {
|
shares.forEach(function(share) {
|
||||||
if (typeof share.matched_at === 'undefined') {
|
if (typeof share.matched_at === 'undefined') {
|
||||||
|
@ -118,8 +118,8 @@ export default React.createClass({
|
||||||
shareUrl: 'https://match.audio/' + shares[0].service + '/' + shares[0].type + '/' + shares[0].id
|
shareUrl: 'https://match.audio/' + shares[0].service + '/' + shares[0].type + '/' + shares[0].id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}.bind(this));
|
});
|
||||||
}.bind(this);
|
};
|
||||||
|
|
||||||
if (!this.state.shares.length) {
|
if (!this.state.shares.length) {
|
||||||
getShares();
|
getShares();
|
||||||
|
@ -134,19 +134,19 @@ export default React.createClass({
|
||||||
|
|
||||||
// Some hacks to pop open the Twitter/Facebook/Google Plus sharing dialogs without using their code.
|
// Some hacks to pop open the Twitter/Facebook/Google Plus sharing dialogs without using their code.
|
||||||
Array.prototype.forEach.call(document.querySelectorAll('.share-dialog'), function(dialog){
|
Array.prototype.forEach.call(document.querySelectorAll('.share-dialog'), function(dialog){
|
||||||
dialog.addEventListener('click', function(event) {
|
dialog.addEventListener('click', function(e) {
|
||||||
event.preventDefault();
|
e.preventDefault();
|
||||||
var w = 845;
|
const w = 845;
|
||||||
var h = 670;
|
const h = 670;
|
||||||
var dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
|
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
|
||||||
var dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;
|
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;
|
||||||
|
|
||||||
var width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
|
const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
|
||||||
var height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
|
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
|
||||||
|
|
||||||
var left = ((width / 2) - (w / 2)) + dualScreenLeft;
|
const left = ((width / 2) - (w / 2)) + dualScreenLeft;
|
||||||
var top = ((height / 2) - (h / 2)) + dualScreenTop;
|
const top = ((height / 2) - (h / 2)) + dualScreenTop;
|
||||||
var newWindow = window.open(dialog.href, 'Share Music', 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
|
const newWindow = window.open(dialog.href, 'Share Music', 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
|
||||||
if (window.focus) {
|
if (window.focus) {
|
||||||
newWindow.focus();
|
newWindow.focus();
|
||||||
}
|
}
|
||||||
|
@ -183,9 +183,9 @@ export default React.createClass({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
{this.state.shares.map(function(item, i){
|
{this.state.shares.map((item, i) => {
|
||||||
return (<MusicItem items={this.state.shares} item={item} inc={i} key={i} />);
|
return (<MusicItem items={this.state.shares} item={item} inc={i} key={i} />);
|
||||||
}.bind(this))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue