61 lines
2.2 KiB
TypeScript
61 lines
2.2 KiB
TypeScript
import { load as cheerioLoad } from 'cheerio';
|
|
import { DiscoverOptions } from '../types/Discovery';
|
|
import { ParseError } from '../utils/Parse';
|
|
|
|
export default class DiscoverOptionsParser {
|
|
static parseOptions(html: string): DiscoverOptions {
|
|
const $ = cheerioLoad(html);
|
|
const blob = $('#pagedata[data-blob]').attr('data-blob');
|
|
if (!blob) {
|
|
throw new ParseError('Failed to parse discover options: blob not found in data.', html);
|
|
}
|
|
let parsed;
|
|
try {
|
|
parsed = JSON.parse(blob);
|
|
}
|
|
catch (error: any) {
|
|
throw new ParseError('Failed to parse discover options: JSON error.', blob, error);
|
|
}
|
|
const options = parsed?.discover_2015?.options;
|
|
if (options && typeof options === 'object') {
|
|
const result: DiscoverOptions = {
|
|
genres: [],
|
|
subgenres: {},
|
|
sortBys: [],
|
|
artistRecommendationTypes: [],
|
|
locations: [],
|
|
formats: [],
|
|
times: []
|
|
};
|
|
if (Array.isArray(options.r)) {
|
|
result.artistRecommendationTypes = options.r.map((r: any) => ({ name: r.name, value: r.value }));
|
|
}
|
|
if (Array.isArray(options.l)) {
|
|
result.locations = options.l.map((l: any) => ({ name: l.name, value: l.value }));
|
|
}
|
|
if (Array.isArray(options.w)) {
|
|
result.times = options.w.map((w: any) => ({ name: w.name, value: w.value, title: w.title }));
|
|
}
|
|
if (Array.isArray(options.f)) {
|
|
result.formats = options.f.map((f: any) => ({ name: f.name, value: f.value }));
|
|
}
|
|
if (Array.isArray(options.s)) {
|
|
result.sortBys = options.s.map((s: any) => ({ name: s.name, value: s.value }));
|
|
}
|
|
if (typeof options.t === 'object') {
|
|
for (const [ genre, subgenres ] of Object.entries(options.t)) {
|
|
if (Array.isArray(subgenres)) {
|
|
result.subgenres[genre] = subgenres.map((sg: any) => ({ name: sg.name, value: sg.value }));
|
|
}
|
|
}
|
|
}
|
|
if (Array.isArray(options.g)) {
|
|
result.genres = options.g.map((g: any) => ({ name: g.name, value: g.value }));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
throw new ParseError('Failed to parse discover options: blob is missing or has invalid \'discover_2015.options\' field.', parsed);
|
|
}
|
|
}
|