Fix Google Play Music and Spotify

This commit is contained in:
Jonathan Cremin 2017-07-20 14:31:07 +01:00
parent 688ec0f2f9
commit 6c29d50f1e
21 changed files with 566 additions and 559 deletions

View file

@ -1,101 +1,122 @@
import { parse } from 'url';
import bluebird from 'bluebird';
import spotifyCB from 'spotify';
import request from 'superagent';
import 'superagent-bluebird-promise';
const spotify = bluebird.promisifyAll(spotifyCB);
import { match as urlMatch } from './url';
import SpotifyWebApi from 'spotify-web-api-node';
import urlMatch from './url';
export let id = "spotify";
const spotify = new SpotifyWebApi({
clientId: process.env.SPOTIFY_CLIENT_ID,
clientSecret: process.env.SPOTIFY_CLIENT_SECRET,
redirectUri: 'https://match.audio',
});
export const match = urlMatch;
export function* parseUrl(url) {
var matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
function exactMatch(needle, haystack, type) {
// try to find exact match
return haystack.find((entry) => {
if (entry.type !== type) {
return false;
}
if (matches && matches[2]) {
return yield lookupId(matches[2], matches[1]);
}
if (entry.name === needle) {
return entry;
}
return false;
});
}
function looseMatch(needle, haystack, type) {
// try to find exact match
return haystack.find((entry) => {
if (entry.type !== type) {
return false;
}
if (entry.name.indexOf(needle) >= 0) {
return entry;
}
return false;
});
}
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;
}
const token = yield spotify.clientCredentialsGrant();
spotify.setAccessToken(token.body['access_token']);
let data = yield spotify[`get${type.charAt(0).toUpperCase()}${type.slice(1)}s`]([id]);
var artist = data.artists[0];
data = data.body[`${type}s`][0];
if (type == "album") {
const artist = data.artists[0];
if (type === 'album') {
return {
service: "spotify",
type: type,
service: 'spotify',
type,
id: data.id,
name: data.name,
streamUrl: "https://play.spotify.com/" + type + "/" + data.id,
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:"),
small: data.images[1].url.replace('http:', 'https:'),
large: data.images[0].url.replace('http:', 'https:'),
},
artist: {
name: artist.name
}
name: artist.name,
},
};
} else if (type == "track") {
} else if (type === 'track') {
return {
service: "spotify",
type: type,
service: 'spotify',
type,
id: data.id,
name: data.name,
streamUrl: "https://play.spotify.com/" + type + "/" + data.id,
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:"),
small: data.album.images[1].url.replace('http:', 'https:'),
large: data.album.images[0].url.replace('http:', 'https:'),
},
artist: {
name: artist.name
name: artist.name,
},
album: {
name: data.album.name
}
name: data.album.name,
},
};
}
return { service: 'spotify' };
}
export function* search(data, original={}) {
export function* search(data, original = {}) {
const token = yield spotify.clientCredentialsGrant();
spotify.setAccessToken(token.body['access_token']);
const markets = ['US', 'GB', 'JP', 'BR', 'DE', 'ES'];
const cleanParam = function(str) {
var chopChars = ['&', '[', '('];
chopChars.forEach(function(chr) {
function cleanParam(str) {
const chopChars = ['&', '[', '('];
chopChars.forEach((chr) => {
if (data.artist.name.indexOf('&') > 0) {
str = str.substring(0, data.artist.name.indexOf(chr));
str = str.substring(0, data.artist.name.indexOf(chr)); // eslint-disable-line no-param-reassign,max-len
}
})
return str.replace(/[\:\?]+/, "");
});
return str.replace(/[:?]+/, '');
}
let query, album;
let query;
const type = data.type;
if (type == "album") {
query = "artist:" + cleanParam(data.artist.name) + " album:" + cleanParam(data.name);
album = data.name;
} else if (type == "track") {
query = "artist:" + cleanParam(data.artist.name) + " track:" + cleanParam(data.name) + ( cleanParam(data.albumName).length > 0 ? " album:" + cleanParam(data.albumName): "");
album = data.albumName;
if (type === 'album') {
query = `artist:${cleanParam(data.artist.name)} album:${cleanParam(data.name)}`;
} else if (type === 'track') {
query = `artist:${cleanParam(data.artist.name)} track:${cleanParam(data.name)}${cleanParam(data.albumName).length > 0 ? ` album:${cleanParam(data.albumName)}` : ''}`;
}
for (let market of markets) {
const response = yield request.get('https://api.spotify.com/v1/search?type=' + type + '&q=' + encodeURI(query) + '&market=' + market);
const items = response.body[type + 's'].items;
for (const market of markets) { // eslint-disable-line
const response = yield spotify[`search${type.charAt(0).toUpperCase()}${type.slice(1)}s`](query, { market });
const items = response.body[`${type}s`].items;
const name = original.name || data.name;
let match;
if (!(match = exactMatch(name, items, type))) {
let match = exactMatch(name, items, type);
if (!match) {
match = looseMatch(name, items, type);
}
@ -107,31 +128,17 @@ export function* search(data, original={}) {
}
}
}
return {service: "spotify"};
return { service: 'spotify' };
}
function exactMatch(needle, haystack, type) {
// try to find exact match
return haystack.find(function(entry) {
if (entry.type !== type) {
return false;
}
export function* parseUrl(url) {
const matches = parse(url).path.match(/\/(album|track)[/]+([^/]+)/);
if (entry.name === needle) {
return entry;
}
});
if (matches && matches[2]) {
return yield lookupId(matches[2], matches[1]);
}
throw new Error();
}
function looseMatch(needle, haystack, type) {
// try to find exact match
return haystack.find(function(entry) {
if (entry.type !== type) {
return false;
}
if (entry.name.indexOf(needle) >= 0) {
return entry
}
});
}
export const id = 'spotify';
export const match = urlMatch;

View file

@ -1,11 +1,11 @@
import { parse } from 'url';
export function* match(url, type) {
export default function match(url) {
const parsed = parse(url);
if (!parsed.host.match(/spotify\.com$/)) {
return false;
}
const matches = parse(url).path.match(/\/(album|track)[\/]+([^\/]+)/);
const matches = parse(url).path.match(/\/(album|track)[/]+([^/]+)/);
return matches && !!matches[2];
};
}