mirror of
https://github.com/iptv-org/iptv
synced 2026-10-21 18:46:20 -04:00
Update scripts
This commit is contained in:
1 parent
9902121ac0
commit
9d7cac7bda
21 files changed
+129
-55
No files matched your search
@@ -84,6 +84,20 @@ async function main() {
|
|||||||
errors = errors.concat(validateStreamId(streamId))
|
errors = errors.concat(validateStreamId(streamId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
data.missing([
|
||||||
|
'stream_id',
|
||||||
|
'quality',
|
||||||
|
'live_247',
|
||||||
|
'geo_blocked',
|
||||||
|
'http_user_agent',
|
||||||
|
'http_referrer'
|
||||||
|
])
|
||||||
|
) {
|
||||||
|
errors.push('The request does not contain any changes')
|
||||||
|
done()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done()
|
done()
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ async function main() {
|
|||||||
|
|
||||||
if (streams.isEmpty()) return
|
if (streams.isEmpty()) return
|
||||||
|
|
||||||
const playlist = new Playlist(streams, { public: false })
|
const playlist = new Playlist(streams, { public: false, raw: true })
|
||||||
await streamsStorage.save(filepath, playlist.toString())
|
await streamsStorage.save(filepath, playlist.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,20 +44,35 @@ async function main() {
|
|||||||
logger.info('generating raw/...')
|
logger.info('generating raw/...')
|
||||||
await new RawGenerator({ streams, logFile }).generate()
|
await new RawGenerator({ streams, logFile }).generate()
|
||||||
|
|
||||||
|
logger.info('create unique names...')
|
||||||
|
const channelCountries = new Map<string, Set<string>>()
|
||||||
|
streams.forEach((stream: Stream) => {
|
||||||
|
if (!channelCountries.has(stream.channelName)) {
|
||||||
|
channelCountries.set(stream.channelName, new Set())
|
||||||
|
}
|
||||||
|
channelCountries.get(stream.channelName)!.add(stream.countryName)
|
||||||
|
})
|
||||||
|
for (const stream of streams.all()) {
|
||||||
|
const countries = channelCountries.get(stream.channelName)
|
||||||
|
stream.hasUniqueName = countries ? countries.size === 1 : false
|
||||||
|
}
|
||||||
|
|
||||||
logger.info('sorting streams...')
|
logger.info('sorting streams...')
|
||||||
streams = streams.sortBy(
|
streams = streams.sortBy(
|
||||||
[
|
[
|
||||||
(stream: Stream) => stream.getId(),
|
(stream: Stream) => stream.channelUniqueName,
|
||||||
|
(stream: Stream) => (stream.hasMainFeed ? 1 : 0),
|
||||||
|
(stream: Stream) => stream.feedName,
|
||||||
(stream: Stream) => (stream.isGeoBlocked ? -1 : 0),
|
(stream: Stream) => (stream.isGeoBlocked ? -1 : 0),
|
||||||
(stream: Stream) => (stream.isNot247 ? -1 : 0),
|
(stream: Stream) => (stream.isNot247 ? -1 : 0),
|
||||||
(stream: Stream) => stream.getVerticalResolution()
|
(stream: Stream) => stream.getVerticalResolution()
|
||||||
],
|
],
|
||||||
['asc', 'desc', 'desc', 'desc']
|
['asc', 'desc', 'asc', 'desc', 'desc', 'desc']
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info('filtering streams...')
|
logger.info('filtering streams...')
|
||||||
streams = streams
|
streams = streams
|
||||||
.filter((stream: Stream) => !!stream.getId())
|
.filter((stream: Stream) => stream.hasChannel() && stream.hasFeed())
|
||||||
.uniqBy((stream: Stream) => stream.getId() || uniqueId())
|
.uniqBy((stream: Stream) => stream.getId() || uniqueId())
|
||||||
|
|
||||||
const { categories, countries, subdivisions, cities, regions } = data
|
const { categories, countries, subdivisions, cities, regions } = data
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ async function removeBrokenLinks() {
|
|||||||
|
|
||||||
streams = streams.filter((stream: Stream) => !isBroken(stream))
|
streams = streams.filter((stream: Stream) => !isBroken(stream))
|
||||||
|
|
||||||
const playlist = new Playlist(streams, { public: false })
|
const playlist = new Playlist(streams, { public: false, raw: true })
|
||||||
await rootStorage.save(filepath, playlist.toString())
|
await rootStorage.save(filepath, playlist.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ async function saveStreams() {
|
|||||||
let filteredStreams = new Collection<Stream>(groupedStreams.get(filepath))
|
let filteredStreams = new Collection<Stream>(groupedStreams.get(filepath))
|
||||||
filteredStreams = filteredStreams.filter((stream: Stream) => stream.removed === false)
|
filteredStreams = filteredStreams.filter((stream: Stream) => stream.removed === false)
|
||||||
|
|
||||||
const playlist = new Playlist(filteredStreams, { public: false })
|
const playlist = new Playlist(filteredStreams, { public: false, raw: true })
|
||||||
await streamsStorage.save(filepath, playlist.toString())
|
await streamsStorage.save(filepath, playlist.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Logger, Collection, Dictionary } from '@freearhey/core'
|
import { Logger, Collection, Dictionary } from '@freearhey/core'
|
||||||
|
import { OptionValues, program } from 'commander'
|
||||||
import { Storage } from '@freearhey/storage-js'
|
import { Storage } from '@freearhey/storage-js'
|
||||||
import { PlaylistParser } from '../../core'
|
import { PlaylistParser } from '../../core'
|
||||||
import { data, loadData } from '../../api'
|
import { data, loadData } from '../../api'
|
||||||
@@ -6,10 +7,14 @@ import { ROOT_DIR } from '../../constants'
|
|||||||
import { isURI } from '../../utils.js'
|
import { isURI } from '../../utils.js'
|
||||||
import { Stream } from '../../models'
|
import { Stream } from '../../models'
|
||||||
import * as sdk from '@iptv-org/sdk'
|
import * as sdk from '@iptv-org/sdk'
|
||||||
import { program } from 'commander'
|
|
||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
|
|
||||||
program.argument('[filepath...]', 'Path to file to validate').parse(process.argv)
|
program
|
||||||
|
.argument('[filepath...]', 'Path to file to validate')
|
||||||
|
.option('--log-level <level>', 'Specify the minimum log level (error or warning)')
|
||||||
|
.parse(process.argv)
|
||||||
|
|
||||||
|
const options: OptionValues = program.opts()
|
||||||
|
|
||||||
type LogItem = {
|
type LogItem = {
|
||||||
type: string
|
type: string
|
||||||
@@ -51,7 +56,7 @@ async function main() {
|
|||||||
const streams = streamsGroupedByFilepath.get(filepath)
|
const streams = streamsGroupedByFilepath.get(filepath)
|
||||||
if (!streams) continue
|
if (!streams) continue
|
||||||
|
|
||||||
const log = new Collection<LogItem>()
|
let log = new Collection<LogItem>()
|
||||||
streams.forEach((stream: Stream) => {
|
streams.forEach((stream: Stream) => {
|
||||||
if (!stream.channel) {
|
if (!stream.channel) {
|
||||||
log.add({
|
log.add({
|
||||||
@@ -130,6 +135,12 @@ async function main() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (options.logLevel === 'error') {
|
||||||
|
log = log.filter(i => ['error'].includes(i.type))
|
||||||
|
} else if (options.logLevel === 'warning') {
|
||||||
|
log = log.filter(i => ['warning', 'error'].includes(i.type))
|
||||||
|
}
|
||||||
|
|
||||||
if (log.isNotEmpty()) {
|
if (log.isNotEmpty()) {
|
||||||
console.log(`\n${chalk.underline(filepath)}`)
|
console.log(`\n${chalk.underline(filepath)}`)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export class DataSet {
|
|||||||
return this._data.has(key)
|
return this._data.has(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
missing(key: string): boolean {
|
missing(key: string | string[]): boolean {
|
||||||
const keys = Array.isArray(key) ? key : [key]
|
const keys = Array.isArray(key) ? key : [key]
|
||||||
|
|
||||||
return keys.every(_key => this._data.get(_key) === undefined)
|
return keys.every(_key => this._data.get(_key) === undefined)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export class CategoriesGenerator implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async generate() {
|
async generate() {
|
||||||
const streams = this.streams.sortBy([(stream: Stream) => stream.title])
|
const streams = this.streams
|
||||||
|
|
||||||
this.categories.forEach(async (category: sdk.Models.Category) => {
|
this.categories.forEach(async (category: sdk.Models.Category) => {
|
||||||
const categoryStreams = streams
|
const categoryStreams = streams
|
||||||
@@ -41,7 +41,7 @@ export class CategoriesGenerator implements Generator {
|
|||||||
return stream
|
return stream
|
||||||
})
|
})
|
||||||
|
|
||||||
const playlist = new Playlist(categoryStreams, { public: true })
|
const playlist = new Playlist(categoryStreams, { public: true, raw: false })
|
||||||
const filepath = `categories/${category.id}.m3u`
|
const filepath = `categories/${category.id}.m3u`
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
@@ -50,7 +50,7 @@ export class CategoriesGenerator implements Generator {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const undefinedStreams = streams.filter((stream: Stream) => stream.getCategories().isEmpty())
|
const undefinedStreams = streams.filter((stream: Stream) => stream.getCategories().isEmpty())
|
||||||
const playlist = new Playlist(undefinedStreams, { public: true })
|
const playlist = new Playlist(undefinedStreams, { public: true, raw: false })
|
||||||
const filepath = 'categories/undefined.m3u'
|
const filepath = 'categories/undefined.m3u'
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ export class CitiesGenerator implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
const streams = this.streams
|
const streams = this.streams.filter((stream: Stream) => stream.isSFW())
|
||||||
.sortBy((stream: Stream) => stream.title)
|
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
|
||||||
|
|
||||||
const streamsGroupedByCityCode = {}
|
const streamsGroupedByCityCode = {}
|
||||||
streams.forEach((stream: Stream) => {
|
streams.forEach((stream: Stream) => {
|
||||||
@@ -43,7 +41,7 @@ export class CitiesGenerator implements Generator {
|
|||||||
for (const cityCode in streamsGroupedByCityCode) {
|
for (const cityCode in streamsGroupedByCityCode) {
|
||||||
const cityStreams = streamsGroupedByCityCode[cityCode]
|
const cityStreams = streamsGroupedByCityCode[cityCode]
|
||||||
|
|
||||||
const playlist = new Playlist(cityStreams, { public: true })
|
const playlist = new Playlist(cityStreams, { public: true, raw: false })
|
||||||
const filepath = `cities/${cityCode.toLowerCase()}.m3u`
|
const filepath = `cities/${cityCode.toLowerCase()}.m3u`
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ export class CountriesGenerator implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
const streams = this.streams
|
const streams = this.streams.filter((stream: Stream) => stream.isSFW())
|
||||||
.sortBy((stream: Stream) => stream.title)
|
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
|
||||||
|
|
||||||
const streamsGroupedByCountryCode = {}
|
const streamsGroupedByCountryCode = {}
|
||||||
streams.forEach((stream: Stream) => {
|
streams.forEach((stream: Stream) => {
|
||||||
@@ -43,7 +41,7 @@ export class CountriesGenerator implements Generator {
|
|||||||
for (const countryCode in streamsGroupedByCountryCode) {
|
for (const countryCode in streamsGroupedByCountryCode) {
|
||||||
const countryStreams = streamsGroupedByCountryCode[countryCode]
|
const countryStreams = streamsGroupedByCountryCode[countryCode]
|
||||||
|
|
||||||
const playlist = new Playlist(countryStreams, { public: true })
|
const playlist = new Playlist(countryStreams, { public: true, raw: false })
|
||||||
const filepath = `countries/${countryCode.toLowerCase()}.m3u`
|
const filepath = `countries/${countryCode.toLowerCase()}.m3u`
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
@@ -52,7 +50,10 @@ export class CountriesGenerator implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const internationalStreams = streams.filter((stream: Stream) => stream.isInternational())
|
const internationalStreams = streams.filter((stream: Stream) => stream.isInternational())
|
||||||
const internationalPlaylist = new Playlist(internationalStreams, { public: true })
|
const internationalPlaylist = new Playlist(internationalStreams, {
|
||||||
|
public: true,
|
||||||
|
displayUniqueName: true
|
||||||
|
})
|
||||||
const internationalFilepath = 'countries/int.m3u'
|
const internationalFilepath = 'countries/int.m3u'
|
||||||
await this.storage.save(internationalFilepath, internationalPlaylist.toString())
|
await this.storage.save(internationalFilepath, internationalPlaylist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
@@ -66,7 +67,7 @@ export class CountriesGenerator implements Generator {
|
|||||||
const undefinedStreams = streams.filter((stream: Stream) =>
|
const undefinedStreams = streams.filter((stream: Stream) =>
|
||||||
stream.getBroadcastAreaCodes().isEmpty()
|
stream.getBroadcastAreaCodes().isEmpty()
|
||||||
)
|
)
|
||||||
const undefinedPlaylist = new Playlist(undefinedStreams, { public: true })
|
const undefinedPlaylist = new Playlist(undefinedStreams, { public: true, raw: false })
|
||||||
const undefinedFilepath = 'countries/undefined.m3u'
|
const undefinedFilepath = 'countries/undefined.m3u'
|
||||||
await this.storage.save(undefinedFilepath, undefinedPlaylist.toString())
|
await this.storage.save(undefinedFilepath, undefinedPlaylist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export class IndexCategoryGenerator implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
const streams = this.streams.sortBy(stream => stream.title).filter(stream => stream.isSFW())
|
const streams = this.streams.filter(stream => stream.isSFW())
|
||||||
|
|
||||||
let groupedStreams = new Collection<Stream>()
|
let groupedStreams = new Collection<Stream>()
|
||||||
streams.forEach((stream: Stream) => {
|
streams.forEach((stream: Stream) => {
|
||||||
@@ -46,7 +46,7 @@ export class IndexCategoryGenerator implements Generator {
|
|||||||
return stream.groupTitle
|
return stream.groupTitle
|
||||||
})
|
})
|
||||||
|
|
||||||
const playlist = new Playlist(groupedStreams, { public: true })
|
const playlist = new Playlist(groupedStreams, { public: true, raw: false })
|
||||||
const filepath = 'index.category.m3u'
|
const filepath = 'index.category.m3u'
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ export class IndexCountryGenerator implements Generator {
|
|||||||
let groupedStreams = new Collection<Stream>()
|
let groupedStreams = new Collection<Stream>()
|
||||||
|
|
||||||
this.streams
|
this.streams
|
||||||
.sortBy((stream: Stream) => stream.title)
|
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
.filter((stream: Stream) => stream.isSFW())
|
||||||
.forEach((stream: Stream) => {
|
.forEach((stream: Stream) => {
|
||||||
const broadcastAreaCountries = stream.getBroadcastCountries()
|
const broadcastAreaCountries = stream.getBroadcastCountries()
|
||||||
@@ -57,7 +56,7 @@ export class IndexCountryGenerator implements Generator {
|
|||||||
return stream.groupTitle
|
return stream.groupTitle
|
||||||
})
|
})
|
||||||
|
|
||||||
const playlist = new Playlist(groupedStreams, { public: true })
|
const playlist = new Playlist(groupedStreams, { public: true, raw: false })
|
||||||
const filepath = 'index.country.m3u'
|
const filepath = 'index.country.m3u'
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ export class IndexGenerator implements Generator {
|
|||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
const sfwStreams = this.streams
|
const sfwStreams = this.streams
|
||||||
.sortBy(stream => stream.title)
|
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
.filter((stream: Stream) => stream.isSFW())
|
||||||
.map((stream: Stream) => {
|
.map((stream: Stream) => {
|
||||||
const groupTitle = stream
|
const groupTitle = stream
|
||||||
@@ -35,7 +34,7 @@ export class IndexGenerator implements Generator {
|
|||||||
return stream
|
return stream
|
||||||
})
|
})
|
||||||
|
|
||||||
const playlist = new Playlist(sfwStreams, { public: true })
|
const playlist = new Playlist(sfwStreams, { public: true, raw: false })
|
||||||
const filepath = 'index.m3u'
|
const filepath = 'index.m3u'
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ export class IndexLanguageGenerator implements Generator {
|
|||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
let groupedStreams = new Collection<Stream>()
|
let groupedStreams = new Collection<Stream>()
|
||||||
this.streams
|
this.streams
|
||||||
.sortBy((stream: Stream) => stream.title)
|
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
.filter((stream: Stream) => stream.isSFW())
|
||||||
.forEach((stream: Stream) => {
|
.forEach((stream: Stream) => {
|
||||||
const streamLanguages = stream.getLanguages()
|
const streamLanguages = stream.getLanguages()
|
||||||
@@ -47,7 +46,7 @@ export class IndexLanguageGenerator implements Generator {
|
|||||||
return stream.groupTitle
|
return stream.groupTitle
|
||||||
})
|
})
|
||||||
|
|
||||||
const playlist = new Playlist(groupedStreams, { public: true })
|
const playlist = new Playlist(groupedStreams, { public: true, raw: false })
|
||||||
const filepath = 'index.language.m3u'
|
const filepath = 'index.language.m3u'
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ export class LanguagesGenerator implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
const streams: Collection<Stream> = this.streams
|
const streams: Collection<Stream> = this.streams.filter((stream: Stream) => stream.isSFW())
|
||||||
.sortBy((stream: Stream) => stream.title)
|
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
|
||||||
|
|
||||||
const languages = new Collection<sdk.Models.Language>()
|
const languages = new Collection<sdk.Models.Language>()
|
||||||
streams.forEach((stream: Stream) => {
|
streams.forEach((stream: Stream) => {
|
||||||
@@ -39,7 +37,7 @@ export class LanguagesGenerator implements Generator {
|
|||||||
|
|
||||||
if (languageStreams.isEmpty()) return
|
if (languageStreams.isEmpty()) return
|
||||||
|
|
||||||
const playlist = new Playlist(languageStreams, { public: true })
|
const playlist = new Playlist(languageStreams, { public: true, raw: false })
|
||||||
const filepath = `languages/${language.code}.m3u`
|
const filepath = `languages/${language.code}.m3u`
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
@@ -50,7 +48,7 @@ export class LanguagesGenerator implements Generator {
|
|||||||
const undefinedStreams = streams.filter((stream: Stream) => stream.getLanguages().isEmpty())
|
const undefinedStreams = streams.filter((stream: Stream) => stream.getLanguages().isEmpty())
|
||||||
if (undefinedStreams.isEmpty()) return
|
if (undefinedStreams.isEmpty()) return
|
||||||
|
|
||||||
const playlist = new Playlist(undefinedStreams, { public: true })
|
const playlist = new Playlist(undefinedStreams, { public: true, raw: false })
|
||||||
const filepath = 'languages/undefined.m3u'
|
const filepath = 'languages/undefined.m3u'
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class RawGenerator implements Generator {
|
|||||||
|
|
||||||
return stream
|
return stream
|
||||||
})
|
})
|
||||||
const playlist = new Playlist(streams, { public: true })
|
const playlist = new Playlist(streams, { public: true, raw: true })
|
||||||
const filepath = `raw/${filename}`
|
const filepath = `raw/${filename}`
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ export class RegionsGenerator implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
const streams = this.streams
|
const streams = this.streams.filter((stream: Stream) => stream.isSFW())
|
||||||
.sortBy((stream: Stream) => stream.title)
|
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
|
||||||
|
|
||||||
const streamsGroupedByRegionCode = {}
|
const streamsGroupedByRegionCode = {}
|
||||||
streams.forEach((stream: Stream) => {
|
streams.forEach((stream: Stream) => {
|
||||||
@@ -43,7 +41,7 @@ export class RegionsGenerator implements Generator {
|
|||||||
for (const regionCode in streamsGroupedByRegionCode) {
|
for (const regionCode in streamsGroupedByRegionCode) {
|
||||||
const regionStreams = streamsGroupedByRegionCode[regionCode]
|
const regionStreams = streamsGroupedByRegionCode[regionCode]
|
||||||
|
|
||||||
const playlist = new Playlist(regionStreams, { public: true })
|
const playlist = new Playlist(regionStreams, { public: true, raw: false })
|
||||||
const filepath = `regions/${regionCode.toLowerCase()}.m3u`
|
const filepath = `regions/${regionCode.toLowerCase()}.m3u`
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export class SourcesGenerator implements Generator {
|
|||||||
|
|
||||||
return stream
|
return stream
|
||||||
})
|
})
|
||||||
const playlist = new Playlist(streams, { public: true })
|
const playlist = new Playlist(streams, { public: true, raw: false })
|
||||||
const filepath = `sources/${filename}`
|
const filepath = `sources/${filename}`
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ export class SubdivisionsGenerator implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
const streams = this.streams
|
const streams = this.streams.filter((stream: Stream) => stream.isSFW())
|
||||||
.sortBy((stream: Stream) => stream.title)
|
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
|
||||||
|
|
||||||
const streamsGroupedBySubdivisionCode = {}
|
const streamsGroupedBySubdivisionCode = {}
|
||||||
streams.forEach((stream: Stream) => {
|
streams.forEach((stream: Stream) => {
|
||||||
@@ -43,7 +41,7 @@ export class SubdivisionsGenerator implements Generator {
|
|||||||
for (const subdivisionCode in streamsGroupedBySubdivisionCode) {
|
for (const subdivisionCode in streamsGroupedBySubdivisionCode) {
|
||||||
const subdivisionStreams = streamsGroupedBySubdivisionCode[subdivisionCode]
|
const subdivisionStreams = streamsGroupedBySubdivisionCode[subdivisionCode]
|
||||||
|
|
||||||
const playlist = new Playlist(subdivisionStreams, { public: true })
|
const playlist = new Playlist(subdivisionStreams, { public: true, raw: false })
|
||||||
const filepath = `subdivisions/${subdivisionCode.toLowerCase()}.m3u`
|
const filepath = `subdivisions/${subdivisionCode.toLowerCase()}.m3u`
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logFile.append(
|
this.logFile.append(
|
||||||
|
|||||||
@@ -2,17 +2,18 @@ import { Collection } from '@freearhey/core'
|
|||||||
import * as sdk from '@iptv-org/sdk'
|
import * as sdk from '@iptv-org/sdk'
|
||||||
import { Stream } from '../models'
|
import { Stream } from '../models'
|
||||||
|
|
||||||
type PlaylistOptions = {
|
export type PlaylistOptions = {
|
||||||
public?: boolean
|
public?: boolean
|
||||||
|
raw?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Playlist {
|
export class Playlist {
|
||||||
streams: Collection<Stream>
|
streams: Collection<Stream>
|
||||||
public: boolean
|
options?: PlaylistOptions
|
||||||
|
|
||||||
constructor(streams: Collection<Stream>, options?: PlaylistOptions) {
|
constructor(streams: Collection<Stream>, options?: PlaylistOptions) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.public = options?.public === true
|
this.options = options
|
||||||
}
|
}
|
||||||
|
|
||||||
getGuides(): Collection<sdk.Models.Guide> {
|
getGuides(): Collection<sdk.Models.Guide> {
|
||||||
@@ -59,7 +60,7 @@ export class Playlist {
|
|||||||
output += '\r\n'
|
output += '\r\n'
|
||||||
|
|
||||||
this.streams.forEach((stream: Stream) => {
|
this.streams.forEach((stream: Stream) => {
|
||||||
output += stream.toString({ public: this.public }) + '\r\n'
|
output += stream.toString(this.options) + '\r\n'
|
||||||
})
|
})
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import * as sdk from '@iptv-org/sdk'
|
|||||||
import { DataSet } from '../core'
|
import { DataSet } from '../core'
|
||||||
import { data } from '../api'
|
import { data } from '../api'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
import { PlaylistOptions } from './playlist'
|
||||||
|
|
||||||
export class Stream extends sdk.Models.Stream {
|
export class Stream extends sdk.Models.Stream {
|
||||||
filepath?: string
|
filepath?: string
|
||||||
@@ -16,6 +17,12 @@ export class Stream extends sdk.Models.Stream {
|
|||||||
guides = new Collection<sdk.Models.Guide>()
|
guides = new Collection<sdk.Models.Guide>()
|
||||||
isNot247?: boolean
|
isNot247?: boolean
|
||||||
isGeoBlocked?: boolean
|
isGeoBlocked?: boolean
|
||||||
|
hasMainFeed?: boolean = false
|
||||||
|
hasUniqueName?: boolean = false
|
||||||
|
channelName?: string
|
||||||
|
feedName?: string
|
||||||
|
countryName?: string
|
||||||
|
channelUniqueName?: string
|
||||||
|
|
||||||
setGuides(guides?: sdk.Models.Guide[]) {
|
setGuides(guides?: sdk.Models.Guide[]) {
|
||||||
this.guides = new Collection(guides)
|
this.guides = new Collection(guides)
|
||||||
@@ -113,6 +120,17 @@ export class Stream extends sdk.Models.Stream {
|
|||||||
stream.isNot247 = labels.includes('Not 24/7')
|
stream.isNot247 = labels.includes('Not 24/7')
|
||||||
stream.isGeoBlocked = labels.includes('Geo-blocked')
|
stream.isGeoBlocked = labels.includes('Geo-blocked')
|
||||||
|
|
||||||
|
const feed = stream.getFeed()
|
||||||
|
stream.hasMainFeed = feed?.is_main
|
||||||
|
stream.feedName = feed?.name
|
||||||
|
|
||||||
|
const channel = stream.getChannel()
|
||||||
|
stream.channelName = channel?.name
|
||||||
|
|
||||||
|
const country = channel?.getCountry()
|
||||||
|
stream.countryName = country?.name
|
||||||
|
stream.channelUniqueName = `${channel?.name} (${country?.name})`
|
||||||
|
|
||||||
return stream
|
return stream
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,6 +334,14 @@ export class Stream extends sdk.Models.Stream {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasChannel(): boolean {
|
||||||
|
return !!this.channel && !!this.getChannel()
|
||||||
|
}
|
||||||
|
|
||||||
|
hasFeed(): boolean {
|
||||||
|
return !!this.feed && !!this.getFeed()
|
||||||
|
}
|
||||||
|
|
||||||
hasCategory(category: sdk.Models.Category): boolean {
|
hasCategory(category: sdk.Models.Category): boolean {
|
||||||
const channel = this.getChannel()
|
const channel = this.getChannel()
|
||||||
|
|
||||||
@@ -418,8 +444,25 @@ export class Stream extends sdk.Models.Stream {
|
|||||||
return logo ? logo.url : ''
|
return logo ? logo.url : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
getFullTitle(): string {
|
getTitle(options: PlaylistOptions): string {
|
||||||
let title = `${this.title}`
|
const raw = options.raw || false
|
||||||
|
let title = ''
|
||||||
|
if (raw) {
|
||||||
|
title += this.title
|
||||||
|
} else {
|
||||||
|
if (!this.hasUniqueName) {
|
||||||
|
title += this.channelUniqueName
|
||||||
|
} else {
|
||||||
|
title += this.channelName
|
||||||
|
}
|
||||||
|
if (this.feedName && !this.hasMainFeed) title += ' ' + this.feedName
|
||||||
|
}
|
||||||
|
|
||||||
|
return title
|
||||||
|
}
|
||||||
|
|
||||||
|
getFullTitle(options: PlaylistOptions): string {
|
||||||
|
let title = this.getTitle(options)
|
||||||
|
|
||||||
if (this.quality) {
|
if (this.quality) {
|
||||||
title += ` (${this.quality})`
|
title += ` (${this.quality})`
|
||||||
@@ -447,8 +490,8 @@ export class Stream extends sdk.Models.Stream {
|
|||||||
return labels
|
return labels
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(options: { public?: boolean } = {}) {
|
toString(options: PlaylistOptions = {}) {
|
||||||
options = { ...{ public: false }, ...options }
|
options = { ...{ public: false, raw: false }, ...options }
|
||||||
|
|
||||||
let output = `#EXTINF:-1 tvg-id="${this.getTvgId()}"`
|
let output = `#EXTINF:-1 tvg-id="${this.getTvgId()}"`
|
||||||
|
|
||||||
@@ -466,7 +509,7 @@ export class Stream extends sdk.Models.Stream {
|
|||||||
output += ` group-title="${this.groupTitle}"`
|
output += ` group-title="${this.groupTitle}"`
|
||||||
}
|
}
|
||||||
|
|
||||||
output += `,${this.getFullTitle()}`
|
output += `,${this.getFullTitle(options)}`
|
||||||
|
|
||||||
if (this.referrer) {
|
if (this.referrer) {
|
||||||
output += `\r\n#EXTVLCOPT:http-referrer=${this.referrer}`
|
output += `\r\n#EXTVLCOPT:http-referrer=${this.referrer}`
|
||||||
|
|||||||
Reference in new issue
Block a user