1
0
Fork 0

jsdoc comments all over the place

This commit is contained in:
boyska 2022-01-30 14:01:38 +01:00
parent eadb0fa7b6
commit ba0a79cc49
4 changed files with 142 additions and 2 deletions

View file

@ -1,16 +1,28 @@
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)
@ -23,6 +35,9 @@ class RadioSchedule {
return ev_now[0]
}
/**
* @returns {RadioShow} if nothing is going on right now, `null` is returned
*/
getNowShow(now) {
var ev = this.getNowEvent(now)
@ -38,10 +53,18 @@ class RadioSchedule {
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
}
@ -102,6 +125,12 @@ async function get(manifest) {
}
}
/**
* 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);
@ -115,3 +144,28 @@ module.exports = {
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
*/

View file

@ -11,6 +11,8 @@
"search": true,
"collapse": true,
"typedefs": false,
"private": false,
"navLevel": 0,
"removeQuotes": "none",
"scripts": []
}

View file

@ -15,7 +15,17 @@ function getAttribute(el, attr, default_value) {
return default_value;
}
/**
* Represents everything we know about a radio. This includes, but is not limited to, radiomanifest.xml.
*/
class Radio {
/**
* @param {Array} [sources] optional
* @param {string} [scheduleURL]
* @param {string} [showsURL]
* @param {string} [feed]
*/
constructor (sources, scheduleURL, showsURL, feed) {
this.streaming = new RadioStreaming(sources)
this.scheduleURL = scheduleURL
@ -26,31 +36,64 @@ class Radio {
this.schedule = null
}
/**
* @returns {RadioStreaming}
*/
getStreaming () {
return this.streaming
}
/**
* Change radio name
*/
setName (name) {
this.name = name
}
/**
*
* @returns {Array<RadioShow>}
*/
getShows() {
return this.shows
}
/**
* @returns {RadioShow} The lookup is exact and case-sensitive. If no such show can be found, `null`
* is returned.
*/
getShowByName (showName) {
if (this.shows === undefined) return null
return this.shows.find(s => s.name === showName)
}
/**
* @returns {RadioSchedule} If no schedule is present, `null` is returned.
*/
getSchedule () {
return this.schedule
}
/**
* Find if a show is running at the given moment. If there's none, `null` is returned.
* If possible, a complete {@link RadioShow} including full informations (from shows.xml) is returned.
* If, instead, we know from the `schedule` that there must be a show, but have no additional detail, a
* {@link RadioShow} object will be created on the fly.
*
* @param {ICAL.Time} [now] If omitted, the current time is used.
* @returns {RadioShow} If we don't know what's going on at the given moment, `null` is returned.
*/
getShowAtTime (now) {
if (this.schedule === undefined || this.schedule === null) return null
return this.getSchedule().getNowShow(now)
}
/**
* This static method can create a Radio object from a valid radiomanifest.xml file
*
* @param xml An already parsed xml block
* @returns {Radio}
*/
static fromDOM (xml) {
const doc = xml.cloneNode(true)
let res = doc.evaluate('/radio-manifest/streaming/source', doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
@ -92,6 +135,10 @@ class Radio {
}
}
/**
* Represents the streaming capabilities of a radio.
* This has probably been derived from the <streaming> block in radiomanifest.xml
*/
class RadioStreaming {
constructor (sources) {
this.sources = sources.sort(
@ -99,22 +146,34 @@ class RadioStreaming {
)
}
/**
* Get the list of possible options that are provided to the user
* @returns {Array<string>}
*/
getOptions() {
return this.sources.map(function (x) {
return x.getAttribute('name')
})
}
// this is private
/**
* @private
*/
getPriority(element) {
return parseInt(getAttribute(element, 'priority', '1'))
}
// this is private
/**
* @private
*/
getTopPrioritySources() {
var topPriority = this.getPriority(this.sources[0])
return this.sources.filter(
(src) => parseInt(src.getAttribute('priority'), 10) === topPriority
)
}
/**
* @return {string} url of the source. Note that this is much probably a playlist, in M3U format
*/
getSource(name) {
if (name === undefined) {
return this.getTopPrioritySources()[0]
@ -126,6 +185,11 @@ class RadioStreaming {
return s.getAttribute('src')
}
/**
* This is your go-to function whenever you need a list of URLs to play.
* They will be picked honoring priorities, and expanding the playlist source
* @return {Array<string>}
*/
async pickURLs() {
var allSources = this.getTopPrioritySources()
var allAudios = []
@ -136,12 +200,24 @@ class RadioStreaming {
}
return allAudios
}
/**
* Just like {@link RadioStreaming#pickURLs}, but get a single URL
* @return {string}
*/
async pickURL() {
var allAudios = await this.pickURLs()
return allAudios[0]
}
}
/**
* Create everything you need - **you should start from here**
*
* @param {string} siteurl URL of website you want to load
* @param {Object} options options. Currenly unused
* @return {Radio}
*/
async function get (siteurl, options) {
let resp = await fetch(getManifestUrl(siteurl))
let text = await resp.text()

View file

@ -1,3 +1,7 @@
/**
* Represents a single show. This show could be defined in the shows.xml file, or could be inferred from the
* schedule.
*/
class RadioShow {
constructor(name, description, website, feed, schedule, radio_calendar) {
this.name = name
@ -23,6 +27,10 @@ class RadioShow {
}
/**
* @private
* @return {Array<RadioShow>}
*/
function parseRadioShows(xml) {
const doc = xml.cloneNode(true)
const bookmarks = doc.evaluate('//bookmark', doc, showsNamespaceResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)