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)
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
|
@ -32,4 +32,4 @@ So there's no surprises for contributors later, I plan on using referral tags wh
|
|||
|
||||
## 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 zlib from 'zlib';
|
||||
import koa from 'koa';
|
||||
import route from 'koa-route';
|
||||
import logger from 'koa-logger';
|
||||
|
@ -13,8 +14,7 @@ import index from './routes/index';
|
|||
import search from './routes/search';
|
||||
import share from './routes/share';
|
||||
import itunesProxy from './routes/itunes-proxy';
|
||||
import {routes} from './views/app';
|
||||
import zlib from 'zlib';
|
||||
import { routes } from './views/app';
|
||||
import createHandler from './lib/react-handler';
|
||||
|
||||
import debuglog from 'debug';
|
||||
|
@ -29,6 +29,7 @@ app.use(function* (next) {
|
|||
} catch (err) {
|
||||
if (!err.status) {
|
||||
debug('Error: %o', err);
|
||||
throw err;
|
||||
} else if (err.status === 404) {
|
||||
let Handler = yield createHandler(routes, this.request.url);
|
||||
|
||||
|
@ -90,20 +91,10 @@ app.use(route.get('/recent', function* () {
|
|||
this.body = {recents: recents};
|
||||
}));
|
||||
|
||||
module.exports = app;
|
||||
|
||||
if (!module.parent) {
|
||||
if (process.env.LOCALHOST_KEY) {
|
||||
require('spdy').createServer({
|
||||
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));
|
||||
});
|
||||
}
|
||||
|
||||
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';
|
||||
const debug = require('debug')('match.audio');
|
||||
|
||||
// Shut mongodb-promisified up.
|
||||
const dir = console.dir;
|
||||
console.dir = function() {};
|
||||
const MongoClient = require('mongodb-promisified')().MongoClient;
|
||||
console.dir = dir;
|
||||
import mongodb from 'mongodb-promisified';
|
||||
const MongoClient = mongodb().MongoClient;
|
||||
import debuglog from 'debug';
|
||||
const debug = debuglog('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);
|
||||
debug('Successfully connected to Mongodb');
|
||||
client.matches = client.collection('matches');
|
||||
|
|
|
@ -4,25 +4,19 @@ import fs from 'fs';
|
|||
var services = [];
|
||||
|
||||
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) {
|
||||
services.push(service);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = function(url) {
|
||||
|
||||
var matchedService;
|
||||
services.some(function(service) {
|
||||
matchedService = service.match(url) ? service : null;
|
||||
return matchedService;
|
||||
});
|
||||
|
||||
if (matchedService) {
|
||||
return matchedService.parseUrl(url).timeout(10000).then(function(result) {
|
||||
return matchedService.lookupId(result.id, result.type).then(function(item) {
|
||||
return item;
|
||||
});
|
||||
});
|
||||
export default function* (url) {
|
||||
let matchedService;
|
||||
for (let service of services) {
|
||||
matchedService = yield service.match(url);
|
||||
if (matchedService) {
|
||||
const result = yield service.parseUrl(url);
|
||||
return yield service.lookupId(result.id, result.type);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
module.exports = [];
|
||||
const services = [];
|
||||
|
||||
fs.readdirSync(path.join(__dirname, 'services')).forEach(function(file) {
|
||||
var service = require(path.join(__dirname, 'services', file));
|
||||
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 'superagent-bluebird-promise';
|
||||
import { match as urlMatch } from './url';
|
||||
|
||||
module.exports.id = 'deezer';
|
||||
export let id = 'deezer';
|
||||
|
||||
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)[\/]+([^\/]+)/);
|
||||
|
||||
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 {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) {
|
||||
return str.replace(/[\:\?\&]+/, '');
|
||||
};
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
"use strict";
|
||||
var parse = require('url').parse;
|
||||
import { parse } from 'url';
|
||||
|
||||
module.exports.match = function(url) {
|
||||
var parsed = parse(url);
|
||||
export function* match(url) {
|
||||
const parsed = parse(url);
|
||||
if (!parsed.host.match(/deezer\.com$/)) {
|
||||
return false;
|
||||
}
|
||||
var matches = parsed.path.match(/\/(album|track)[\/]+([^\/]+)/);
|
||||
const matches = parsed.path.match(/\/(album|track)[\/]+([^\/]+)/);
|
||||
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;
|
||||
var Promise = require("bluebird");
|
||||
var PlayMusic = require("playmusic");
|
||||
var pm = Promise.promisifyAll(new PlayMusic());
|
||||
const pm = bluebird.promisifyAll(new PlayMusic());
|
||||
|
||||
module.exports.id = "google";
|
||||
export let id = 'google';
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
module.exports.match = require("./url").match;
|
||||
export const match = urlMatch;
|
||||
|
||||
module.exports.parseUrl = function(url) {
|
||||
return ready.then(function() {
|
||||
var parsed = parse(url.replace(/\+/g, "%20"));
|
||||
var path = parsed.path;
|
||||
var hash = parsed.hash;
|
||||
if (hash) {
|
||||
var parts = hash.split("/");
|
||||
var type = parts[1];
|
||||
var id = parts[2];
|
||||
var artist = decodeURIComponent(parts[3]);
|
||||
var album = decodeURIComponent(parts[4]);
|
||||
export function* parseUrl(url) {
|
||||
yield ready;
|
||||
const parsed = parse(url.replace(/\+/g, '%20'));
|
||||
const path = parsed.path;
|
||||
const hash = parsed.hash;
|
||||
if (hash) {
|
||||
const parts = hash.split('/');
|
||||
const type = parts[1];
|
||||
const id = parts[2];
|
||||
const artist = decodeURIComponent(parts[3]);
|
||||
const album = decodeURIComponent(parts[4]);
|
||||
|
||||
if (type !== "album" && type !== "track") {
|
||||
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;
|
||||
if (type !== 'album' && type !== 'track') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return pm.searchAsync(query, 5).then(function(result) {
|
||||
|
||||
if (!result.entries) {
|
||||
var matches = album.match(/^[^\(\[]+/);
|
||||
if (matches && matches[0] && matches[0] !== album) {
|
||||
var cleanedData = JSON.parse(JSON.stringify(data));
|
||||
if (type === "album") {
|
||||
cleanedData.name = matches[0].trim();
|
||||
} else if (type === "track") {
|
||||
cleanedData.album.name = matches[0].trim();
|
||||
}
|
||||
return module.exports.search(cleanedData);
|
||||
} else {
|
||||
return {service: "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 {
|
||||
var id;
|
||||
if (type === "album") {
|
||||
id = result.album.albumId;
|
||||
} else if (type === "track") {
|
||||
id = result.track.nid;
|
||||
}
|
||||
|
||||
return module.exports.lookupId(id, type);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (id.length > 0) {
|
||||
return {id: id, type: type};
|
||||
} else {
|
||||
return yield search({type: type, name: album, artist: {name: artist}});
|
||||
}
|
||||
} else if(path) {
|
||||
const matches = path.match(/\/music\/m\/([\w]+)/);
|
||||
const type = matches[1][0] === 'T' ? 'track' : 'album';
|
||||
return yield lookupId(matches[1], type);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export function* lookupId(id, type) {
|
||||
yield ready;
|
||||
if (type === 'album') {
|
||||
const album = yield pm.getAlbumAsync(id, false);
|
||||
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
|
||||
}
|
||||
};
|
||||
} 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";
|
||||
var parse = require('url').parse;
|
||||
import { parse } from 'url';
|
||||
|
||||
module.exports.match = function(url) {
|
||||
export function* match(url) {
|
||||
var parsed = parse(url.replace(/\+/g, "%20"));
|
||||
if (!parsed.host.match(/play\.google\.com$/)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var path = parsed.path;
|
||||
var hash = parsed.hash;
|
||||
const path = parsed.path;
|
||||
const hash = parsed.hash;
|
||||
|
||||
if (hash) {
|
||||
var parts = hash.split("/");
|
||||
var id = parts[2];
|
||||
var artist = parts[3];
|
||||
const parts = hash.split("/");
|
||||
const id = parts[2];
|
||||
const artist = parts[3];
|
||||
|
||||
if (id.length > 0) {
|
||||
return true;
|
||||
|
@ -21,7 +20,7 @@ module.exports.match = function(url) {
|
|||
return true;
|
||||
}
|
||||
} else if(path) {
|
||||
var matches = path.match(/\/music\/m\/([\w]+)/);
|
||||
const matches = path.match(/\/music\/m\/([\w]+)/);
|
||||
if (matches[1]) {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import {parse} from 'url';
|
||||
import { parse } from 'url';
|
||||
import querystring from 'querystring';
|
||||
import request from 'superagent';
|
||||
import 'superagent-bluebird-promise';
|
||||
import { match as urlMatch } from './url';
|
||||
|
||||
module.exports.id = 'itunes';
|
||||
export let id = 'itunes';
|
||||
|
||||
const apiRoot = 'https://itunes.apple.com';
|
||||
|
||||
module.exports.match = require('./url').match;
|
||||
export const match = urlMatch;
|
||||
|
||||
module.exports.parseUrl = function* (url) {
|
||||
let parsed = parse(url);
|
||||
let matches = parsed.path.match(/[\/]?([\/]?[a-z]{2}?)?[\/]+album[\/]+([^\/]+)[\/]+([^\?]+)/);
|
||||
let query = querystring.parse(parsed.query);
|
||||
export function* parseUrl(url) {
|
||||
const parsed = parse(url);
|
||||
const matches = parsed.path.match(/[\/]?([\/]?[a-z]{2}?)?[\/]+album[\/]+([^\/]+)[\/]+([^\?]+)/);
|
||||
const query = querystring.parse(parsed.query);
|
||||
|
||||
if (matches) {
|
||||
let type = 'album';
|
||||
|
@ -23,11 +24,11 @@ module.exports.parseUrl = function* (url) {
|
|||
}
|
||||
return yield module.exports.lookupId(id, type, matches[1] || 'us');
|
||||
} 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}/)) {
|
||||
cc = id.substr(0, 2);
|
||||
id = id.substr(2);
|
||||
|
@ -38,13 +39,13 @@ module.exports.lookupId = function* (id, type, cc) {
|
|||
path = '/' + cc + path;
|
||||
}
|
||||
|
||||
let response = yield request.get(apiRoot + path);
|
||||
const response = yield request.get(apiRoot + path);
|
||||
let result = JSON.parse(response.text);
|
||||
|
||||
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;
|
||||
return Promise.reject(error);
|
||||
throw error;
|
||||
} else {
|
||||
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 type = data.type;
|
||||
const type = data.type;
|
||||
|
||||
if (type === 'album') {
|
||||
query = data.artist.name + ' ' + data.name;
|
||||
|
@ -88,27 +89,27 @@ module.exports.search = function* (data) {
|
|||
entity = 'musicTrack';
|
||||
}
|
||||
|
||||
let path = '/search?term=' + encodeURIComponent(query) + '&media=music&entity=' + entity;
|
||||
let response = yield request.get(apiRoot + path);
|
||||
const path = '/search?term=' + encodeURIComponent(query) + '&media=music&entity=' + entity;
|
||||
const response = yield request.get(apiRoot + path);
|
||||
let result = JSON.parse(response.text);
|
||||
|
||||
if (!result.results[0]) {
|
||||
let matches = album.match(/^[^\(\[]+/);
|
||||
const matches = album.match(/^[^\(\[]+/);
|
||||
if (matches && matches[0] && matches[0] !== album) {
|
||||
let cleanedData = JSON.parse(JSON.stringify(data));
|
||||
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 module.exports.search(cleanedData);
|
||||
return yield search(cleanedData);
|
||||
} else {
|
||||
return Promise.resolve({service: 'itunes'});
|
||||
return {service: 'itunes'};
|
||||
}
|
||||
} else {
|
||||
result = result.results[0];
|
||||
|
||||
let item = {
|
||||
const item = {
|
||||
service: 'itunes',
|
||||
type: type,
|
||||
id: 'us' + result.collectionId,
|
||||
|
@ -129,6 +130,6 @@ module.exports.search = function* (data) {
|
|||
name: result.collectionName
|
||||
};
|
||||
}
|
||||
return Promise.resolve(item);
|
||||
return item;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
"use strict";
|
||||
var parse = require('url').parse;
|
||||
var querystring = require('querystring');
|
||||
import { parse } from 'url';
|
||||
import querystring from 'querystring';
|
||||
|
||||
module.exports.match = function(url, type) {
|
||||
var parsed = parse(url);
|
||||
export function* match(url, type) {
|
||||
const parsed = parse(url);
|
||||
|
||||
if (!parsed.host.match(/itunes.apple\.com$/)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var matches = parsed.path.match(/[\/]?([\/]?[a-z]{2}?)?[\/]+album[\/]+([^\/]+)[\/]+([^\?]+)/);
|
||||
var query = querystring.parse(parsed.query);
|
||||
const matches = parsed.path.match(/[\/]?([\/]?[a-z]{2}?)?[\/]+album[\/]+([^\/]+)[\/]+([^\?]+)/);
|
||||
const query = querystring.parse(parsed.query);
|
||||
|
||||
return !!matches[3];
|
||||
};
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { parse } from 'url';
|
||||
|
||||
export function match(url) {
|
||||
var parsed = parse(url);
|
||||
export function* match(url) {
|
||||
const parsed = parse(url);
|
||||
if (!parsed.host.match(/rd\.io$/) && !parsed.host.match(/rdio\.com$/)) {
|
||||
return false;
|
||||
}
|
||||
var regular = parsed.path.match(/[\/]*artist[\/]*([^\/]*)[\/]*album[\/]*([^\/]*)[\/]*([track]*)?[\/]*([^\/]*)/);
|
||||
var short = parsed.path.match(/[\/]*x[\/]*([^\/]*)/);
|
||||
const regular = parsed.path.match(/[\/]*artist[\/]*([^\/]*)[\/]*album[\/]*([^\/]*)[\/]*([track]*)?[\/]*([^\/]*)/);
|
||||
const short = parsed.path.match(/[\/]*x[\/]*([^\/]*)/);
|
||||
return (regular && !!regular[2]) || (short && !!short[1]);
|
||||
};
|
||||
|
|
|
@ -1,70 +1,70 @@
|
|||
"use strict";
|
||||
var parse = require('url').parse;
|
||||
var Promise = require('bluebird');
|
||||
var spotify = Promise.promisifyAll(require('spotify'));
|
||||
import { parse } from 'url';
|
||||
import bluebird from 'bluebird';
|
||||
import spotifyCB from '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)[\/]+([^\/]+)/);
|
||||
|
||||
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) {
|
||||
return spotify.lookupAsync({id: id, type: type}).then(function(data) {
|
||||
if (data.error) {
|
||||
var error = new Error("Not Found");
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
export function* lookupId(id, type) {
|
||||
const data = yield spotify.lookupAsync({id: id, type: type});
|
||||
if (data.error) {
|
||||
var error = new Error("Not Found");
|
||||
error.status = 404;
|
||||
throw error;
|
||||
}
|
||||
|
||||
var artist = data.artists[0];
|
||||
var artist = data.artists[0];
|
||||
|
||||
if (type == "album") {
|
||||
return {
|
||||
service: "spotify",
|
||||
type: type,
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
streamUrl: "https://play.spotify.com/" + type + "/" + data.id,
|
||||
purchaseUrl: null,
|
||||
artwork: {
|
||||
small: data.images[1].url.replace("http:", "https:"),
|
||||
large: data.images[0].url.replace("http:", "https:"),
|
||||
},
|
||||
artist: {
|
||||
name: artist.name
|
||||
}
|
||||
};
|
||||
} else if (type == "track") {
|
||||
return {
|
||||
service: "spotify",
|
||||
type: type,
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
streamUrl: "https://play.spotify.com/" + type + "/" + data.id,
|
||||
purchaseUrl: null,
|
||||
artwork: {
|
||||
small: data.album.images[1].url.replace("http:", "https:"),
|
||||
large: data.album.images[0].url.replace("http:", "https:"),
|
||||
},
|
||||
artist: {
|
||||
name: artist.name
|
||||
},
|
||||
album: {
|
||||
name: data.album.name
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
if (type == "album") {
|
||||
return {
|
||||
service: "spotify",
|
||||
type: type,
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
streamUrl: "https://play.spotify.com/" + type + "/" + data.id,
|
||||
purchaseUrl: null,
|
||||
artwork: {
|
||||
small: data.images[1].url.replace("http:", "https:"),
|
||||
large: data.images[0].url.replace("http:", "https:"),
|
||||
},
|
||||
artist: {
|
||||
name: artist.name
|
||||
}
|
||||
};
|
||||
} else if (type == "track") {
|
||||
return {
|
||||
service: "spotify",
|
||||
type: type,
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
streamUrl: "https://play.spotify.com/" + type + "/" + data.id,
|
||||
purchaseUrl: null,
|
||||
artwork: {
|
||||
small: data.album.images[1].url.replace("http:", "https:"),
|
||||
large: data.album.images[0].url.replace("http:", "https:"),
|
||||
},
|
||||
artist: {
|
||||
name: artist.name
|
||||
},
|
||||
album: {
|
||||
name: data.album.name
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.search = function(data) {
|
||||
export function* search(data) {
|
||||
var cleanParam = function(str) {
|
||||
var chopChars = ['&', '[', '('];
|
||||
chopChars.forEach(function(chr) {
|
||||
|
@ -85,28 +85,26 @@ module.exports.search = function(data) {
|
|||
album = data.album.name;
|
||||
}
|
||||
|
||||
return spotify.searchAsync({query: query, type: type}).then(function(results) {
|
||||
if (!results[type + "s"].items[0]) {
|
||||
return {service: "spotify"};
|
||||
} else {
|
||||
var found;
|
||||
var choppedAlbum = data.type == "album" ? cleanParam(data.name) : cleanParam(data.album.name);
|
||||
if (!choppedAlbum.length) {
|
||||
return module.exports.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);
|
||||
const results = yield spotify.searchAsync({query: query, type: type});
|
||||
if (!results[type + "s"].items[0]) {
|
||||
return {service: "spotify"};
|
||||
} else {
|
||||
let found;
|
||||
const choppedAlbum = data.type == "album" ? cleanParam(data.name) : cleanParam(data.album.name);
|
||||
if (!choppedAlbum.length) {
|
||||
return yield 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";
|
||||
var parse = require('url').parse;
|
||||
import { parse } from 'url';
|
||||
|
||||
module.exports.match = function(url, type) {
|
||||
var parsed = parse(url);
|
||||
export function* match(url, type) {
|
||||
const parsed = parse(url);
|
||||
if (!parsed.host.match(/spotify\.com$/)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
|
||||
const matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
|
||||
return matches && !!matches[2];
|
||||
};
|
||||
|
|
|
@ -1,40 +1,45 @@
|
|||
"use strict";
|
||||
var parse = require('url').parse;
|
||||
var Promise = require('bluebird');
|
||||
var request = require('superagent');
|
||||
require('superagent-bluebird-promise');
|
||||
import { parse } from 'url';
|
||||
import querystring from 'querystring';
|
||||
import request from 'superagent';
|
||||
import '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) {
|
||||
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,
|
||||
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() {
|
||||
var authUrl = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
|
||||
var scope = "http://music.xboxlive.com";
|
||||
var grantType = "client_credentials";
|
||||
|
||||
var data = {client_id: credentials.clientId, client_secret: credentials.clientSecret, scope: scope, grant_type: grantType};
|
||||
return request.post(authUrl).send(data).set('Content-type', 'application/x-www-form-urlencoded').promise().then(function(res) {
|
||||
return res.body.access_token;
|
||||
});
|
||||
function* getAccessToken() {
|
||||
const authUrl = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
|
||||
const scope = "http://music.xboxlive.com";
|
||||
const grantType = "client_credentials";
|
||||
|
||||
const data = {
|
||||
client_id: credentials.clientId,
|
||||
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) {
|
||||
var result = res.body.Tracks.Items[0];
|
||||
result = res.body.Tracks.Items[0];
|
||||
} else {
|
||||
var result = res.body.Albums.Items[0];
|
||||
result = res.body.Albums.Items[0];
|
||||
}
|
||||
var item = {
|
||||
let item = {
|
||||
service: "xbox",
|
||||
type: res.body.Tracks ? "track" : "album",
|
||||
id: result.Id,
|
||||
|
@ -55,37 +60,33 @@ var formatResponse = function(res) {
|
|||
return item;
|
||||
}
|
||||
|
||||
module.exports.match = require('./url').match;
|
||||
export const match = urlMatch;
|
||||
|
||||
module.exports.parseUrl = function(url) {
|
||||
var parsed = parse(url);
|
||||
var parts = parsed.path.split("/");
|
||||
var type = parts[1];
|
||||
var idMatches = parts[4].match(/[\w\-]+/);
|
||||
var id = idMatches[0];
|
||||
export function* parseUrl(url) {
|
||||
const parsed = parse(url);
|
||||
const parts = parsed.path.split("/");
|
||||
const type = parts[1];
|
||||
const idMatches = parts[4].match(/[\w\-]+/);
|
||||
const id = idMatches[0];
|
||||
if (!id) {
|
||||
return false;
|
||||
}
|
||||
return module.exports.lookupId("music." + id, type);
|
||||
return yield lookupId("music." + id, type);
|
||||
}
|
||||
|
||||
module.exports.lookupId = function(id, type) {
|
||||
return getAccessToken().then(function(access_token){
|
||||
var path = "/" + id + "/lookup";
|
||||
return request.get(apiRoot + path).set("Authorization", "Bearer " + access_token).promise().then(function(res) {
|
||||
return formatResponse(res);
|
||||
}, function(res) {
|
||||
return {service: "xbox"};
|
||||
});
|
||||
});
|
||||
export function* lookupId(id, type) {
|
||||
const access_token = yield getAccessToken();
|
||||
const path = "/" + id + "/lookup";
|
||||
const result = yield request.get(apiRoot + path).set("Authorization", "Bearer " + access_token).promise();
|
||||
return result ? formatResponse(result) : {service: "xbox"};
|
||||
};
|
||||
|
||||
module.exports.search = function(data) {
|
||||
export function* search(data) {
|
||||
var cleanParam = function(str) {
|
||||
return str.replace(/[\:\?\&]+/, "");
|
||||
}
|
||||
var query, album;
|
||||
var type = data.type;
|
||||
let query, album;
|
||||
const type = data.type;
|
||||
|
||||
if (type == "album") {
|
||||
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);
|
||||
album = data.album.name
|
||||
}
|
||||
return getAccessToken().then(function(access_token){
|
||||
var path = "/music/search?q=" + encodeURIComponent(query) + "&filters=" + type + "s";
|
||||
return request.get(apiRoot + path).set("Authorization", "Bearer " + access_token).promise().then(function(res) {
|
||||
return formatResponse(res);
|
||||
}, function(res) {
|
||||
return {service: "xbox"};
|
||||
});
|
||||
});
|
||||
const access_token = yield getAccessToken();
|
||||
const path = "/music/search?q=" + encodeURIComponent(query) + "&filters=" + type + "s";
|
||||
const result = yield request.get(apiRoot + path).set("Authorization", "Bearer " + access_token).promise()
|
||||
return result ? formatResponse(result) : {service: "xbox"};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
"use strict";
|
||||
var parse = require('url').parse;
|
||||
|
||||
module.exports.match = function(url, type) {
|
||||
var parsed = parse(url);
|
||||
import { parse } from 'url';
|
||||
|
||||
export function* match(url, type) {
|
||||
const parsed = parse(url);
|
||||
if (!parsed.host.match(/music.xbox.com$/)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var parts = parsed.path.split("/");
|
||||
|
||||
const parts = parsed.path.split("/");
|
||||
return (parts[1] == "album" || parts[1] == "track") && parts[4];
|
||||
};
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
"use strict";
|
||||
var parse = require('url').parse;
|
||||
var Promise = require('bluebird');
|
||||
var request = require('superagent');
|
||||
require('superagent-bluebird-promise');
|
||||
import { parse } from 'url';
|
||||
import querystring from 'querystring';
|
||||
import request from 'superagent';
|
||||
import 'superagent-bluebird-promise';
|
||||
|
||||
var credentials = {
|
||||
const credentials = {
|
||||
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) {
|
||||
return request.get(apiRoot + topic + "?key=" + credentials.key).promise().then(function(res) {
|
||||
return res.body;
|
||||
})
|
||||
export function* get(topic) {
|
||||
const result = yield request.get(apiRoot + topic + "?key=" + credentials.key).promise();
|
||||
return result.body;
|
||||
}
|
||||
|
||||
|
||||
module.exports.get("/m/0dwcrm_");
|
|
@ -1,139 +1,124 @@
|
|||
"use strict";
|
||||
var parse = require('url').parse;
|
||||
var freebase = require('./freebase');
|
||||
var querystring = require('querystring');
|
||||
var moment = require('moment');
|
||||
var Promise = require('bluebird');
|
||||
var request = require('superagent');
|
||||
require('superagent-bluebird-promise');
|
||||
import { parse } from 'url';
|
||||
import querystring from 'querystring';
|
||||
import moment from 'moment';
|
||||
import request from 'superagent';
|
||||
import 'superagent-bluebird-promise';
|
||||
import { match as urlMatch } from './url';
|
||||
import freebase from './freebase';
|
||||
|
||||
module.exports.id = "youtube";
|
||||
module.exports.id = 'youtube';
|
||||
|
||||
if (!process.env.YOUTUBE_KEY) {
|
||||
console.warn("YOUTUBE_KEY environment variable not found, deactivating Youtube.");
|
||||
} else {
|
||||
console.warn('YOUTUBE_KEY environment variable not found, deactivating Youtube.');
|
||||
}
|
||||
|
||||
var credentials = {
|
||||
const credentials = {
|
||||
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) {
|
||||
id = parsed.path.substr(1);
|
||||
if (!id) {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
return module.exports.lookupId(id, "track");
|
||||
return lookupId(id, 'track');
|
||||
}
|
||||
|
||||
module.exports.lookupId = function(id, type) {
|
||||
|
||||
var path = "/videos?part=snippet%2CtopicDetails%2CcontentDetails&id=" + id + "&key=" + credentials.key;
|
||||
|
||||
return request.get(apiRoot + path).promise().then(function(res) {
|
||||
var item = res.body.items[0];
|
||||
if (item.topicDetails.topicIds) {
|
||||
var promises = [];
|
||||
var match = {
|
||||
id: id,
|
||||
service: "youtube",
|
||||
name: item.snippet.title,
|
||||
type: "track",
|
||||
album: {name: ""},
|
||||
streamUrl: "https://youtu.be/" + id,
|
||||
purchaseUrl: null,
|
||||
artwork: {
|
||||
small: item.snippet.thumbnails.medium.url,
|
||||
large: item.snippet.thumbnails.high.url,
|
||||
}
|
||||
};
|
||||
item.topicDetails.topicIds.forEach(function(topicId) {
|
||||
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"};
|
||||
export function* lookupId(id, type) {
|
||||
|
||||
const path = '/videos?part=snippet%2CtopicDetails%2CcontentDetails&id=' + id + '&key=' + credentials.key;
|
||||
|
||||
const result = yield request.get(apiRoot + path).promise();
|
||||
const item = res.body.items[0];
|
||||
if (!item.topicDetails.topicIds) {
|
||||
return {service: 'youtube'};
|
||||
}
|
||||
|
||||
const promises = [];
|
||||
const match = {
|
||||
id: id,
|
||||
service: 'youtube',
|
||||
name: item.snippet.title,
|
||||
type: 'track',
|
||||
album: {name: ''},
|
||||
streamUrl: 'https://youtu.be/' + id,
|
||||
purchaseUrl: null,
|
||||
artwork: {
|
||||
small: item.snippet.thumbnails.medium.url,
|
||||
large: item.snippet.thumbnails.high.url,
|
||||
}
|
||||
}, 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) {
|
||||
var query, album;
|
||||
var type = data.type;
|
||||
export function* search(data) {
|
||||
let query, album;
|
||||
const type = data.type;
|
||||
|
||||
if (type == "album") {
|
||||
query = data.artist.name + " " + data.name;
|
||||
if (type == 'album') {
|
||||
query = data.artist.name + ' ' + data.name;
|
||||
album = data.name;
|
||||
} else if (type == "track") {
|
||||
query = data.artist.name + " " + data.name;
|
||||
} else if (type == 'track') {
|
||||
query = data.artist.name + ' ' + data.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) {
|
||||
var result = res.body.items[0];
|
||||
const result = yield request.get(apiRoot + path).promise();
|
||||
const item = result.body.items[0];
|
||||
|
||||
if (!result) {
|
||||
return {service:"youtube", type: "video"};
|
||||
} else {
|
||||
return {
|
||||
service: "youtube",
|
||||
type: "video",
|
||||
id: result.id.videoId,
|
||||
name: result.snippet.title,
|
||||
streamUrl: "https://www.youtube.com/watch?v=" + result.id.videoId,
|
||||
purchaseUrl: null,
|
||||
artwork: {
|
||||
small: result.snippet.thumbnails.medium.url,
|
||||
large: result.snippet.thumbnails.high.url,
|
||||
}
|
||||
};
|
||||
}
|
||||
}, function(err) {
|
||||
console.log(err)
|
||||
return {service: "youtube"};
|
||||
});
|
||||
if (!item) {
|
||||
return {service:'youtube', type: 'video'};
|
||||
} else {
|
||||
return {
|
||||
service: 'youtube',
|
||||
type: 'video',
|
||||
id: item.id.videoId,
|
||||
name: item.snippet.title,
|
||||
streamUrl: 'https://www.youtube.com/watch?v=' + item.id.videoId,
|
||||
purchaseUrl: null,
|
||||
artwork: {
|
||||
small: item.snippet.thumbnails.medium.url,
|
||||
large: item.snippet.thumbnails.high.url,
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
"use strict";
|
||||
var parse = require("url").parse;
|
||||
var querystring = require('querystring');
|
||||
import { parse } from 'url';
|
||||
import querystring from 'querystring';
|
||||
|
||||
module.exports.match = function(url, type) {
|
||||
var parsed = parse(url);
|
||||
|
||||
export function* match(url, type) {
|
||||
const parsed = parse(url);
|
||||
if (parsed.host.match(/youtu\.be$/)) {
|
||||
return true;
|
||||
} else if (parsed.host.match(/youtube\.com$/)) {
|
||||
var query = querystring.parse(parsed.query);
|
||||
const query = querystring.parse(parsed.query);
|
||||
return !!query.v;
|
||||
}
|
||||
return false;
|
||||
|
|
12
package.json
12
package.json
|
@ -1,26 +1,24 @@
|
|||
{
|
||||
"name": "match.audio",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"repository": "https://github.com/kudos/match.audio",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "babel -d public/views views",
|
||||
"cover": "istanbul cover _mocha -- --require babel/register --require co-mocha test/**/*.js",
|
||||
"start": "babel-node app.js",
|
||||
"postinstall": "npm run build",
|
||||
"test": "mocha --require co-mocha --compilers js:babel/register test/**/*.js --timeout=10000",
|
||||
"watch": "parallelshell \"npm run watch-js\" \"npm run watch-server\"",
|
||||
"watch-js": "babel --modules system -wd public/views views",
|
||||
"watch-server": "nodemon -x \"babel-node\" -e js,jsx -i public/ app.js"
|
||||
},
|
||||
"engines": {
|
||||
"iojs": "^2.5.0",
|
||||
"iojs": "^3.1.0",
|
||||
"npm": "^3.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel": "~5.8.3",
|
||||
"babelify": "~6.1.3",
|
||||
"bluebird": "~2.9.34",
|
||||
"browserify": "~11.0.0",
|
||||
"co": "~4.6.0",
|
||||
"debug": "~2.2.0",
|
||||
"jspm": "~0.16.0",
|
||||
|
@ -39,7 +37,6 @@
|
|||
"react": "~0.13.3",
|
||||
"react-google-analytics": "~0.2.0",
|
||||
"react-router": "~0.13.3",
|
||||
"reactify": "~1.1.1",
|
||||
"spotify": "~0.3.0",
|
||||
"superagent": "~1.3.0",
|
||||
"superagent-bluebird-promise": "~2.0.2"
|
||||
|
@ -52,8 +49,7 @@
|
|||
"mocha": "~2.2.5",
|
||||
"nodemon": "~1.4.1",
|
||||
"parallelshell": "~2.0.0",
|
||||
"should": "~7.0.1",
|
||||
"spdy": "~2.0.4"
|
||||
"should": "~7.0.1"
|
||||
},
|
||||
"jspm": {
|
||||
"directories": {
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import createHandler from '../lib/react-handler';
|
||||
import {routes} from '../views/app';
|
||||
import { routes } from '../views/app';
|
||||
|
||||
module.exports = function* () {
|
||||
let recents = [];
|
||||
let docs = yield this.db.matches.find().sort({'created_at': -1}).limit(6).toArray();
|
||||
export default function* () {
|
||||
const recents = [];
|
||||
const docs = yield this.db.matches.find().sort({'created_at': -1}).limit(6).toArray();
|
||||
docs.forEach(function(doc) {
|
||||
let shares = Object.keys(doc.services).map(function (key) {return doc.services[key]; });
|
||||
shares.some(function(item) {
|
||||
|
@ -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}));
|
||||
|
||||
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';
|
||||
|
||||
module.exports = function* (next) {
|
||||
let url = 'http://' + this.request.url.substr(8);
|
||||
let parsed = parse(url);
|
||||
export default function* (next) {
|
||||
const url = 'http://' + this.request.url.substr(8);
|
||||
const parsed = parse(url);
|
||||
if (parsed.host.match(/mzstatic\.com/)) {
|
||||
let proxyResponse = yield request.get(url);
|
||||
const proxyResponse = yield request.get(url);
|
||||
this.set(proxyResponse.headers);
|
||||
this.body = proxyResponse.body;
|
||||
} else {
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import {parse} from 'url';
|
||||
import { parse } from 'url';
|
||||
import co from 'co';
|
||||
import lookup from '../lib/lookup';
|
||||
import services from '../lib/services';
|
||||
|
||||
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.'}});
|
||||
|
||||
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 :('}});
|
||||
|
||||
item.matched_at = new Date(); // eslint-disable-line camelcase
|
||||
let matches = {};
|
||||
const matches = {};
|
||||
matches[item.service] = item;
|
||||
|
||||
|
||||
|
@ -32,9 +32,9 @@ module.exports = function* () {
|
|||
continue;
|
||||
}
|
||||
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
|
||||
let update = {};
|
||||
const update = {};
|
||||
update['services.' + match.service] = match;
|
||||
yield this.db.matches.updateOne({_id: item.service + '$$' + item.id}, {'$set': update});
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react';
|
||||
import createHandler from '../lib/react-handler';
|
||||
import {routes} from '../views/app';
|
||||
import { routes } from '../views/app';
|
||||
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.sort(function(a, b) {
|
||||
return a.id && !b.id;
|
||||
|
@ -13,7 +13,7 @@ let formatAndSort = function(matches, serviceId) {
|
|||
return matches;
|
||||
};
|
||||
|
||||
module.exports = function* (serviceId, type, itemId, format, next) {
|
||||
export default function* (serviceId, type, itemId, format, next) {
|
||||
let matchedService;
|
||||
services.some(function(service) {
|
||||
matchedService = serviceId === service.id ? service : null;
|
||||
|
@ -24,19 +24,18 @@ module.exports = function* (serviceId, type, itemId, format, next) {
|
|||
return yield next;
|
||||
}
|
||||
|
||||
let shares = [];
|
||||
let doc = yield this.db.matches.findOne({_id: serviceId + '$$' + itemId});
|
||||
const doc = yield this.db.matches.findOne({_id: serviceId + '$$' + itemId});
|
||||
|
||||
this.assert(doc, 404, 'Not Found');
|
||||
|
||||
shares = formatAndSort(doc.services, serviceId);
|
||||
const shares = formatAndSort(doc.services, serviceId);
|
||||
|
||||
if (format === 'json') {
|
||||
this.body = {shares: shares};
|
||||
} 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}));
|
||||
|
||||
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(){
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
import 'should';
|
||||
import deezer from '../../lib/services/deezer';
|
||||
import * as deezer from '../../lib/services/deezer';
|
||||
|
||||
describe('Deezer', function(){
|
||||
describe('lookupId', 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');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
describe('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');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
@ -29,12 +29,12 @@ describe('Deezer', function(){
|
|||
describe('lookupUrl', function(){
|
||||
describe('parseUrl', 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);
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
import 'should';
|
||||
import google from '../../lib/services/google';
|
||||
import * as google from '../../lib/services/google';
|
||||
|
||||
describe('Google Play Music', function(){
|
||||
describe('lookupId', 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)');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
describe('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');
|
||||
});
|
||||
});
|
||||
|
||||
describe('lookupUrl', 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');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
import 'should';
|
||||
import itunes from '../../lib/services/itunes';
|
||||
import * as itunes from '../../lib/services/itunes';
|
||||
|
||||
describe('iTunes Music', function(){
|
||||
describe('lookupId', 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');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
describe('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');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
@ -29,12 +29,12 @@ describe('iTunes Music', function(){
|
|||
describe('lookupUrl', function(){
|
||||
describe('parseUrl', 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');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,26 +4,26 @@ import * as rdio from '../../lib/services/rdio';
|
|||
describe('Rdio', function(){
|
||||
describe('lookupId', 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)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('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)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseUrl', 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)');
|
||||
});
|
||||
|
||||
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)');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
import 'should';
|
||||
import spotify from '../../lib/services/spotify';
|
||||
import * as spotify from '../../lib/services/spotify';
|
||||
|
||||
describe('Spotify', function(){
|
||||
describe('lookupId', 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)');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
describe('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)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseUrl', 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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
import 'should';
|
||||
import xbox from '../../lib/services/xbox';
|
||||
import * as xbox from '../../lib/services/xbox';
|
||||
|
||||
describe('Xbox Music', function(){
|
||||
describe('lookupId', 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');
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
describe('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');
|
||||
});
|
||||
});
|
||||
|
||||
describe('lookupUrl', 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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import 'should';
|
||||
import youtube from '../../lib/services/youtube';
|
||||
import * as youtube from '../../lib/services/youtube';
|
||||
|
||||
describe('Youtube', function(){
|
||||
describe('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');
|
||||
});
|
||||
});
|
||||
|
|
10
views/app.js
10
views/app.js
|
@ -1,12 +1,12 @@
|
|||
import React from 'react';
|
||||
import Router, {Route, DefaultRoute, NotFoundRoute, RouteHandler} from 'react-router';
|
||||
import ga, {Initializer as GAInitiailizer} from 'react-google-analytics';
|
||||
import Router, { Route, DefaultRoute, NotFoundRoute, RouteHandler } from 'react-router';
|
||||
import ga, { Initializer as GAInitiailizer } from 'react-google-analytics';
|
||||
import Home from './home';
|
||||
import Share from './share';
|
||||
import Head from './head';
|
||||
import ErrorView from './error';
|
||||
|
||||
let App = React.createClass({
|
||||
const App = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<html>
|
||||
|
@ -24,7 +24,7 @@ let App = React.createClass({
|
|||
}
|
||||
});
|
||||
|
||||
let routes = (
|
||||
const routes = (
|
||||
<Route name='home' handler={App} path='/'>
|
||||
<DefaultRoute handler={Home} />
|
||||
<Route name='share' path=':service/:type/:id' handler={Share}/>
|
||||
|
@ -45,4 +45,4 @@ if (typeof window !== 'undefined') {
|
|||
ga('send', 'pageview');
|
||||
}
|
||||
|
||||
export {routes};
|
||||
export { routes };
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import {State} from 'react-router';
|
||||
import { State } from 'react-router';
|
||||
|
||||
export default React.createClass({
|
||||
|
||||
|
@ -8,9 +8,9 @@ export default React.createClass({
|
|||
router: React.PropTypes.func.isRequired
|
||||
},
|
||||
render: function() {
|
||||
var 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';
|
||||
var shareUrl = 'https://match.audio/' + this.getParams().service + '/' + this.getParams().type + '/' + this.getParams().id;
|
||||
const image = this.props.shares ? this.props.shares[0].artwork.large : 'https://match.audio/images/logo-512.png';
|
||||
const title = this.props.shares ? this.props.shares[0].name + ' by ' + this.props.shares[0].artist.name : 'Match Audio';
|
||||
const shareUrl = 'https://match.audio/' + this.getParams().service + '/' + this.getParams().type + '/' + this.getParams().id;
|
||||
return (
|
||||
<head>
|
||||
<script dangerouslySetInnerHTML={{__html: 'var timerStart = Date.now();'}}></script>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import request from 'superagent';
|
||||
import {Navigation, State, Link} from 'react-router';
|
||||
import { Navigation, State, Link } from 'react-router';
|
||||
import Faq from './faq';
|
||||
import Foot from './foot';
|
||||
|
||||
var Recent = React.createClass({
|
||||
const Recent = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (<div className='row'>
|
||||
|
@ -21,7 +21,7 @@ var Recent = React.createClass({
|
|||
|
||||
});
|
||||
|
||||
var RecentItem = React.createClass({
|
||||
const RecentItem = React.createClass({
|
||||
|
||||
render: function() {
|
||||
if (!this.props.item.artwork) {
|
||||
|
@ -38,7 +38,7 @@ var RecentItem = React.createClass({
|
|||
|
||||
});
|
||||
|
||||
var SearchForm = React.createClass({
|
||||
const SearchForm = React.createClass({
|
||||
|
||||
mixins: [ Navigation, State ],
|
||||
|
||||
|
@ -50,26 +50,25 @@ var SearchForm = React.createClass({
|
|||
},
|
||||
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
submitting: true
|
||||
});
|
||||
var that = this;
|
||||
e.preventDefault();
|
||||
var url = this.refs.url.getDOMNode().value.trim();
|
||||
const url = this.refs.url.getDOMNode().value.trim();
|
||||
if (!url) {
|
||||
that.setState({
|
||||
this.setState({
|
||||
submitting: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
request.post('/search').send({url: url}).end(function(req, res) {
|
||||
that.setState({
|
||||
request.post('/search').send({url: url}).end((req, res) => {
|
||||
this.setState({
|
||||
submitting: false
|
||||
});
|
||||
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 () {
|
||||
// Use this only on first page load, refresh whenever we navigate back.
|
||||
if (this.props.recents) {
|
||||
var recents = this.props.recents;
|
||||
const recents = this.props.recents;
|
||||
delete this.props.recents;
|
||||
return {
|
||||
recents: recents
|
||||
|
@ -115,11 +114,11 @@ export default React.createClass({
|
|||
|
||||
componentDidMount: function () {
|
||||
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({
|
||||
recents: res.body.recents
|
||||
});
|
||||
}.bind(this));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react';
|
||||
import request from 'superagent';
|
||||
import {State, Link} from 'react-router';
|
||||
import { State, Link } from 'react-router';
|
||||
import Foot from './foot';
|
||||
|
||||
var MusicItem = React.createClass({
|
||||
const MusicItem = React.createClass({
|
||||
|
||||
render: function() {
|
||||
if (!this.props.item.matched_at) {
|
||||
|
@ -88,7 +88,7 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
componentDidMount: function () {
|
||||
var complete = this.state.shares.length > 0;
|
||||
let complete = this.state.shares.length > 0;
|
||||
|
||||
this.state.shares.forEach(function(share) {
|
||||
if (typeof share.matched_at === 'undefined') {
|
||||
|
@ -96,9 +96,9 @@ export default React.createClass({
|
|||
}
|
||||
});
|
||||
|
||||
var getShares = function() {
|
||||
request.get(this.getPathname() + '.json').end(function(err, res) {
|
||||
var shares = res.body.shares;
|
||||
const getShares = () => {
|
||||
request.get(this.getPathname() + '.json').end((err, res) => {
|
||||
const shares = res.body.shares;
|
||||
complete = true;
|
||||
shares.forEach(function(share) {
|
||||
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
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
});
|
||||
};
|
||||
|
||||
if (!this.state.shares.length) {
|
||||
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.
|
||||
Array.prototype.forEach.call(document.querySelectorAll('.share-dialog'), function(dialog){
|
||||
dialog.addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
var w = 845;
|
||||
var h = 670;
|
||||
var dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
|
||||
var dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;
|
||||
dialog.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
const w = 845;
|
||||
const h = 670;
|
||||
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
|
||||
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;
|
||||
|
||||
var 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 width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
|
||||
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
|
||||
|
||||
var left = ((width / 2) - (w / 2)) + dualScreenLeft;
|
||||
var 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 left = ((width / 2) - (w / 2)) + dualScreenLeft;
|
||||
const top = ((height / 2) - (h / 2)) + dualScreenTop;
|
||||
const newWindow = window.open(dialog.href, 'Share Music', 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
|
||||
if (window.focus) {
|
||||
newWindow.focus();
|
||||
}
|
||||
|
@ -183,9 +183,9 @@ export default React.createClass({
|
|||
</div>
|
||||
</div>
|
||||
<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} />);
|
||||
}.bind(this))}
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue