epg-grabber 0.29.4 → 0.29.6

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.
@@ -23,7 +23,7 @@ program
23
23
  .option('-o, --output <output>', 'Path to output file')
24
24
  .option('--channels <channels>', 'Path to channels.xml file')
25
25
  .option('--lang <lang>', 'Set default language for all programs')
26
- .option('--days <days>', 'Number of days for which to grab the program', parseNumber, 1)
26
+ .option('--days <days>', 'Number of days for which to grab the program', parseNumber)
27
27
  .option('--delay <delay>', 'Delay between requests (in mileseconds)', parseNumber)
28
28
  .option('--timeout <timeout>', 'Set a timeout for each request (in mileseconds)', parseNumber)
29
29
  .option(
@@ -72,10 +72,11 @@ async function main() {
72
72
 
73
73
  let programs = []
74
74
  let i = 1
75
- let days = options.days || 1
75
+ let days = config.days || 1
76
76
  const total = channels.length * days
77
77
  const utcDate = getUTCDate()
78
- const dates = Array.from({ length: config.days }, (_, i) => utcDate.add(i, 'd'))
78
+ const dates = Array.from({ length: days }, (_, i) => utcDate.add(i, 'd'))
79
+ console.log(dates)
79
80
  for (let channel of channels) {
80
81
  if (!channel.logo && config.logo) {
81
82
  channel.logo = await grabber.loadLogo(channel)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epg-grabber",
3
- "version": "0.29.4",
3
+ "version": "0.29.6",
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/xmltv.js CHANGED
@@ -6,142 +6,142 @@ const el = createElement
6
6
  module.exports.generate = generate
7
7
 
8
8
  function generate({ channels, programs, date = getUTCDate() }) {
9
- if (!channels.every(c => c instanceof Channel)) {
10
- throw new Error('"channels" must be an array of Channels')
11
- }
9
+ if (!channels.every(c => c instanceof Channel)) {
10
+ throw new Error('"channels" must be an array of Channels')
11
+ }
12
12
 
13
- if (!programs.every(p => p instanceof Program)) {
14
- throw new Error('"programs" must be an array of Programs')
15
- }
13
+ if (!programs.every(p => p instanceof Program)) {
14
+ throw new Error('"programs" must be an array of Programs')
15
+ }
16
16
 
17
- if (!isDate(date)) {
18
- throw new Error('"date" must be a valid date')
19
- }
17
+ if (!isDate(date)) {
18
+ throw new Error('"date" must be a valid date')
19
+ }
20
20
 
21
- let output = `<?xml version="1.0" encoding="UTF-8" ?>`
22
- output += createElements(channels, programs, date)
21
+ let output = `<?xml version="1.0" encoding="UTF-8" ?>`
22
+ output += createElements(channels, programs, date)
23
23
 
24
- return output
24
+ return output
25
25
  }
26
26
 
27
27
  function createElements(channels, programs, date) {
28
- return el('tv', { date: formatDate(date, 'YYYYMMDD') }, [
29
- ...channels.map(channel => {
30
- return (
31
- '\r\n' +
32
- el('channel', { id: channel.id }, [
33
- el('display-name', {}, [escapeString(channel.name)]),
34
- el('icon', { src: channel.logo }),
35
- el('url', {}, [channel.url])
36
- ])
37
- )
38
- }),
39
- ...programs.map(program => {
40
- return (
41
- '\r\n' +
42
- el(
43
- 'programme',
44
- {
45
- start: formatDate(program.start, 'YYYYMMDDHHmmss ZZ'),
46
- stop: formatDate(program.stop, 'YYYYMMDDHHmmss ZZ'),
47
- channel: program.channel
48
- },
49
- [
50
- ...program.titles.map(title =>
51
- el('title', { lang: title.lang }, [escapeString(title.value)])
52
- ),
53
- ...program.sub_titles.map(sub_title =>
54
- el('sub-title', { lang: sub_title.lang }, [escapeString(sub_title.value)])
55
- ),
56
- ...program.descriptions.map(desc =>
57
- el('desc', { lang: desc.lang }, [escapeString(desc.value)])
58
- ),
59
- el('credits', {}, [
60
- ...program.directors.map(data => createCastMember('director', data)),
61
- ...program.actors.map(data => createCastMember('actor', data)),
62
- ...program.writers.map(data => createCastMember('writer', data)),
63
- ...program.adapters.map(data => createCastMember('adapter', data)),
64
- ...program.producers.map(data => createCastMember('producer', data)),
65
- ...program.composers.map(data => createCastMember('composer', data)),
66
- ...program.editors.map(data => createCastMember('editor', data)),
67
- ...program.presenters.map(data => createCastMember('presenter', data)),
68
- ...program.commentators.map(data => createCastMember('commentator', data)),
69
- ...program.guests.map(data => createCastMember('guest', data))
70
- ]),
71
- el('date', {}, [formatDate(program.date, 'YYYYMMDD')]),
72
- ...program.categories.map(category =>
73
- el('category', { lang: category.lang }, [escapeString(category.value)])
74
- ),
75
- el('icon', { src: program.icon.src }),
76
- ...program.urls.map(createURL),
77
- ...program.episodeNumbers.map(episode =>
78
- el('episode-num', { system: episode.system }, [episode.value])
79
- ),
80
- ...program.ratings.map(rating =>
81
- el('rating', { system: rating.system }, [
82
- el('value', {}, [rating.value]),
83
- el('icon', { src: rating.icon })
84
- ])
85
- )
86
- ]
87
- )
88
- )
89
- }),
90
- '\r\n'
91
- ])
28
+ return el('tv', { date: formatDate(date, 'YYYYMMDD') }, [
29
+ ...channels.map(channel => {
30
+ return (
31
+ '\r\n' +
32
+ el('channel', { id: channel.id }, [
33
+ el('display-name', {}, [escapeString(channel.name)]),
34
+ el('icon', { src: channel.logo }),
35
+ el('url', {}, [channel.url])
36
+ ])
37
+ )
38
+ }),
39
+ ...programs.map(program => {
40
+ return (
41
+ '\r\n' +
42
+ el(
43
+ 'programme',
44
+ {
45
+ start: formatDate(program.start, 'YYYYMMDDHHmmss ZZ'),
46
+ stop: formatDate(program.stop, 'YYYYMMDDHHmmss ZZ'),
47
+ channel: program.channel
48
+ },
49
+ [
50
+ ...program.titles.map(title =>
51
+ el('title', { lang: title.lang }, [escapeString(title.value)])
52
+ ),
53
+ ...program.sub_titles.map(sub_title =>
54
+ el('sub-title', { lang: sub_title.lang }, [escapeString(sub_title.value)])
55
+ ),
56
+ ...program.descriptions.map(desc =>
57
+ el('desc', { lang: desc.lang }, [escapeString(desc.value)])
58
+ ),
59
+ el('credits', {}, [
60
+ ...program.directors.map(data => createCastMember('director', data)),
61
+ ...program.actors.map(data => createCastMember('actor', data)),
62
+ ...program.writers.map(data => createCastMember('writer', data)),
63
+ ...program.adapters.map(data => createCastMember('adapter', data)),
64
+ ...program.producers.map(data => createCastMember('producer', data)),
65
+ ...program.composers.map(data => createCastMember('composer', data)),
66
+ ...program.editors.map(data => createCastMember('editor', data)),
67
+ ...program.presenters.map(data => createCastMember('presenter', data)),
68
+ ...program.commentators.map(data => createCastMember('commentator', data)),
69
+ ...program.guests.map(data => createCastMember('guest', data))
70
+ ]),
71
+ el('date', {}, [formatDate(program.date, 'YYYYMMDD')]),
72
+ ...program.categories.map(category =>
73
+ el('category', { lang: category.lang }, [escapeString(category.value)])
74
+ ),
75
+ el('icon', { src: program.icon.src }),
76
+ ...program.urls.map(createURL),
77
+ ...program.episodeNumbers.map(episode =>
78
+ el('episode-num', { system: episode.system }, [episode.value])
79
+ ),
80
+ ...program.ratings.map(rating =>
81
+ el('rating', { system: rating.system }, [
82
+ el('value', {}, [escapeString(rating.value)]),
83
+ el('icon', { src: rating.icon })
84
+ ])
85
+ )
86
+ ]
87
+ )
88
+ )
89
+ }),
90
+ '\r\n'
91
+ ])
92
92
  }
93
93
 
94
94
  function createCastMember(position, data) {
95
- return el(position, {}, [
96
- escapeString(data.value),
97
- ...data.url.map(createURL),
98
- ...data.image.map(createImage)
99
- ])
95
+ return el(position, {}, [
96
+ escapeString(data.value),
97
+ ...data.url.map(createURL),
98
+ ...data.image.map(createImage)
99
+ ])
100
100
  }
101
101
 
102
102
  function createImage(image) {
103
- return el(
104
- 'image',
105
- {
106
- type: image.type,
107
- size: image.size,
108
- orient: image.orient,
109
- system: image.system
110
- },
111
- [image.value]
112
- )
103
+ return el(
104
+ 'image',
105
+ {
106
+ type: image.type,
107
+ size: image.size,
108
+ orient: image.orient,
109
+ system: image.system
110
+ },
111
+ [image.value]
112
+ )
113
113
  }
114
114
 
115
115
  function createURL(url) {
116
- return el('url', { system: url.system }, [url.value])
116
+ return el('url', { system: url.system }, [url.value])
117
117
  }
118
118
 
119
119
  function createElement(name, attrs = {}, children = []) {
120
- return toString({ name, attrs, children })
120
+ return toString({ name, attrs, children })
121
121
  }
122
122
 
123
123
  function toString(elem) {
124
- if (typeof elem === 'string' || typeof elem === 'number') return elem
124
+ if (typeof elem === 'string' || typeof elem === 'number') return elem
125
125
 
126
- let attrs = ''
127
- for (let key in elem.attrs) {
128
- let value = elem.attrs[key]
129
- if (value) {
130
- attrs += ` ${key}="${escapeString(value)}"`
131
- }
132
- }
126
+ let attrs = ''
127
+ for (let key in elem.attrs) {
128
+ let value = elem.attrs[key]
129
+ if (value) {
130
+ attrs += ` ${key}="${escapeString(value)}"`
131
+ }
132
+ }
133
133
 
134
- if (elem.children.filter(Boolean).length) {
135
- let children = ''
136
- elem.children.forEach(childElem => {
137
- children += toString(childElem)
138
- })
134
+ if (elem.children.filter(Boolean).length) {
135
+ let children = ''
136
+ elem.children.forEach(childElem => {
137
+ children += toString(childElem)
138
+ })
139
139
 
140
- return `<${elem.name}${attrs}>${children}</${elem.name}>`
141
- }
140
+ return `<${elem.name}${attrs}>${children}</${elem.name}>`
141
+ }
142
142
 
143
- if (!attrs) return ''
144
- if (!['icon'].includes(elem.name)) return ''
143
+ if (!attrs) return ''
144
+ if (!['icon'].includes(elem.name)) return ''
145
145
 
146
- return `<${elem.name}${attrs}/>`
146
+ return `<${elem.name}${attrs}/>`
147
147
  }
@@ -5,6 +5,7 @@ dayjs.extend(utc)
5
5
 
6
6
  module.exports = {
7
7
  site: 'example.com',
8
+ days: 2,
8
9
  channels: 'example.channels.xml',
9
10
  output: 'tests/output/guide.xml',
10
11
  url: () => 'http://example.com/20210319/1tv.json',
@@ -1,4 +1,4 @@
1
- <?xml version="1.0" encoding="UTF-8" ?><tv date="20221120">
1
+ <?xml version="1.0" encoding="UTF-8" ?><tv date="20230110">
2
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
3
  <channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>
4
4
  <programme start="20220101000000 +0000" stop="20220101010000 +0000" channel="1TV.com"><title lang="fr">Program1</title></programme>
@@ -1,4 +1,4 @@
1
- <?xml version="1.0" encoding="UTF-8" ?><tv date="20221120">
1
+ <?xml version="1.0" encoding="UTF-8" ?><tv date="20230110">
2
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
3
  <channel id="2TV.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>
4
4
  </tv>
package/tests/bin.test.js CHANGED
@@ -12,18 +12,18 @@ function stdoutResultTester(stdout) {
12
12
  }
13
13
 
14
14
  it('can load config', () => {
15
- const result = execSync(
15
+ const stdout = execSync(
16
16
  `node ${pwd}/bin/epg-grabber.js --config=tests/__data__/input/example.config.js --delay=0`,
17
17
  {
18
18
  encoding: 'utf8'
19
19
  }
20
20
  )
21
21
 
22
- expect(stdoutResultTester(result)).toBe(true)
22
+ expect(stdoutResultTester(stdout)).toBe(true)
23
23
  })
24
24
 
25
25
  it('can load mini config', () => {
26
- const result = execSync(
26
+ const stdout = execSync(
27
27
  `node ${pwd}/bin/epg-grabber.js \
28
28
  --config=tests/__data__/input/mini.config.js \
29
29
  --channels=tests/__data__/input/example.channels.xml \
@@ -38,14 +38,14 @@ it('can load mini config', () => {
38
38
  }
39
39
  )
40
40
 
41
- expect(stdoutResultTester(result)).toBe(true)
42
- expect(result.includes("File 'tests/__data__/output/mini.guide.xml' successfully saved")).toBe(
41
+ expect(stdoutResultTester(stdout)).toBe(true)
42
+ expect(stdout.includes("File 'tests/__data__/output/mini.guide.xml' successfully saved")).toBe(
43
43
  true
44
44
  )
45
45
  })
46
46
 
47
47
  it('can generate gzip version', () => {
48
- const result = execSync(
48
+ const stdout = execSync(
49
49
  `node ${pwd}/bin/epg-grabber.js \
50
50
  --config=tests/__data__/input/mini.config.js \
51
51
  --channels=tests/__data__/input/example.channels.xml \
@@ -56,14 +56,14 @@ it('can generate gzip version', () => {
56
56
  }
57
57
  )
58
58
 
59
- expect(stdoutResultTester(result)).toBe(true)
60
- expect(result.includes("File 'tests/__data__/output/mini.guide.xml.gz' successfully saved")).toBe(
59
+ expect(stdoutResultTester(stdout)).toBe(true)
60
+ expect(stdout.includes("File 'tests/__data__/output/mini.guide.xml.gz' successfully saved")).toBe(
61
61
  true
62
62
  )
63
63
  })
64
64
 
65
65
  it('removes duplicates of the program', () => {
66
- const result = execSync(
66
+ const stdout = execSync(
67
67
  `node ${pwd}/bin/epg-grabber.js \
68
68
  --config=tests/__data__/input/duplicates.config.js \
69
69
  --channels=tests/__data__/input/example.channels.xml \
@@ -5,7 +5,7 @@ import fs from 'fs'
5
5
  it('can load config', () => {
6
6
  const config = loadConfig(require(path.resolve('./tests/__data__/input/example.config.js')))
7
7
  expect(config).toMatchObject({
8
- days: 1,
8
+ days: 2,
9
9
  delay: 3000,
10
10
  lang: 'en',
11
11
  site: 'example.com'
@@ -36,7 +36,7 @@ it('can generate xmltv', () => {
36
36
  icon: 'https://example.com/images/Program1.png?x=шеллы&sid=777',
37
37
  rating: {
38
38
  system: 'MPAA',
39
- value: 'PG',
39
+ value: 'P&G',
40
40
  icon: 'http://example.com/pg_symbol.png'
41
41
  },
42
42
  director: [
@@ -74,6 +74,6 @@ it('can generate xmltv', () => {
74
74
  const output = xmltv.generate({ channels, programs })
75
75
 
76
76
  expect(output).toBe(
77
- '<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.co"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.co"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.co"><title>Program 1</title><sub-title>Sub-title &amp; 1</sub-title><desc>Description for Program 1</desc><credits><director>Director 1<url system="TestSystem">http://example.com/director1.html</url><image>https://example.com/image1.jpg</image><image type="person" size="2" orient="P" system="TestSystem">https://example.com/image2.jpg</image></director><director>Director 2</director><actor>Actor 1</actor><actor>Actor 2</actor><writer>Writer 1</writer></credits><date>20220506</date><category>Test</category><icon src="https://example.com/images/Program1.png?x=шеллы&amp;sid=777"/><url>http://example.com/title.html</url><episode-num system="xmltv_ns">8.238.0/1</episode-num><episode-num system="onscreen">S09E239</episode-num><rating system="MPAA"><value>PG</value><icon src="http://example.com/pg_symbol.png"/></rating></programme>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="2TV.co"><title lang="es">Program 2</title></programme>\r\n</tv>'
77
+ '<?xml version="1.0" encoding="UTF-8" ?><tv date="20220505">\r\n<channel id="1TV.co"><display-name>1 TV</display-name><icon src="https://example.com/logos/1TV.png"/><url>https://example.com</url></channel>\r\n<channel id="2TV.co"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.co"><title>Program 1</title><sub-title>Sub-title &amp; 1</sub-title><desc>Description for Program 1</desc><credits><director>Director 1<url system="TestSystem">http://example.com/director1.html</url><image>https://example.com/image1.jpg</image><image type="person" size="2" orient="P" system="TestSystem">https://example.com/image2.jpg</image></director><director>Director 2</director><actor>Actor 1</actor><actor>Actor 2</actor><writer>Writer 1</writer></credits><date>20220506</date><category>Test</category><icon src="https://example.com/images/Program1.png?x=шеллы&amp;sid=777"/><url>http://example.com/title.html</url><episode-num system="xmltv_ns">8.238.0/1</episode-num><episode-num system="onscreen">S09E239</episode-num><rating system="MPAA"><value>P&amp;G</value><icon src="http://example.com/pg_symbol.png"/></rating></programme>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="2TV.co"><title lang="es">Program 2</title></programme>\r\n</tv>'
78
78
  )
79
79
  })