mirror of
https://github.com/iptv-org/iptv.git
synced 2025-05-12 10:00:05 -04:00
Merge pull request #12638 from iptv-org/patch-2023.04.48
Add "format" script
This commit is contained in:
commit
116c589ed1
23 changed files with 157 additions and 54 deletions
|
@ -1,14 +1,11 @@
|
||||||
# IPTV
|
# IPTV
|
||||||
|
|
||||||
[](https://github.com/iptv-org/iptv/actions/workflows/auto-update.yml)
|
|
||||||
|
|
||||||
Collection of publicly available IPTV (Internet Protocol television) channels from all over the world.
|
Collection of publicly available IPTV (Internet Protocol television) channels from all over the world.
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
- 🚀 [How to use?](#how-to-use)
|
- 🚀 [How to use?](#how-to-use)
|
||||||
- 📺 [Playlists](#playlists)
|
- 📺 [Playlists](#playlists)
|
||||||
- 🗓 [EPG](#epg)
|
|
||||||
- 🗄 [Database](#database)
|
- 🗄 [Database](#database)
|
||||||
- 👨💻 [API](#api)
|
- 👨💻 [API](#api)
|
||||||
- 📚 [Resources](#resources)
|
- 📚 [Resources](#resources)
|
||||||
|
|
|
@ -5,14 +5,16 @@
|
||||||
"api:generate": "node scripts/commands/api/generate.js",
|
"api:generate": "node scripts/commands/api/generate.js",
|
||||||
"api:deploy": "npx gh-pages -a -m \"Deploy to iptv-org/api\" -d .api -r https://$GITHUB_TOKEN@github.com/iptv-org/api.git -x",
|
"api:deploy": "npx gh-pages -a -m \"Deploy to iptv-org/api\" -d .api -r https://$GITHUB_TOKEN@github.com/iptv-org/api.git -x",
|
||||||
"db:create": "node scripts/commands/database/create.js",
|
"db:create": "node scripts/commands/database/create.js",
|
||||||
|
"playlist:format": "node scripts/commands/playlist/format.js",
|
||||||
"playlist:generate": "node scripts/commands/playlist/generate.js",
|
"playlist:generate": "node scripts/commands/playlist/generate.js",
|
||||||
"playlist:validate": "node scripts/commands/playlist/validate.js",
|
"playlist:validate": "node scripts/commands/playlist/validate.js",
|
||||||
"playlist:lint": "npx m3u-linter -c m3u-linter.json",
|
"playlist:lint": "npx m3u-linter -c m3u-linter.json",
|
||||||
"playlist:deploy": "npx gh-pages -a -m \"Deploy to GitHub Pages\" -d .gh-pages -r https://$GITHUB_TOKEN@github.com/iptv-org/iptv.git -x",
|
"playlist:deploy": "npx gh-pages -a -m \"Deploy to GitHub Pages\" -d .gh-pages -r https://$GITHUB_TOKEN@github.com/iptv-org/iptv.git -x",
|
||||||
"readme:update": "node scripts/commands/readme/update.js",
|
"readme:update": "node scripts/commands/readme/update.js",
|
||||||
|
"format": "npm run db:create && npm run playlist:format",
|
||||||
|
"check": "npm run api:load && npm run playlist:lint && npm run playlist:validate",
|
||||||
"update": "npm run api:load && npm run db:create && npm run playlist:generate && npm run api:generate && npm run readme:update",
|
"update": "npm run api:load && npm run db:create && npm run playlist:generate && npm run api:generate && npm run readme:update",
|
||||||
"deploy": "npm run playlist:deploy && npm run api:deploy",
|
"deploy": "npm run playlist:deploy && npm run api:deploy",
|
||||||
"check": "npm run api:load && npm run playlist:lint && npm run playlist:validate",
|
|
||||||
"test": "jest --runInBand"
|
"test": "jest --runInBand"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
|
|
2
scripts/.gitignore
vendored
2
scripts/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
/logs/
|
|
||||||
/database/
|
|
|
@ -1,10 +1,10 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
mkdir -p scripts/data
|
mkdir -p scripts/tmp/data
|
||||||
curl -L -o scripts/data/blocklist.json https://iptv-org.github.io/api/blocklist.json
|
curl -L -o scripts/tmp/data/blocklist.json https://iptv-org.github.io/api/blocklist.json
|
||||||
curl -L -o scripts/data/categories.json https://iptv-org.github.io/api/categories.json
|
curl -L -o scripts/tmp/data/categories.json https://iptv-org.github.io/api/categories.json
|
||||||
curl -L -o scripts/data/channels.json https://iptv-org.github.io/api/channels.json
|
curl -L -o scripts/tmp/data/channels.json https://iptv-org.github.io/api/channels.json
|
||||||
curl -L -o scripts/data/countries.json https://iptv-org.github.io/api/countries.json
|
curl -L -o scripts/tmp/data/countries.json https://iptv-org.github.io/api/countries.json
|
||||||
curl -L -o scripts/data/languages.json https://iptv-org.github.io/api/languages.json
|
curl -L -o scripts/tmp/data/languages.json https://iptv-org.github.io/api/languages.json
|
||||||
curl -L -o scripts/data/regions.json https://iptv-org.github.io/api/regions.json
|
curl -L -o scripts/tmp/data/regions.json https://iptv-org.github.io/api/regions.json
|
||||||
curl -L -o scripts/data/subdivisions.json https://iptv-org.github.io/api/subdivisions.json
|
curl -L -o scripts/tmp/data/subdivisions.json https://iptv-org.github.io/api/subdivisions.json
|
|
@ -1,4 +1,4 @@
|
||||||
const { db, file, parser, store, logger, api } = require('../../core')
|
const { db, file, parser, store, logger } = require('../../core')
|
||||||
const { program } = require('commander')
|
const { program } = require('commander')
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
|
|
||||||
|
@ -8,21 +8,7 @@ const options = program
|
||||||
.opts()
|
.opts()
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
logger.info('starting...')
|
|
||||||
|
|
||||||
await saveToDatabase(await findStreams())
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
||||||
|
|
||||||
async function findStreams() {
|
|
||||||
logger.info(`loading channels...`)
|
|
||||||
await api.channels.load()
|
|
||||||
const channels = _.keyBy(await api.channels.all(), 'id')
|
|
||||||
|
|
||||||
logger.info(`looking for streams...`)
|
logger.info(`looking for streams...`)
|
||||||
await db.streams.load()
|
|
||||||
|
|
||||||
const streams = []
|
const streams = []
|
||||||
const files = await file.list(`${options.inputDir}/**/*.m3u`)
|
const files = await file.list(`${options.inputDir}/**/*.m3u`)
|
||||||
for (const filepath of files) {
|
for (const filepath of files) {
|
||||||
|
@ -31,9 +17,8 @@ async function findStreams() {
|
||||||
item.filepath = filepath
|
item.filepath = filepath
|
||||||
|
|
||||||
const stream = store.create()
|
const stream = store.create()
|
||||||
const channel = channels[item.tvg.id]
|
|
||||||
|
|
||||||
stream.set('channel', { channel: channel ? channel.id : null })
|
stream.set('channel', { channel: item.tvg.id })
|
||||||
stream.set('title', { title: item.name })
|
stream.set('title', { title: item.name })
|
||||||
stream.set('filepath', { filepath: item.filepath })
|
stream.set('filepath', { filepath: item.filepath })
|
||||||
stream.set('url', { url: item.url })
|
stream.set('url', { url: item.url })
|
||||||
|
@ -45,13 +30,11 @@ async function findStreams() {
|
||||||
}
|
}
|
||||||
logger.info(`found ${streams.length} streams`)
|
logger.info(`found ${streams.length} streams`)
|
||||||
|
|
||||||
return streams
|
|
||||||
}
|
|
||||||
|
|
||||||
async function saveToDatabase(streams = []) {
|
|
||||||
logger.info('saving to the database...')
|
logger.info('saving to the database...')
|
||||||
|
await db.streams.load()
|
||||||
await db.streams.reset()
|
await db.streams.reset()
|
||||||
const data = streams.map(stream => stream.data())
|
const data = streams.map(stream => stream.data())
|
||||||
await db.streams.insert(data)
|
await db.streams.insert(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
26
scripts/commands/playlist/format.js
Normal file
26
scripts/commands/playlist/format.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
const { create: createPlaylist } = require('../../core/playlist')
|
||||||
|
const { db, logger, file } = require('../../core')
|
||||||
|
const { orderBy } = require('natural-orderby')
|
||||||
|
const _ = require('lodash')
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
logger.info('loading streams...')
|
||||||
|
await db.streams.load()
|
||||||
|
let streams = await db.streams.find({})
|
||||||
|
|
||||||
|
logger.info('sorting links...')
|
||||||
|
streams = orderBy(
|
||||||
|
streams,
|
||||||
|
['channel', s => (s.channel ? '' : s.title), 'url'],
|
||||||
|
['asc', 'asc', 'asc']
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info('saving...')
|
||||||
|
const files = _.groupBy(streams, 'filepath')
|
||||||
|
for (const filepath in files) {
|
||||||
|
const playlist = createPlaylist(files[filepath], { public: false })
|
||||||
|
await file.create(filepath, playlist.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
|
@ -2,7 +2,7 @@ const { file, markdown, parser, logger, api } = require('../../core')
|
||||||
const { create: createTable } = require('../../core/table')
|
const { create: createTable } = require('../../core/table')
|
||||||
const { program } = require('commander')
|
const { program } = require('commander')
|
||||||
|
|
||||||
const LOGS_DIR = process.env.LOGS_DIR || 'scripts/logs/generators'
|
const LOGS_DIR = process.env.LOGS_DIR || 'scripts/tmp/logs/generators'
|
||||||
|
|
||||||
const options = program
|
const options = program
|
||||||
.option('-c, --config <config>', 'Set path to config file', '.readme/config.json')
|
.option('-c, --config <config>', 'Set path to config file', '.readme/config.json')
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
const file = require('./file')
|
const file = require('./file')
|
||||||
|
|
||||||
const DATA_DIR = process.env.DATA_DIR || './scripts/data'
|
const DATA_DIR = process.env.DATA_DIR || './scripts/tmp/data'
|
||||||
|
|
||||||
class API {
|
class API {
|
||||||
constructor(filepath) {
|
constructor(filepath) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const nedb = require('nedb-promises')
|
const nedb = require('nedb-promises')
|
||||||
const file = require('./file')
|
const file = require('./file')
|
||||||
|
|
||||||
const DB_DIR = process.env.DB_DIR || './scripts/database'
|
const DB_DIR = process.env.DB_DIR || './scripts/tmp/database'
|
||||||
|
|
||||||
class Database {
|
class Database {
|
||||||
constructor(filepath) {
|
constructor(filepath) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ const logger = require('./logger')
|
||||||
const file = require('./file')
|
const file = require('./file')
|
||||||
|
|
||||||
const PUBLIC_DIR = process.env.PUBLIC_DIR || '.gh-pages'
|
const PUBLIC_DIR = process.env.PUBLIC_DIR || '.gh-pages'
|
||||||
const LOGS_DIR = process.env.LOGS_DIR || 'scripts/logs/generators'
|
const LOGS_DIR = process.env.LOGS_DIR || 'scripts/tmp/logs/generators'
|
||||||
|
|
||||||
const generator = {}
|
const generator = {}
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
*
|
*
|
||||||
!.gitignore
|
!.gitignore
|
|
@ -1,14 +1,11 @@
|
||||||
# IPTV
|
# IPTV
|
||||||
|
|
||||||
[](https://github.com/iptv-org/iptv/actions/workflows/auto-update.yml)
|
|
||||||
|
|
||||||
Collection of publicly available IPTV (Internet Protocol television) channels from all over the world.
|
Collection of publicly available IPTV (Internet Protocol television) channels from all over the world.
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
- 🚀 [How to use?](#how-to-use)
|
- 🚀 [How to use?](#how-to-use)
|
||||||
- 📺 [Playlists](#playlists)
|
- 📺 [Playlists](#playlists)
|
||||||
- 🗓 [EPG](#epg)
|
|
||||||
- 🗄 [Database](#database)
|
- 🗄 [Database](#database)
|
||||||
- 👨💻 [API](#api)
|
- 👨💻 [API](#api)
|
||||||
- 📚 [Resources](#resources)
|
- 📚 [Resources](#resources)
|
||||||
|
@ -454,10 +451,6 @@ Same thing, but split up into separate files:
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## EPG
|
|
||||||
|
|
||||||
The playlists already contain links to all guides, so players with support the `x-tvg-url` tag should load it automatically. Otherwise, you can choose one of the guides featured in the [iptv-org/epg](https://github.com/iptv-org/epg) repository.
|
|
||||||
|
|
||||||
## Database
|
## Database
|
||||||
|
|
||||||
All channel data is taken from the [iptv-org/database](https://github.com/iptv-org/database) repository. If you find any errors please open a new [issue](https://github.com/iptv-org/database/issues) there.
|
All channel data is taken from the [iptv-org/database](https://github.com/iptv-org/database) repository. If you find any errors please open a new [issue](https://github.com/iptv-org/database/issues) there.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{"channel":null,"title":"TVN","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://example.com/playlist2.m3u8","http_referrer":null,"user_agent":null,"_id":"UAYbCvjOWvqXHH95"}
|
{"channel":"ATV.ad","title":"ATV (720p) [Offline]","filepath":"tests/__data__/input/streams/ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http_referrer":"http://imn.iq","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","_id":"k4XpZHQAyqyTbcf0"}
|
||||||
{"channel":"LibyasChannel.ly","title":"Libyas Channel","filepath":"tests/__data__/input/streams/ly.m3u","url":"https://master.starmena-cloud.com/hls/libyas.m3u8","http_referrer":null,"user_agent":null,"_id":"I0rJlwp3rZEy2SnG"}
|
{"channel":"LibyasChannel.ly","title":"Libyas Channel","filepath":"tests/__data__/input/streams/ly.m3u","url":"https://master.starmena-cloud.com/hls/libyas.m3u8","http_referrer":null,"user_agent":null,"_id":"ki4YjAoNNoIY8sSm"}
|
||||||
{"channel":"EverydayHeroes.us","title":"Everyday Heroes (720p)","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://a.jsrdn.com/broadcast/7b1451fa52/+0000/c.m3u8","http_referrer":null,"user_agent":null,"_id":"tdzk1IN7wLJxfGab"}
|
{"channel":null,"title":"1A Network (720p)","filepath":"tests/__data__/input/streams/unsorted.m3u","url":"https://simultv.s.llnwi.net/n4s4/2ANetwork/interlink.m3u8","http_referrer":null,"user_agent":null,"_id":"IZpCJjjWPaBYh7Dr"}
|
||||||
{"channel":null,"title":"ATV (720p) [Offline]","filepath":"tests/__data__/input/streams/ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http_referrer":"http://imn.iq","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","_id":"3evMHt3nFsZjhzas"}
|
{"channel":null,"title":"Fox Sports 2 Asia (Thai) (720p)","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://example.com/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"6c4J4vs8K69wMJ7S"}
|
||||||
{"channel":null,"title":"ABC (720p)","filepath":"tests/__data__/input/streams/wrong_id.m3u","url":"https://example.com/playlist2.m3u8","http_referrer":null,"user_agent":null,"_id":"agJlTEr8wwpbWgw0"}
|
{"channel":null,"title":"TVN","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://example.com/playlist2.m3u8","http_referrer":null,"user_agent":null,"_id":"xEmbX384v3t3F5Wg"}
|
||||||
{"channel":null,"title":"Fox Sports 2 Asia (Thai) (720p)","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://example.com/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"FpMhoWjtpnVuYlO9"}
|
{"channel":"EverydayHeroes.us","title":"Everyday Heroes (720p)","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://a.jsrdn.com/broadcast/7b1451fa52/+0000/c.m3u8","http_referrer":null,"user_agent":null,"_id":"BZsRPt8VS4kIJnfi"}
|
||||||
|
{"channel":"qib22lAq1L.us","title":"ABC (720p)","filepath":"tests/__data__/input/streams/wrong_id.m3u","url":"https://example.com/playlist2.m3u8","http_referrer":null,"user_agent":null,"_id":"eFUlUnST5zJSBWAF"}
|
||||||
|
|
5
tests/__data__/expected/streams/ad.m3u
Normal file
5
tests/__data__/expected/streams/ad.m3u
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:-1 tvg-id="AndorraTV.ad" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",ATV (720p) [Offline]
|
||||||
|
#EXTVLCOPT:http-referrer=http://imn.iq
|
||||||
|
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||||
|
https://iptv-all.lanesh4d0w.repl.co/andorra/atv
|
5
tests/__data__/expected/streams/af.m3u
Normal file
5
tests/__data__/expected/streams/af.m3u
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:-1 tvg-id="KayhanTV.af",Kayhan TV
|
||||||
|
http://208.93.117.113/live/Stream1/playlist.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="Sharq.af",Sharq
|
||||||
|
http://51.210.199.50/hls/stream.m3u8
|
6
tests/__data__/expected/streams/aw.m3u
Normal file
6
tests/__data__/expected/streams/aw.m3u
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:-1 tvg-id="Telearuba.aw",Telearuba (720p)
|
||||||
|
http://cdn.setar.aw:1935/Telearuba/smil:telearuba.smil/playlist.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="Telearuba.aw" user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36",Telearuba (480p) [Not 24/7]
|
||||||
|
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36
|
||||||
|
https://backend-server-dot-telearuba-app.appspot.com/media/livestream13/playlist.m3u8
|
7
tests/__data__/expected/streams/es.m3u
Normal file
7
tests/__data__/expected/streams/es.m3u
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:-1 tvg-id="",Caillou
|
||||||
|
https://dhx-caillou-1-es.samsung.wurl.tv/playlist.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="",iHola Play
|
||||||
|
https://rakuten-hola-2-es.samsung.wurl.tv/playlist.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="",Planeta Junior TV
|
||||||
|
https://deaplaneta-planetakidz-1-es.samsung.wurl.tv/playlist.m3u8
|
11
tests/__data__/expected/streams/nl.m3u
Normal file
11
tests/__data__/expected/streams/nl.m3u
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (342p) [Geo-blocked]
|
||||||
|
http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (1080p) [Geo-blocked]
|
||||||
|
http://stream.tvtap.net:8081/live/nl-npo1.stream/30fps.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (1080p) [Geo-blocked]
|
||||||
|
http://stream.tvtap.net:8081/live/nl-npo1.stream/60fps.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (342p)
|
||||||
|
http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (302p) [Geo-blocked]
|
||||||
|
http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8
|
3
tests/__data__/expected/streams/pe.m3u
Normal file
3
tests/__data__/expected/streams/pe.m3u
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:-1 tvg-id="Tele2000.pe",Tele 2000
|
||||||
|
https://servilive.com:3126/live/tele2000live.m3u8
|
9
tests/__data__/expected/streams/ru.m3u
Normal file
9
tests/__data__/expected/streams/ru.m3u
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
|
||||||
|
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
|
||||||
|
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
|
||||||
|
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
|
||||||
|
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
|
5
tests/__data__/expected/streams/uk.m3u
Normal file
5
tests/__data__/expected/streams/uk.m3u
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (720p) [Not 24/7]
|
||||||
|
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
|
||||||
|
#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (480p) [Geo-blocked]
|
||||||
|
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8
|
20
tests/__data__/input/database/playlist_format.streams.db
Normal file
20
tests/__data__/input/database/playlist_format.streams.db
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{"title":"ЛДПР ТВ (1080p)","channel":"LDPRTV.ru","filepath":"tests/__data__/output/streams/ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"2ST8btby3mmsgPF3"}
|
||||||
|
{"title":"ЛДПР ТВ (1080p)","channel":"LDPRTV.ru","filepath":"tests/__data__/output/streams/ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"2ST8btby3mmsgPF0"}
|
||||||
|
{"title":"ЛДПР ТВ (1080p)","channel":"LDPRTV.ru","filepath":"tests/__data__/output/streams/ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"2ST8btby3mmsgPF1"}
|
||||||
|
{"title":"ЛДПР ТВ (1080p)","channel":"LDPRTV.ru","filepath":"tests/__data__/output/streams/ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"2ST8btby3mmsgPF2"}
|
||||||
|
{"title":"BBC News HD (720p) [Not 24/7]","channel":"BBCNews.uk","filepath":"tests/__data__/output/streams/uk.m3u","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","http_referrer":null,"user_agent":null,"_id":"3TbieV1ptnZVCIdn"}
|
||||||
|
{"title":"ATV (720p) [Offline]","channel":"AndorraTV.ad","filepath":"tests/__data__/output/streams/ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http_referrer":"http://imn.iq","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","_id":"I6cjG2xCBRFFP4sz"}
|
||||||
|
{"title":"BBC News HD (480p) [Geo-blocked]","channel":"BBCNews.uk","filepath":"tests/__data__/output/streams/uk.m3u","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"WTbieV1ptnZVCIdn"}
|
||||||
|
{"title":"Kayhan TV","channel":"KayhanTV.af","filepath":"tests/__data__/output/streams/af.m3u","url":"http://208.93.117.113/live/Stream1/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"cFFpFVzSn6xFMUF3"}
|
||||||
|
{"title":"Sharq","channel":"Sharq.af","filepath":"tests/__data__/output/streams/af.m3u","url":"http://51.210.199.50/hls/stream.m3u8","http_referrer":null,"user_agent":null,"_id":"u7iyA6cjtf1iWWAZ"}
|
||||||
|
{"channel":"NPO1.nl","title":"NPO 1 (342p) [Geo-blocked]","filepath":"tests/__data__/output/streams/nl.m3u","url":"http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8","http_referrer":null,"user_agent":null,"_id":"mvUyDVuS5gc8gLJV"}
|
||||||
|
{"channel":"NPO1.nl","title":"NPO 1 (1080p) [Geo-blocked]","filepath":"tests/__data__/output/streams/nl.m3u","url":"http://stream.tvtap.net:8081/live/nl-npo1.stream/30fps.m3u8","http_referrer":null,"user_agent":null,"_id":"8WVbsxsYeOL7kHQl"}
|
||||||
|
{"channel":"NPO1.nl","title":"NPO 1 (1080p) [Geo-blocked]","filepath":"tests/__data__/output/streams/nl.m3u","url":"http://stream.tvtap.net:8081/live/nl-npo1.stream/60fps.m3u8","http_referrer":null,"user_agent":null,"_id":"8WVbsxsYeOL7kHQB"}
|
||||||
|
{"channel":"NPO2.nl","title":"NPO 2 (342p)","filepath":"tests/__data__/output/streams/nl.m3u","url":"http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8","http_referrer":null,"user_agent":null,"_id":"2p1TNGO0mF0MJOGy"}
|
||||||
|
{"channel":"NPO2.nl","title":"NPO 2 (302p) [Geo-blocked]","filepath":"tests/__data__/output/streams/nl.m3u","url":"http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"nhL85BL7YM5OR7cn"}
|
||||||
|
{"title":"Tele 2000","channel":"Tele2000.pe","filepath":"tests/__data__/output/streams/pe.m3u","url":"https://servilive.com:3126/live/tele2000live.m3u8","http_referrer":null,"user_agent":null,"_id":"cF0pFVzSn6xFMUF3"}
|
||||||
|
{"title":"Planeta Junior TV","channel":"","filepath":"tests/__data__/output/streams/es.m3u","url":"https://deaplaneta-planetakidz-1-es.samsung.wurl.tv/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"1BT8btby3mmsgPF0"}
|
||||||
|
{"title":"Caillou","channel":"","filepath":"tests/__data__/output/streams/es.m3u","url":"https://dhx-caillou-1-es.samsung.wurl.tv/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"3BT8btby3mmsgPF0"}
|
||||||
|
{"title":"iHola Play","channel":"","filepath":"tests/__data__/output/streams/es.m3u","url":"https://rakuten-hola-2-es.samsung.wurl.tv/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"2BT8btby3mmsgPF0"}
|
||||||
|
{"title":"Telearuba (720p)","channel":"Telearuba.aw","filepath":"tests/__data__/output/streams/aw.m3u","url":"http://cdn.setar.aw:1935/Telearuba/smil:telearuba.smil/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"6BT8btby3mmsgPF0"}
|
||||||
|
{"title":"Telearuba (480p) [Not 24/7]","channel":"Telearuba.aw","filepath":"tests/__data__/output/streams/aw.m3u","url":"https://backend-server-dot-telearuba-app.appspot.com/media/livestream13/playlist.m3u8","http_referrer":null,"user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36","_id":"4BT8btby3mmsgPF0"}
|
32
tests/commands/playlist/format.test.js
Normal file
32
tests/commands/playlist/format.test.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
const { execSync } = require('child_process')
|
||||||
|
const fs = require('fs-extra')
|
||||||
|
const path = require('path')
|
||||||
|
const glob = require('glob')
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fs.emptyDirSync('tests/__data__/output')
|
||||||
|
fs.copyFileSync(
|
||||||
|
'tests/__data__/input/database/playlist_format.streams.db',
|
||||||
|
'tests/__data__/output/streams.db'
|
||||||
|
)
|
||||||
|
|
||||||
|
const stdout = execSync('DB_DIR=tests/__data__/output npm run playlist:format', {
|
||||||
|
encoding: 'utf8'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can format playlists', () => {
|
||||||
|
const files = glob
|
||||||
|
.sync('tests/__data__/expected/streams/*.m3u')
|
||||||
|
.map(f => f.replace('tests/__data__/expected/', ''))
|
||||||
|
|
||||||
|
files.forEach(filepath => {
|
||||||
|
expect(content(`output/${filepath}`), filepath).toBe(content(`expected/${filepath}`))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function content(filepath) {
|
||||||
|
return fs.readFileSync(`tests/__data__/${filepath}`, {
|
||||||
|
encoding: 'utf8'
|
||||||
|
})
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue