11#! /usr/bin/env node
22
3- const fs = require ( 'fs' )
4- const argv = require ( 'commander' )
5- const getStdin = require ( 'get-stdin' )
6- const ProgressBar = require ( 'progress' )
7- const dateFormat = require ( 'dateformat' )
8- const { version, homepage } = require ( '../package.json' )
9- const IPTVChecker = require ( '../src/index' )
10- const Logger = require ( '../src/Logger' )
11-
12- let seedFile
13- let bar
14- const stats = {
15- total : 0 ,
16- online : 0 ,
17- offline : 0 ,
18- duplicates : 0 ,
19- }
20-
21- argv
22- . version ( version , '-v, --version' )
3+ import app from '../package.json' with { type : 'json' }
4+ import { Playlist } from '../src/core/Playlist.js'
5+ import { Logger } from '../src/core/Logger.js'
6+ import { IPTVChecker } from '../src/index.js'
7+ import dateFormat from 'dateformat'
8+ import { program } from 'commander'
9+ import ProgressBar from 'progress'
10+ import getStdin from 'get-stdin'
11+ import { cpus } from 'os'
12+ import fs from 'fs'
13+
14+ let stdin
15+
16+ program
17+ . version ( app . version , '-v, --version' )
2318 . name ( 'iptv-checker' )
2419 . description ( 'Utility to check M3U playlists entries' )
25- . usage ( '[options] [file-or-url]' )
26- . option ( '-o, --output <output>' , 'Path to output directory' )
27- . option (
28- '-t, --timeout <timeout>' ,
29- 'Set the number of milliseconds for each request' ,
30- 60000
31- )
20+ . usage ( '[options] [file|url]' )
3221 . option (
33- '-p , --parallel <number >' ,
34- 'Batch size of items to check concurrently ' ,
35- 1
22+ '-o , --output <dir >' ,
23+ 'Path to output directory ' ,
24+ `iptv-checker_ ${ dateFormat ( new Date ( ) , 'yyyymmddhhMMss' ) } `
3625 )
26+ . option ( '-t, --timeout <number>' , 'Set the number of milliseconds for each request' , 60000 )
27+ . option ( '-d, --delay <number>' , 'Set delay between requests in milliseconds' , 0 )
28+ . option ( '-r, --retry <number>' , 'Set the number of retries for failed requests' , 0 )
29+ . option ( '-p, --parallel <number>' , 'Batch size of items to check concurrently' , cpus ( ) . length )
3730 . option (
38- '-a, --user-agent <user-agent >' ,
31+ '-a, --user-agent <string >' ,
3932 'Set custom HTTP User-Agent' ,
40- `IPTVChecker/${ version } (${ homepage } )`
33+ `IPTVChecker/${ app . version } (${ app . homepage } )`
4134 )
35+ . option ( '-x, --proxy <url>' , 'Set HTTP proxy to tunnel through' )
4236 . option ( '-k, --insecure' , 'Allow insecure connections when using SSL' )
43- . option ( '-d , --debug' , 'Toggle debug mode' )
44- . action ( function ( file = null ) {
45- seedFile = file
37+ . option ( '-D , --debug' , 'Enable debug mode' )
38+ . action ( ( str = null ) => {
39+ stdin = str
4640 } )
41+ . argument ( '[file|url]' , 'Path to the file or url' )
4742 . parse ( process . argv )
4843
49- process . env [ 'NODE_TLS_REJECT_UNAUTHORIZED' ] = ! + argv . insecure
44+ const options = program . opts ( )
45+
46+ process . env [ 'NODE_TLS_REJECT_UNAUTHORIZED' ] = ! + options . insecure
5047
5148const config = {
52- debug : argv . debug || false ,
53- insecure : argv . insecure ,
54- userAgent : argv . userAgent ,
55- timeout : parseInt ( argv . timeout ) ,
56- parallel : + argv . parallel ,
49+ debug : options . debug || false ,
50+ insecure : options . insecure ,
51+ userAgent : options . userAgent ,
52+ proxy : options . proxy ,
53+ timeout : parseInt ( options . timeout ) ,
54+ parallel : + options . parallel ,
55+ delay : + options . delay ,
56+ retry : + options . retry ,
5757 setUp,
58- afterEach,
58+ afterEach
5959}
6060
61- const logger = new Logger ( config )
62-
63- const outputDir =
64- argv . output || `iptv-checker- ${ dateFormat ( new Date ( ) , 'd-m-yyyy-hh-MM-ss' ) } `
65- const onlineFile = ` ${ outputDir } /online.m3u`
66- const offlineFile = ` ${ outputDir } /offline.m3u`
67- const duplicatesFile = ` ${ outputDir } /duplicates.m3u`
61+ let bar
62+ const stats = {
63+ total : 0 ,
64+ online : 0 ,
65+ offline : 0 ,
66+ duplicates : 0
67+ }
6868
69+ const outputDir = options . output
6970try {
7071 fs . lstatSync ( outputDir )
7172} catch ( e ) {
7273 fs . mkdirSync ( outputDir )
7374}
7475
75- fs . writeFileSync ( onlineFile , '#EXTM3U\n' )
76- fs . writeFileSync ( offlineFile , '#EXTM3U\n' )
77- fs . writeFileSync ( duplicatesFile , '#EXTM3U\n' )
76+ const onlinePlaylist = new Playlist ( ` ${ outputDir } /online.m3u` )
77+ const offlinePlaylist = new Playlist ( ` ${ outputDir } /offline.m3u` )
78+ const duplicatesPlaylist = new Playlist ( ` ${ outputDir } /duplicates.m3u` )
7879
7980init ( )
8081
8182async function init ( ) {
83+ const logger = new Logger ( config )
84+
8285 try {
83- if ( ! seedFile || ! seedFile . length ) seedFile = await getStdin ( )
86+ if ( ! stdin || ! stdin . length ) stdin = await getStdin ( )
8487
8588 const checker = new IPTVChecker ( config )
86- const checked = await checker . checkPlaylist ( seedFile )
89+ const checked = await checker . checkPlaylist ( stdin )
8790
8891 stats . online = checked . items . filter ( item => item . status . ok ) . length
8992 stats . offline = checked . items . filter (
@@ -97,7 +100,7 @@ async function init() {
97100 `Total: ${ stats . total } ` ,
98101 `Online: ${ stats . online } ` . green ,
99102 `Offline: ${ stats . offline } ` . red ,
100- `Duplicates: ${ stats . duplicates } ` . yellow ,
103+ `Duplicates: ${ stats . duplicates } ` . yellow
101104 ] . join ( '\n' )
102105
103106 logger . info ( `\n${ result } ` )
@@ -110,11 +113,11 @@ async function init() {
110113
111114function afterEach ( item ) {
112115 if ( item . status . ok ) {
113- writeToFile ( onlineFile , item )
116+ onlinePlaylist . append ( item )
114117 } else if ( item . status . code === `DUPLICATE` ) {
115- writeToFile ( duplicatesFile , item )
118+ duplicatesPlaylist . append ( item )
116119 } else {
117- writeToFile ( offlineFile , item , item . status . message )
120+ offlinePlaylist . append ( item )
118121 }
119122
120123 if ( ! config . debug ) {
@@ -125,17 +128,6 @@ function afterEach(item) {
125128function setUp ( playlist ) {
126129 stats . total = playlist . items . length
127130 bar = new ProgressBar ( '[:bar] :current/:total (:percent) ' , {
128- total : stats . total ,
131+ total : stats . total
129132 } )
130133}
131-
132- function writeToFile ( path , item , message = null ) {
133- const lines = item . raw . split ( '\n' )
134- const extinf = lines [ 0 ]
135-
136- if ( message ) {
137- lines [ 0 ] = `${ extinf . trim ( ) } (${ message } )`
138- }
139-
140- fs . appendFileSync ( path , `${ lines . join ( '\n' ) } \n` )
141- }
0 commit comments