2021-10-05 23:36:28 +02:00
|
|
|
#! /usr/bin/env node
|
|
|
|
|
|
|
|
const { Command } = require('commander')
|
|
|
|
const program = new Command()
|
2022-01-19 13:54:42 +01:00
|
|
|
const { merge } = require('lodash')
|
2022-03-15 12:52:59 +01:00
|
|
|
const { gzip } = require('node-gzip')
|
2022-06-11 20:01:39 +02:00
|
|
|
const file = require('../src/file')
|
2022-06-16 14:20:19 +02:00
|
|
|
const { EPGGrabber, parseChannels, generateXMLTV } = require('../src/index')
|
2022-06-11 20:01:39 +02:00
|
|
|
const { create: createLogger } = require('../src/logger')
|
2022-06-16 14:07:56 +02:00
|
|
|
const { parseNumber, getUTCDate } = require('../src/utils')
|
2022-06-11 20:01:39 +02:00
|
|
|
const { name, version, description } = require('../package.json')
|
2022-08-29 03:14:12 +02:00
|
|
|
const _ = require('lodash')
|
2022-06-16 14:07:56 +02:00
|
|
|
const dayjs = require('dayjs')
|
|
|
|
const utc = require('dayjs/plugin/utc')
|
|
|
|
|
|
|
|
dayjs.extend(utc)
|
2021-10-05 23:36:28 +02:00
|
|
|
|
|
|
|
program
|
|
|
|
.name(name)
|
|
|
|
.version(version, '-v, --version')
|
|
|
|
.description(description)
|
2021-10-06 02:02:06 +02:00
|
|
|
.requiredOption('-c, --config <config>', 'Path to [site].config.js file')
|
2021-10-06 02:52:34 +02:00
|
|
|
.option('-o, --output <output>', 'Path to output file')
|
2021-10-05 23:36:28 +02:00
|
|
|
.option('--channels <channels>', 'Path to channels.xml file')
|
2021-10-06 02:52:34 +02:00
|
|
|
.option('--lang <lang>', 'Set default language for all programs')
|
2023-01-10 09:20:36 +01:00
|
|
|
.option('--days <days>', 'Number of days for which to grab the program', parseNumber)
|
2023-01-13 09:22:30 +01:00
|
|
|
.option('--delay <delay>', 'Delay between requests (in milliseconds)', parseNumber)
|
|
|
|
.option('--timeout <timeout>', 'Set a timeout for each request (in milliseconds)', parseNumber)
|
2022-03-29 14:59:58 +02:00
|
|
|
.option(
|
2022-05-03 18:18:52 +02:00
|
|
|
'--cache-ttl <cacheTtl>',
|
2022-03-29 14:59:58 +02:00
|
|
|
'Maximum time for storing each request (in milliseconds)',
|
2022-06-16 14:07:56 +02:00
|
|
|
parseNumber
|
2022-03-29 14:59:58 +02:00
|
|
|
)
|
2022-03-15 12:52:59 +01:00
|
|
|
.option('--gzip', 'Compress the output', false)
|
2021-10-05 23:36:28 +02:00
|
|
|
.option('--debug', 'Enable debug mode', false)
|
2022-03-06 14:18:05 +01:00
|
|
|
.option('--curl', 'Display request as CURL', false)
|
2021-11-16 15:59:26 +01:00
|
|
|
.option('--log <log>', 'Path to log file')
|
|
|
|
.option('--log-level <level>', 'Set log level', 'info')
|
2021-10-05 23:36:28 +02:00
|
|
|
.parse(process.argv)
|
|
|
|
|
|
|
|
const options = program.opts()
|
2022-06-11 20:01:39 +02:00
|
|
|
const logger = createLogger(options)
|
2021-11-16 15:59:26 +01:00
|
|
|
|
2021-10-05 23:36:28 +02:00
|
|
|
async function main() {
|
2021-11-16 15:59:26 +01:00
|
|
|
logger.info('Starting...')
|
2021-10-05 23:36:28 +02:00
|
|
|
|
2021-11-16 15:59:26 +01:00
|
|
|
logger.info(`Loading '${options.config}'...`)
|
2022-06-11 20:01:39 +02:00
|
|
|
let config = require(file.resolve(options.config))
|
2021-11-18 15:31:47 +01:00
|
|
|
config = merge(config, {
|
|
|
|
days: options.days,
|
|
|
|
debug: options.debug,
|
2022-03-15 12:52:59 +01:00
|
|
|
gzip: options.gzip,
|
2022-03-06 14:18:05 +01:00
|
|
|
curl: options.curl,
|
2021-11-18 15:31:47 +01:00
|
|
|
lang: options.lang,
|
|
|
|
delay: options.delay,
|
2023-03-19 05:39:35 +01:00
|
|
|
request: {
|
|
|
|
ignoreCookieErrors: true,
|
|
|
|
}
|
2021-11-18 15:31:47 +01:00
|
|
|
})
|
2021-10-06 02:02:06 +02:00
|
|
|
|
2022-05-03 18:18:52 +02:00
|
|
|
if (options.timeout) config.request.timeout = options.timeout
|
|
|
|
if (options.cacheTtl) config.request.cache.ttl = options.cacheTtl
|
2021-10-05 23:36:28 +02:00
|
|
|
if (options.channels) config.channels = options.channels
|
|
|
|
else if (config.channels)
|
2022-06-11 20:01:39 +02:00
|
|
|
config.channels = file.join(file.dirname(options.config), config.channels)
|
2021-10-05 23:36:28 +02:00
|
|
|
else throw new Error("The required 'channels' property is missing")
|
|
|
|
|
2021-11-16 15:59:26 +01:00
|
|
|
if (!config.channels) return logger.error('Path to [site].channels.xml is missing')
|
|
|
|
logger.info(`Loading '${config.channels}'...`)
|
2022-06-11 20:01:39 +02:00
|
|
|
const grabber = new EPGGrabber(config)
|
|
|
|
|
|
|
|
const channelsXML = file.read(config.channels)
|
2022-06-15 17:00:23 +02:00
|
|
|
const { channels } = parseChannels(channelsXML)
|
2021-10-14 23:09:36 +02:00
|
|
|
|
2021-10-05 23:36:28 +02:00
|
|
|
let programs = []
|
2021-11-16 15:59:26 +01:00
|
|
|
let i = 1
|
2023-01-10 09:20:36 +01:00
|
|
|
let days = config.days || 1
|
2021-11-16 15:59:26 +01:00
|
|
|
const total = channels.length * days
|
2022-06-11 20:01:39 +02:00
|
|
|
const utcDate = getUTCDate()
|
2023-01-10 09:20:36 +01:00
|
|
|
const dates = Array.from({ length: days }, (_, i) => utcDate.add(i, 'd'))
|
2021-10-05 23:36:28 +02:00
|
|
|
for (let channel of channels) {
|
2022-06-11 20:01:39 +02:00
|
|
|
if (!channel.logo && config.logo) {
|
|
|
|
channel.logo = await grabber.loadLogo(channel)
|
|
|
|
}
|
|
|
|
|
2022-01-31 03:48:01 +01:00
|
|
|
for (let date of dates) {
|
|
|
|
await grabber
|
2022-03-29 14:59:58 +02:00
|
|
|
.grab(channel, date, (data, err) => {
|
2022-01-31 03:48:01 +01:00
|
|
|
logger.info(
|
2022-06-16 14:20:19 +02:00
|
|
|
`[${i}/${total}] ${config.site} - ${data.channel.id} - ${dayjs
|
|
|
|
.utc(data.date)
|
2022-06-16 14:07:56 +02:00
|
|
|
.format('MMM D, YYYY')} (${data.programs.length} programs)`
|
2022-01-31 03:48:01 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
if (err) logger.error(err.message)
|
|
|
|
|
|
|
|
if (i < total) i++
|
|
|
|
})
|
|
|
|
.then(results => {
|
|
|
|
programs = programs.concat(results)
|
|
|
|
})
|
|
|
|
}
|
2021-10-05 23:36:28 +02:00
|
|
|
}
|
|
|
|
|
2022-08-29 03:14:12 +02:00
|
|
|
programs = _.uniqBy(programs, p => p.start + p.channel)
|
|
|
|
|
2022-06-15 17:00:23 +02:00
|
|
|
const xml = generateXMLTV({ channels, programs })
|
2022-03-15 12:52:59 +01:00
|
|
|
let outputPath = options.output || config.output
|
|
|
|
if (options.gzip) {
|
|
|
|
outputPath = outputPath || 'guide.xml.gz'
|
|
|
|
const compressed = await gzip(xml)
|
2022-06-11 20:01:39 +02:00
|
|
|
file.write(outputPath, compressed)
|
2022-03-15 12:52:59 +01:00
|
|
|
} else {
|
|
|
|
outputPath = outputPath || 'guide.xml'
|
2022-06-11 20:01:39 +02:00
|
|
|
file.write(outputPath, xml)
|
2022-03-15 12:52:59 +01:00
|
|
|
}
|
2021-10-05 23:36:28 +02:00
|
|
|
|
2021-11-16 15:59:26 +01:00
|
|
|
logger.info(`File '${outputPath}' successfully saved`)
|
|
|
|
logger.info('Finish')
|
2021-10-05 23:36:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
main()
|