/** * 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, };