diff --git a/package-lock.json b/package-lock.json index 129d55824..f65726e28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "m3u-linter": "^0.3.0", "markdown-include": "^0.4.3", "mz": "^2.7.0", + "natural-orderby": "^2.0.3", "nedb-promises": "^5.0.2", "normalize-url": "^6.1.0", "transliteration": "^2.2.0", @@ -3180,6 +3181,14 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, + "node_modules/natural-orderby": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz", + "integrity": "sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==", + "engines": { + "node": "*" + } + }, "node_modules/nedb-promises": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/nedb-promises/-/nedb-promises-5.0.2.tgz", @@ -6665,6 +6674,11 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, + "natural-orderby": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz", + "integrity": "sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==" + }, "nedb-promises": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/nedb-promises/-/nedb-promises-5.0.2.tgz", diff --git a/package.json b/package.json index 9ea1ec6b5..5589ed18b 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "m3u-linter": "^0.3.0", "markdown-include": "^0.4.3", "mz": "^2.7.0", + "natural-orderby": "^2.0.3", "nedb-promises": "^5.0.2", "normalize-url": "^6.1.0", "transliteration": "^2.2.0", diff --git a/scripts/commands/generate-playlists.js b/scripts/commands/generate-playlists.js index f37a43eaf..0fa4a1960 100644 --- a/scripts/commands/generate-playlists.js +++ b/scripts/commands/generate-playlists.js @@ -1,32 +1,41 @@ -const { db, generator, api } = require('../core') +const { db, generator, api, logger } = require('../core') const _ = require('lodash') async function main() { const streams = await loadStreams() + logger.info('generating categories/...') await generator.generate('categories', streams) + logger.info('generating countries/...') await generator.generate('countries', streams) + logger.info('generating languages/...') await generator.generate('languages', streams) + logger.info('generating regions/...') await generator.generate('regions', streams) + logger.info('generating index.category.m3u...') await generator.generate('index_category_m3u', streams) + logger.info('generating index.country.m3u...') await generator.generate('index_country_m3u', streams) + logger.info('generating index.language.m3u...') await generator.generate('index_language_m3u', streams) + logger.info('generating index.m3u...') await generator.generate('index_m3u', streams) + logger.info('generating index.nsfw.m3u...') await generator.generate('index_nsfw_m3u', streams) + logger.info('generating index.region.m3u...') await generator.generate('index_region_m3u', streams) } main() async function loadStreams() { + await db.streams.load() + let streams = await db.streams.find({}) + await api.channels.load() let channels = await api.channels.all() channels = _.keyBy(channels, 'id') - await api.countries.load() - let countries = await api.countries.all() - countries = _.keyBy(countries, 'code') - await api.categories.load() let categories = await api.categories.all() categories = _.keyBy(categories, 'id') @@ -35,55 +44,36 @@ async function loadStreams() { let languages = await api.languages.all() languages = _.keyBy(languages, 'code') - await api.regions.load() - let regions = await api.regions.all() - regions = _.keyBy(regions, 'code') - await api.guides.load() let guides = await api.guides.all() guides = _.groupBy(guides, 'channel') - await db.streams.load() - let streams = await db.streams.find({}) - return streams.map(stream => { const channel = channels[stream.channel_id] || null - stream.channel = channel if (channel) { - stream.broadcast_area = channel.broadcast_area.map(item => { - const [_, code] = item.split('/') - return code - }) - stream.regions = channel.broadcast_area - .reduce((acc, item) => { - const [type, code] = item.split('/') - switch (type) { - case 'r': - acc.push(regions[code]) - break - case 's': - const [c] = item.split('-') - const r1 = _.filter(regions, { countries: [c] }) - acc = acc.concat(r1) - break - case 'c': - const r2 = _.filter(regions, { countries: [code] }) - acc = acc.concat(r2) - break - } - return acc - }, []) + stream.group_title = channel.categories + .map(id => (categories[id] ? categories[id].name : null)) .filter(i => i) - stream.categories = channel.categories.map(id => categories[id]) - stream.languages = channel.languages.map(code => languages[code]) - stream.guides = guides[stream.channel_id] ? guides[stream.channel_id].map(g => g.url) : [] - } else { - stream.broadcast_area = [] - stream.categories = [] - stream.languages = [] - stream.regions = [] - stream.guides = [] + .sort() + .join(';') + stream.tvg_language = channel.languages + .map(code => (languages[code] ? languages[code].name : '')) + .filter(i => i) + .sort() + .join(';') + stream.tvg_country = channel.broadcast_area + .map(item => { + const [_, code] = item.split('/') + return code + }) + .filter(i => i) + .sort() + .join(';') + stream.tvg_logo = channel.logo + stream.tvg_url = + guides[channel.id] && guides[channel.id].length ? guides[channel.id][0].url : null + stream.channel = channel } return stream diff --git a/scripts/core/generator.js b/scripts/core/generator.js index 169ce8372..52893589a 100644 --- a/scripts/core/generator.js +++ b/scripts/core/generator.js @@ -3,22 +3,23 @@ const logger = require('./logger') const file = require('./file') const generators = require('../generators') const _ = require('lodash') +const { orderBy } = require('natural-orderby') const PUBLIC_DIR = process.env.PUBLIC_DIR || '.gh-pages' const LOGS_DIR = process.env.LOGS_DIR || 'scripts/logs/generators' const generator = {} -generator.generate = async function (name, items = []) { +generator.generate = async function (name, streams = []) { if (typeof generators[name] === 'function') { try { - items = _.orderBy( - items, + streams = orderBy( + streams, ['channel_name', 'status.level', 'resolution.height'], ['asc', 'asc', 'desc'] ) - items = _.uniqBy(items, s => s.channel_id || _.uniqueId()) - let output = await generators[name].bind()(items) + streams = _.uniqBy(streams, stream => stream.channel_id || _.uniqueId()) + let output = await generators[name].bind()(streams) output = Array.isArray(output) ? output : [output] for (const type of output) { const playlist = createPlaylist(type.items, { public: true }) diff --git a/scripts/core/playlist.js b/scripts/core/playlist.js index 43f5ad1bc..4d6c90c47 100644 --- a/scripts/core/playlist.js +++ b/scripts/core/playlist.js @@ -53,10 +53,8 @@ playlist.create = function (items = [], options = {}) { const header = {} if (options.public) { - let guides = items.map(item => item.guides) - guides = _.uniq(_.flatten(guides)).sort().join(',') - - header['x-tvg-url'] = guides + let guides = items.map(item => item.tvg_url).filter(i => i) + header['x-tvg-url'] = _.uniq(guides).sort().join(',') } p.setHeader(header) diff --git a/scripts/generators/categories.js b/scripts/generators/categories.js index da3e28665..0d95cd34a 100644 --- a/scripts/generators/categories.js +++ b/scripts/generators/categories.js @@ -10,7 +10,7 @@ module.exports = async function (streams = []) { output.push({ filepath: `categories/${category.id}.m3u`, items }) } - let items = _.filter(streams, s => !s.categories.length) + let items = _.filter(streams, stream => !stream.channel || !stream.channel.categories.length) output.push({ filepath: 'categories/undefined.m3u', items }) return output diff --git a/scripts/generators/countries.js b/scripts/generators/countries.js index 42f3deffc..cb3829052 100644 --- a/scripts/generators/countries.js +++ b/scripts/generators/countries.js @@ -2,20 +2,28 @@ const api = require('../core/api') const _ = require('lodash') module.exports = async function (streams = []) { - const output = [] + streams = _.filter(streams, stream => !stream.channel || stream.channel.is_nsfw === false) + await api.countries.load() const countries = await api.countries.all() await api.regions.load() const regions = await api.regions.all() - streams = _.filter(streams, s => !s.channel || s.channel.is_nsfw === false) + + const output = [] for (const country of countries) { - const areaCodes = _.filter(regions, { countries: [country.code] }).map(r => r.code) - areaCodes.push(country.code) - let items = _.filter(streams, s => _.intersection(areaCodes, s.broadcast_area).length) + const countryAreaCodes = _.filter(regions, { countries: [country.code] }).map( + r => `r/${r.code}` + ) + countryAreaCodes.push(`c/${country.code}`) + let items = _.filter( + streams, + stream => + stream.channel && _.intersection(stream.channel.broadcast_area, countryAreaCodes).length + ) output.push({ filepath: `countries/${country.code.toLowerCase()}.m3u`, items }) } - let items = _.filter(streams, s => !s.broadcast_area.length) + let items = _.filter(streams, stream => !stream.channel || !stream.channel.broadcast_area.length) output.push({ filepath: 'countries/undefined.m3u', items }) return output diff --git a/scripts/generators/index_category_m3u.js b/scripts/generators/index_category_m3u.js index fa3b4b181..0e8b364a6 100644 --- a/scripts/generators/index_category_m3u.js +++ b/scripts/generators/index_category_m3u.js @@ -3,19 +3,32 @@ const _ = require('lodash') module.exports = async function (streams = []) { streams = _.filter(streams, s => !s.channel || s.channel.is_nsfw === false) + + await api.categories.load() + let categories = await api.categories.all() + categories = _.keyBy(categories, 'id') + let items = [] streams.forEach(stream => { - if (!stream.categories.length) return items.push(stream) - - stream.categories.forEach(category => { + if (!stream.channel || !stream.channel.categories.length) { const item = _.cloneDeep(stream) - item.group_title = category.name + item.group_title = null + items.push(item) + + return + } + + stream.channel.categories.forEach(id => { + const item = _.cloneDeep(stream) + item.group_title = categories[id] ? categories[id].name : null items.push(item) }) }) - items = _.sortBy(items, i => { - if (i.group_title === 'Undefined') return '_' - return i.group_title + + items = _.sortBy(items, item => { + if (!item.group_title) return '' + + return item.group_title }) return { filepath: 'index.category.m3u', items } diff --git a/scripts/generators/index_country_m3u.js b/scripts/generators/index_country_m3u.js index 30c70677c..d7944bf5a 100644 --- a/scripts/generators/index_country_m3u.js +++ b/scripts/generators/index_country_m3u.js @@ -2,6 +2,8 @@ const api = require('../core/api') const _ = require('lodash') module.exports = async function (streams = []) { + streams = _.filter(streams, s => !s.channel || s.channel.is_nsfw === false) + await api.regions.load() let regions = await api.regions.all() regions = _.keyBy(regions, 'code') @@ -10,10 +12,14 @@ module.exports = async function (streams = []) { let countries = await api.countries.all() countries = _.keyBy(countries, 'code') - streams = _.filter(streams, s => !s.channel || s.channel.is_nsfw === false) let items = [] streams.forEach(stream => { - if (!stream.channel) return items.push(stream) + if (!stream.channel || !stream.channel.broadcast_area.length) { + const item = _.cloneDeep(stream) + item.group_title = null + items.push(item) + return + } getBroadcastCountries(stream.channel, { countries, regions }).forEach(country => { const item = _.cloneDeep(stream) @@ -21,9 +27,10 @@ module.exports = async function (streams = []) { items.push(item) }) }) - items = _.sortBy(items, i => { - if (i.group_title === 'Undefined') return '_' - return i.group_title + + items = _.sortBy(items, item => { + if (!item.group_title) return false + return item.group_title }) return { filepath: 'index.country.m3u', items } diff --git a/scripts/generators/index_language_m3u.js b/scripts/generators/index_language_m3u.js index 4f9889be5..c50c17a8e 100644 --- a/scripts/generators/index_language_m3u.js +++ b/scripts/generators/index_language_m3u.js @@ -3,18 +3,28 @@ const _ = require('lodash') module.exports = async function (streams = []) { streams = _.filter(streams, s => !s.channel || s.channel.is_nsfw === false) + + await api.languages.load() + let languages = await api.languages.all() + languages = _.keyBy(languages, 'code') + let items = [] streams.forEach(stream => { - if (!stream.languages.length) return items.push(stream) - - stream.languages.forEach(language => { + if (!stream.channel || !stream.channel.languages.length) { const item = _.cloneDeep(stream) - item.group_title = language.name + item.group_title = null + items.push(stream) + return + } + + stream.channel.languages.forEach(code => { + const item = _.cloneDeep(stream) + item.group_title = languages[code] ? languages[code].name : null items.push(item) }) }) items = _.sortBy(items, i => { - if (i.group_title === 'Undefined') return '_' + if (!i.group_title) return '' return i.group_title }) diff --git a/scripts/generators/index_region_m3u.js b/scripts/generators/index_region_m3u.js index 86f00f2fb..bafcb3fd6 100644 --- a/scripts/generators/index_region_m3u.js +++ b/scripts/generators/index_region_m3u.js @@ -2,21 +2,55 @@ const api = require('../core/api') const _ = require('lodash') module.exports = async function (streams = []) { - streams = _.filter(streams, s => !s.channel || s.channel.is_nsfw === false) + streams = _.filter(streams, stream => !stream.channel || stream.channel.is_nsfw === false) + + await api.regions.load() + let regions = await api.regions.all() + regions = _.keyBy(regions, 'code') + let items = [] streams.forEach(stream => { - if (!stream.regions.length) return items.push(stream) + if (!stream.channel || !stream.channel.broadcast_area.length) { + const item = _.cloneDeep(stream) + item.group_title = null + items.push(item) + return + } - stream.regions.forEach(region => { + getChannelRegions(stream.channel, { regions }).forEach(region => { const item = _.cloneDeep(stream) item.group_title = region.name items.push(item) }) }) + items = _.sortBy(items, i => { - if (i.group_title === 'Undefined') return '_' + if (!i.group_title) return '' return i.group_title }) return { filepath: 'index.region.m3u', items } } + +function getChannelRegions(channel, { regions }) { + return channel.broadcast_area + .reduce((acc, item) => { + const [type, code] = item.split('/') + switch (type) { + case 'r': + acc.push(regions[code]) + break + case 's': + const [c] = item.split('-') + const r1 = _.filter(regions, { countries: [c] }) + acc = acc.concat(r1) + break + case 'c': + const r2 = _.filter(regions, { countries: [code] }) + acc = acc.concat(r2) + break + } + return acc + }, []) + .filter(i => i) +} diff --git a/scripts/generators/languages.js b/scripts/generators/languages.js index cff825592..51ca967d1 100644 --- a/scripts/generators/languages.js +++ b/scripts/generators/languages.js @@ -16,7 +16,7 @@ module.exports = async function (streams = []) { } } - let items = _.filter(streams, s => !s.languages.length) + let items = _.filter(streams, stream => !stream.channel || !stream.channel.languages.length) output.push({ filepath: 'languages/undefined.m3u', items }) return output diff --git a/scripts/generators/regions.js b/scripts/generators/regions.js index c48cbad44..6df03e852 100644 --- a/scripts/generators/regions.js +++ b/scripts/generators/regions.js @@ -5,15 +5,18 @@ module.exports = async function (streams = []) { const output = [] await api.regions.load() const regions = await api.regions.all() - streams = _.filter(streams, s => !s.channel || s.channel.is_nsfw === false) + streams = _.filter(streams, stream => !stream.channel || stream.channel.is_nsfw === false) for (const region of regions) { - const areaCodes = region.countries - areaCodes.push(region.code) - let items = _.filter(streams, s => _.intersection(areaCodes, s.broadcast_area).length) + const areaCodes = region.countries.map(code => `c/${code}`) + areaCodes.push(`r/${region.code}`) + let items = _.filter( + streams, + stream => stream.channel && _.intersection(stream.channel.broadcast_area, areaCodes).length + ) output.push({ filepath: `regions/${region.code.toLowerCase()}.m3u`, items }) } - let items = _.filter(streams, s => !s.broadcast_area.length) + let items = _.filter(streams, stream => !stream.channel || !stream.channel.broadcast_area.length) output.push({ filepath: 'regions/undefined.m3u', items }) return output diff --git a/scripts/store/getters/group_title.js b/scripts/store/getters/group_title.js index 15ea1a9a3..c67c955de 100644 --- a/scripts/store/getters/group_title.js +++ b/scripts/store/getters/group_title.js @@ -1,12 +1,3 @@ module.exports = function () { - if (this.group_title !== undefined) return this.group_title - - if (Array.isArray(this.categories) && this.categories.length) { - return this.categories - .map(i => i.name) - .sort() - .join(';') - } - - return 'Undefined' + return this.group_title || 'Undefined' } diff --git a/scripts/store/getters/index.js b/scripts/store/getters/index.js index df20631e0..21f17b262 100644 --- a/scripts/store/getters/index.js +++ b/scripts/store/getters/index.js @@ -1,7 +1,7 @@ exports.group_title = require('./group_title') exports.title = require('./title') -exports.tvg_country = require('./tvg_country') exports.tvg_id = require('./tvg_id') -exports.tvg_language = require('./tvg_language') exports.tvg_logo = require('./tvg_logo') exports.tvg_url = require('./tvg_url') +exports.tvg_country = require('./tvg_country') +exports.tvg_language = require('./tvg_language') diff --git a/scripts/store/getters/tvg_country.js b/scripts/store/getters/tvg_country.js index fb23daf09..f3015d773 100644 --- a/scripts/store/getters/tvg_country.js +++ b/scripts/store/getters/tvg_country.js @@ -1,3 +1,3 @@ module.exports = function () { - return Array.isArray(this.broadcast_area) ? this.broadcast_area.join(';') : '' + return this.tvg_country || '' } diff --git a/scripts/store/getters/tvg_language.js b/scripts/store/getters/tvg_language.js index 2ad39c7fe..ba4de84ed 100644 --- a/scripts/store/getters/tvg_language.js +++ b/scripts/store/getters/tvg_language.js @@ -1,3 +1,3 @@ module.exports = function () { - return Array.isArray(this.languages) ? this.languages.map(i => i.name).join(';') : '' + return this.tvg_language || '' } diff --git a/scripts/store/getters/tvg_logo.js b/scripts/store/getters/tvg_logo.js index c152968c4..8b289fea0 100644 --- a/scripts/store/getters/tvg_logo.js +++ b/scripts/store/getters/tvg_logo.js @@ -1,3 +1,3 @@ module.exports = function () { - return this.channel && this.channel.logo ? this.channel.logo : '' + return this.tvg_logo || '' } diff --git a/scripts/store/getters/tvg_url.js b/scripts/store/getters/tvg_url.js index 9bd084c78..2bb1bb1e4 100644 --- a/scripts/store/getters/tvg_url.js +++ b/scripts/store/getters/tvg_url.js @@ -1,3 +1,3 @@ module.exports = function () { - return this.guides.length ? this.guides[0] : '' + return this.tvg_url || '' } diff --git a/tests/__data__/expected/.gh-pages/categories/general.m3u b/tests/__data__/expected/.gh-pages/categories/general.m3u index a5890b5ab..1ca910b7c 100644 --- a/tests/__data__/expected/.gh-pages/categories/general.m3u +++ b/tests/__data__/expected/.gh-pages/categories/general.m3u @@ -1,4 +1,4 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD (720p) [Not 24/7] http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/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="General",ЛДПР ТВ (1080p) diff --git a/tests/__data__/expected/.gh-pages/categories/news.m3u b/tests/__data__/expected/.gh-pages/categories/news.m3u index 3993d1c4a..8bbcae29c 100644 --- a/tests/__data__/expected/.gh-pages/categories/news.m3u +++ b/tests/__data__/expected/.gh-pages/categories/news.m3u @@ -1,3 +1,3 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD (720p) [Not 24/7] http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 diff --git a/tests/__data__/expected/.gh-pages/countries/ca.m3u b/tests/__data__/expected/.gh-pages/countries/ca.m3u index fb0a0ce72..0b41d029c 100644 --- a/tests/__data__/expected/.gh-pages/countries/ca.m3u +++ b/tests/__data__/expected/.gh-pages/countries/ca.m3u @@ -1,4 +1,4 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD (720p) [Not 24/7] http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 #EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-country="CA" tvg-language="French" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia diff --git a/tests/__data__/expected/.gh-pages/countries/ru.m3u b/tests/__data__/expected/.gh-pages/countries/ru.m3u index a5890b5ab..1ca910b7c 100644 --- a/tests/__data__/expected/.gh-pages/countries/ru.m3u +++ b/tests/__data__/expected/.gh-pages/countries/ru.m3u @@ -1,4 +1,4 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD (720p) [Not 24/7] http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/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="General",ЛДПР ТВ (1080p) diff --git a/tests/__data__/expected/.gh-pages/countries/uk.m3u b/tests/__data__/expected/.gh-pages/countries/uk.m3u index 3993d1c4a..8bbcae29c 100644 --- a/tests/__data__/expected/.gh-pages/countries/uk.m3u +++ b/tests/__data__/expected/.gh-pages/countries/uk.m3u @@ -1,3 +1,3 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD (720p) [Not 24/7] http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 diff --git a/tests/__data__/expected/.gh-pages/index.category.m3u b/tests/__data__/expected/.gh-pages/index.category.m3u index 28b3cbe20..5478245cd 100644 --- a/tests/__data__/expected/.gh-pages/index.category.m3u +++ b/tests/__data__/expected/.gh-pages/index.category.m3u @@ -1,4 +1,4 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General",BBC News HD (720p) [Not 24/7] http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/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="General",ЛДПР ТВ (1080p) diff --git a/tests/__data__/expected/.gh-pages/index.country.m3u b/tests/__data__/expected/.gh-pages/index.country.m3u index f854d225d..78f959ce4 100644 --- a/tests/__data__/expected/.gh-pages/index.country.m3u +++ b/tests/__data__/expected/.gh-pages/index.country.m3u @@ -1,4 +1,4 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="Afghanistan",BBC News HD (720p) [Not 24/7] http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="Albania",BBC News HD (720p) [Not 24/7] diff --git a/tests/__data__/expected/.gh-pages/index.language.m3u b/tests/__data__/expected/.gh-pages/index.language.m3u index 2d6aa2a7e..3a43dc07b 100644 --- a/tests/__data__/expected/.gh-pages/index.language.m3u +++ b/tests/__data__/expected/.gh-pages/index.language.m3u @@ -1,4 +1,4 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="English",BBC News HD (720p) [Not 24/7] http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 #EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-country="CA" tvg-language="French" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="French",Meteomedia diff --git a/tests/__data__/expected/.gh-pages/index.m3u b/tests/__data__/expected/.gh-pages/index.m3u index 1e10afcac..defab9463 100644 --- a/tests/__data__/expected/.gh-pages/index.m3u +++ b/tests/__data__/expected/.gh-pages/index.m3u @@ -1,4 +1,4 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="AndorraTV.ad" tvg-country="AD" tvg-language="Valencian" tvg-logo="" group-title="Undefined",ATV (720p) [Offline] https://iptv-all.lanesh4d0w.repl.co/andorra/atv #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD (720p) [Not 24/7] diff --git a/tests/__data__/expected/.gh-pages/index.nsfw.m3u b/tests/__data__/expected/.gh-pages/index.nsfw.m3u index 7646b9b52..95db56354 100644 --- a/tests/__data__/expected/.gh-pages/index.nsfw.m3u +++ b/tests/__data__/expected/.gh-pages/index.nsfw.m3u @@ -1,4 +1,4 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="AndorraTV.ad" tvg-country="AD" tvg-language="Valencian" tvg-logo="" group-title="Undefined",ATV (720p) [Offline] https://iptv-all.lanesh4d0w.repl.co/andorra/atv #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD (720p) [Not 24/7] diff --git a/tests/__data__/expected/.gh-pages/index.region.m3u b/tests/__data__/expected/.gh-pages/index.region.m3u index 73ec6be9b..2f40d87d1 100644 --- a/tests/__data__/expected/.gh-pages/index.region.m3u +++ b/tests/__data__/expected/.gh-pages/index.region.m3u @@ -1,4 +1,4 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-country="CA" tvg-language="French" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Americas",Meteomedia http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/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="Asia",ЛДПР ТВ (1080p) diff --git a/tests/__data__/expected/.gh-pages/languages/eng.m3u b/tests/__data__/expected/.gh-pages/languages/eng.m3u index 3993d1c4a..8bbcae29c 100644 --- a/tests/__data__/expected/.gh-pages/languages/eng.m3u +++ b/tests/__data__/expected/.gh-pages/languages/eng.m3u @@ -1,3 +1,3 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD (720p) [Not 24/7] http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 diff --git a/tests/__data__/expected/.gh-pages/regions/int.m3u b/tests/__data__/expected/.gh-pages/regions/int.m3u index d2bb00ce0..11a540bc9 100644 --- a/tests/__data__/expected/.gh-pages/regions/int.m3u +++ b/tests/__data__/expected/.gh-pages/regions/int.m3u @@ -1,4 +1,4 @@ -#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml" +#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml" #EXTINF:-1 tvg-id="AndorraTV.ad" tvg-country="AD" tvg-language="Valencian" tvg-logo="" group-title="Undefined",ATV (720p) [Offline] https://iptv-all.lanesh4d0w.repl.co/andorra/atv #EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD (720p) [Not 24/7]