mirror of
https://github.com/iptv-org/iptv.git
synced 2025-05-12 18:10:04 -04:00
Update generate-playlists.js
This commit is contained in:
parent
96403d463e
commit
62ce78bbdf
32 changed files with 187 additions and 117 deletions
|
@ -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
|
||||
|
|
|
@ -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 })
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
})
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = function () {
|
||||
return Array.isArray(this.broadcast_area) ? this.broadcast_area.join(';') : ''
|
||||
return this.tvg_country || ''
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = function () {
|
||||
return Array.isArray(this.languages) ? this.languages.map(i => i.name).join(';') : ''
|
||||
return this.tvg_language || ''
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = function () {
|
||||
return this.channel && this.channel.logo ? this.channel.logo : ''
|
||||
return this.tvg_logo || ''
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = function () {
|
||||
return this.guides.length ? this.guides[0] : ''
|
||||
return this.tvg_url || ''
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue