forked from boyska/radiomanifest.js
support schedule
This commit is contained in:
parent
d524cbbace
commit
5bfe52c235
3 changed files with 136 additions and 5 deletions
117
calendar.js
Normal file
117
calendar.js
Normal file
|
@ -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,
|
||||||
|
}
|
|
@ -31,6 +31,7 @@
|
||||||
"webpack-cli": "^4.9.1"
|
"webpack-cli": "^4.9.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"ical.js": "^1.5.0",
|
||||||
"isomorphic-unfetch": "^3.1.0"
|
"isomorphic-unfetch": "^3.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const fetch = require('isomorphic-unfetch')
|
const fetch = require('isomorphic-unfetch')
|
||||||
const shows = require('./shows.js')
|
const shows = require('./shows.js')
|
||||||
|
const calendar = require('./calendar.js')
|
||||||
|
|
||||||
function getStreaminfoUrl (siteurl) {
|
function getStreaminfoUrl (siteurl) {
|
||||||
return siteurl + '/streaminfo.json' // XXX: improve this logic
|
return siteurl + '/streaminfo.json' // XXX: improve this logic
|
||||||
|
@ -15,13 +16,14 @@ function getAttribute(el, attr, default_value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Radio {
|
class Radio {
|
||||||
constructor (sources, schedule, showsURL, feed) {
|
constructor (sources, scheduleURL, showsURL, feed) {
|
||||||
this.streaming = new RadioStreaming(sources)
|
this.streaming = new RadioStreaming(sources)
|
||||||
this.schedule = schedule
|
this.scheduleURL = scheduleURL
|
||||||
this.showsURL = showsURL
|
this.showsURL = showsURL
|
||||||
this.feed = feed
|
this.feed = feed
|
||||||
this.name = ''
|
this.name = ''
|
||||||
this.shows = []
|
this.shows = []
|
||||||
|
this.schedule = null
|
||||||
}
|
}
|
||||||
|
|
||||||
getStreaming () {
|
getStreaming () {
|
||||||
|
@ -36,10 +38,12 @@ class Radio {
|
||||||
return this.shows
|
return this.shows
|
||||||
}
|
}
|
||||||
getShowByName (showName) {
|
getShowByName (showName) {
|
||||||
|
if (this.shows === undefined) return null
|
||||||
return this.shows.find(s => s.name === showName)
|
return this.shows.find(s => s.name === showName)
|
||||||
}
|
}
|
||||||
|
|
||||||
getSchedule () {
|
getSchedule () {
|
||||||
|
return this.schedule
|
||||||
}
|
}
|
||||||
|
|
||||||
getShowAtTime () {
|
getShowAtTime () {
|
||||||
|
@ -62,9 +66,9 @@ class Radio {
|
||||||
|
|
||||||
res = doc.evaluate('/radio-manifest/schedule', doc)
|
res = doc.evaluate('/radio-manifest/schedule', doc)
|
||||||
const scheduleEl = res.iterateNext()
|
const scheduleEl = res.iterateNext()
|
||||||
let schedule = null
|
let scheduleURL = null
|
||||||
if (scheduleEl !== null) {
|
if (scheduleEl !== null) {
|
||||||
schedule = scheduleEl.getAttribute('src')
|
scheduleURL = scheduleEl.getAttribute('src')
|
||||||
}
|
}
|
||||||
|
|
||||||
res = xml.evaluate('/radio-manifest/shows', xml)
|
res = xml.evaluate('/radio-manifest/shows', xml)
|
||||||
|
@ -81,7 +85,7 @@ class Radio {
|
||||||
feed = feedEl.getAttribute('src')
|
feed = feedEl.getAttribute('src')
|
||||||
}
|
}
|
||||||
|
|
||||||
const manifest = new Radio(sources, schedule, showsURL, feed)
|
const manifest = new Radio(sources, scheduleURL, showsURL, feed)
|
||||||
return manifest
|
return manifest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,6 +154,15 @@ async function get (siteurl, options) {
|
||||||
console.error("Error while fetching shows file", e)
|
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
|
resp = null
|
||||||
try {
|
try {
|
||||||
resp = await fetch(getStreaminfoUrl(siteurl))
|
resp = await fetch(getStreaminfoUrl(siteurl))
|
||||||
|
|
Loading…
Reference in a new issue