radiomanifest.js 3.5 KB

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