epg-grabber 0.15.1 → 0.17.1

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
@@ -94,6 +94,7 @@ module.exports = {
94
94
  lang: 'fr', // default language for all programs (default: 'en')
95
95
  days: 3, // number of days for which to grab the program (default: 1)
96
96
  delay: 5000, // delay between requests (default: 3000)
97
+ ignore: true, // skip all channels during request (default: false)
97
98
 
98
99
  request: { // request options (details: https://github.com/axios/axios#request-config)
99
100
 
@@ -158,12 +159,14 @@ module.exports = {
158
159
  return [
159
160
  {
160
161
  title, // program title (required)
161
- start, // program start time (required)
162
- stop, // program end time (optional)
163
- description, // program description (optional)
164
- category, // program category (optional)
165
- icon, // program icon (optional)
166
- lang // program language (default: 'en')
162
+ start, // start time of the program (required)
163
+ stop, // end time of the program (required)
164
+ description, // description of the program (optional)
165
+ category, // program type (optional)
166
+ season, // season number (optional)
167
+ episode, // episode number (optional)
168
+ icon, // image associated with the program (optional)
169
+ lang // language of the description (default: 'en')
167
170
  },
168
171
  ...
169
172
  ]
@@ -7,7 +7,7 @@ const path = require('path')
7
7
  const grabber = require('../src/index')
8
8
  const utils = require('../src/utils')
9
9
  const { name, version, description } = require('../package.json')
10
- const merge = require('lodash.merge')
10
+ const { merge } = require('lodash')
11
11
  const { createLogger, format, transports } = require('winston')
12
12
  const { combine, timestamp, printf } = format
13
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epg-grabber",
3
- "version": "0.15.1",
3
+ "version": "0.17.1",
4
4
  "description": "Node.js CLI tool for grabbing EPG from different sites",
5
5
  "main": "src/index.js",
6
6
  "preferGlobal": true,
@@ -34,7 +34,7 @@
34
34
  "commander": "^7.1.0",
35
35
  "dayjs": "^1.10.4",
36
36
  "glob": "^7.1.6",
37
- "lodash.merge": "^4.6.2",
37
+ "lodash": "^4.17.21",
38
38
  "tough-cookie": "^4.0.0",
39
39
  "winston": "^3.3.3",
40
40
  "xml-js": "^1.6.11"
package/src/index.js CHANGED
@@ -14,6 +14,12 @@ module.exports = {
14
14
 
15
15
  let programs = []
16
16
  for (let item of queue) {
17
+ if (config.ignore) {
18
+ item.programs = []
19
+ cb(item, new Error('Skipped'))
20
+ continue
21
+ }
22
+
17
23
  await utils
18
24
  .buildRequest(item, config)
19
25
  .then(request => utils.fetchData(request))
package/src/utils.js CHANGED
@@ -1,10 +1,11 @@
1
1
  const fs = require('fs')
2
+ const { padStart } = require('lodash')
2
3
  const path = require('path')
3
4
  const axios = require('axios').default
4
5
  const axiosCookieJarSupport = require('axios-cookiejar-support').default
5
6
  const tough = require('tough-cookie')
6
7
  const convert = require('xml-js')
7
- const merge = require('lodash.merge')
8
+ const { merge } = require('lodash')
8
9
  const dayjs = require('dayjs')
9
10
  const utc = require('dayjs/plugin/utc')
10
11
  dayjs.extend(utc)
@@ -126,6 +127,8 @@ utils.convertToXMLTV = function ({ channels, programs }) {
126
127
  const start = program.start ? dayjs.unix(program.start).utc().format('YYYYMMDDHHmmss ZZ') : ''
127
128
  const stop = program.stop ? dayjs.unix(program.stop).utc().format('YYYYMMDDHHmmss ZZ') : ''
128
129
  const lang = program.lang || 'en'
130
+ const xmltv_ns = createXMLTVNS(program.season, program.episode)
131
+ const onscreen = createOnScreen(program.season, program.episode)
129
132
  const icon = utils.escapeString(program.icon)
130
133
 
131
134
  if (start && stop && title) {
@@ -143,6 +146,14 @@ utils.convertToXMLTV = function ({ channels, programs }) {
143
146
  })
144
147
  }
145
148
 
149
+ if (xmltv_ns) {
150
+ output += `<episode-num system="xmltv_ns">${xmltv_ns}</episode-num>`
151
+ }
152
+
153
+ if (onscreen) {
154
+ output += `<episode-num system="onscreen">${onscreen}</episode-num>`
155
+ }
156
+
146
157
  if (icon) {
147
158
  output += `<icon src="${icon}"/>`
148
159
  }
@@ -153,6 +164,21 @@ utils.convertToXMLTV = function ({ channels, programs }) {
153
164
 
154
165
  output += '</tv>'
155
166
 
167
+ function createXMLTVNS(s, e) {
168
+ if (!s || !e) return null
169
+
170
+ return `${s - 1}.${e - 1}.0/1`
171
+ }
172
+
173
+ function createOnScreen(s, e) {
174
+ if (!s || !e) return null
175
+
176
+ s = padStart(s, 2, '0')
177
+ e = padStart(e, 2, '0')
178
+
179
+ return `S${s}E${e}`
180
+ }
181
+
156
182
  return output
157
183
  }
158
184
 
@@ -244,7 +270,7 @@ utils.parseResponse = async (item, response, config) => {
244
270
  })
245
271
 
246
272
  if (!item.channel.logo && config.logo) {
247
- item.channel.logo = await utils.loadLogo(data, config)
273
+ data.channel.logo = await utils.loadLogo(data, config)
248
274
  }
249
275
 
250
276
  return await utils.parsePrograms(data, config)
@@ -269,6 +295,8 @@ utils.parsePrograms = async function (data, config) {
269
295
  title: program.title,
270
296
  description: program.description || null,
271
297
  category: program.category || null,
298
+ season: program.season || null,
299
+ episode: program.episode || null,
272
300
  icon: program.icon || null,
273
301
  channel: channel.xmltv_id,
274
302
  lang: program.lang || channel.lang || config.lang || 'en',
package/tests/bin.test.js CHANGED
@@ -1,8 +1,6 @@
1
1
  const { execSync } = require('child_process')
2
- const pwd = `${__dirname}/..`
3
- import axios from 'axios'
4
2
 
5
- jest.mock('axios')
3
+ const pwd = `${__dirname}/..`
6
4
 
7
5
  function stdoutResultTester(stdout) {
8
6
  return [`Finish`].every(val => {
@@ -22,8 +20,6 @@ it('can load config', () => {
22
20
  })
23
21
 
24
22
  it('can load mini config', () => {
25
- axios.mockImplementation(() => Promise.resolve({ data: '' }))
26
-
27
23
  const result = execSync(
28
24
  `node ${pwd}/bin/epg-grabber.js \
29
25
  --config=tests/input/mini.config.js \
@@ -32,7 +28,8 @@ it('can load mini config', () => {
32
28
  --lang=fr \
33
29
  --days=3 \
34
30
  --delay=0 \
35
- --timeout=10000`,
31
+ --debug \
32
+ --timeout=1`,
36
33
  {
37
34
  encoding: 'utf8'
38
35
  }
@@ -71,3 +71,23 @@ it('can grab single channel programs', done => {
71
71
  done()
72
72
  })
73
73
  })
74
+
75
+ it('return "Skipped" error if ignore option in config is true', done => {
76
+ const config = {
77
+ site: 'example.com',
78
+ ignore: true,
79
+ url: `http://example.com/20210319/1tv.json`,
80
+ parser: () => []
81
+ }
82
+ const channel = {
83
+ site: 'example.com',
84
+ site_id: 'cnn',
85
+ xmltv_id: 'CNN.us',
86
+ lang: 'en',
87
+ name: 'CNN'
88
+ }
89
+ grabber.grab(channel, config, (data, err) => {
90
+ expect(err.message).toBe('Skipped')
91
+ done()
92
+ })
93
+ })
@@ -1,5 +1,11 @@
1
+ const dayjs = require('dayjs')
2
+ const utc = require('dayjs/plugin/utc')
3
+
4
+ dayjs.extend(utc)
5
+
1
6
  module.exports = {
2
7
  site: 'example.com',
8
+ ignore: true,
3
9
  channels: 'example.com.channels.xml',
4
10
  output: 'tests/output/guide.xml',
5
11
  url: () => 'http://example.com/20210319/1tv.json',
@@ -13,6 +19,20 @@ module.exports = {
13
19
  return { accountID: '123' }
14
20
  }
15
21
  },
16
- parser: () => [],
22
+ parser: () => {
23
+ return [
24
+ {
25
+ title: 'Title',
26
+ description: 'Description',
27
+ lang: 'en',
28
+ category: ['Category1', 'Category2'],
29
+ icon: 'https://example.com/image.jpg',
30
+ season: 9,
31
+ episode: 238,
32
+ start: dayjs.utc('2022-01-01 00:00:00'),
33
+ stop: dayjs.utc('2022-01-01 01:00:00')
34
+ }
35
+ ]
36
+ },
17
37
  logo: () => 'http://example.com/logos/1TV.png?x=шеллы&sid=777'
18
38
  }
@@ -1,5 +1,6 @@
1
1
  module.exports = {
2
2
  site: 'example.com',
3
+ ignore: true,
3
4
  url: 'http://example.com/20210319/1tv.json',
4
5
  parser: () => []
5
6
  }
@@ -7,6 +7,7 @@ it('can load valid config.js', () => {
7
7
  const config = utils.loadConfig(require(path.resolve('./tests/input/example.com.config.js')))
8
8
  expect(config).toMatchObject({
9
9
  days: 1,
10
+ ignore: true,
10
11
  delay: 3000,
11
12
  lang: 'en',
12
13
  site: 'example.com'
@@ -59,6 +60,8 @@ it('can convert object to xmltv string', () => {
59
60
  start: 1616133600,
60
61
  stop: 1616135400,
61
62
  category: 'Test',
63
+ season: 9,
64
+ episode: 239,
62
65
  icon: 'https://example.com/images/Program1.png?x=шеллы&sid=777',
63
66
  channel: '1TV.com',
64
67
  lang: 'it'
@@ -66,7 +69,7 @@ it('can convert object to xmltv string', () => {
66
69
  ]
67
70
  const output = utils.convertToXMLTV({ channels, programs })
68
71
  expect(output).toBe(
69
- '<?xml version="1.0" encoding="UTF-8" ?><tv>\r\n<channel id="1TV.com"><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.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test</category><icon src="https://example.com/images/Program1.png?x=шеллы&amp;sid=777"/></programme>\r\n</tv>'
72
+ '<?xml version="1.0" encoding="UTF-8" ?><tv>\r\n<channel id="1TV.com"><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.com"><display-name>2 TV</display-name><url>https://example.com</url></channel>\r\n<programme start="20210319060000 +0000" stop="20210319063000 +0000" channel="1TV.com"><title lang="it">Program 1</title><desc lang="it">Description for Program 1</desc><category lang="it">Test</category><episode-num system="xmltv_ns">8.238.0/1</episode-num><episode-num system="onscreen">S09E239</episode-num><icon src="https://example.com/images/Program1.png?x=шеллы&amp;sid=777"/></programme>\r\n</tv>'
70
73
  )
71
74
  })
72
75
 
@@ -195,6 +198,28 @@ it('can load logo async', done => {
195
198
  })
196
199
  })
197
200
 
201
+ it('can parse programs', done => {
202
+ const config = utils.loadConfig(require(path.resolve('./tests/input/example.com.config.js')))
203
+ return utils
204
+ .parsePrograms({ channel: { xmltv_id: '1tv', lang: 'en' } }, config)
205
+ .then(programs => {
206
+ expect(programs).toMatchObject([
207
+ {
208
+ title: 'Title',
209
+ description: 'Description',
210
+ lang: 'en',
211
+ category: ['Category1', 'Category2'],
212
+ icon: 'https://example.com/image.jpg',
213
+ season: 9,
214
+ episode: 238,
215
+ start: 1640995200,
216
+ stop: 1640998800
217
+ }
218
+ ])
219
+ done()
220
+ })
221
+ })
222
+
198
223
  it('can parse programs async', done => {
199
224
  const config = utils.loadConfig(require(path.resolve('./tests/input/async.config.js')))
200
225
  return utils