Ver código fonte

support schedule

boyska 2 anos atrás
pai
commit
5bfe52c235
3 arquivos alterados com 136 adições e 5 exclusões
  1. 117 0
      calendar.js
  2. 1 0
      package.json
  3. 18 5
      radiomanifest.js

+ 117 - 0
calendar.js

@@ -0,0 +1,117 @@
+const ICAL = require('ical.js')
+const shows = require('./shows.js')
+
+class RadioSchedule {
+  constructor (calendar, radio) {
+    this.calendar = calendar  // ICAL.Calendar
+    this.radio = radio  // radiomanifest.Radio
+  }
+
+  getEvents() {
+    return this.calendar.getAllSubcomponents('vevent');
+
+  }
+  getNowEvent(now) {
+    var ev_now = this.getEvents().filter(function(vevent) {
+      const ev = new ICAL.Event(vevent)
+      return isNow(ev, now)
+    })
+    if(ev_now.length === 0)
+      return null
+    if(ev_now.length > 1)
+      console.log("More than one event right now?!")
+    return ev_now[0]
+  }
+
+  getNowShow(now) {
+    var ev = this.getNowEvent(now)
+
+    if (ev === null) return null
+    if (this.radio !== undefined) {
+      const showid = RadioSchedule.veventGetShowID(ev)
+      var show = this.radio.getShowByName(showid)
+      if (show === null || show === undefined) {
+        return new shows.RadioShow(RadioSchedule.veventGetSummary(ev))
+      }
+      return show;
+    }
+    return new shows.RadioShow(RadioSchedule.veventGetSummary(ev))
+  }
+
+  getNextEvent(now) {
+    // XXX
+  }
+
+  getNextShow(now) {
+    // XXX
+  }
+  static veventGetSummary(vevent) {
+      return vevent.getFirstProperty('summary').getFirstValue()
+  }
+  static veventGetShowID(vevent) {
+      return RadioSchedule.veventGetSummary(vevent)  // XXX: X-Show-ID
+  }
+
+}
+
+
+function isNow(vEvent, now) {
+    if (now === undefined) {
+          now = ICAL.Time.now()
+        }
+    if (vEvent.isRecurring()) {
+          return isNowRecurring(vEvent, now)
+        }
+    return (now < vEvent.endDate) && (now > event.startDate);
+}
+
+
+function isNowRecurring(vEvent, now) {
+  var expand = vEvent.iterator(vEvent.startDate)
+  var next, next_end;
+
+  while ((next = expand.next())) {
+    next_end = next.clone()
+    next_end.addDuration(vEvent.duration)
+
+    if (next_end > now) {
+      break;
+    }
+  }
+  return (now < next_end && now > next);
+}
+
+
+async function get(manifest) {
+  if (manifest.scheduleURL) {
+    let resp = null
+    try {
+      resp = await fetch(manifest.scheduleURL)
+    } catch (e) {
+      true
+    }
+    if (resp !== null) {
+      try {
+        text = await resp.text()
+        return parse(text)
+      } catch (e) {
+        console.error('Error while parsing schedule', e)
+        throw e
+      }
+    }
+  }
+}
+
+function parse(text) {
+  var jcalData = ICAL.parse(text);
+  var vcalendar = new ICAL.Component(jcalData);
+
+  return new RadioSchedule(vcalendar)
+}
+
+
+module.exports = {
+  get: get,
+  parse: parse,
+  RadioSchedule: RadioSchedule,
+}

+ 1 - 0
package.json

@@ -31,6 +31,7 @@
     "webpack-cli": "^4.9.1"
   },
   "dependencies": {
+    "ical.js": "^1.5.0",
     "isomorphic-unfetch": "^3.1.0"
   }
 }

+ 18 - 5
radiomanifest.js

@@ -1,5 +1,6 @@
 const fetch = require('isomorphic-unfetch')
 const shows = require('./shows.js')
+const calendar = require('./calendar.js')
 
 function getStreaminfoUrl (siteurl) {
   return siteurl + '/streaminfo.json' // XXX: improve this logic
@@ -15,13 +16,14 @@ function getAttribute(el, attr, default_value) {
 }
 
 class Radio {
-  constructor (sources, schedule, showsURL, feed) {
+  constructor (sources, scheduleURL, showsURL, feed) {
     this.streaming = new RadioStreaming(sources)
-    this.schedule = schedule
+    this.scheduleURL = scheduleURL
     this.showsURL = showsURL
     this.feed = feed
     this.name = ''
     this.shows = []
+    this.schedule = null
   }
 
   getStreaming () {
@@ -36,10 +38,12 @@ class Radio {
     return this.shows
   }
   getShowByName (showName) {
+    if (this.shows === undefined) return null
     return this.shows.find(s => s.name === showName)
   }
 
   getSchedule () {
+    return this.schedule
   }
 
   getShowAtTime () {
@@ -62,9 +66,9 @@ class Radio {
 
     res = doc.evaluate('/radio-manifest/schedule', doc)
     const scheduleEl = res.iterateNext()
-    let schedule = null
+    let scheduleURL = null
     if (scheduleEl !== null) {
-      schedule = scheduleEl.getAttribute('src')
+      scheduleURL = scheduleEl.getAttribute('src')
     }
 
     res = xml.evaluate('/radio-manifest/shows', xml)
@@ -81,7 +85,7 @@ class Radio {
       feed = feedEl.getAttribute('src')
     }
 
-    const manifest = new Radio(sources, schedule, showsURL, feed)
+    const manifest = new Radio(sources, scheduleURL, showsURL, feed)
     return manifest
   }
 }
@@ -150,6 +154,15 @@ async function get (siteurl, options) {
     console.error("Error while fetching shows file", e)
   }
 
+  try {
+    manifest.schedule = await calendar.get(manifest)
+    if (manifest.schedule !== undefined)
+      manifest.schedule.radio = manifest
+  } catch (e) {
+    console.error("Error while fetching shows file", e)
+  }
+
+
   resp = null
   try {
     resp = await fetch(getStreaminfoUrl(siteurl))