123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- const ICAL = require('ical.js')
- const shows = require('./shows.js')
- /**
- * Represent a schedule (ie: a .ics file)
- */
- class RadioSchedule {
- constructor (calendar, radio) {
- this.calendar = calendar // ICAL.Calendar
- this.radio = radio // radiomanifest.Radio
- }
- /**
- * Get a list of all known {@link vEvent}s
- *
- * @returns {Array<external:ICAL~Component>}
- * */
- getEvents() {
- return this.calendar.getAllSubcomponents('vevent');
- }
- /**
- * @returns {external:ICAL~Component} if nothing is going on right now, `null` is returned
- */
- 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]
- }
- /**
- * @returns {RadioShow} if nothing is going on right now, `null` is returned
- */
- 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))
- }
- /**
- * @todo To be implemented
- */
- getNextEvent(now) {
- // XXX
- }
- /**
- * @todo To be implemented
- * @returns {NextShow} if there is no next show, nothing will be returned
- */
- 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
- }
- }
- }
- }
- /**
- * Parse ICAL and get a RadioSchedule
- *
- * @param {string} text The text, in ICS format
- * @returns {RadioSchedule}
- */
- 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,
- }
- /**
- * @typedef {Object} NextShow
- * @property {RadioShow} show The next show scheduled
- * @property {external:ICAL~Time} time When it will start
- */
- /**
- * @external ICAL
- * @see https://mozilla-comm.github.io/ical.js/api/index.html
- */
- /**
- * @class Component
- * @memberof external:ICAL
- * @inner
- * @see https://mozilla-comm.github.io/ical.js/api/ICAL.Component.html
- */
- /**
- * @class Time
- * @memberof external:ICAL
- * @inner
- * @see https://mozilla-comm.github.io/ical.js/api/ICAL.Time.html
- */
|