radiomanifest.js 3.1 KB

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