combine.fm/lib/services/deezer/index.js

149 lines
3.9 KiB
JavaScript
Raw Normal View History

2015-08-20 23:22:57 +01:00
import { parse } from 'url';
2015-06-03 21:45:54 -07:00
import request from 'superagent';
2017-11-11 20:55:09 +00:00
import debuglog from 'debug';
2017-07-20 14:31:07 +01:00
import urlMatch from './url';
2017-11-11 20:55:09 +00:00
const debug = debuglog('combine.fm:deezer');
2015-06-03 21:45:54 -07:00
const apiRoot = 'https://api.deezer.com';
2015-08-20 23:22:57 +01:00
export function parseUrl(url) {
2017-07-20 14:31:07 +01:00
const matches = parse(url).path.match(/\/(album|track)[/]+([^/]+)/);
if (matches && matches[2]) {
return module.exports.lookupId(matches[2], matches[1]);
}
2017-07-20 14:31:07 +01:00
throw new Error();
}
function exactMatch(needle, haystack, type, various) {
2018-04-08 16:31:46 +01:00
// try to find exact match
2017-07-20 14:31:07 +01:00
return haystack.find((entry) => {
if (!entry[type] || (various && (entry.artist.name !== 'Various' || entry.artist.name !== 'Various Artists'))) {
return false;
}
const title = entry[type].title;
if (title) {
return entry;
}
return false;
});
}
function looseMatch(needle, haystack, type, various) {
2018-04-08 16:31:46 +01:00
// try to find exact match
2017-07-20 14:31:07 +01:00
return haystack.find((entry) => {
if (!entry[type] || (various && (entry.artist.name !== 'Various' || entry.artist.name !== 'Various Artists'))) {
return false;
}
const name = entry[type].title || entry[type].name;
if (name.indexOf(needle) >= 0) {
return entry[type];
}
return false;
});
}
2018-04-14 00:18:48 +01:00
export async function lookupId(id, type) {
2017-11-11 20:55:09 +00:00
const path = `/${type}/${id}?size=xl`;
2018-04-14 00:18:48 +01:00
const { body } = await request.get(apiRoot + path);
2015-06-03 21:45:54 -07:00
if (!body || body.error) {
2017-07-20 14:31:07 +01:00
const error = new Error('Not Found');
2015-06-03 21:45:54 -07:00
error.status = 404;
return Promise.reject(error);
}
2017-07-20 14:31:07 +01:00
const item = body;
2017-11-11 20:55:09 +00:00
2017-07-20 14:31:07 +01:00
const artwork = {
2017-11-11 20:55:09 +00:00
small: item.cover_medium || item.artist.picture_medium,
large: item.cover_xl || item.artist.picture_xl,
2015-06-03 21:45:54 -07:00
};
2017-11-11 20:55:09 +00:00
2015-06-03 21:45:54 -07:00
if (type === 'album') {
return Promise.resolve({
service: 'deezer',
2017-07-20 14:31:07 +01:00
type,
2015-06-03 21:45:54 -07:00
id: item.id,
name: item.title,
streamUrl: item.link,
purchaseUrl: null,
2017-07-20 14:31:07 +01:00
artwork,
2015-06-03 21:45:54 -07:00
artist: {
2017-07-20 14:31:07 +01:00
name: item.artist.name,
},
2015-06-03 21:45:54 -07:00
});
} else if (type === 'track') {
return Promise.resolve({
service: 'deezer',
2017-07-20 14:31:07 +01:00
type,
2015-06-03 21:45:54 -07:00
id: item.id,
name: item.title,
streamUrl: item.album.link,
purchaseUrl: null,
2017-07-20 14:31:07 +01:00
artwork,
2015-06-03 21:45:54 -07:00
artist: {
2017-07-20 14:31:07 +01:00
name: item.artist.name,
2015-06-03 21:45:54 -07:00
},
album: {
2017-07-20 14:31:07 +01:00
name: item.album.title,
},
2014-12-04 20:02:27 +00:00
});
2015-06-03 21:45:54 -07:00
}
2017-07-20 14:31:07 +01:00
return Promise.reject(new Error());
}
2018-04-14 00:18:48 +01:00
export async function search(data, original = {}) {
2017-07-20 14:31:07 +01:00
function cleanParam(str) {
return str.replace(/[:?&]+/, '');
}
let query;
let album;
const { type } = data;
2017-05-07 20:57:12 +01:00
const various = data.artist.name === 'Various Artists' || data.artist.name === 'Various';
2015-06-03 21:45:54 -07:00
if (type === 'album') {
2017-05-07 20:57:12 +01:00
// Deezer is shitty about artists with these names, strip them instead
if (various) {
query = cleanParam(data.name);
} else {
2017-07-20 14:31:07 +01:00
query = `${cleanParam(data.artist.name)} ${cleanParam(data.name)}`;
2017-05-07 20:57:12 +01:00
}
album = data.name;
2015-06-03 21:45:54 -07:00
} else if (type === 'track') {
2017-07-20 14:31:07 +01:00
query = `${cleanParam(data.artist.name)} ${cleanParam(data.albumName)} ${cleanParam(data.name)}`;
album = data.albumName;
}
2017-07-20 14:31:07 +01:00
const path = `/search/${type}?q=${encodeURIComponent(query)}`;
2017-05-07 20:57:12 +01:00
2018-04-14 00:18:48 +01:00
const response = await request.get(apiRoot + path);
2017-05-07 20:57:12 +01:00
const name = original.name || data.name;
if (response.body.data.length > 0) {
2017-07-20 14:31:07 +01:00
let match = exactMatch(name, response.body.data, data.type, various);
if (!match) {
2017-05-07 20:57:12 +01:00
match = looseMatch(name, response.body.data, data.type, various);
}
2018-04-14 00:18:48 +01:00
return await module.exports.lookupId(response.body.data[0].id, type);
2015-06-03 21:45:54 -07:00
}
2017-07-20 14:31:07 +01:00
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.albumName = matches[0].trim();
2017-05-07 20:57:12 +01:00
}
2018-04-14 00:18:48 +01:00
return await module.exports.search(cleanedData, data);
2017-07-20 14:31:07 +01:00
}
return Promise.resolve({ service: 'deezer' });
2017-05-07 20:57:12 +01:00
}
2017-07-20 14:31:07 +01:00
export const id = 'deezer';
export const match = urlMatch;