iptv-checker 0.20.0 → 0.22.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.
@@ -62,8 +62,6 @@ const config = {
62
62
 
63
63
  const logger = new Logger(config)
64
64
 
65
- logger.debug({ config })
66
-
67
65
  const outputDir =
68
66
  argv.output || `iptv-checker-${dateFormat(new Date(), 'd-m-yyyy-hh-MM-ss')}`
69
67
  const onlineFile = `${outputDir}/online.m3u`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iptv-checker",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "Node.js CLI tool for checking links in IPTV playlists",
5
5
  "main": "src/index.js",
6
6
  "preferGlobal": true,
package/src/helper.js CHANGED
@@ -48,25 +48,54 @@ async function parsePlaylist(input) {
48
48
  return parse(data)
49
49
  }
50
50
 
51
- function parseStdout(string, item) {
51
+ function parseError(output, item) {
52
52
  const url = item.url
53
- const arr = string.split('\n')
54
-
55
- if (arr.length === 0) return
56
-
57
- const line = arr.find(l => {
53
+ const line = output.split('\n').find(l => {
58
54
  return l.indexOf(url) === 0
59
55
  })
60
56
 
61
57
  if (!line) {
62
- if (/^Command failed/.test(string)) {
63
- return 'Operation timed out'
64
- }
58
+ return 'Operation timed out'
65
59
  }
66
60
 
67
61
  return line.replace(`${url}: `, '')
68
62
  }
69
63
 
64
+ function parseStderr(stderr) {
65
+ const requests = stderr
66
+ .split('\r\n\n')
67
+ .map(parseRequest)
68
+ .filter(l => l)
69
+
70
+ return { requests }
71
+ }
72
+
73
+ function parseRequest(string) {
74
+ const urlMatch = string.match(/Opening '(.*)' for reading/)
75
+ const url = urlMatch ? urlMatch[1] : null
76
+ if (!url) return null
77
+ const requestMatch = string.match(/request: (.|[\r\n])+/gm)
78
+ const request = requestMatch ? requestMatch[0] : null
79
+ if (!request) return null
80
+ const arr = request
81
+ .split('\n')
82
+ .map(l => l.trim())
83
+ .filter(l => l)
84
+ const methodMatch = arr[0].match(/request: (GET|POST)/)
85
+ const method = methodMatch ? methodMatch[1] : null
86
+ arr.shift()
87
+ if (!arr) return null
88
+ const headers = {}
89
+ arr.forEach(line => {
90
+ const parts = line.split(': ')
91
+ if (parts && parts[1]) {
92
+ headers[parts[0]] = parts[1]
93
+ }
94
+ })
95
+
96
+ return { method, url, headers }
97
+ }
98
+
70
99
  function checkItem(item) {
71
100
  const { config, logger } = this
72
101
 
@@ -75,12 +104,14 @@ function checkItem(item) {
75
104
  logger.debug(`EXECUTING: "${command}"`)
76
105
 
77
106
  return execAsync(command, { timeout: config.timeout })
78
- .then(({ stdout }) => {
79
- if (stdout && isJSON(stdout)) {
107
+ .then(({ stdout, stderr }) => {
108
+ if (stdout && isJSON(stdout) && stderr) {
80
109
  const metadata = JSON.parse(stdout)
81
110
  if (!metadata.streams.length) {
82
- return { ok: false, reason: 'No working streams' }
111
+ return { ok: false, reason: 'No streams found' }
83
112
  }
113
+ const results = parseStderr(stderr)
114
+ metadata.requests = results.requests
84
115
 
85
116
  return { ok: true, metadata }
86
117
  }
@@ -88,34 +119,36 @@ function checkItem(item) {
88
119
  return { ok: false, reason: 'Parsing error' }
89
120
  })
90
121
  .catch(err => {
91
- const reason = parseStdout(err.message, item)
122
+ const reason = parseError(err.message, item)
92
123
 
93
124
  return { ok: false, reason }
94
125
  })
95
126
  }
96
127
 
97
128
  function buildCommand(item, config) {
98
- const { url, http = {} } = item
99
- const { referrer = ``, 'user-agent': itemUserAgent = `` } = http
100
- const userAgent = itemUserAgent.length ? itemUserAgent : config.userAgent
101
-
129
+ const userAgent = item.http['user-agent'] || config.userAgent
102
130
  let args = [
103
131
  `ffprobe`,
104
132
  `-of json`,
105
- `-v trace`,
133
+ `-v debug`,
106
134
  `-hide_banner`,
107
135
  `-show_streams`,
136
+ `-show_format`,
108
137
  ]
109
138
 
110
- if (referrer.length) {
111
- args.push(`-headers`, `'Referer: ${referrer}'`)
139
+ if (config.timeout) {
140
+ args.push(`-timeout`, `'${config.timeout * 1000}'`)
141
+ }
142
+
143
+ if (item.http.referrer) {
144
+ args.push(`-headers`, `'Referer: ${item.http.referrer}'`)
112
145
  }
113
146
 
114
147
  if (userAgent) {
115
148
  args.push(`-user_agent`, `'${userAgent}'`)
116
149
  }
117
150
 
118
- args.push(`'${url}'`)
151
+ args.push(`'${item.url}'`)
119
152
 
120
153
  args = args.join(` `)
121
154
 
package/src/index.js CHANGED
@@ -90,19 +90,16 @@ class IPTVChecker {
90
90
  }
91
91
 
92
92
  async checkStream(item) {
93
- const config = this.config
94
- const logger = this.logger
95
-
96
- await config.beforeEach(item)
93
+ await this.config.beforeEach(item)
97
94
 
98
- item.status = await helper.checkItem.call({ config, logger }, item)
95
+ item.status = await helper.checkItem.call(this, item)
99
96
  if (item.status.ok) {
100
- logger.debug(`OK: ${item.url}`.green)
97
+ this.logger.debug(`OK: ${item.url}`.green)
101
98
  } else {
102
- logger.debug(`FAILED: ${item.url} (${item.status.reason})`.red)
99
+ this.logger.debug(`FAILED: ${item.url} (${item.status.reason})`.red)
103
100
  }
104
101
 
105
- await config.afterEach(item)
102
+ await this.config.afterEach(item)
106
103
 
107
104
  return item
108
105
  }
package/test/bin.test.js CHANGED
@@ -1,3 +1,4 @@
1
+ const { performance } = require('perf_hooks')
1
2
  const { execSync } = require('child_process')
2
3
  const mkdirp = require('mkdirp')
3
4
  const del = require('del')
@@ -41,3 +42,14 @@ test(`Should process a playlist URL`, () => {
41
42
 
42
43
  expect(stdoutResultTester(result)).toBeTruthy()
43
44
  })
45
+
46
+ test(`Should respect timeout argument`, () => {
47
+ let t0 = performance.now()
48
+ execSync(
49
+ `node ${pwd}/bin/iptv-checker.js -t 7000 -o ${pwd}/test/output ${pwd}/test/input/timeout.m3u`,
50
+ { encoding: 'utf8' }
51
+ )
52
+ let t1 = performance.now()
53
+
54
+ expect(t1 - t0).toBeGreaterThan(7000)
55
+ })
@@ -12,7 +12,8 @@ function resultTester(result) {
12
12
  Reflect.has(item, `status`) &&
13
13
  Reflect.has(item.status, `ok`) &&
14
14
  (Reflect.has(item.status, `reason`) ||
15
- Reflect.has(item.status, `metadata`))
15
+ (Reflect.has(item.status, `metadata`) &&
16
+ Reflect.has(item.status.metadata, `requests`)))
16
17
  )
17
18
  })
18
19
  }
@@ -0,0 +1,3 @@
1
+ #EXTM3U
2
+ #EXTINF:-1,Connection timed out
3
+ https://5b464b69d264e.streamlock.net/Channels_live/ngrp:amordiscos_all/playlist.m3u8