mirror of
https://github.com/iptv-org/iptv.git
synced 2025-05-12 01:50:04 -04:00
Fix errors found by linter
This commit is contained in:
parent
efcae8e3b5
commit
21efb82055
24 changed files with 632 additions and 629 deletions
|
@ -19,19 +19,19 @@ export class HTMLTable {
|
||||||
let output = '<table>\n'
|
let output = '<table>\n'
|
||||||
|
|
||||||
output += ' <thead>\n <tr>'
|
output += ' <thead>\n <tr>'
|
||||||
for (let column of this.columns) {
|
for (const column of this.columns) {
|
||||||
output += `<th align="left">${column.name}</th>`
|
output += `<th align="left">${column.name}</th>`
|
||||||
}
|
}
|
||||||
output += '</tr>\n </thead>\n'
|
output += '</tr>\n </thead>\n'
|
||||||
|
|
||||||
output += ' <tbody>\n'
|
output += ' <tbody>\n'
|
||||||
for (let item of this.data) {
|
for (const item of this.data) {
|
||||||
output += ' <tr>'
|
output += ' <tr>'
|
||||||
let i = 0
|
let i = 0
|
||||||
for (let prop in item) {
|
for (const prop in item) {
|
||||||
const column = this.columns[i]
|
const column = this.columns[i]
|
||||||
let nowrap = column.nowrap ? ` nowrap` : ''
|
const nowrap = column.nowrap ? ' nowrap' : ''
|
||||||
let align = column.align ? ` align="${column.align}"` : ''
|
const align = column.align ? ` align="${column.align}"` : ''
|
||||||
output += `<td${align}${nowrap}>${item[prop]}</td>`
|
output += `<td${align}${nowrap}>${item[prop]}</td>`
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ const octokit = new CustomOctokit()
|
||||||
export class IssueLoader {
|
export class IssueLoader {
|
||||||
async load({ labels }: { labels: string[] | string }) {
|
async load({ labels }: { labels: string[] | string }) {
|
||||||
labels = Array.isArray(labels) ? labels.join(',') : labels
|
labels = Array.isArray(labels) ? labels.join(',') : labels
|
||||||
let issues: any[] = []
|
let issues: object[] = []
|
||||||
if (TESTING) {
|
if (TESTING) {
|
||||||
switch (labels) {
|
switch (labels) {
|
||||||
case 'streams:add':
|
case 'streams:add':
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Dictionary } from '@freearhey/core'
|
import { Dictionary } from '@freearhey/core'
|
||||||
import { Issue } from '../models'
|
import { Issue } from '../models'
|
||||||
import _ from 'lodash'
|
|
||||||
|
|
||||||
const FIELDS = new Dictionary({
|
const FIELDS = new Dictionary({
|
||||||
'Channel ID': 'channel_id',
|
'Channel ID': 'channel_id',
|
||||||
|
@ -21,7 +20,7 @@ const FIELDS = new Dictionary({
|
||||||
})
|
})
|
||||||
|
|
||||||
export class IssueParser {
|
export class IssueParser {
|
||||||
parse(issue: any): Issue {
|
parse(issue: { number: number; body: string; labels: { name: string }[] }): Issue {
|
||||||
const fields = issue.body.split('###')
|
const fields = issue.body.split('###')
|
||||||
|
|
||||||
const data = new Dictionary()
|
const data = new Dictionary()
|
||||||
|
|
|
@ -4,7 +4,7 @@ export type LogItem = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LogParser {
|
export class LogParser {
|
||||||
parse(content: string): any[] {
|
parse(content: string): LogItem[] {
|
||||||
if (!content) return []
|
if (!content) return []
|
||||||
const lines = content.split('\n')
|
const lines = content.split('\n')
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ export class PlaylistParser {
|
||||||
async parse(files: string[]): Promise<Collection> {
|
async parse(files: string[]): Promise<Collection> {
|
||||||
let streams = new Collection()
|
let streams = new Collection()
|
||||||
|
|
||||||
for (let filepath of files) {
|
for (const filepath of files) {
|
||||||
const relativeFilepath = filepath.replace(path.normalize(STREAMS_DIR), '')
|
const relativeFilepath = filepath.replace(path.normalize(STREAMS_DIR), '')
|
||||||
const _streams: Collection = await this.parseFile(relativeFilepath)
|
const _streams: Collection = await this.parseFile(relativeFilepath)
|
||||||
streams = streams.concat(_streams)
|
streams = streams.concat(_streams)
|
||||||
|
|
|
@ -1,55 +1,53 @@
|
||||||
import { Generator } from './generator'
|
import { Generator } from './generator'
|
||||||
import { Collection, Storage, Logger } from '@freearhey/core'
|
import { Collection, Storage, Logger } from '@freearhey/core'
|
||||||
import { Stream, Category, Playlist } from '../models'
|
import { Stream, Category, Playlist } from '../models'
|
||||||
import { PUBLIC_DIR } from '../constants'
|
import { PUBLIC_DIR } from '../constants'
|
||||||
|
|
||||||
type CategoriesGeneratorProps = {
|
type CategoriesGeneratorProps = {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
categories: Collection
|
categories: Collection
|
||||||
logger: Logger
|
logger: Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CategoriesGenerator implements Generator {
|
export class CategoriesGenerator implements Generator {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
categories: Collection
|
categories: Collection
|
||||||
storage: Storage
|
storage: Storage
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
||||||
constructor({ streams, categories, logger }: CategoriesGeneratorProps) {
|
constructor({ streams, categories, logger }: CategoriesGeneratorProps) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.categories = categories
|
this.categories = categories
|
||||||
this.storage = new Storage(PUBLIC_DIR)
|
this.storage = new Storage(PUBLIC_DIR)
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate() {
|
async generate() {
|
||||||
const streams = this.streams.orderBy([(stream: Stream) => stream.getTitle()])
|
const streams = this.streams.orderBy([(stream: Stream) => stream.getTitle()])
|
||||||
|
|
||||||
this.categories.forEach(async (category: Category) => {
|
this.categories.forEach(async (category: Category) => {
|
||||||
let categoryStreams = streams
|
const categoryStreams = streams
|
||||||
.filter((stream: Stream) => stream.hasCategory(category))
|
.filter((stream: Stream) => stream.hasCategory(category))
|
||||||
.map((stream: Stream) => {
|
.map((stream: Stream) => {
|
||||||
const groupTitle = stream.categories
|
const streamCategories = stream.categories
|
||||||
? stream.categories
|
.map((category: Category) => category.name)
|
||||||
.map((category: Category) => category.name)
|
.sort()
|
||||||
.sort()
|
const groupTitle = stream.categories ? streamCategories.join(';') : ''
|
||||||
.join(';')
|
stream.groupTitle = groupTitle
|
||||||
: ''
|
|
||||||
stream.groupTitle = groupTitle
|
return stream
|
||||||
|
})
|
||||||
return stream
|
|
||||||
})
|
const playlist = new Playlist(categoryStreams, { public: true })
|
||||||
|
const filepath = `categories/${category.id}.m3u`
|
||||||
const playlist = new Playlist(categoryStreams, { public: true })
|
await this.storage.save(filepath, playlist.toString())
|
||||||
const filepath = `categories/${category.id}.m3u`
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
await this.storage.save(filepath, playlist.toString())
|
})
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
|
||||||
})
|
const undefinedStreams = streams.filter((stream: Stream) => stream.noCategories())
|
||||||
|
const playlist = new Playlist(undefinedStreams, { public: true })
|
||||||
const undefinedStreams = streams.filter((stream: Stream) => stream.noCategories())
|
const filepath = 'categories/undefined.m3u'
|
||||||
const playlist = new Playlist(undefinedStreams, { public: true })
|
await this.storage.save(filepath, playlist.toString())
|
||||||
const filepath = `categories/undefined.m3u`
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
await this.storage.save(filepath, playlist.toString())
|
}
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,85 +1,85 @@
|
||||||
import { Generator } from './generator'
|
import { Generator } from './generator'
|
||||||
import { Collection, Storage, Logger } from '@freearhey/core'
|
import { Collection, Storage, Logger } from '@freearhey/core'
|
||||||
import { Country, Region, Subdivision, Stream, Playlist } from '../models'
|
import { Country, Region, Subdivision, Stream, Playlist } from '../models'
|
||||||
import { PUBLIC_DIR } from '../constants'
|
import { PUBLIC_DIR } from '../constants'
|
||||||
|
|
||||||
type CountriesGeneratorProps = {
|
type CountriesGeneratorProps = {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
regions: Collection
|
regions: Collection
|
||||||
subdivisions: Collection
|
subdivisions: Collection
|
||||||
countries: Collection
|
countries: Collection
|
||||||
logger: Logger
|
logger: Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CountriesGenerator implements Generator {
|
export class CountriesGenerator implements Generator {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
countries: Collection
|
countries: Collection
|
||||||
regions: Collection
|
regions: Collection
|
||||||
subdivisions: Collection
|
subdivisions: Collection
|
||||||
storage: Storage
|
storage: Storage
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
||||||
constructor({ streams, countries, regions, subdivisions, logger }: CountriesGeneratorProps) {
|
constructor({ streams, countries, regions, subdivisions, logger }: CountriesGeneratorProps) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.countries = countries
|
this.countries = countries
|
||||||
this.regions = regions
|
this.regions = regions
|
||||||
this.subdivisions = subdivisions
|
this.subdivisions = subdivisions
|
||||||
this.storage = new Storage(PUBLIC_DIR)
|
this.storage = new Storage(PUBLIC_DIR)
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
let streams = this.streams
|
const streams = this.streams
|
||||||
.orderBy([stream => stream.getTitle()])
|
.orderBy([stream => stream.getTitle()])
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
.filter((stream: Stream) => stream.isSFW())
|
||||||
let regions = this.regions.filter((region: Region) => region.code !== 'INT')
|
const regions = this.regions.filter((region: Region) => region.code !== 'INT')
|
||||||
|
|
||||||
this.countries.forEach(async (country: Country) => {
|
this.countries.forEach(async (country: Country) => {
|
||||||
const countrySubdivisions = this.subdivisions.filter(
|
const countrySubdivisions = this.subdivisions.filter(
|
||||||
(subdivision: Subdivision) => subdivision.country === country.code
|
(subdivision: Subdivision) => subdivision.country === country.code
|
||||||
)
|
)
|
||||||
|
|
||||||
const countrySubdivisionsCodes = countrySubdivisions.map(
|
const countrySubdivisionsCodes = countrySubdivisions.map(
|
||||||
(subdivision: Subdivision) => `s/${subdivision.code}`
|
(subdivision: Subdivision) => `s/${subdivision.code}`
|
||||||
)
|
)
|
||||||
|
|
||||||
const countryAreaCodes = regions
|
const countryAreaCodes = regions
|
||||||
.filter((region: Region) => region.countries.includes(country.code))
|
.filter((region: Region) => region.countries.includes(country.code))
|
||||||
.map((region: Region) => `r/${region.code}`)
|
.map((region: Region) => `r/${region.code}`)
|
||||||
.concat(countrySubdivisionsCodes)
|
.concat(countrySubdivisionsCodes)
|
||||||
.add(`c/${country.code}`)
|
.add(`c/${country.code}`)
|
||||||
|
|
||||||
const countryStreams = streams.filter(stream =>
|
const countryStreams = streams.filter(stream =>
|
||||||
stream.broadcastArea.intersects(countryAreaCodes)
|
stream.broadcastArea.intersects(countryAreaCodes)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (countryStreams.isEmpty()) return
|
if (countryStreams.isEmpty()) return
|
||||||
|
|
||||||
const playlist = new Playlist(countryStreams, { public: true })
|
const playlist = new Playlist(countryStreams, { public: true })
|
||||||
const filepath = `countries/${country.code.toLowerCase()}.m3u`
|
const filepath = `countries/${country.code.toLowerCase()}.m3u`
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
|
|
||||||
countrySubdivisions.forEach(async (subdivision: Subdivision) => {
|
countrySubdivisions.forEach(async (subdivision: Subdivision) => {
|
||||||
const subdivisionStreams = streams.filter(stream =>
|
const subdivisionStreams = streams.filter(stream =>
|
||||||
stream.broadcastArea.includes(`s/${subdivision.code}`)
|
stream.broadcastArea.includes(`s/${subdivision.code}`)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (subdivisionStreams.isEmpty()) return
|
if (subdivisionStreams.isEmpty()) return
|
||||||
|
|
||||||
const playlist = new Playlist(subdivisionStreams, { public: true })
|
const playlist = new Playlist(subdivisionStreams, { public: true })
|
||||||
const filepath = `subdivisions/${subdivision.code.toLowerCase()}.m3u`
|
const filepath = `subdivisions/${subdivision.code.toLowerCase()}.m3u`
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const internationalStreams = streams.filter(stream => stream.isInternational())
|
const internationalStreams = streams.filter(stream => stream.isInternational())
|
||||||
if (internationalStreams.notEmpty()) {
|
if (internationalStreams.notEmpty()) {
|
||||||
const playlist = new Playlist(internationalStreams, { public: true })
|
const playlist = new Playlist(internationalStreams, { public: true })
|
||||||
const filepath = `countries/int.m3u`
|
const filepath = 'countries/int.m3u'
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
export * from './categoriesGenerator'
|
export * from './categoriesGenerator'
|
||||||
export * from './countriesGenerator'
|
export * from './countriesGenerator'
|
||||||
export * from './languagesGenerator'
|
export * from './languagesGenerator'
|
||||||
export * from './regionsGenerator'
|
export * from './regionsGenerator'
|
||||||
export * from './indexGenerator'
|
export * from './indexGenerator'
|
||||||
export * from './indexNsfwGenerator'
|
export * from './indexNsfwGenerator'
|
||||||
export * from './indexCategoryGenerator'
|
export * from './indexCategoryGenerator'
|
||||||
export * from './indexCountryGenerator'
|
export * from './indexCountryGenerator'
|
||||||
export * from './indexLanguageGenerator'
|
export * from './indexLanguageGenerator'
|
||||||
export * from './indexRegionGenerator'
|
export * from './indexRegionGenerator'
|
||||||
|
|
|
@ -1,53 +1,53 @@
|
||||||
import { Generator } from './generator'
|
import { Generator } from './generator'
|
||||||
import { Collection, Storage, Logger } from '@freearhey/core'
|
import { Collection, Storage, Logger } from '@freearhey/core'
|
||||||
import { Stream, Playlist, Category } from '../models'
|
import { Stream, Playlist, Category } from '../models'
|
||||||
import { PUBLIC_DIR } from '../constants'
|
import { PUBLIC_DIR } from '../constants'
|
||||||
|
|
||||||
type IndexCategoryGeneratorProps = {
|
type IndexCategoryGeneratorProps = {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
logger: Logger
|
logger: Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IndexCategoryGenerator implements Generator {
|
export class IndexCategoryGenerator implements Generator {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
storage: Storage
|
storage: Storage
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
||||||
constructor({ streams, logger }: IndexCategoryGeneratorProps) {
|
constructor({ streams, logger }: IndexCategoryGeneratorProps) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.storage = new Storage(PUBLIC_DIR)
|
this.storage = new Storage(PUBLIC_DIR)
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
const streams = this.streams
|
const streams = this.streams
|
||||||
.orderBy(stream => stream.getTitle())
|
.orderBy(stream => stream.getTitle())
|
||||||
.filter(stream => stream.isSFW())
|
.filter(stream => stream.isSFW())
|
||||||
|
|
||||||
let groupedStreams = new Collection()
|
let groupedStreams = new Collection()
|
||||||
streams.forEach((stream: Stream) => {
|
streams.forEach((stream: Stream) => {
|
||||||
if (stream.noCategories()) {
|
if (stream.noCategories()) {
|
||||||
const streamClone = stream.clone()
|
const streamClone = stream.clone()
|
||||||
streamClone.groupTitle = 'Undefined'
|
streamClone.groupTitle = 'Undefined'
|
||||||
groupedStreams.add(streamClone)
|
groupedStreams.add(streamClone)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.categories.forEach((category: Category) => {
|
stream.categories.forEach((category: Category) => {
|
||||||
const streamClone = stream.clone()
|
const streamClone = stream.clone()
|
||||||
streamClone.groupTitle = category.name
|
streamClone.groupTitle = category.name
|
||||||
groupedStreams.push(streamClone)
|
groupedStreams.push(streamClone)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
groupedStreams = groupedStreams.orderBy(stream => {
|
groupedStreams = groupedStreams.orderBy(stream => {
|
||||||
if (stream.groupTitle === 'Undefined') return 'ZZ'
|
if (stream.groupTitle === 'Undefined') return 'ZZ'
|
||||||
return stream.groupTitle
|
return stream.groupTitle
|
||||||
})
|
})
|
||||||
|
|
||||||
const playlist = new Playlist(groupedStreams, { public: true })
|
const playlist = new Playlist(groupedStreams, { public: true })
|
||||||
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.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,104 +1,104 @@
|
||||||
import { Generator } from './generator'
|
import { Generator } from './generator'
|
||||||
import { Collection, Storage, Logger } from '@freearhey/core'
|
import { Collection, Storage, Logger } from '@freearhey/core'
|
||||||
import { Stream, Playlist, Country, Subdivision, Region } from '../models'
|
import { Stream, Playlist, Country, Subdivision, Region } from '../models'
|
||||||
import { PUBLIC_DIR } from '../constants'
|
import { PUBLIC_DIR } from '../constants'
|
||||||
|
|
||||||
type IndexCountryGeneratorProps = {
|
type IndexCountryGeneratorProps = {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
regions: Collection
|
regions: Collection
|
||||||
countries: Collection
|
countries: Collection
|
||||||
subdivisions: Collection
|
subdivisions: Collection
|
||||||
logger: Logger
|
logger: Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IndexCountryGenerator implements Generator {
|
export class IndexCountryGenerator implements Generator {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
countries: Collection
|
countries: Collection
|
||||||
regions: Collection
|
regions: Collection
|
||||||
subdivisions: Collection
|
subdivisions: Collection
|
||||||
storage: Storage
|
storage: Storage
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
||||||
constructor({ streams, regions, countries, subdivisions, logger }: IndexCountryGeneratorProps) {
|
constructor({ streams, regions, countries, subdivisions, logger }: IndexCountryGeneratorProps) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.countries = countries
|
this.countries = countries
|
||||||
this.regions = regions
|
this.regions = regions
|
||||||
this.subdivisions = subdivisions
|
this.subdivisions = subdivisions
|
||||||
this.storage = new Storage(PUBLIC_DIR)
|
this.storage = new Storage(PUBLIC_DIR)
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
let groupedStreams = new Collection()
|
let groupedStreams = new Collection()
|
||||||
|
|
||||||
this.streams
|
this.streams
|
||||||
.orderBy(stream => stream.getTitle())
|
.orderBy(stream => stream.getTitle())
|
||||||
.filter(stream => stream.isSFW())
|
.filter(stream => stream.isSFW())
|
||||||
.forEach(stream => {
|
.forEach(stream => {
|
||||||
if (stream.noBroadcastArea()) {
|
if (stream.noBroadcastArea()) {
|
||||||
const streamClone = stream.clone()
|
const streamClone = stream.clone()
|
||||||
streamClone.groupTitle = 'Undefined'
|
streamClone.groupTitle = 'Undefined'
|
||||||
groupedStreams.add(streamClone)
|
groupedStreams.add(streamClone)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream.isInternational()) {
|
if (stream.isInternational()) {
|
||||||
const streamClone = stream.clone()
|
const streamClone = stream.clone()
|
||||||
streamClone.groupTitle = 'International'
|
streamClone.groupTitle = 'International'
|
||||||
groupedStreams.add(streamClone)
|
groupedStreams.add(streamClone)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getStreamBroadcastCountries(stream).forEach((country: Country) => {
|
this.getStreamBroadcastCountries(stream).forEach((country: Country) => {
|
||||||
const streamClone = stream.clone()
|
const streamClone = stream.clone()
|
||||||
streamClone.groupTitle = country.name
|
streamClone.groupTitle = country.name
|
||||||
groupedStreams.add(streamClone)
|
groupedStreams.add(streamClone)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
groupedStreams = groupedStreams.orderBy((stream: Stream) => {
|
groupedStreams = groupedStreams.orderBy((stream: Stream) => {
|
||||||
if (stream.groupTitle === 'International') return 'ZZ'
|
if (stream.groupTitle === 'International') return 'ZZ'
|
||||||
if (stream.groupTitle === 'Undefined') return 'ZZZ'
|
if (stream.groupTitle === 'Undefined') return 'ZZZ'
|
||||||
|
|
||||||
return stream.groupTitle
|
return stream.groupTitle
|
||||||
})
|
})
|
||||||
|
|
||||||
const playlist = new Playlist(groupedStreams, { public: true })
|
const playlist = new Playlist(groupedStreams, { public: true })
|
||||||
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.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
}
|
}
|
||||||
|
|
||||||
getStreamBroadcastCountries(stream: Stream) {
|
getStreamBroadcastCountries(stream: Stream) {
|
||||||
const groupedRegions = this.regions.keyBy((region: Region) => region.code)
|
const groupedRegions = this.regions.keyBy((region: Region) => region.code)
|
||||||
const groupedCountries = this.countries.keyBy((country: Country) => country.code)
|
const groupedCountries = this.countries.keyBy((country: Country) => country.code)
|
||||||
const groupedSubdivisions = this.subdivisions.keyBy(
|
const groupedSubdivisions = this.subdivisions.keyBy(
|
||||||
(subdivision: Subdivision) => subdivision.code
|
(subdivision: Subdivision) => subdivision.code
|
||||||
)
|
)
|
||||||
|
|
||||||
let broadcastCountries = new Collection()
|
let broadcastCountries = new Collection()
|
||||||
|
|
||||||
stream.broadcastArea.forEach(broadcastAreaCode => {
|
stream.broadcastArea.forEach(broadcastAreaCode => {
|
||||||
const [type, code] = broadcastAreaCode.split('/')
|
const [type, code] = broadcastAreaCode.split('/')
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'c':
|
case 'c':
|
||||||
broadcastCountries.add(code)
|
broadcastCountries.add(code)
|
||||||
break
|
break
|
||||||
case 'r':
|
case 'r':
|
||||||
if (code !== 'INT' && groupedRegions.has(code)) {
|
if (code !== 'INT' && groupedRegions.has(code)) {
|
||||||
broadcastCountries = broadcastCountries.concat(groupedRegions.get(code).countries)
|
broadcastCountries = broadcastCountries.concat(groupedRegions.get(code).countries)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 's':
|
case 's':
|
||||||
if (groupedSubdivisions.has(code)) {
|
if (groupedSubdivisions.has(code)) {
|
||||||
broadcastCountries.add(groupedSubdivisions.get(code).country)
|
broadcastCountries.add(groupedSubdivisions.get(code).country)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return broadcastCountries
|
return broadcastCountries
|
||||||
.uniq()
|
.uniq()
|
||||||
.map(code => groupedCountries.get(code))
|
.map(code => groupedCountries.get(code))
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
import { Collection, Logger, Storage } from '@freearhey/core'
|
import { Collection, Logger, Storage } from '@freearhey/core'
|
||||||
import { Stream, Playlist } from '../models'
|
import { Stream, Playlist } from '../models'
|
||||||
import { Generator } from './generator'
|
import { Generator } from './generator'
|
||||||
import { PUBLIC_DIR } from '../constants'
|
import { PUBLIC_DIR } from '../constants'
|
||||||
|
|
||||||
type IndexGeneratorProps = {
|
type IndexGeneratorProps = {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
logger: Logger
|
logger: Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IndexGenerator implements Generator {
|
export class IndexGenerator implements Generator {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
storage: Storage
|
storage: Storage
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
||||||
constructor({ streams, logger }: IndexGeneratorProps) {
|
constructor({ streams, logger }: IndexGeneratorProps) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.storage = new Storage(PUBLIC_DIR)
|
this.storage = new Storage(PUBLIC_DIR)
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
const sfwStreams = this.streams
|
const sfwStreams = this.streams
|
||||||
.orderBy(stream => stream.getTitle())
|
.orderBy(stream => stream.getTitle())
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
.filter((stream: Stream) => stream.isSFW())
|
||||||
|
|
||||||
const playlist = new Playlist(sfwStreams, { public: true })
|
const playlist = new Playlist(sfwStreams, { public: true })
|
||||||
const filepath = 'index.m3u'
|
const filepath = 'index.m3u'
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +1,52 @@
|
||||||
import { Generator } from './generator'
|
import { Generator } from './generator'
|
||||||
import { Collection, Storage, Logger } from '@freearhey/core'
|
import { Collection, Storage, Logger } from '@freearhey/core'
|
||||||
import { Stream, Playlist, Language } from '../models'
|
import { Stream, Playlist, Language } from '../models'
|
||||||
import { PUBLIC_DIR } from '../constants'
|
import { PUBLIC_DIR } from '../constants'
|
||||||
|
|
||||||
type IndexLanguageGeneratorProps = {
|
type IndexLanguageGeneratorProps = {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
logger: Logger
|
logger: Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IndexLanguageGenerator implements Generator {
|
export class IndexLanguageGenerator implements Generator {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
storage: Storage
|
storage: Storage
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
||||||
constructor({ streams, logger }: IndexLanguageGeneratorProps) {
|
constructor({ streams, logger }: IndexLanguageGeneratorProps) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.storage = new Storage(PUBLIC_DIR)
|
this.storage = new Storage(PUBLIC_DIR)
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
let groupedStreams = new Collection()
|
let groupedStreams = new Collection()
|
||||||
this.streams
|
this.streams
|
||||||
.orderBy(stream => stream.getTitle())
|
.orderBy(stream => stream.getTitle())
|
||||||
.filter(stream => stream.isSFW())
|
.filter(stream => stream.isSFW())
|
||||||
.forEach(stream => {
|
.forEach(stream => {
|
||||||
if (stream.noLanguages()) {
|
if (stream.noLanguages()) {
|
||||||
const streamClone = stream.clone()
|
const streamClone = stream.clone()
|
||||||
streamClone.groupTitle = 'Undefined'
|
streamClone.groupTitle = 'Undefined'
|
||||||
groupedStreams.add(streamClone)
|
groupedStreams.add(streamClone)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.languages.forEach((language: Language) => {
|
stream.languages.forEach((language: Language) => {
|
||||||
const streamClone = stream.clone()
|
const streamClone = stream.clone()
|
||||||
streamClone.groupTitle = language.name
|
streamClone.groupTitle = language.name
|
||||||
groupedStreams.add(streamClone)
|
groupedStreams.add(streamClone)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
groupedStreams = groupedStreams.orderBy((stream: Stream) => {
|
groupedStreams = groupedStreams.orderBy((stream: Stream) => {
|
||||||
if (stream.groupTitle === 'Undefined') return 'ZZ'
|
if (stream.groupTitle === 'Undefined') return 'ZZ'
|
||||||
return stream.groupTitle
|
return stream.groupTitle
|
||||||
})
|
})
|
||||||
|
|
||||||
const playlist = new Playlist(groupedStreams, { public: true })
|
const playlist = new Playlist(groupedStreams, { public: true })
|
||||||
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.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
import { Collection, Logger, Storage } from '@freearhey/core'
|
import { Collection, Logger, Storage } from '@freearhey/core'
|
||||||
import { Stream, Playlist } from '../models'
|
import { Stream, Playlist } from '../models'
|
||||||
import { Generator } from './generator'
|
import { Generator } from './generator'
|
||||||
import { PUBLIC_DIR } from '../constants'
|
import { PUBLIC_DIR } from '../constants'
|
||||||
|
|
||||||
type IndexNsfwGeneratorProps = {
|
type IndexNsfwGeneratorProps = {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
logger: Logger
|
logger: Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IndexNsfwGenerator implements Generator {
|
export class IndexNsfwGenerator implements Generator {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
storage: Storage
|
storage: Storage
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
||||||
constructor({ streams, logger }: IndexNsfwGeneratorProps) {
|
constructor({ streams, logger }: IndexNsfwGeneratorProps) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.storage = new Storage(PUBLIC_DIR)
|
this.storage = new Storage(PUBLIC_DIR)
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
const allStreams = this.streams.orderBy((stream: Stream) => stream.getTitle())
|
const allStreams = this.streams.orderBy((stream: Stream) => stream.getTitle())
|
||||||
|
|
||||||
const playlist = new Playlist(allStreams, { public: true })
|
const playlist = new Playlist(allStreams, { public: true })
|
||||||
const filepath = 'index.nsfw.m3u'
|
const filepath = 'index.nsfw.m3u'
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,83 +1,83 @@
|
||||||
import { Generator } from './generator'
|
import { Generator } from './generator'
|
||||||
import { Collection, Storage, Logger } from '@freearhey/core'
|
import { Collection, Storage, Logger } from '@freearhey/core'
|
||||||
import { Stream, Playlist, Region } from '../models'
|
import { Stream, Playlist, Region } from '../models'
|
||||||
import { PUBLIC_DIR } from '../constants'
|
import { PUBLIC_DIR } from '../constants'
|
||||||
|
|
||||||
type IndexRegionGeneratorProps = {
|
type IndexRegionGeneratorProps = {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
regions: Collection
|
regions: Collection
|
||||||
logger: Logger
|
logger: Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IndexRegionGenerator implements Generator {
|
export class IndexRegionGenerator implements Generator {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
regions: Collection
|
regions: Collection
|
||||||
storage: Storage
|
storage: Storage
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
||||||
constructor({ streams, regions, logger }: IndexRegionGeneratorProps) {
|
constructor({ streams, regions, logger }: IndexRegionGeneratorProps) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.regions = regions
|
this.regions = regions
|
||||||
this.storage = new Storage(PUBLIC_DIR)
|
this.storage = new Storage(PUBLIC_DIR)
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
let groupedStreams = new Collection()
|
let groupedStreams = new Collection()
|
||||||
this.streams
|
this.streams
|
||||||
.orderBy((stream: Stream) => stream.getTitle())
|
.orderBy((stream: Stream) => stream.getTitle())
|
||||||
.filter((stream: Stream) => stream.isSFW())
|
.filter((stream: Stream) => stream.isSFW())
|
||||||
.forEach((stream: Stream) => {
|
.forEach((stream: Stream) => {
|
||||||
if (stream.noBroadcastArea()) {
|
if (stream.noBroadcastArea()) {
|
||||||
const streamClone = stream.clone()
|
const streamClone = stream.clone()
|
||||||
streamClone.groupTitle = 'Undefined'
|
streamClone.groupTitle = 'Undefined'
|
||||||
groupedStreams.push(streamClone)
|
groupedStreams.push(streamClone)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getStreamRegions(stream).forEach((region: Region) => {
|
this.getStreamRegions(stream).forEach((region: Region) => {
|
||||||
const streamClone = stream.clone()
|
const streamClone = stream.clone()
|
||||||
streamClone.groupTitle = region.name
|
streamClone.groupTitle = region.name
|
||||||
groupedStreams.push(streamClone)
|
groupedStreams.push(streamClone)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
groupedStreams = groupedStreams.orderBy((stream: Stream) => {
|
groupedStreams = groupedStreams.orderBy((stream: Stream) => {
|
||||||
if (stream.groupTitle === 'Undefined') return 'ZZ'
|
if (stream.groupTitle === 'Undefined') return 'ZZ'
|
||||||
return stream.groupTitle
|
return stream.groupTitle
|
||||||
})
|
})
|
||||||
|
|
||||||
const playlist = new Playlist(groupedStreams, { public: true })
|
const playlist = new Playlist(groupedStreams, { public: true })
|
||||||
const filepath = 'index.region.m3u'
|
const filepath = 'index.region.m3u'
|
||||||
await this.storage.save(filepath, playlist.toString())
|
await this.storage.save(filepath, playlist.toString())
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
}
|
}
|
||||||
|
|
||||||
getStreamRegions(stream: Stream) {
|
getStreamRegions(stream: Stream) {
|
||||||
let streamRegions = new Collection()
|
let streamRegions = new Collection()
|
||||||
stream.broadcastArea.forEach(broadcastAreaCode => {
|
stream.broadcastArea.forEach(broadcastAreaCode => {
|
||||||
const [type, code] = broadcastAreaCode.split('/')
|
const [type, code] = broadcastAreaCode.split('/')
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'r':
|
case 'r':
|
||||||
const groupedRegions = this.regions.keyBy((region: Region) => region.code)
|
const groupedRegions = this.regions.keyBy((region: Region) => region.code)
|
||||||
streamRegions.add(groupedRegions.get(code))
|
streamRegions.add(groupedRegions.get(code))
|
||||||
break
|
break
|
||||||
case 's':
|
case 's':
|
||||||
const [countryCode] = code.split('-')
|
const [countryCode] = code.split('-')
|
||||||
const subdivisionRegions = this.regions.filter((region: Region) =>
|
const subdivisionRegions = this.regions.filter((region: Region) =>
|
||||||
region.countries.includes(countryCode)
|
region.countries.includes(countryCode)
|
||||||
)
|
)
|
||||||
streamRegions = streamRegions.concat(subdivisionRegions)
|
streamRegions = streamRegions.concat(subdivisionRegions)
|
||||||
break
|
break
|
||||||
case 'c':
|
case 'c':
|
||||||
const countryRegions = this.regions.filter((region: Region) =>
|
const countryRegions = this.regions.filter((region: Region) =>
|
||||||
region.countries.includes(code)
|
region.countries.includes(code)
|
||||||
)
|
)
|
||||||
streamRegions = streamRegions.concat(countryRegions)
|
streamRegions = streamRegions.concat(countryRegions)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return streamRegions
|
return streamRegions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +1,52 @@
|
||||||
import { Generator } from './generator'
|
import { Generator } from './generator'
|
||||||
import { Collection, Storage, Logger } from '@freearhey/core'
|
import { Collection, Storage, Logger } from '@freearhey/core'
|
||||||
import { Playlist, Language, Stream } from '../models'
|
import { Playlist, Language, Stream } from '../models'
|
||||||
import { PUBLIC_DIR } from '../constants'
|
import { PUBLIC_DIR } from '../constants'
|
||||||
|
|
||||||
type LanguagesGeneratorProps = { streams: Collection; logger: Logger }
|
type LanguagesGeneratorProps = { streams: Collection; logger: Logger }
|
||||||
|
|
||||||
export class LanguagesGenerator implements Generator {
|
export class LanguagesGenerator implements Generator {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
storage: Storage
|
storage: Storage
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
||||||
constructor({ streams, logger }: LanguagesGeneratorProps) {
|
constructor({ streams, logger }: LanguagesGeneratorProps) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.storage = new Storage(PUBLIC_DIR)
|
this.storage = new Storage(PUBLIC_DIR)
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
let streams = this.streams.orderBy(stream => stream.getTitle()).filter(stream => stream.isSFW())
|
const streams = this.streams
|
||||||
|
.orderBy(stream => stream.getTitle())
|
||||||
let languages = new Collection()
|
.filter(stream => stream.isSFW())
|
||||||
streams.forEach((stream: Stream) => {
|
|
||||||
languages = languages.concat(stream.languages)
|
let languages = new Collection()
|
||||||
})
|
streams.forEach((stream: Stream) => {
|
||||||
|
languages = languages.concat(stream.languages)
|
||||||
languages
|
})
|
||||||
.uniqBy((language: Language) => language.code)
|
|
||||||
.orderBy((language: Language) => language.name)
|
languages
|
||||||
.forEach(async (language: Language) => {
|
.uniqBy((language: Language) => language.code)
|
||||||
const languageStreams = streams.filter(stream => stream.hasLanguage(language))
|
.orderBy((language: Language) => language.name)
|
||||||
|
.forEach(async (language: Language) => {
|
||||||
if (languageStreams.isEmpty()) return
|
const languageStreams = streams.filter(stream => stream.hasLanguage(language))
|
||||||
|
|
||||||
const playlist = new Playlist(languageStreams, { public: true })
|
if (languageStreams.isEmpty()) return
|
||||||
const filepath = `languages/${language.code}.m3u`
|
|
||||||
await this.storage.save(filepath, playlist.toString())
|
const playlist = new Playlist(languageStreams, { public: true })
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
const filepath = `languages/${language.code}.m3u`
|
||||||
})
|
await this.storage.save(filepath, playlist.toString())
|
||||||
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
const undefinedStreams = streams.filter(stream => stream.noLanguages())
|
})
|
||||||
|
|
||||||
if (undefinedStreams.isEmpty()) return
|
const undefinedStreams = streams.filter(stream => stream.noLanguages())
|
||||||
|
|
||||||
const playlist = new Playlist(undefinedStreams, { public: true })
|
if (undefinedStreams.isEmpty()) return
|
||||||
const filepath = 'languages/undefined.m3u'
|
|
||||||
await this.storage.save(filepath, playlist.toString())
|
const playlist = new Playlist(undefinedStreams, { public: true })
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
const filepath = 'languages/undefined.m3u'
|
||||||
}
|
await this.storage.save(filepath, playlist.toString())
|
||||||
}
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,51 +1,53 @@
|
||||||
import { Generator } from './generator'
|
import { Generator } from './generator'
|
||||||
import { Collection, Storage, Logger } from '@freearhey/core'
|
import { Collection, Storage, Logger } from '@freearhey/core'
|
||||||
import { Playlist, Subdivision, Region } from '../models'
|
import { Playlist, Subdivision, Region } from '../models'
|
||||||
import { PUBLIC_DIR } from '../constants'
|
import { PUBLIC_DIR } from '../constants'
|
||||||
|
|
||||||
type RegionsGeneratorProps = {
|
type RegionsGeneratorProps = {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
regions: Collection
|
regions: Collection
|
||||||
subdivisions: Collection
|
subdivisions: Collection
|
||||||
logger: Logger
|
logger: Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RegionsGenerator implements Generator {
|
export class RegionsGenerator implements Generator {
|
||||||
streams: Collection
|
streams: Collection
|
||||||
regions: Collection
|
regions: Collection
|
||||||
subdivisions: Collection
|
subdivisions: Collection
|
||||||
storage: Storage
|
storage: Storage
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
||||||
constructor({ streams, regions, subdivisions, logger }: RegionsGeneratorProps) {
|
constructor({ streams, regions, subdivisions, logger }: RegionsGeneratorProps) {
|
||||||
this.streams = streams
|
this.streams = streams
|
||||||
this.regions = regions
|
this.regions = regions
|
||||||
this.subdivisions = subdivisions
|
this.subdivisions = subdivisions
|
||||||
this.storage = new Storage(PUBLIC_DIR)
|
this.storage = new Storage(PUBLIC_DIR)
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
async generate(): Promise<void> {
|
async generate(): Promise<void> {
|
||||||
let streams = this.streams.orderBy(stream => stream.getTitle()).filter(stream => stream.isSFW())
|
const streams = this.streams
|
||||||
|
.orderBy(stream => stream.getTitle())
|
||||||
this.regions.forEach(async (region: Region) => {
|
.filter(stream => stream.isSFW())
|
||||||
if (region.code === 'INT') return
|
|
||||||
|
this.regions.forEach(async (region: Region) => {
|
||||||
const regionSubdivisionsCodes = this.subdivisions
|
if (region.code === 'INT') return
|
||||||
.filter((subdivision: Subdivision) => region.countries.indexOf(subdivision.country) > -1)
|
|
||||||
.map((subdivision: Subdivision) => `s/${subdivision.code}`)
|
const regionSubdivisionsCodes = this.subdivisions
|
||||||
|
.filter((subdivision: Subdivision) => region.countries.indexOf(subdivision.country) > -1)
|
||||||
const regionCodes = region.countries
|
.map((subdivision: Subdivision) => `s/${subdivision.code}`)
|
||||||
.map((code: string) => `c/${code}`)
|
|
||||||
.concat(regionSubdivisionsCodes)
|
const regionCodes = region.countries
|
||||||
.add(`r/${region.code}`)
|
.map((code: string) => `c/${code}`)
|
||||||
|
.concat(regionSubdivisionsCodes)
|
||||||
const regionStreams = streams.filter(stream => stream.broadcastArea.intersects(regionCodes))
|
.add(`r/${region.code}`)
|
||||||
|
|
||||||
const playlist = new Playlist(regionStreams, { public: true })
|
const regionStreams = streams.filter(stream => stream.broadcastArea.intersects(regionCodes))
|
||||||
const filepath = `regions/${region.code.toLowerCase()}.m3u`
|
|
||||||
await this.storage.save(filepath, playlist.toString())
|
const playlist = new Playlist(regionStreams, { public: true })
|
||||||
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
const filepath = `regions/${region.code.toLowerCase()}.m3u`
|
||||||
})
|
await this.storage.save(filepath, playlist.toString())
|
||||||
}
|
this.logger.info(JSON.stringify({ filepath, count: playlist.streams.count() }))
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@ export class Playlist {
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
let output = `#EXTM3U\n`
|
let output = '#EXTM3U\n'
|
||||||
|
|
||||||
this.streams.forEach((stream: Stream) => {
|
this.streams.forEach((stream: Stream) => {
|
||||||
output += stream.toString(this.options) + `\n`
|
output += stream.toString(this.options) + '\n'
|
||||||
})
|
})
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
|
@ -48,7 +48,7 @@ export class CountryTable implements Table {
|
||||||
} else if (countryCode === 'INT') {
|
} else if (countryCode === 'INT') {
|
||||||
data.add([
|
data.add([
|
||||||
'ZZ',
|
'ZZ',
|
||||||
`🌍 International`,
|
'🌍 International',
|
||||||
logItem.count,
|
logItem.count,
|
||||||
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
|
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
|
||||||
])
|
])
|
||||||
|
|
|
@ -4,14 +4,14 @@ import fs from 'fs-extra'
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fs.emptyDirSync('tests/__data__/output')
|
fs.emptyDirSync('tests/__data__/output')
|
||||||
|
|
||||||
const stdout = execSync(
|
execSync(
|
||||||
'STREAMS_DIR=tests/__data__/input/streams_generate API_DIR=tests/__data__/output/.api npm run api:generate',
|
'STREAMS_DIR=tests/__data__/input/streams_generate API_DIR=tests/__data__/output/.api npm run api:generate',
|
||||||
{ encoding: 'utf8' }
|
{ encoding: 'utf8' }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can create streams.json', () => {
|
it('can create streams.json', () => {
|
||||||
expect(content(`output/.api/streams.json`)).toMatchObject(content(`expected/.api/streams.json`))
|
expect(content('output/.api/streams.json')).toMatchObject(content('expected/.api/streams.json'))
|
||||||
})
|
})
|
||||||
|
|
||||||
function content(filepath: string) {
|
function content(filepath: string) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ beforeEach(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can format playlists', () => {
|
it('can format playlists', () => {
|
||||||
const stdout = execSync('STREAMS_DIR=tests/__data__/output/streams npm run playlist:format', {
|
execSync('STREAMS_DIR=tests/__data__/output/streams npm run playlist:format', {
|
||||||
encoding: 'utf8'
|
encoding: 'utf8'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as glob from 'glob'
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fs.emptyDirSync('tests/__data__/output')
|
fs.emptyDirSync('tests/__data__/output')
|
||||||
|
|
||||||
const stdout = execSync(
|
execSync(
|
||||||
'STREAMS_DIR=tests/__data__/input/streams_generate DATA_DIR=tests/__data__/input/data PUBLIC_DIR=tests/__data__/output/.gh-pages LOGS_DIR=tests/__data__/output/logs npm run playlist:generate',
|
'STREAMS_DIR=tests/__data__/input/streams_generate DATA_DIR=tests/__data__/input/data PUBLIC_DIR=tests/__data__/output/.gh-pages LOGS_DIR=tests/__data__/output/logs npm run playlist:generate',
|
||||||
{ encoding: 'utf8' }
|
{ encoding: 'utf8' }
|
||||||
)
|
)
|
||||||
|
@ -20,8 +20,8 @@ it('can generate playlists and logs', () => {
|
||||||
expect(content(`output/${filepath}`), filepath).toBe(content(`expected/${filepath}`))
|
expect(content(`output/${filepath}`), filepath).toBe(content(`expected/${filepath}`))
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(content(`output/logs/generators.log`).split('\n').sort()).toStrictEqual(
|
expect(content('output/logs/generators.log').split('\n').sort()).toStrictEqual(
|
||||||
content(`expected/logs/generators.log`).split('\n').sort()
|
content('expected/logs/generators.log').split('\n').sort()
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ it('can format playlists', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(stdout).toBe(
|
expect(stdout).toBe(
|
||||||
`OUTPUT=closes #14151, closes #14140, closes #14139, closes #14110, closes #14179, closes #14178\n`
|
'OUTPUT=closes #14151, closes #14140, closes #14139, closes #14110, closes #14179, closes #14178\n'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,13 @@ it('show an error if channel name in the blocklist', () => {
|
||||||
)
|
)
|
||||||
console.log(stdout)
|
console.log(stdout)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
|
// @ts-ignore
|
||||||
expect(error.status).toBe(1)
|
expect(error.status).toBe(1)
|
||||||
expect(
|
expect(
|
||||||
|
// @ts-ignore
|
||||||
error.stdout.includes(
|
error.stdout.includes(
|
||||||
`us_blocked.m3u\n 2 error "Fox Sports 2 Asia (Thai)" is on the blocklist due to claims of copyright holders (https://github.com/iptv-org/iptv/issues/0000)\n\n1 problems (1 errors, 0 warnings)\n`
|
'us_blocked.m3u\n 2 error "Fox Sports 2 Asia (Thai)" is on the blocklist due to claims of copyright holders (https://github.com/iptv-org/iptv/issues/0000)\n\n1 problems (1 errors, 0 warnings)\n'
|
||||||
)
|
)
|
||||||
).toBe(true)
|
).toBe(true)
|
||||||
}
|
}
|
||||||
|
@ -30,7 +32,7 @@ it('show a warning if channel has wrong id', () => {
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
stdout.includes(
|
stdout.includes(
|
||||||
`wrong_id.m3u\n 2 warning "qib22lAq1L.us" is not in the database\n\n1 problems (0 errors, 1 warnings)\n`
|
'wrong_id.m3u\n 2 warning "qib22lAq1L.us" is not in the database\n\n1 problems (0 errors, 1 warnings)\n'
|
||||||
)
|
)
|
||||||
).toBe(true)
|
).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,7 +14,7 @@ beforeEach(() => {
|
||||||
'tests/__data__/output/.readme/template.md'
|
'tests/__data__/output/.readme/template.md'
|
||||||
)
|
)
|
||||||
|
|
||||||
const stdout = execSync(
|
execSync(
|
||||||
'DATA_DIR=tests/__data__/input/data LOGS_DIR=tests/__data__/input/logs README_DIR=tests/__data__/output/.readme npm run readme:update',
|
'DATA_DIR=tests/__data__/input/data LOGS_DIR=tests/__data__/input/logs README_DIR=tests/__data__/output/.readme npm run readme:update',
|
||||||
{ encoding: 'utf8' }
|
{ encoding: 'utf8' }
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue