epg-grabber 0.31.0 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -75,7 +75,7 @@ Arguments:
75
75
 
76
76
  - `-c, --config`: path to config file
77
77
  - `-o, --output`: path to output file or path template (example: `guides/{site}.{lang}.xml`; default: `guide.xml`)
78
- - `--channels`: path to list of channels
78
+ - `--channels`: path to list of channels; you can also use wildcard to specify the path to multiple files at once (example: `example.com_*.channels.xml`)
79
79
  - `--lang`: set default language for all programs (default: `en`)
80
80
  - `--days`: number of days for which to grab the program (default: `1`)
81
81
  - `--delay`: delay between requests in milliseconds (default: `3000`)
@@ -94,7 +94,7 @@ Arguments:
94
94
  module.exports = {
95
95
  site: 'example.com', // site domain name (required)
96
96
  output: 'example.com.guide.xml', // path to output file or path template (example: 'guides/{site}.{lang}.xml'; default: 'guide.xml')
97
- channels: 'example.com.channels.xml', // path to channels.xml file (required)
97
+ channels: 'example.com.channels.xml', // path to list of channels; you can also use an array to specify the path to multiple files at once (example: ['channels1.xml', 'channels2.xml']; required)
98
98
  lang: 'fr', // default language for all programs (default: 'en')
99
99
  days: 3, // number of days for which to grab the program (default: 1)
100
100
  delay: 5000, // delay between requests (default: 3000)
@@ -22,7 +22,7 @@ program
22
22
  .description(description)
23
23
  .requiredOption('-c, --config <config>', 'Path to [site].config.js file')
24
24
  .option('-o, --output <output>', 'Path to output file')
25
- .option('--channels <channels>', 'Path to channels.xml file')
25
+ .option('--channels <channels>', 'Path to list of channels')
26
26
  .option('--lang <lang>', 'Set default language for all programs')
27
27
  .option('--days <days>', 'Number of days for which to grab the program', parseNumber)
28
28
  .option('--delay <delay>', 'Delay between requests (in milliseconds)', parseNumber)
@@ -65,17 +65,31 @@ async function main() {
65
65
 
66
66
  if (options.timeout) config.request.timeout = options.timeout
67
67
  if (options.cacheTtl) config.request.cache.ttl = options.cacheTtl
68
+
68
69
  if (options.channels) config.channels = options.channels
69
- else if (config.channels)
70
- config.channels = file.join(file.dirname(options.config), config.channels)
71
- else throw new Error("The required 'channels' property is missing")
72
70
 
73
- if (!config.channels) return logger.error('Path to [site].channels.xml is missing')
74
- logger.info(`Loading '${config.channels}'...`)
75
- const grabber = new EPGGrabber(config)
71
+ let parsedChannels = []
72
+ if (config.channels) {
73
+ const dir = file.dirname(options.config)
74
+
75
+ let files = []
76
+ if (Array.isArray(config.channels)) {
77
+ files = config.channels.map(path => file.join(dir, path))
78
+ } else if (typeof config.channels === 'string') {
79
+ files = await file.list(config.channels)
80
+ } else {
81
+ throw new Error('The "channels" attribute must be of type array or string')
82
+ }
83
+
84
+ for (let filepath of files) {
85
+ logger.info(`Loading '${filepath}'...`)
86
+ const channelsXML = file.read(filepath)
87
+ const { channels } = parseChannels(channelsXML)
88
+ parsedChannels = parsedChannels.concat(channels)
89
+ }
90
+ } else throw new Error('Path to "channels" is missing')
76
91
 
77
- const channelsXML = file.read(config.channels)
78
- const { channels: parsedChannels } = parseChannels(channelsXML)
92
+ const grabber = new EPGGrabber(config)
79
93
 
80
94
  let template = options.output || config.output
81
95
  const variables = file.templateVariables(template)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epg-grabber",
3
- "version": "0.31.0",
3
+ "version": "0.32.0",
4
4
  "description": "Node.js CLI tool for grabbing EPG from different sites",
5
5
  "main": "src/index.js",
6
6
  "preferGlobal": true,
package/src/file.js CHANGED
@@ -1,6 +1,8 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
+ const glob = require('glob')
3
4
 
5
+ module.exports.list = list
4
6
  module.exports.read = read
5
7
  module.exports.write = write
6
8
  module.exports.resolve = resolve
@@ -9,6 +11,14 @@ module.exports.dirname = dirname
9
11
  module.exports.templateVariables = templateVariables
10
12
  module.exports.templateFormat = templateFormat
11
13
 
14
+ function list(pattern) {
15
+ return new Promise(resolve => {
16
+ glob(pattern, function (err, files) {
17
+ resolve(files)
18
+ })
19
+ })
20
+ }
21
+
12
22
  function read(filepath) {
13
23
  return fs.readFileSync(path.resolve(filepath), { encoding: 'utf-8' })
14
24
  }
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <site site="example2.com">
3
+ <channels>
4
+ <channel xmltv_id="3TV.com" site_id="3">3 TV</channel>
5
+ <channel xmltv_id="4TV.com" site_id="4">4 TV</channel>
6
+ </channels>
7
+ </site>
@@ -0,0 +1,32 @@
1
+ const dayjs = require('dayjs')
2
+ const utc = require('dayjs/plugin/utc')
3
+
4
+ dayjs.extend(utc)
5
+
6
+ module.exports = {
7
+ site: 'example.com',
8
+ days: 2,
9
+ channels: ['example.channels.xml', 'example_2.channels.xml'],
10
+ output: 'tests/__data__/output/guide.xml',
11
+ url: () => 'http://example.com/20210319/1tv.json',
12
+ request: {
13
+ method: 'POST',
14
+ headers: {
15
+ 'Content-Type': 'application/json',
16
+ Cookie: 'abc=123'
17
+ },
18
+ data() {
19
+ return { accountID: '123' }
20
+ }
21
+ },
22
+ parser: () => {
23
+ return [
24
+ {
25
+ title: 'Program1',
26
+ start: 1640995200000,
27
+ stop: 1640998800000
28
+ }
29
+ ]
30
+ },
31
+ logo: () => 'http://example.com/logos/1TV.png?x=шеллы&sid=777'
32
+ }
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?><tv date="20230709">
2
+ <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>
3
+ <channel id="2TV.com"><display-name>2 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example.com</url></channel>
4
+ <channel id="3TV.com"><display-name>3 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example2.com</url></channel>
5
+ <channel id="4TV.com"><display-name>4 TV</display-name><icon src="http://example.com/logos/1TV.png?x=шеллы&amp;sid=777"/><url>https://example2.com</url></channel>
6
+ </tv>
package/tests/bin.test.js CHANGED
@@ -105,3 +105,25 @@ it('removes duplicates of the program', () => {
105
105
 
106
106
  expect(output.programs).toEqual(expected.programs)
107
107
  })
108
+
109
+ it('can load multiple "channels.xml" files at once', () => {
110
+ const stdout = execSync(
111
+ `node ${pwd}/bin/epg-grabber.js --config=tests/__data__/input/example.config.js --channels=tests/__data__/input/example*.channels.xml --timeout=1`,
112
+ {
113
+ encoding: 'utf8'
114
+ }
115
+ )
116
+
117
+ expect(stdoutResultTester(stdout)).toBe(true)
118
+ })
119
+
120
+ it('can parse list of "channels.xml" from array', () => {
121
+ const stdout = execSync(
122
+ `node ${pwd}/bin/epg-grabber.js --config=tests/__data__/input/example_channels.config.js --timeout=1`,
123
+ {
124
+ encoding: 'utf8'
125
+ }
126
+ )
127
+
128
+ expect(stdoutResultTester(stdout)).toBe(true)
129
+ })
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8" ?><tv date="20230521">
2
- <channel id="1TV.com"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>
3
- <channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>
4
- <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="1TV.com"><title lang="fr">Program1</title></programme>
5
- <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="2TV.com"><title>Program1</title></programme>
6
- </tv>