const { db, logger, file, parser } = require('../core') const _ = require('lodash') const dayjs = require('dayjs') const utc = require('dayjs/plugin/utc') dayjs.extend(utc) let channels = [] let programs = [] const DB_DIR = process.env.DB_DIR || 'scripts/database' const PUBLIC_DIR = process.env.PUBLIC_DIR || '.gh-pages' async function main() { await setUp() await generateChannelsJson() await generateProgramsJson() } main() async function setUp() { channels = await db.channels.find({}).sort({ xmltv_id: 1 }) programs = await db.programs.find({}) } async function generateChannelsJson() { logger.info('Generating channels.json...') let output = {} channels.forEach(channel => { if (!output[channel.xmltv_id]) { const countryCode = channel.xmltv_id.split('.')[1] output[channel.xmltv_id] = { id: channel.xmltv_id, name: [channel.name], logo: channel.logo || null, country: countryCode ? countryCode.toUpperCase() : null } } else { if (!output[channel.xmltv_id].logo && channel.logo) { output[channel.xmltv_id].logo = channel.logo } if (!output[channel.xmltv_id].name.includes(channel.name)) { output[channel.xmltv_id].name.push(channel.name) } } }) await file.create( `${PUBLIC_DIR}/api/channels.json`, JSON.stringify(Object.values(output), null, 2) ) } async function generateProgramsJson() { logger.info('Generating programs.json...') let items = programs items = _.sortBy(items, ['channel', 'start']) items = _.groupBy(items, 'channel') for (let channel in items) { let channelPrograms = items[channel] channelPrograms = Object.values(_.groupBy(channelPrograms, i => i.site))[0] let slots = _.groupBy(channelPrograms, i => `${i.start}_${i.stop}`) for (let slotId in slots) { let program = { channel, title: [], description: [], categories: [], image: null, start: null, stop: null } slots[slotId].forEach(item => { // program.site = item.site if (item.title) program.title.push({ lang: item.lang, value: item.title }) if (item.description) program.description.push({ lang: item.lang, value: item.description }) if (item.category) program.categories.push({ lang: item.lang, value: item.category }) program.image = program.image || item.icon program.start = item.start program.stop = item.stop }) program.title = _.uniqBy(program.title, 'lang') program.description = _.uniqBy(program.description, 'lang') program.categories = _.uniqBy(program.categories, 'lang') slots[slotId] = program } items[channel] = Object.values(slots) } await file.create(`${PUBLIC_DIR}/api/programs.json`, JSON.stringify(items, null, 2)) } // 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) // } // 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() // }