173 lines
5.3 KiB
JavaScript
173 lines
5.3 KiB
JavaScript
const XMLWriter = require('xml-writer')
|
|
const fs = require('fs')
|
|
|
|
module.exports = { WriteXMLTV: WriteXMLTV, shutdown: shutdown }
|
|
|
|
let isShutdown = false;
|
|
let isWorking = false;
|
|
|
|
async function WriteXMLTV(json, xmlSettings, throttle, cacheImageService) {
|
|
if (isShutdown) {
|
|
return;
|
|
}
|
|
if (isWorking) {
|
|
console.log("Concurrent xmltv write attempt detected, skipping");
|
|
return;
|
|
}
|
|
isWorking = true;
|
|
try {
|
|
await writePromise(json, xmlSettings, throttle, cacheImageService);
|
|
} catch (err) {
|
|
console.error("Error writing xmltv", err);
|
|
}
|
|
isWorking = false;
|
|
}
|
|
|
|
function writePromise(json, xmlSettings, throttle, cacheImageService) {
|
|
return new Promise((resolve, reject) => {
|
|
let ws = fs.createWriteStream(xmlSettings.file)
|
|
let xw = new XMLWriter(true, (str, enc) => ws.write(str, enc))
|
|
ws.on('close', () => { resolve() })
|
|
ws.on('error', (err) => { reject(err) })
|
|
_writeDocStart(xw)
|
|
async function middle() {
|
|
let channelNumbers = [];
|
|
Object.keys(json).forEach( (key, index) => channelNumbers.push(key) );
|
|
let channels = channelNumbers.map( (number) => json[number].channel );
|
|
_writeChannels( xw, channels );
|
|
for (let i = 0; i < channelNumbers.length; i++) {
|
|
let number = channelNumbers[i];
|
|
await _writePrograms(xw, json[number].channel, json[number].programs, throttle, xmlSettings, cacheImageService);
|
|
}
|
|
}
|
|
middle().then( () => {
|
|
_writeDocEnd(xw, ws)
|
|
}).catch( (err) => {
|
|
console.error("Error", err);
|
|
}).then( () => ws.end() );
|
|
})
|
|
}
|
|
|
|
function _writeDocStart(xw) {
|
|
xw.startDocument()
|
|
xw.startElement('tv')
|
|
xw.writeAttribute('generator-info-name', 'psuedotv-plex')
|
|
}
|
|
function _writeDocEnd(xw, ws) {
|
|
xw.endElement()
|
|
xw.endDocument()
|
|
}
|
|
|
|
function _writeChannels(xw, channels) {
|
|
for (let i = 0; i < channels.length; i++) {
|
|
xw.startElement('channel')
|
|
xw.writeAttribute('id', channels[i].number)
|
|
xw.startElement('display-name')
|
|
xw.writeAttribute('lang', 'en')
|
|
xw.text(channels[i].name)
|
|
xw.endElement()
|
|
if (channels[i].icon) {
|
|
xw.startElement('icon')
|
|
xw.writeAttribute('src', channels[i].icon)
|
|
xw.endElement()
|
|
}
|
|
xw.endElement()
|
|
}
|
|
}
|
|
|
|
async function _writePrograms(xw, channel, programs, throttle, xmlSettings, cacheImageService) {
|
|
for (let i = 0; i < programs.length; i++) {
|
|
if (! isShutdown) {
|
|
await throttle();
|
|
}
|
|
await _writeProgramme(channel, programs[i], xw, xmlSettings, cacheImageService);
|
|
}
|
|
}
|
|
|
|
async function _writeProgramme(channel, program, xw, xmlSettings, cacheImageService) {
|
|
// Programme
|
|
xw.startElement('programme')
|
|
xw.writeAttribute('start', _createXMLTVDate(program.start))
|
|
xw.writeAttribute('stop', _createXMLTVDate(program.stop ))
|
|
xw.writeAttribute('channel', channel.number)
|
|
// Title
|
|
xw.startElement('title')
|
|
xw.writeAttribute('lang', 'en')
|
|
xw.text(program.title);
|
|
xw.endElement();
|
|
xw.writeRaw('\n <previously-shown/>')
|
|
|
|
//sub-title
|
|
if ( typeof(program.sub) !== 'undefined') {
|
|
xw.startElement('sub-title')
|
|
xw.writeAttribute('lang', 'en')
|
|
xw.text(program.sub.title)
|
|
xw.endElement()
|
|
|
|
xw.startElement('episode-num')
|
|
xw.writeAttribute('system', 'onscreen')
|
|
xw.text( "S" + (program.sub.season) + ' E' + (program.sub.episode) )
|
|
xw.endElement()
|
|
|
|
xw.startElement('episode-num')
|
|
xw.writeAttribute('system', 'xmltv_ns')
|
|
xw.text((program.sub.season - 1) + '.' + (program.sub.episode - 1) + '.0/1')
|
|
xw.endElement()
|
|
|
|
}
|
|
// Icon
|
|
if (typeof program.icon !== 'undefined') {
|
|
xw.startElement('icon');
|
|
let icon = program.icon;
|
|
if (xmlSettings.enableImageCache === true) {
|
|
const imgUrl = cacheImageService.registerImageOnDatabase(icon);
|
|
icon = `{{host}}/cache/images/${imgUrl}`;
|
|
}
|
|
xw.writeAttribute('src', icon);
|
|
xw.endElement();
|
|
}
|
|
// Desc
|
|
xw.startElement('desc')
|
|
xw.writeAttribute('lang', 'en')
|
|
if ( (typeof(program.summary) !== 'undefined') && (program.summary.length > 0) ) {
|
|
xw.text(program.summary)
|
|
} else {
|
|
xw.text(channel.name)
|
|
}
|
|
xw.endElement()
|
|
// Rating
|
|
if ( (program.rating != null) && (typeof program.rating !== 'undefined') ) {
|
|
xw.startElement('rating')
|
|
xw.writeAttribute('system', 'MPAA')
|
|
xw.writeElement('value', program.rating)
|
|
xw.endElement()
|
|
}
|
|
// End of Programme
|
|
xw.endElement()
|
|
}
|
|
function _createXMLTVDate(d) {
|
|
return d.substring(0,19).replace(/[-T:]/g,"") + " +0000";
|
|
}
|
|
function wait(x) {
|
|
return new Promise((resolve) => {
|
|
setTimeout(resolve, x);
|
|
});
|
|
}
|
|
|
|
async function shutdown() {
|
|
isShutdown = true;
|
|
console.log("Shutting down xmltv writer.");
|
|
if (isWorking) {
|
|
let s = "Wait for xmltv writer...";
|
|
while (isWorking) {
|
|
console.log(s);
|
|
await wait(100);
|
|
s = "Still waiting for xmltv writer...";
|
|
}
|
|
console.log("Write finished.");
|
|
} else {
|
|
console.log("xmltv writer had no pending jobs.");
|
|
}
|
|
}
|
|
|