radiomanifest.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. const fetch = require('isomorphic-unfetch')
  2. function getStreaminfoUrl (siteurl) {
  3. return siteurl + '/streaminfo.json' // XXX: improve this logic
  4. }
  5. function getManifestUrl (siteurl) {
  6. return siteurl + '/radiomanifest.xml' // XXX: improve this logic
  7. }
  8. class Radio {
  9. constructor (sources, schedule, shows, feed) {
  10. this.streaming = new RadioStreaming(sources)
  11. this.schedule = schedule
  12. this.shows = shows
  13. this.feed = feed
  14. this.name = ''
  15. }
  16. getStreaming () {
  17. return this.streaming
  18. }
  19. setName (name) {
  20. this.name = name
  21. }
  22. getShowByName (showName) {
  23. }
  24. getSchedule () {
  25. }
  26. getShowAtTime () {
  27. }
  28. static fromDOM (xml) {
  29. const doc = xml.cloneNode(true)
  30. let res = doc.evaluate('/radio-manifest/streaming/source', doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
  31. const sources = []
  32. for (let i = 0; i < res.snapshotLength; i++) {
  33. const src = res.snapshotItem(i)
  34. if (!src.hasAttribute('priority')) {
  35. src.setAttribute('priority', '0')
  36. } else if (parseInt(src.getAttribute('priority'), 10) < 0) {
  37. continue
  38. }
  39. sources.push(src)
  40. }
  41. sources.sort(function cmp (a, b) {
  42. return parseInt(a.getAttribute('priority', 10)) < parseInt(b.getAttribute('priority', 10))
  43. })
  44. res = doc.evaluate('/radio-manifest/schedule', doc)
  45. const scheduleEl = res.iterateNext()
  46. let schedule = null
  47. if (scheduleEl !== null) {
  48. schedule = scheduleEl.getAttribute('src')
  49. }
  50. res = xml.evaluate('/radio-manifest/shows', xml)
  51. const showsEl = res.iterateNext()
  52. let shows = null
  53. if (showsEl !== null) {
  54. shows = showsEl.getAttribute('src')
  55. }
  56. res = xml.evaluate('/radio-manifest/feed', xml)
  57. const feedEl = res.iterateNext()
  58. let feed = null
  59. if (feedEl !== null) {
  60. feed = feedEl.getAttribute('src')
  61. }
  62. const manifest = new Radio(sources, schedule, shows, feed)
  63. return manifest
  64. }
  65. }
  66. function RadioStreaming (sources) {
  67. this.sources = sources
  68. }
  69. RadioStreaming.prototype.getOptions = function () {
  70. return this.sources.map(function (x) {
  71. return x.getAttribute('name')
  72. })
  73. }
  74. RadioStreaming.prototype.getSource = function (name) {
  75. if (name === undefined) {
  76. }
  77. const s = this.sources.find(function (x) {
  78. return x.getAttribute('name') === name
  79. })
  80. if (s === undefined) return s
  81. return s.getAttribute('src')
  82. }
  83. async function get (siteurl, options) {
  84. let resp = await fetch(getManifestUrl(siteurl))
  85. let text = await resp.text()
  86. const parser = new DOMParser()
  87. const dom = parser.parseFromString(text, 'text/xml')
  88. const manifest = Radio.fromDOM(dom)
  89. resp = null
  90. try {
  91. resp = await fetch(getStreaminfoUrl(siteurl))
  92. } catch (e) {
  93. true
  94. }
  95. if(resp !== null) {
  96. try {
  97. text = await resp.text()
  98. const data = JSON.parse(text)
  99. const name = data['icy-name']
  100. if (name !== undefined) {
  101. manifest.setName(name)
  102. }
  103. } catch (e) {
  104. if (e instanceof SyntaxError) {
  105. true
  106. } else {
  107. console.error('Error', e)
  108. throw e
  109. }
  110. }
  111. }
  112. // XXX: in base alle options fai fetch anche di altra roba
  113. return manifest
  114. }
  115. function parseM3U (body) {
  116. body.split('\n').filter((e) => {
  117. if (e.startsWith('#')) {
  118. return false
  119. } else {
  120. try { new URL(e); return true } catch { return false }
  121. }
  122. })
  123. }
  124. module.exports = {
  125. get: get,
  126. objs: {
  127. Radio: Radio,
  128. RadioStreaming: RadioStreaming
  129. },
  130. parsers: {
  131. M3U: parseM3U,
  132. radioManifest: Radio.fromDOM
  133. }
  134. }