diff --git a/tests/__data__/.gitignore b/tests/__data__/.gitignore new file mode 100644 index 0000000000..d0dea4f002 --- /dev/null +++ b/tests/__data__/.gitignore @@ -0,0 +1,2 @@ +output/ +temp/ \ No newline at end of file diff --git a/tests/__data__/input/channels/ad_example.m3u b/tests/__data__/input/channels/ad_example.m3u new file mode 100644 index 0000000000..52612ebde6 --- /dev/null +++ b/tests/__data__/input/channels/ad_example.m3u @@ -0,0 +1,3 @@ +#EXTM3U +#EXTINF:-1 tvg-id="ATV.ad" tvg-country="AD" tvg-language="Catalan" tvg-logo="https://i.imgur.com/kJCjeQ4.png" group-title="General",ATV (720p) [Offline] +https://iptv-all.lanesh4d0w.repl.co/andorra/atv \ No newline at end of file diff --git a/tests/__data__/input/channels/us_blocked.m3u b/tests/__data__/input/channels/us_blocked.m3u new file mode 100644 index 0000000000..f08f25184e --- /dev/null +++ b/tests/__data__/input/channels/us_blocked.m3u @@ -0,0 +1,3 @@ +#EXTM3U +#EXTINF:-1 tvg-id="FoxSports2Asia.us" tvg-country="TH" tvg-language="Thai" tvg-logo="" group-title="Sports",Fox Sports 2 Asia (Thai) (720p) +https://example.com/playlist.m3u8 diff --git a/tests/__data__/input/codes.json b/tests/__data__/input/codes.json new file mode 100644 index 0000000000..3f8989427b --- /dev/null +++ b/tests/__data__/input/codes.json @@ -0,0 +1 @@ +[{"tvg_id":"AndorraTV.ad","display_name":"Andorra TV","country":"ad","guides":["https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml"],"logo":"https://www.andorradifusio.ad/images/logo/andorradifusio_logo_22122020091723.png"}] \ No newline at end of file diff --git a/tests/__data__/input/logs/check-streams/cluster_1.log b/tests/__data__/input/logs/check-streams/cluster_1.log new file mode 100644 index 0000000000..a152151d3a --- /dev/null +++ b/tests/__data__/input/logs/check-streams/cluster_1.log @@ -0,0 +1,3 @@ +{"_id":"I6cjG2xCBRFFP4sz","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http":{"referrer":"","user-agent":""},"error":"Operation timed out","streams":[],"requests":[]} +{"_id":"3TbieV1ptnZVCIdn","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","http":{"referrer":"","user-agent":""},"error":"Server returned 404 Not Found","streams":[],"requests":[]} + {"_id":"2ST8btby3mmsgPF0","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http":{"referrer":"","user-agent":""},"error":null,"streams":[{"index":0,"codec_name":"timed_id3","codec_long_name":"timed ID3 metadata","codec_type":"data","codec_tag_string":"ID3 ","codec_tag":"0x20334449","r_frame_rate":"0/0","avg_frame_rate":"0/0","time_base":"1/90000","disposition":{"default":0,"dub":0,"original":0,"comment":0,"lyrics":0,"karaoke":0,"forced":0,"hearing_impaired":0,"visual_impaired":0,"clean_effects":0,"attached_pic":0,"timed_thumbnails":0},"tags":{"variant_bitrate":"6527203"}},{"index":1,"codec_name":"h264","codec_long_name":"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10","profile":"Main","codec_type":"video","codec_tag_string":"[27][0][0][0]","codec_tag":"0x001b","width":1920,"height":1080,"coded_width":1920,"coded_height":1080,"closed_captions":0,"has_b_frames":0,"sample_aspect_ratio":"1:1","display_aspect_ratio":"16:9","pix_fmt":"yuv420p","level":40,"chroma_location":"left","refs":1,"is_avc":"false","nal_length_size":"0","r_frame_rate":"50/1","avg_frame_rate":"50/1","time_base":"1/90000","start_pts":8171218184,"start_time":"90791.313156","bits_per_raw_sample":"8","disposition":{"default":0,"dub":0,"original":0,"comment":0,"lyrics":0,"karaoke":0,"forced":0,"hearing_impaired":0,"visual_impaired":0,"clean_effects":0,"attached_pic":0,"timed_thumbnails":0},"tags":{"variant_bitrate":"6527203"}},{"index":2,"codec_name":"aac","codec_long_name":"AAC (Advanced Audio Coding)","profile":"LC","codec_type":"audio","codec_tag_string":"[15][0][0][0]","codec_tag":"0x000f","sample_fmt":"fltp","sample_rate":"48000","channels":2,"channel_layout":"stereo","bits_per_sample":0,"r_frame_rate":"0/0","avg_frame_rate":"0/0","time_base":"1/90000","start_pts":8171229134,"start_time":"90791.434822","disposition":{"default":0,"dub":0,"original":0,"comment":0,"lyrics":0,"karaoke":0,"forced":0,"hearing_impaired":0,"visual_impaired":0,"clean_effects":0,"attached_pic":0,"timed_thumbnails":0},"tags":{"variant_bitrate":"6527203"}}],"requests":[{"method":"GET","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","headers":{"User-Agent":"Lavf/58.76.100","Accept":"*/*","Range":"bytes=0-","Connection":"close","Host":"46.46.143.222:1935","Icy-MetaData":"1"}},{"method":"GET","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/chunklist_w1629502765.m3u8","headers":{"User-Agent":"Lavf/58.76.100","Accept":"*/*","Range":"bytes=0-","Connection":"keep-alive","Host":"46.46.143.222:1935","Icy-MetaData":"1"}},{"method":"GET","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/media_w1629502765_1085323.ts","headers":{"User-Agent":"Lavf/58.76.100","Accept":"*/*","Range":"bytes=0-","Connection":"keep-alive","Host":"46.46.143.222:1935","Icy-MetaData":"1"}},{"method":"GET","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/media_w1629502765_1085324.ts","headers":{"User-Agent":"Lavf/58.76.100","Accept":"*/*","Range":"bytes=0-","Connection":"keep-alive","Host":"46.46.143.222:1935","Icy-MetaData":"1"}}]} \ No newline at end of file diff --git a/tests/__data__/input/logs/generate-playlists/categories.log b/tests/__data__/input/logs/generate-playlists/categories.log new file mode 100644 index 0000000000..5f4d99cf2b --- /dev/null +++ b/tests/__data__/input/logs/generate-playlists/categories.log @@ -0,0 +1,3 @@ +{"name":"General","slug":"general","count":1} +{"name":"News","slug":"news","count":1} +{"name":"Other","slug":"other","count":0} diff --git a/tests/__data__/input/logs/generate-playlists/countries.log b/tests/__data__/input/logs/generate-playlists/countries.log new file mode 100644 index 0000000000..e8e3f180d1 --- /dev/null +++ b/tests/__data__/input/logs/generate-playlists/countries.log @@ -0,0 +1,5 @@ +{"name":"Andorra","code":"AD","count":0} +{"name":"Russia","code":"RU","count":1} +{"name":"United Kingdom","code":"UK","count":1} +{"name":"International","code":"INT","count":0} +{"name":"Undefined","code":"UNDEFINED","count":0} diff --git a/tests/__data__/input/logs/generate-playlists/languages.log b/tests/__data__/input/logs/generate-playlists/languages.log new file mode 100644 index 0000000000..4a5a060f85 --- /dev/null +++ b/tests/__data__/input/logs/generate-playlists/languages.log @@ -0,0 +1,4 @@ +{"name":"Catalan","code":"cat","count":0} +{"name":"English","code":"eng","count":1} +{"name":"Russian","code":"rus","count":1} +{"name":"Undefined","code":"undefined","count":0} diff --git a/tests/__data__/input/logs/generate-playlists/regions.log b/tests/__data__/input/logs/generate-playlists/regions.log new file mode 100644 index 0000000000..8d78fde4fe --- /dev/null +++ b/tests/__data__/input/logs/generate-playlists/regions.log @@ -0,0 +1,5 @@ +{"name":"Asia","code":"ASIA","count":1} +{"name":"Commonwealth of Independent States","code":"CIS","count":1} +{"name":"Europe","code":"EUR","count":2} +{"name":"Europe, the Middle East and Africa","code":"EMEA","count":2} +{"name":"Undefined","code":"UNDEFINED","count":0} diff --git a/tests/__data__/input/readme.json b/tests/__data__/input/readme.json new file mode 100644 index 0000000000..d226f0e660 --- /dev/null +++ b/tests/__data__/input/readme.json @@ -0,0 +1,4 @@ +{ + "build" : "tests/__data__/output/readme.md", + "files" : ["./.readme/template.md"] +} \ No newline at end of file diff --git a/tests/__data__/input/readme.md b/tests/__data__/input/readme.md new file mode 100644 index 0000000000..9ba2befb9a --- /dev/null +++ b/tests/__data__/input/readme.md @@ -0,0 +1,182 @@ +# IPTV + +[![auto-update](https://github.com/iptv-org/iptv/actions/workflows/auto-update.yml/badge.svg)](https://github.com/iptv-org/iptv/actions/workflows/auto-update.yml) + +Collection of publicly available IPTV channels from all over the world. + +Internet Protocol television (IPTV) is the delivery of television content over Internet Protocol (IP) networks. + +## Usage + +To watch IPTV you just need to paste this link `https://iptv-org.github.io/iptv/index.m3u` to any player which supports M3U-playlists. + +![VLC Network Panel](.readme/preview.png) + +Also you can instead use one of these playlists: + +- `https://iptv-org.github.io/iptv/index.category.m3u` (grouped by category) +- `https://iptv-org.github.io/iptv/index.language.m3u` (grouped by language) +- `https://iptv-org.github.io/iptv/index.country.m3u` (grouped by country) +- `https://iptv-org.github.io/iptv/index.region.m3u` (grouped by region) +- `https://iptv-org.github.io/iptv/index.nsfw.m3u` (includes adult channels) + +Or select one of the playlists from the list below. + +### Playlists by category + +
+Expand +
+ + + + + + + + + + + +
CategoryChannelsPlaylist
General1https://iptv-org.github.io/iptv/categories/general.m3u
News1https://iptv-org.github.io/iptv/categories/news.m3u
Other0https://iptv-org.github.io/iptv/categories/other.m3u
+ +
+ +### Playlists by language + +
+Expand +
+ + + + + + + + + + + + +
LanguageChannelsPlaylist
Catalan0https://iptv-org.github.io/iptv/languages/cat.m3u
English1https://iptv-org.github.io/iptv/languages/eng.m3u
Russian1https://iptv-org.github.io/iptv/languages/rus.m3u
Undefined0https://iptv-org.github.io/iptv/languages/undefined.m3u
+ +
+ +### Playlists by region + +
+Expand +
+ + + + + + + + + + + + + +
RegionChannelsPlaylist
Asia1https://iptv-org.github.io/iptv/regions/asia.m3u
Commonwealth of Independent States1https://iptv-org.github.io/iptv/regions/cis.m3u
Europe2https://iptv-org.github.io/iptv/regions/eur.m3u
Europe, the Middle East and Africa2https://iptv-org.github.io/iptv/regions/emea.m3u
Undefined0https://iptv-org.github.io/iptv/regions/undefined.m3u
+ +
+ +### Playlists by country + +
+Expand +
+ + + + + + + + + + + + + +
CountryChannelsPlaylist
🇦🇩 Andorra0https://iptv-org.github.io/iptv/countries/ad.m3u
🇷🇺 Russia1https://iptv-org.github.io/iptv/countries/ru.m3u
🇬🇧 United Kingdom1https://iptv-org.github.io/iptv/countries/uk.m3u
🌍 International0https://iptv-org.github.io/iptv/countries/int.m3u
Undefined0https://iptv-org.github.io/iptv/countries/undefined.m3u
+ +
+ +## For Developers + +In addition to the above methods, you can also get a list of all available channels in JSON format. + +To do this, you just have to make a GET request to: + +``` +https://iptv-org.github.io/iptv/channels.json +``` + +If successful, you should get the following response: + +
+Expand +
+ +``` +[ + ... + { + "name": "CNN", + "logo": "https://i.imgur.com/ilZJT5s.png", + "url": "http://ott-cdn.ucom.am/s27/index.m3u8", + "categories": [ + { + "name": "News", + "slug": "news" + } + ], + "countries": [ + { + "code": "us", + "name": "United States" + }, + { + "code": "ca", + "name": "Canada" + } + ], + "languages": [ + { + "code": "eng", + "name": "English" + } + ], + "tvg": { + "id": "cnn.us", + "name": "CNN", + "url": "http://epg.streamstv.me/epg/guide-usa.xml.gz" + } + }, + ... +] +``` +
+ +## EPG + +Playlists already have a built-in list of EPG, so players that support the `url-tvg` tag should load it automatically. If not, you can find a list of available programs here: + +https://github.com/iptv-org/epg + +## Resources + +You can find links to various IPTV related resources in this repository [iptv-org/awesome-iptv](https://github.com/iptv-org/awesome-iptv). + +## Contribution + +Please make sure to read the [Contributing Guide](CONTRIBUTING.md) before sending an issue or making a pull request. + +## Legal + +No video files are stored in this repository. The repository simply contains user-submitted links to publicly available video stream URLs, which to the best of our knowledge have been intentionally made publicly by the copyright holders. If any links in these playlists infringe on your rights as a copyright holder, they may be removed by sending a pull request or opening an issue. However, note that we have **no control** over the destination of the link, and just removing the link from the playlist will not remove its contents from the web. Note that linking does not directly infringe copyright because no copy is made on the site providing the link, and thus this is **not** a valid reason to send a DMCA notice to GitHub. To remove this content from the web, you should contact the web host that's actually hosting the content (**not** GitHub, nor the maintainers of this repository). diff --git a/tests/__data__/input/test.db b/tests/__data__/input/test.db new file mode 100644 index 0000000000..bb5733aae0 --- /dev/null +++ b/tests/__data__/input/test.db @@ -0,0 +1,3 @@ +{"name":"ЛДПР ТВ","id":"LDPRTV.ru","filepath":"tests/__data__/output/channels/ru.m3u","src_country":{"name":"Russia","code":"RU","lang":"rus"},"tvg_country":"RU","countries":[{"name":"Russia","code":"RU","lang":"rus"}],"regions":[{"name":"Asia","code":"ASIA"},{"name":"Commonwealth of Independent States","code":"CIS"},{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"Russian","code":"rus"}],"categories":[{"name":"General","slug":"general","nsfw":false}],"tvg_url":"","guides":["https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml"],"logo":"https://iptvx.one/icn/ldpr-tv.png","resolution":{"height":1080,"width":null},"status":{"label":"","code":"online","level":1},"url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":false,"updated":false,"cluster_id":1,"_id":"2ST8btby3mmsgPF0"} +{"name":"BBC News HD","id":"BBCNews.uk","filepath":"tests/__data__/output/channels/uk.m3u","src_country":{"name":"United Kingdom","code":"UK","lang":"eng"},"tvg_country":"UK","countries":[{"name":"United Kingdom","code":"UK","lang":"eng"}],"regions":[{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"English","code":"eng"}],"categories":[{"name":"News","slug":"news","nsfw":false}],"tvg_url":"","guides":[],"logo":"https://i.imgur.com/eNPIQ9f.png","resolution":{"height":720,"width":null},"status":{"label":"Not 24/7","code":"not_247","level":3},"url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":false,"updated":false,"cluster_id":3,"_id":"3TbieV1ptnZVCIdn"} +{"name":"ATV","id":"AndorraTV.ad","filepath":"tests/__data__/output/channels/ad.m3u","src_country":{"name":"Andorra","code":"AD","lang":"cat"},"tvg_country":"AD","countries":[{"name":"Andorra","code":"AD","lang":"cat"}],"regions":[{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"Catalan","code":"cat"}],"categories":[{"name":"General","slug":"general","nsfw":false}],"tvg_url":"","guides":[],"logo":"https://i.imgur.com/kJCjeQ4.png","resolution":{"height":720,"width":null},"status":{"label":"Offline","code":"offline","level":5},"url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":true,"updated":false,"cluster_id":1,"_id":"I6cjG2xCBRFFP4sz"} diff --git a/tests/commands/check-streams.test.js b/tests/commands/check-streams.test.js new file mode 100644 index 0000000000..250a2dc49b --- /dev/null +++ b/tests/commands/check-streams.test.js @@ -0,0 +1,44 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.rmdirSync('tests/__data__/output', { recursive: true }) + fs.mkdirSync('tests/__data__/output') + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('return results if stream with error', () => { + const result = execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db LOGS_PATH=tests/__data__/output/logs node scripts/commands/check-streams.js --cluster-id=1 --timeout=1', + { encoding: 'utf8' } + ) + const logs = fs.readFileSync( + path.resolve('tests/__data__/output/logs/check-streams/cluster_1.log'), + { + encoding: 'utf8' + } + ) + const lines = logs.split('\n') + expect(JSON.parse(lines[0])).toMatchObject({ + _id: '2ST8btby3mmsgPF0', + url: 'http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8', + http: { referrer: '', 'user-agent': '' }, + error: 'Operation timed out', + streams: [], + requests: [] + }) + expect(JSON.parse(lines[1])).toMatchObject({ + _id: 'I6cjG2xCBRFFP4sz', + url: 'https://iptv-all.lanesh4d0w.repl.co/andorra/atv', + http: { referrer: '', 'user-agent': '' }, + error: 'Operation timed out', + streams: [], + requests: [] + }) +}) diff --git a/tests/commands/cleanup-database.test.js b/tests/commands/cleanup-database.test.js new file mode 100644 index 0000000000..bd541e8e7d --- /dev/null +++ b/tests/commands/cleanup-database.test.js @@ -0,0 +1,25 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('can remove broken links from database', () => { + const result = execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db node scripts/commands/cleanup-database.js', + { encoding: 'utf8' } + ) + + const database = fs.readFileSync('tests/__data__/temp/test.db', { encoding: 'utf8' }) + const lines = database.split('\n') + expect(lines[0]).toBe( + `{"name":"ЛДПР ТВ","id":"LDPRTV.ru","filepath":"tests/__data__/output/channels/ru.m3u","src_country":{"name":"Russia","code":"RU","lang":"rus"},"tvg_country":"RU","countries":[{"name":"Russia","code":"RU","lang":"rus"}],"regions":[{"name":"Asia","code":"ASIA"},{"name":"Commonwealth of Independent States","code":"CIS"},{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"Russian","code":"rus"}],"categories":[{"name":"General","slug":"general","nsfw":false}],"tvg_url":"","guides":["https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml"],"logo":"https://iptvx.one/icn/ldpr-tv.png","resolution":{"height":1080,"width":null},"status":{"label":"","code":"online","level":1},"url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":false,"updated":false,"cluster_id":1,"_id":"2ST8btby3mmsgPF0"}` + ) +}) diff --git a/tests/commands/create-database.test.js b/tests/commands/create-database.test.js new file mode 100644 index 0000000000..4a1a9c494c --- /dev/null +++ b/tests/commands/create-database.test.js @@ -0,0 +1,45 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.rmdirSync('tests/__data__/output', { recursive: true }) + fs.mkdirSync('tests/__data__/output') +}) + +it('can create database', () => { + execSync( + 'DB_FILEPATH=tests/__data__/output/test.db node scripts/commands/create-database.js --input-dir=tests/__data__/input/channels --max-clusters=1', + { encoding: 'utf8' } + ) + + const database = fs.readFileSync(path.resolve('tests/__data__/output/test.db'), { + encoding: 'utf8' + }) + const item = database.split('\n').find(i => i.includes('ATV.ad')) + expect(JSON.parse(item)).toMatchObject({ + name: 'ATV', + id: 'ATV.ad', + filepath: 'tests/__data__/input/channels/ad_example.m3u', + src_country: { name: 'Andorra', code: 'AD', lang: 'cat' }, + tvg_country: 'AD', + countries: [{ name: 'Andorra', code: 'AD', lang: 'cat' }], + regions: [ + { name: 'Europe, the Middle East and Africa', code: 'EMEA' }, + { name: 'Europe', code: 'EUR' } + ], + languages: [{ name: 'Catalan', code: 'cat' }], + categories: [{ name: 'General', slug: 'general', nsfw: false }], + tvg_url: '', + guides: [], + logo: 'https://i.imgur.com/kJCjeQ4.png', + resolution: { height: 720, width: null }, + status: { label: 'Offline', code: 'offline', level: 5 }, + url: 'https://iptv-all.lanesh4d0w.repl.co/andorra/atv', + http: { referrer: '', 'user-agent': '' }, + is_nsfw: false, + is_broken: true, + updated: false, + cluster_id: 1 + }) +}) diff --git a/tests/commands/create-matrix.test.js b/tests/commands/create-matrix.test.js new file mode 100644 index 0000000000..5310cd1df5 --- /dev/null +++ b/tests/commands/create-matrix.test.js @@ -0,0 +1,20 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('can create valid matrix', () => { + const result = execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db node scripts/commands/create-matrix.js', + { encoding: 'utf8' } + ) + expect(result).toBe('::set-output name=matrix::{"cluster_id":[1,3]}\n') +}) diff --git a/tests/commands/generate-playlists.test.js b/tests/commands/generate-playlists.test.js new file mode 100644 index 0000000000..f68cf0f6bd --- /dev/null +++ b/tests/commands/generate-playlists.test.js @@ -0,0 +1,204 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +function content(filepath) { + return fs.readFileSync(`tests/__data__/output/${filepath}`, { + encoding: 'utf8' + }) +} + +beforeEach(() => { + fs.rmdirSync('tests/__data__/output', { recursive: true }) + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') + + execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db PUBLIC_PATH=tests/__data__/output/.gh-pages LOGS_PATH=tests/__data__/output/logs node scripts/commands/generate-playlists.js', + { encoding: 'utf8' } + ) +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('can generate categories', () => { + expect(content('.gh-pages/categories/general.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/categories/news.m3u')).toBe(`#EXTM3U x-tvg-url="" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +`) +}) + +it('can generate countries', () => { + expect(content('.gh-pages/countries/ru.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/countries/uk.m3u')).toBe(`#EXTM3U x-tvg-url="" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +`) +}) + +it('can generate languages', () => { + expect(content('.gh-pages/languages/rus.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/languages/eng.m3u')).toBe(`#EXTM3U x-tvg-url="" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +`) +}) + +it('can generate regions', () => { + expect(content('.gh-pages/regions/asia.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/regions/cis.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/regions/emea.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/regions/eur.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate channels.json', () => { + expect(content('.gh-pages/channels.json')).toBe( + `[{"name":"BBC News HD","logo":"https://i.imgur.com/eNPIQ9f.png","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","categories":[{"name":"News","slug":"news"}],"countries":[{"name":"United Kingdom","code":"UK"}],"languages":[{"name":"English","code":"eng"}],"tvg":{"id":"BBCNews.uk","name":"BBC News HD","url":""}},{"name":"ЛДПР ТВ","logo":"https://iptvx.one/icn/ldpr-tv.png","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","categories":[{"name":"General","slug":"general"}],"countries":[{"name":"Russia","code":"RU"}],"languages":[{"name":"Russian","code":"rus"}],"tvg":{"id":"LDPRTV.ru","name":"ЛДПР ТВ","url":"https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml"}}]` + ) +}) + +it('can generate index.category.m3u', () => { + expect(content('.gh-pages/index.category.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate index.country.m3u', () => { + expect(content('.gh-pages/index.country.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russia",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="United Kingdom",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +`) +}) + +it('can generate index.language.m3u', () => { + expect(content('.gh-pages/index.language.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="English",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russian",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate index.region.m3u', () => { + expect(content('.gh-pages/index.region.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Asia",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Commonwealth of Independent States",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="Europe",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Europe",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="Europe, the Middle East and Africa",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Europe, the Middle East and Africa",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate index.m3u', () => { + expect(content('.gh-pages/index.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate index.nsfw.m3u', () => { + expect(content('.gh-pages/index.nsfw.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate logs categories', () => { + expect(content('logs/generate-playlists/categories.log')) + .toBe(`{"name":"General","slug":"general","count":1} +{"name":"News","slug":"news","count":1} +{"name":"Other","slug":"other","count":0} +`) +}) + +it('can generate logs countries', () => { + expect(content('logs/generate-playlists/countries.log')) + .toBe(`{"name":"Andorra","code":"AD","count":0} +{"name":"Russia","code":"RU","count":1} +{"name":"United Kingdom","code":"UK","count":1} +{"name":"International","code":"INT","count":0} +{"name":"Undefined","code":"UNDEFINED","count":0} +`) +}) + +it('can generate logs languages', () => { + expect(content('logs/generate-playlists/languages.log')) + .toBe(`{"name":"Catalan","code":"cat","count":0} +{"name":"English","code":"eng","count":1} +{"name":"Russian","code":"rus","count":1} +{"name":"Undefined","code":"undefined","count":0} +`) +}) + +it('can generate logs regions', () => { + expect(content('logs/generate-playlists/regions.log')) + .toBe(`{"name":"Asia","code":"ASIA","count":1} +{"name":"Commonwealth of Independent States","code":"CIS","count":1} +{"name":"Europe","code":"EUR","count":2} +{"name":"Europe, the Middle East and Africa","code":"EMEA","count":2} +{"name":"Undefined","code":"UNDEFINED","count":0} +`) +}) diff --git a/tests/commands/update-database.test.js b/tests/commands/update-database.test.js new file mode 100644 index 0000000000..d235e9a29d --- /dev/null +++ b/tests/commands/update-database.test.js @@ -0,0 +1,100 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('can update database', () => { + const result = execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db LOGS_PATH=tests/__data__/input/logs EPG_CODES_FILEPATH=tests/__data__/input/codes.json node scripts/commands/update-database.js', + { encoding: 'utf8' } + ) + const database = fs.readFileSync('tests/__data__/temp/test.db', { encoding: 'utf8' }) + const lines = database.split('\n') + expect(JSON.parse(lines[0])).toMatchObject({ + name: 'ЛДПР ТВ', + id: 'LDPRTV.ru', + filepath: 'tests/__data__/output/channels/ru.m3u', + src_country: { name: 'Russia', code: 'RU', lang: 'rus' }, + tvg_country: 'RU', + countries: [{ name: 'Russia', code: 'RU', lang: 'rus' }], + regions: [ + { name: 'Asia', code: 'ASIA' }, + { name: 'Commonwealth of Independent States', code: 'CIS' }, + { name: 'Europe, the Middle East and Africa', code: 'EMEA' }, + { name: 'Europe', code: 'EUR' } + ], + languages: [{ name: 'Russian', code: 'rus' }], + categories: [{ name: 'General', slug: 'general', nsfw: false }], + tvg_url: '', + guides: ['https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml'], + logo: 'https://iptvx.one/icn/ldpr-tv.png', + resolution: { height: 1080, width: 1920 }, + status: { label: '', code: 'online', level: 1 }, + url: 'http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8', + http: { referrer: '', 'user-agent': '' }, + is_nsfw: false, + is_broken: false, + updated: true, + cluster_id: 1, + _id: '2ST8btby3mmsgPF0' + }) + expect(JSON.parse(lines[1])).toMatchObject({ + name: 'BBC News HD', + id: 'BBCNews.uk', + filepath: 'tests/__data__/output/channels/uk.m3u', + src_country: { name: 'United Kingdom', code: 'UK', lang: 'eng' }, + tvg_country: 'UK', + countries: [{ name: 'United Kingdom', code: 'UK', lang: 'eng' }], + regions: [ + { name: 'Europe, the Middle East and Africa', code: 'EMEA' }, + { name: 'Europe', code: 'EUR' } + ], + languages: [{ name: 'English', code: 'eng' }], + categories: [{ name: 'News', slug: 'news', nsfw: false }], + tvg_url: '', + guides: [], + logo: 'https://i.imgur.com/eNPIQ9f.png', + resolution: { height: 720, width: null }, + status: { label: 'Not 24/7', code: 'not_247', level: 3 }, + url: 'http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8', + http: { referrer: '', 'user-agent': '' }, + is_nsfw: false, + is_broken: false, + updated: false, + cluster_id: 3, + _id: '3TbieV1ptnZVCIdn' + }) + expect(JSON.parse(lines[2])).toMatchObject({ + name: 'ATV', + id: 'AndorraTV.ad', + filepath: 'tests/__data__/output/channels/ad.m3u', + src_country: { name: 'Andorra', code: 'AD', lang: 'cat' }, + tvg_country: 'AD', + countries: [{ name: 'Andorra', code: 'AD', lang: 'cat' }], + regions: [ + { name: 'Europe, the Middle East and Africa', code: 'EMEA' }, + { name: 'Europe', code: 'EUR' } + ], + languages: [{ name: 'Catalan', code: 'cat' }], + categories: [{ name: 'General', slug: 'general', nsfw: false }], + tvg_url: '', + guides: ['https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml'], + logo: 'https://i.imgur.com/kJCjeQ4.png', + resolution: { height: 720, width: null }, + status: { label: 'Timeout', code: 'timeout', level: 4 }, + url: 'https://iptv-all.lanesh4d0w.repl.co/andorra/atv', + http: { referrer: '', 'user-agent': '' }, + is_nsfw: false, + is_broken: true, + updated: true, + cluster_id: 1 + }) +}) diff --git a/tests/commands/update-playlists.test.js b/tests/commands/update-playlists.test.js new file mode 100644 index 0000000000..1656f051d7 --- /dev/null +++ b/tests/commands/update-playlists.test.js @@ -0,0 +1,37 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('can update playlist', () => { + const result = execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db node scripts/commands/update-playlists.js', + { encoding: 'utf8' } + ) + + const adPlaylist = fs.readFileSync('tests/__data__/output/channels/ad.m3u', { + encoding: 'utf8' + }) + + expect(adPlaylist).toBe(`#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-country="AD" tvg-language="Catalan" tvg-logo="https://i.imgur.com/kJCjeQ4.png" group-title="General",ATV (720p) [Offline] +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +`) + + const ruPlaylist = fs.readFileSync('tests/__data__/output/channels/ru.m3u', { + encoding: 'utf8' + }) + + expect(ruPlaylist).toBe(`#EXTM3U +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) diff --git a/tests/commands/update-readme.test.js b/tests/commands/update-readme.test.js new file mode 100644 index 0000000000..716215473e --- /dev/null +++ b/tests/commands/update-readme.test.js @@ -0,0 +1,23 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.rmdirSync(path.resolve('tests/__data__/output'), { recursive: true }) +}) + +it('can update readme.md', () => { + const result = execSync( + 'LOGS_PATH=tests/__data__/input/logs node scripts/commands/update-readme.js --config=tests/__data__/input/readme.json', + { encoding: 'utf8' } + ) + + const readme = fs.readFileSync(path.resolve('tests/__data__/output/readme.md'), { + encoding: 'utf8' + }) + const expected = fs.readFileSync(path.resolve('tests/__data__/input/readme.md'), { + encoding: 'utf8' + }) + + expect(readme).toBe(expected) +}) diff --git a/tests/commands/validate.test.js b/tests/commands/validate.test.js new file mode 100644 index 0000000000..7460b01589 --- /dev/null +++ b/tests/commands/validate.test.js @@ -0,0 +1,16 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +it('can validate channels name', () => { + try { + execSync('node scripts/commands/validate.js --input-dir=tests/__data__/input/channels', { + encoding: 'utf8' + }) + } catch (err) { + expect(err.status).toBe(1) + expect(err.stdout).toBe( + `tests/__data__/input/channels/us_blocked.m3u:2 'Fox Sports' is on the blocklist due to claims of copyright holders (https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md)\n\n` + ) + } +})