/** * Represents a single show. This show could be defined in the shows.xml file, or could be inferred from the * schedule. */ class RadioShow { constructor(name, description, website, feed, schedule, radio_calendar) { this.name = name this.description = description this.website = website this.feed = feed this.schedule = schedule this.radio_calendar = radio_calendar } getName() { return this.name } getWebsite() { return this.website } getFeed() { return this.feed } getSchedule() { return this.schedule } } /** * @private * @return {Array} */ function parseRadioShows(xml) { const doc = xml.cloneNode(true) const bookmarks = doc.evaluate('//bookmark', doc, showsNamespaceResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null) const shows = [] for (let i = 0; i < bookmarks.snapshotLength; i++) { const bm = bookmarks.snapshotItem(i) let name = doc.evaluate('./info/metadata/show:name', bm, showsNamespaceResolver, XPathResult.STRING_TYPE).stringValue if (name === '') { name = doc.evaluate('./title', bm, showsNamespaceResolver, XPathResult.STRING_TYPE).stringValue } let website = doc.evaluate('./info/metadata/show:website', bm, showsNamespaceResolver, XPathResult.STRING_TYPE).stringValue if (website === '') { website = bm.getAttribute('href') } const feed = doc.evaluate('./info/metadata/show:feed', bm, showsNamespaceResolver, XPathResult.STRING_TYPE).stringValue const schedule = doc.evaluate('./info/metadata/show:schedule', bm, showsNamespaceResolver, XPathResult.STRING_TYPE).stringValue let description = doc.evaluate('./info/metadata/show:description', bm, showsNamespaceResolver, XPathResult.STRING_TYPE).stringValue if (description === '') { description = doc.evaluate('./desc', bm, showsNamespaceResolver, XPathResult.STRING_TYPE).stringValue } const show = new RadioShow(name, description || null, website || null, feed || null, schedule || null) shows.push(show) } return shows } async function getShows(manifest) { if (manifest.showsURL) { let resp = null try { resp = await fetch(manifest.showsURL) } catch (e) { true } if (resp !== null) { try { const text = await resp.text() const parser = new DOMParser() const showsDom = parser.parseFromString(text, 'text/xml') return parseRadioShows(showsDom) } catch (e) { console.error('Error while parsing shows file', e) throw e } } } } function showsNamespaceResolver(prefix) { const prefixes = { show: 'https://radiomanifest.degenerazione.xyz/shows/', } return prefixes[prefix] || null } export default { get: getShows, parse: parseRadioShows, RadioShow: RadioShow, }