Update generate-playlists.js

This commit is contained in:
Aleksandr Statciuk 2022-02-08 01:11:47 +03:00
parent 96403d463e
commit 62ce78bbdf
32 changed files with 187 additions and 117 deletions

14
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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

View File

@ -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 })

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -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 }

View File

@ -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
})

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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'
}

View File

@ -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')

View File

@ -1,3 +1,3 @@
module.exports = function () {
return Array.isArray(this.broadcast_area) ? this.broadcast_area.join(';') : ''
return this.tvg_country || ''
}

View File

@ -1,3 +1,3 @@
module.exports = function () {
return Array.isArray(this.languages) ? this.languages.map(i => i.name).join(';') : ''
return this.tvg_language || ''
}

View File

@ -1,3 +1,3 @@
module.exports = function () {
return this.channel && this.channel.logo ? this.channel.logo : ''
return this.tvg_logo || ''
}

View File

@ -1,3 +1,3 @@
module.exports = function () {
return this.guides.length ? this.guides[0] : ''
return this.tvg_url || ''
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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]

View File

@ -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

View File

@ -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]

View File

@ -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]

View File

@ -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)

View File

@ -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

View File

@ -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]