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,21 +1,18 @@
import { parse } from 'url';
import querystring from 'querystring';
import request from 'superagent';
import 'superagent-bluebird-promise';
import { match as urlMatch } from './url';
import debuglog from 'debug';
import urlMatch from './url';
const debug = debuglog('match.audio: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.');
debug('XBOX_CLIENT_ID and XBOX_CLIENT_SECRET environment variables not found, deactivating Xbox Music.');
}
const credentials = {
clientId: process.env.XBOX_CLIENT_ID,
clientSecret: process.env.XBOX_CLIENT_SECRET
clientSecret: process.env.XBOX_CLIENT_SECRET,
};
const apiRoot = 'https://music.xboxlive.com/1/content';
@ -28,10 +25,14 @@ function* getAccessToken() {
const data = {
client_id: credentials.clientId,
client_secret: credentials.clientSecret,
scope: scope,
grant_type: grantType
scope,
grant_type: grantType,
};
const result = yield request.post(authUrl).timeout(10000).send(data).set('Content-type', 'application/x-www-form-urlencoded').promise();
const result = yield request.post(authUrl)
.timeout(10000)
.send(data)
.set('Content-type', 'application/x-www-form-urlencoded')
.promise();
return result.body.access_token;
}
@ -44,41 +45,27 @@ function formatResponse(match) {
streamUrl: match.Link,
purchaseUrl: null,
artwork: {
small: match.ImageUrl.replace('http://', 'https://') + '&w=250&h=250',
large: match.ImageUrl.replace('http://', 'https://') + '&w=500&h=500'
small: `${match.ImageUrl.replace('http://', 'https://')}&w=250&h=250`,
large: `${match.ImageUrl.replace('http://', 'https://')}&w=500&h=500`,
},
artist: {
name: match.Artists[0].Artist.Name
}
name: match.Artists[0].Artist.Name,
},
};
if (match.Album) {
item.album = {name: match.Album.Name}
item.album = { name: match.Album.Name };
}
return item;
}
function* apiCall(path) {
const access_token = yield getAccessToken();
return request.get(apiRoot + path).timeout(10000).set('Authorization', 'Bearer ' + access_token).promise();
}
export const match = urlMatch;
export function* parseUrl(url) {
const parsed = parse(url);
const parts = parsed.path.split('/');
const type = parts[1];
const idMatches = parts[4].match(/bz.[\w\-]+/);
const id = idMatches[0].replace('bz.', 'music.');
if (!id) {
return false;
}
return yield lookupId(id, type);
const accessToken = yield getAccessToken();
return request.get(apiRoot + path).timeout(10000).set('Authorization', `Bearer ${accessToken}`).promise();
}
export function* lookupId(id, type) {
const path = '/' + id + '/lookup';
const apiType = type.charAt(0).toUpperCase() + type.substr(1) + 's';
const path = `/${id}/lookup`;
const apiType = `${type.charAt(0).toUpperCase() + type.substr(1)}s`;
try {
const result = yield apiCall(path);
return formatResponse(result.body[apiType].Items[0]);
@ -86,31 +73,61 @@ export function* lookupId(id, type) {
if (e.status !== 404) {
debug(e.body);
}
return {service: 'xbox'};
return { service: 'xbox' };
}
};
}
export function* parseUrl(url) {
const parsed = parse(url);
const parts = parsed.path.split('/');
const type = parts[1];
const idMatches = parts[4].match(/bz.[\w-]+/);
const id = idMatches[0].replace('bz.', 'music.');
if (!id) {
return false;
}
return yield lookupId(id, type);
}
function exactMatch(item, artist, haystack) {
// try to find exact match
return haystack.find((entry) => {
if (entry.Name === item && entry.Artists[0].Artist.Name === artist) {
return entry;
}
return false;
});
}
function looseMatch(item, artist, haystack) {
// try to find exact match
return haystack.find((entry) => {
if (entry.Name.indexOf(item) >= 0 && entry.Artists[0].Artist.Name.indexOf(artist) >= 0) {
return entry;
}
return false;
});
}
export function* search(data) {
var cleanParam = function(str) {
return str.replace(/[\:\?\&\(\)\[\]]+/g, '');
function cleanParam(str) {
return str.replace(/[:?&()[\]]+/g, '');
}
let query, album;
let query;
const type = data.type;
if (type == 'album') {
query = cleanParam(data.artist.name.substring(0, data.artist.name.indexOf('&'))) + ' ' + cleanParam(data.name);
album = data.name;
} else if (type == 'track') {
query = cleanParam(data.artist.name.substring(0, data.artist.name.indexOf('&'))) + ' ' + cleanParam(data.name);
album = data.albumName
if (type === 'album') {
query = `${cleanParam(data.artist.name.substring(0, data.artist.name.indexOf('&')))} ${cleanParam(data.name)}`;
} else if (type === 'track') {
query = `${cleanParam(data.artist.name.substring(0, data.artist.name.indexOf('&')))} ${cleanParam(data.name)}`;
}
const name = data.name;
const path = '/music/search?q=' + encodeURIComponent(query.trim()) + '&filters=' + type + 's';
const path = `/music/search?q=${encodeURIComponent(query.trim())}&filters=${type}s`;
try {
const result = yield apiCall(path);
const apiType = type.charAt(0).toUpperCase() + type.substr(1) + 's';
const apiType = `${type.charAt(0).toUpperCase() + type.substr(1)}s`;
let match = exactMatch(name, data.artist.name, result.body[apiType].Items, type);
if (!match) {
@ -121,24 +138,10 @@ export function* search(data) {
return formatResponse(match);
}
} catch (err) {
return {service: 'xbox'};
return { service: 'xbox' };
}
};
function exactMatch(item, artist, haystack, type) {
// try to find exact match
return haystack.find(function(entry) {
if (entry.Name === item && entry.Artists[0].Artist.Name === artist) {
return entry;
}
});
return { service: 'xbox' };
}
function looseMatch(item, artist, haystack, type) {
// try to find exact match
return haystack.find(function(entry) {
if (entry.Name.indexOf(item) >= 0 && entry.Artists[0].Artist.Name.indexOf(artist) >= 0) {
return entry;
}
});
}
export const id = 'xbox';
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(/music.microsoft.com$/)) {
return false;
}
const parts = parsed.path.split('/');
return (parts[1] == 'album' || parts[1] == 'track') && parts[4];
};
return (parts[1] === 'album' || parts[1] === 'track') && parts[4];
}