bandcamp-fetch/src/lib/discovery/DiscoverOptionsParser.ts
patrickkfkan be7010c217 v1.0.0
2023-06-10 22:52:27 +08:00

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);
}
}