const { db, logger, file, parser } = require('../core') const _ = require('lodash') const dayjs = require('dayjs') const utc = require('dayjs/plugin/utc') dayjs.extend(utc) let programs = {} const LOGS_PATH = process.env.LOGS_PATH || 'scripts/logs' const PUBLIC_PATH = process.env.PUBLIC_PATH || '.' async function main() { await setUp() await generateGuideXML() } main() async function generateGuideXML() { logger.info(`Generating guide.xml...`) const channels = Object.keys(programs) let items = await db.find({ xmltv_id: { $in: channels } }) items = _.sortBy(items, item => item.name) let buffer = {} items.forEach(item => { if (!buffer[item.xmltv_id]) { const countryCode = item.xmltv_id.split('.')[1] buffer[item.xmltv_id] = { id: item.xmltv_id, display_name: [item.name], logo: item.logo || null, country: countryCode ? countryCode.toUpperCase() : null, site: `https://${programs[item.xmltv_id][0].site}` } } else { if (!buffer[item.xmltv_id].logo && item.logo) { buffer[item.xmltv_id].logo = item.logo } if (!buffer[item.xmltv_id].display_name.includes(item.name)) { buffer[item.xmltv_id].display_name.push(item.name) } } }) items = Object.values(buffer) let outputProgs = [] for (let ip of Object.values(programs)) { outputProgs = outputProgs.concat(ip) } const xml = convertToXMLTV({ channels: items, programs: outputProgs }) await file.write('./guide.xml', xml) } async function setUp() { const f = await file.read(`${PUBLIC_PATH}/scripts/output/programs.json`) programs = JSON.parse(f) } function convertToXMLTV({ channels, programs }) { let output = `\r\n` for (let channel of channels) { output += `` channel.display_name.forEach(displayName => { output += `${escapeString(displayName)}` }) if (channel.logo) { const logo = escapeString(channel.logo) output += `` } output += `${channel.site}` output += `\r\n` } for (let program of programs) { if (!program) continue const start = program.start ? dayjs.unix(program.start).utc().format('YYYYMMDDHHmmss ZZ') : '' const stop = program.stop ? dayjs.unix(program.stop).utc().format('YYYYMMDDHHmmss ZZ') : '' const icon = escapeString(program.icon) if (start && stop) { output += `` program.title.forEach(title => { output += `${escapeString(title.value)}` }) program.description.forEach(description => { output += `${escapeString(description.value)}` }) program.categories.forEach(category => { output += `${escapeString(category.value)}` }) program.icons.forEach(icon => { output += `` }) output += '\r\n' } } output += '' return output } function escapeString(string, defaultValue = '') { if (!string) return defaultValue const regex = new RegExp( '((?:[\0-\x08\x0B\f\x0E-\x1F\uFFFD\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))|([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|(?:\\uD83F[\\uDFFE\\uDFFF])|(?:\\uD87F[\\uDF' + 'FE\\uDFFF])|(?:\\uD8BF[\\uDFFE\\uDFFF])|(?:\\uD8FF[\\uDFFE\\uDFFF])|(?:\\uD93F[\\uDFFE\\uD' + 'FFF])|(?:\\uD97F[\\uDFFE\\uDFFF])|(?:\\uD9BF[\\uDFFE\\uDFFF])|(?:\\uD9FF[\\uDFFE\\uDFFF])' + '|(?:\\uDA3F[\\uDFFE\\uDFFF])|(?:\\uDA7F[\\uDFFE\\uDFFF])|(?:\\uDABF[\\uDFFE\\uDFFF])|(?:\\' + 'uDAFF[\\uDFFE\\uDFFF])|(?:\\uDB3F[\\uDFFE\\uDFFF])|(?:\\uDB7F[\\uDFFE\\uDFFF])|(?:\\uDBBF' + '[\\uDFFE\\uDFFF])|(?:\\uDBFF[\\uDFFE\\uDFFF])(?:[\\0-\\t\\x0B\\f\\x0E-\\u2027\\u202A-\\uD7FF\\' + 'uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|' + '(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))', 'g' ) string = String(string || '').replace(regex, '') return string .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, ''') .replace(/\n|\r/g, ' ') .replace(/ +/g, ' ') .trim() }