123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- const fetch = require('isomorphic-unfetch')
- function getStreaminfoUrl (siteurl) {
- return siteurl + '/streaminfo.json' // XXX: improve this logic
- }
- function getManifestUrl (siteurl) {
- return siteurl + '/radiomanifest.xml' // XXX: improve this logic
- }
- class Radio {
- constructor (sources, schedule, shows, feed) {
- this.streaming = new RadioStreaming(sources)
- this.schedule = schedule
- this.shows = shows
- this.feed = feed
- this.name = ''
- }
- getStreaming () {
- return this.streaming
- }
- setName (name) {
- this.name = name
- }
- getShowByName (showName) {
- }
- getSchedule () {
- }
- getShowAtTime () {
- }
- static fromDOM (xml) {
- const doc = xml.cloneNode(true)
- let res = doc.evaluate('/radio-manifest/streaming/source', doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
- const sources = []
- for (let i = 0; i < res.snapshotLength; i++) {
- const src = res.snapshotItem(i)
- if (!src.hasAttribute('priority')) {
- src.setAttribute('priority', '0')
- } else if (parseInt(src.getAttribute('priority'), 10) < 0) {
- continue
- }
- sources.push(src)
- }
- sources.sort(function cmp (a, b) {
- return parseInt(a.getAttribute('priority', 10)) < parseInt(b.getAttribute('priority', 10))
- })
- res = doc.evaluate('/radio-manifest/schedule', doc)
- const scheduleEl = res.iterateNext()
- let schedule = null
- if (scheduleEl !== null) {
- schedule = scheduleEl.getAttribute('src')
- }
- res = xml.evaluate('/radio-manifest/shows', xml)
- const showsEl = res.iterateNext()
- let shows = null
- if (showsEl !== null) {
- shows = showsEl.getAttribute('src')
- }
- res = xml.evaluate('/radio-manifest/feed', xml)
- const feedEl = res.iterateNext()
- let feed = null
- if (feedEl !== null) {
- feed = feedEl.getAttribute('src')
- }
- const manifest = new Radio(sources, schedule, shows, feed)
- return manifest
- }
- }
- function RadioStreaming (sources) {
- this.sources = sources
- }
- RadioStreaming.prototype.getOptions = function () {
- return this.sources.map(function (x) {
- return x.getAttribute('name')
- })
- }
- RadioStreaming.prototype.getSource = function (name) {
- if (name === undefined) {
- }
- const s = this.sources.find(function (x) {
- return x.getAttribute('name') === name
- })
- if (s === undefined) return s
- return s.getAttribute('src')
- }
- async function get (siteurl, options) {
- let resp = await fetch(getManifestUrl(siteurl))
- let text = await resp.text()
- const parser = new DOMParser()
- const dom = parser.parseFromString(text, 'text/xml')
- const manifest = Radio.fromDOM(dom)
- resp = null
- try {
- resp = await fetch(getStreaminfoUrl(siteurl))
- } catch (e) {
- true
- }
- if(resp !== null) {
- try {
- text = await resp.text()
- const data = JSON.parse(text)
- const name = data['icy-name']
- if (name !== undefined) {
- manifest.setName(name)
- }
- } catch (e) {
- if (e instanceof SyntaxError) {
- true
- } else {
- console.error('Error', e)
- throw e
- }
- }
- }
- // XXX: in base alle options fai fetch anche di altra roba
- return manifest
- }
- function parseM3U (body) {
- body.split('\n').filter((e) => {
- if (e.startsWith('#')) {
- return false
- } else {
- try { new URL(e); return true } catch { return false }
- }
- })
- }
- module.exports = {
- get: get,
- objs: {
- Radio: Radio,
- RadioStreaming: RadioStreaming
- },
- parsers: {
- M3U: parseM3U,
- radioManifest: Radio.fromDOM
- }
- }
|