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

142 lines
4 KiB
JavaScript

import { parse } from 'url';
import querystring from 'querystring';
import request from 'superagent';
import urlMatch from './url';
const apiRoot = 'https://itunes.apple.com';
export async function parseUrl(url) {
const parsed = parse(url);
const matches = parsed.path.match(/[/]?([/]?[a-z]{2}?)?[/]+album[/]+([^/]+)[/]+([^?]+)/);
const query = querystring.parse(parsed.query);
let itunesId = matches[3];
if (matches) {
let type = 'album';
if (matches[3].match(/^id/)) {
itunesId = matches[3].substr(2);
if (query.i) {
type = 'track';
itunesId = query.i;
}
}
return await module.exports.lookupId(itunesId, type, matches[1] || 'us');
}
throw new Error();
}
export async function lookupId(possibleId, type, countrycode) {
let cc = countrycode;
let id = possibleId;
if (String(possibleId).match(/^[a-z]{2}/)) {
cc = possibleId.substr(0, 2);
id = possibleId.substr(2);
}
let path = `/lookup?id=${id}`;
if (cc) {
path = `/${cc}${path}`;
}
const response = await request.get(apiRoot + path);
let result = JSON.parse(response.text);
if (!result.results || result.resultCount === 0 || !result.results[0].collectionId) {
const error = new Error('Not Found');
error.status = 404;
throw error;
} else {
result = result.results[0];
const item = {
service: 'itunes',
type,
id: cc + id,
name: result.trackName ? result.trackName : result.collectionName,
streamUrl: null,
purchaseUrl: result.collectionViewUrl,
artwork: {
small: `${result.artworkUrl100.replace('100x100', '200x200').replace('.mzstatic.com', '.mzstatic.com').replace('http://', 'https://')}`,
large: `${result.artworkUrl100.replace('100x100', '600x600').replace('.mzstatic.com', '.mzstatic.com').replace('http://', 'https://')}`,
},
artist: {
name: result.artistName,
},
};
if (type === 'track') {
item.album = {
name: result.collectionName,
};
}
return item;
}
}
export async function search(data) {
const markets = ['us', 'gb', 'jp', 'br', 'de', 'es'];
let query;
let album;
let entity;
const type = data.type;
if (type === 'album') {
query = `${data.artist.name} ${data.name}`;
album = data.name;
entity = 'album';
} else if (type === 'track') {
query = `${data.artist.name} ${data.albumName} ${data.name}`;
album = data.albumName;
entity = 'musicTrack';
}
for (const market of markets) { // eslint-disable-line
const path = `/${market}/search?term=${encodeURIComponent(query)}&media=music&entity=${entity}`;
const response = await request.get(apiRoot + path);
let result = JSON.parse(response.text);
if (!result.results[0]) {
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();
}
return await search(cleanedData);
}
} else {
result = result.results[0];
const item = {
service: 'itunes',
type,
id: `us${result.collectionId}`,
name: result.trackName ? result.trackName : result.collectionName,
streamUrl: result.collectionViewUrl,
purchaseUrl: result.collectionViewUrl,
artwork: {
small: `${result.artworkUrl100.replace('100x100', '200x200').replace('.mzstatic.com', '.mzstatic.com').replace('http://', 'https://')}`,
large: `${result.artworkUrl100.replace('100x100', '600x600').replace('.mzstatic.com', '.mzstatic.com').replace('http://', 'https://')}`,
},
artist: {
name: result.artistName,
},
};
if (type === 'track') {
item.album = {
name: result.collectionName,
};
}
return item;
}
}
return { service: 'itunes' };
}
export const id = 'itunes';
export const match = urlMatch;