diff --git a/scripts/commands/epg/grab.ts b/scripts/commands/epg/grab.ts index 2dabb6b53..eb9ee55e3 100644 --- a/scripts/commands/epg/grab.ts +++ b/scripts/commands/epg/grab.ts @@ -54,7 +54,10 @@ program .argParser(parseNumber) .env('MAX_CONNECTIONS') ) - .addOption(new Option('--gzip', 'Create a compressed version of the guide as well').env('GZIP')) + .addOption( + new Option('--gzip [path]', 'Create a compressed version of the guide as well').env('GZIP') + ) + .addOption(new Option('--json [path]', 'Create a JSON version of the guide as well').env('JSON')) .addOption(new Option('--curl', 'Display each request as CURL').env('CURL')) .addOption(new Option('--debug', 'Enable debug mode').env('DEBUG')) .parse() @@ -63,7 +66,8 @@ interface GrabOptions { sites?: string[] channels?: string output?: string - gzip?: boolean + gzip?: boolean | string + json?: boolean | string curl?: boolean debug?: boolean maxConnections?: number @@ -109,7 +113,10 @@ async function main() { if (typeof options.maxConnections === 'number') globalConfig.maxConnections = options.maxConnections if (typeof options.curl === 'boolean') globalConfig.curl = options.curl - if (typeof options.gzip === 'boolean') globalConfig.gzip = options.gzip + if (typeof options.gzip === 'boolean' || typeof options.gzip === 'string') + globalConfig.gzip = options.gzip + if (typeof options.json === 'boolean' || typeof options.json === 'string') + globalConfig.json = options.json if (typeof options.debug === 'boolean') globalConfig.debug = options.debug logger.debug(`config: ${JSON.stringify(globalConfig, null, 2)}`) @@ -298,6 +305,7 @@ async function main() { }) const gzip = globalConfig.gzip || defaultConfig.gzip + const json = globalConfig.json || defaultConfig.json for (const groupKey of channelsGroupedByKey.keys()) { const groupChannels = new Collection(channelsGroupedByKey.get(groupKey)) @@ -305,6 +313,7 @@ async function main() { const guide = new Guide({ filepath: groupKey, gzip, + json, channels: groupChannels, programs: groupPrograms }) diff --git a/scripts/commands/guides/update.ts b/scripts/commands/guides/update.ts index f43b96b6c..f1e830dde 100644 --- a/scripts/commands/guides/update.ts +++ b/scripts/commands/guides/update.ts @@ -61,7 +61,10 @@ async function main() { } worker.channelsPath = workerJson.channels - worker.guidePath = workerJson.guide + worker.guideXmlPath = + typeof workerJson.guide === 'string' ? workerJson.guide : workerJson?.guide?.xml + worker.guideGzipPath = workerJson?.guide?.gzip + worker.guideJsonPath = workerJson?.guide?.json if (!worker.channelsPath) { worker.status = 'MISSING_CHANNELS_PATH' @@ -69,8 +72,8 @@ async function main() { continue } - if (!worker.guidePath) { - worker.status = 'MISSING_GUIDE_PATH' + if (!worker.guideXmlPath) { + worker.status = 'MISSING_GUIDE_XML_PATH' logger.error('The "guide" property is missing from the workers config') continue } @@ -91,7 +94,7 @@ async function main() { ) const guideXml = await client - .get(worker.guidePath) + .get(worker.guideXmlPath) .then(res => res.data) .catch(err => { worker.status = err.status @@ -109,6 +112,7 @@ async function main() { logger.info('creating guides table...') const rows = new Collection() workers.forEach((worker: Worker) => { + const links = worker.getLinks() rows.add( new Collection([ { value: worker.host }, @@ -116,10 +120,9 @@ async function main() { { value: worker.getChannelsCount().toString(), align: 'right' }, { value: worker.getLastUpdated(), align: 'left' }, { - value: - worker.status === 'OK' - ? `${worker.channelsPath}
${worker.guidePath}` - : '' + value: links.length + ? links.map(link => `${link.label}`).join(' | ') + : '-' } ]) ) diff --git a/scripts/default.config.js b/scripts/default.config.js index d5e49a641..056695ba7 100644 --- a/scripts/default.config.js +++ b/scripts/default.config.js @@ -5,6 +5,7 @@ export default { maxConnections: 1, curl: false, gzip: false, + json: false, debug: false, request: { maxContentLength: 5242880, diff --git a/scripts/models/guide.ts b/scripts/models/guide.ts index 8c367e6eb..51bc15f4d 100644 --- a/scripts/models/guide.ts +++ b/scripts/models/guide.ts @@ -13,20 +13,23 @@ interface GuideData { channels: Collection programs: Collection filepath: string - gzip: boolean + gzip: boolean | string + json: boolean | string } export class Guide { channels: Collection programs: Collection filepath: string - gzip: boolean + gzip: boolean | string + json: boolean | string constructor(data: GuideData) { this.channels = data.channels this.programs = data.programs this.filepath = data.filepath this.gzip = data.gzip || false + this.json = data.json || false } addChannel(channel: Channel) { @@ -50,10 +53,21 @@ export class Guide { if (this.gzip) { const compressed = pako.gzip(xmltv) - const gzFilepath = `${this.filepath}.gz` + const gzFilepath = typeof this.gzip === 'string' ? this.gzip : `${this.filepath}.gz` const gzFilename = path.basename(gzFilepath) logger.info(` saving to "${gzFilepath}"...`) await storage.save(gzFilename, compressed) } + + if (this.json) { + const filename = path.basename(this.filepath).split('.')[0] + const jsonFilepath = + typeof this.json === 'string' ? this.json : path.join(dir, `${filename}.json`) + const channels = this.channels.map((channel: Channel) => channel.toObject()).all() + const programs = this.programs.map((program: Program) => program.toObject()).all() + const json = JSON.stringify({ channels, programs }) + logger.info(` saving to "${jsonFilepath}"...`) + await storage.save(jsonFilepath, json) + } } } diff --git a/scripts/models/worker.ts b/scripts/models/worker.ts index 94b94dfcb..71480e0bc 100644 --- a/scripts/models/worker.ts +++ b/scripts/models/worker.ts @@ -14,7 +14,9 @@ export interface WorkerData { export class Worker { host: string channelsPath?: string - guidePath?: string + guideXmlPath?: string + guideGzipPath?: string + guideJsonPath?: string channels?: Collection status?: string lastUpdated?: string @@ -41,10 +43,26 @@ export class Worker { return url.href } - getGuideUrl(): string { - if (!this.guidePath) return '' + getGuideXmlUrl(): string { + if (!this.guideXmlPath) return '' - const url = new URL(this.guidePath, this.getBaseUrl()) + const url = new URL(this.guideXmlPath, this.getBaseUrl()) + + return url.href + } + + getGuideGzipUrl(): string { + if (!this.guideGzipPath) return '' + + const url = new URL(this.guideGzipPath, this.getBaseUrl()) + + return url.href + } + + getGuideJsonUrl(): string { + if (!this.guideJsonPath) return '' + + const url = new URL(this.guideJsonPath, this.getBaseUrl()) return url.href } @@ -70,4 +88,25 @@ export class Worker { return dayjs.utc(this.lastUpdated).from(now) } + + getLinks(): { url: string; label: string }[] { + const links = [] + + if (this.guideXmlPath) { + const url = new URL(this.guideXmlPath, this.getBaseUrl()) + links.push({ url: url.href, label: 'XML' }) + } + + if (this.guideGzipPath) { + const url = new URL(this.guideGzipPath, this.getBaseUrl()) + links.push({ url: url.href, label: 'GZIP' }) + } + + if (this.guideJsonPath) { + const url = new URL(this.guideJsonPath, this.getBaseUrl()) + links.push({ url: url.href, label: 'JSON' }) + } + + return links + } }