Update scripts

This commit is contained in:
freearhey
2025-07-20 20:28:58 +03:00
parent 1cedd1af54
commit 3105a56980
10 changed files with 157 additions and 50 deletions

View File

@@ -9,13 +9,14 @@ import {
IndexCategoryGenerator, IndexCategoryGenerator,
IndexLanguageGenerator, IndexLanguageGenerator,
IndexCountryGenerator, IndexCountryGenerator,
SubdivisionsGenerator,
IndexRegionGenerator, IndexRegionGenerator,
CategoriesGenerator, CategoriesGenerator,
CountriesGenerator, CountriesGenerator,
LanguagesGenerator, LanguagesGenerator,
RegionsGenerator, RegionsGenerator,
IndexGenerator,
SourcesGenerator, SourcesGenerator,
IndexGenerator,
RawGenerator RawGenerator
} from '../../generators' } from '../../generators'
@@ -32,6 +33,7 @@ async function main() {
feedsGroupedByChannelId, feedsGroupedByChannelId,
logosGroupedByStreamId, logosGroupedByStreamId,
channelsKeyById, channelsKeyById,
subdivisions,
categories, categories,
countries, countries,
regions regions
@@ -71,6 +73,9 @@ async function main() {
logger.info('generating categories/...') logger.info('generating categories/...')
await new CategoriesGenerator({ categories, streams, logFile }).generate() await new CategoriesGenerator({ categories, streams, logFile }).generate()
logger.info('generating languages/...')
await new LanguagesGenerator({ streams, logFile }).generate()
logger.info('generating countries/...') logger.info('generating countries/...')
await new CountriesGenerator({ await new CountriesGenerator({
countries, countries,
@@ -78,8 +83,12 @@ async function main() {
logFile logFile
}).generate() }).generate()
logger.info('generating languages/...') logger.info('generating subdivisions/...')
await new LanguagesGenerator({ streams, logFile }).generate() await new SubdivisionsGenerator({
subdivisions,
streams,
logFile
}).generate()
logger.info('generating regions/...') logger.info('generating regions/...')
await new RegionsGenerator({ await new RegionsGenerator({

View File

@@ -1,5 +1,11 @@
import { Logger } from '@freearhey/core' import { Logger } from '@freearhey/core'
import { CategoryTable, CountryTable, LanguageTable, RegionTable } from '../../tables' import {
CategoryTable,
CountryTable,
LanguageTable,
RegionTable,
SubdivisionTable
} from '../../tables'
import { Markdown } from '../../core' import { Markdown } from '../../core'
import { README_DIR } from '../../constants' import { README_DIR } from '../../constants'
import path from 'path' import path from 'path'
@@ -9,10 +15,12 @@ async function main() {
logger.info('creating category table...') logger.info('creating category table...')
await new CategoryTable().make() await new CategoryTable().make()
logger.info('creating country table...')
await new CountryTable().make()
logger.info('creating language table...') logger.info('creating language table...')
await new LanguageTable().make() await new LanguageTable().make()
logger.info('creating country table...')
await new CountryTable().make()
logger.info('creating subdivision table...')
await new SubdivisionTable().make()
logger.info('creating region table...') logger.info('creating region table...')
await new RegionTable().make() await new RegionTable().make()

View File

@@ -25,7 +25,7 @@ export class DataProcessor {
const languages = new Collection(data.languages).map(data => new Language(data)) const languages = new Collection(data.languages).map(data => new Language(data))
const languagesKeyByCode = languages.keyBy((language: Language) => language.code) const languagesKeyByCode = languages.keyBy((language: Language) => language.code)
const subdivisions = new Collection(data.subdivisions).map(data => new Subdivision(data)) let subdivisions = new Collection(data.subdivisions).map(data => new Subdivision(data))
const subdivisionsKeyByCode = subdivisions.keyBy((subdivision: Subdivision) => subdivision.code) const subdivisionsKeyByCode = subdivisions.keyBy((subdivision: Subdivision) => subdivision.code)
const subdivisionsGroupedByCountryCode = subdivisions.groupBy( const subdivisionsGroupedByCountryCode = subdivisions.groupBy(
(subdivision: Subdivision) => subdivision.countryCode (subdivision: Subdivision) => subdivision.countryCode
@@ -42,6 +42,10 @@ export class DataProcessor {
) )
const countriesKeyByCode = countries.keyBy((country: Country) => country.code) const countriesKeyByCode = countries.keyBy((country: Country) => country.code)
subdivisions = subdivisions.map((subdivision: Subdivision) =>
subdivision.withCountry(countriesKeyByCode)
)
const timezones = new Collection(data.timezones).map(data => const timezones = new Collection(data.timezones).map(data =>
new Timezone(data).withCountries(countriesKeyByCode) new Timezone(data).withCountries(countriesKeyByCode)
) )

View File

@@ -40,21 +40,6 @@ export class CountriesGenerator implements Generator {
this.logFile.append( this.logFile.append(
JSON.stringify({ type: 'country', filepath, count: playlist.streams.count() }) + EOL JSON.stringify({ type: 'country', filepath, count: playlist.streams.count() }) + EOL
) )
country.getSubdivisions().forEach(async (subdivision: Subdivision) => {
const subdivisionStreams = streams.filter((stream: Stream) =>
stream.isBroadcastInSubdivision(subdivision)
)
if (subdivisionStreams.isEmpty()) return
const playlist = new Playlist(subdivisionStreams, { public: true })
const filepath = `subdivisions/${subdivision.code.toLowerCase()}.m3u`
await this.storage.save(filepath, playlist.toString())
this.logFile.append(
JSON.stringify({ type: 'subdivision', filepath, count: playlist.streams.count() }) + EOL
)
})
}) })
const undefinedStreams = streams.filter((stream: Stream) => !stream.hasBroadcastArea()) const undefinedStreams = streams.filter((stream: Stream) => !stream.hasBroadcastArea())

View File

@@ -10,3 +10,4 @@ export * from './languagesGenerator'
export * from './rawGenerator' export * from './rawGenerator'
export * from './regionsGenerator' export * from './regionsGenerator'
export * from './sourcesGenerator' export * from './sourcesGenerator'
export * from './subdivisionsGenerator'

View File

@@ -0,0 +1,46 @@
import { Country, Subdivision, Stream, Playlist } from '../models'
import { Collection, Storage, File } from '@freearhey/core'
import { PUBLIC_DIR } from '../constants'
import { Generator } from './generator'
import { EOL } from 'node:os'
type SubdivisionsGeneratorProps = {
streams: Collection
subdivisions: Collection
logFile: File
}
export class SubdivisionsGenerator implements Generator {
streams: Collection
subdivisions: Collection
storage: Storage
logFile: File
constructor({ streams, subdivisions, logFile }: SubdivisionsGeneratorProps) {
this.streams = streams.clone()
this.subdivisions = subdivisions
this.storage = new Storage(PUBLIC_DIR)
this.logFile = logFile
}
async generate(): Promise<void> {
const streams = this.streams
.orderBy((stream: Stream) => stream.getTitle())
.filter((stream: Stream) => stream.isSFW())
this.subdivisions.forEach(async (subdivision: Subdivision) => {
const subdivisionStreams = streams.filter((stream: Stream) =>
stream.isBroadcastInSubdivision(subdivision)
)
if (subdivisionStreams.isEmpty()) return
const playlist = new Playlist(subdivisionStreams, { public: true })
const filepath = `subdivisions/${subdivision.code.toLowerCase()}.m3u`
await this.storage.save(filepath, playlist.toString())
this.logFile.append(
JSON.stringify({ type: 'subdivision', filepath, count: playlist.streams.count() }) + EOL
)
})
}
}

View File

@@ -190,8 +190,15 @@ export class Feed {
isBroadcastInSubdivision(subdivision: Subdivision): boolean { isBroadcastInSubdivision(subdivision: Subdivision): boolean {
if (this.isInternational()) return false if (this.isInternational()) return false
if (this.broadcastSubdivisionCodes.includes(subdivision.code)) return true
if (
this.broadcastSubdivisionCodes.isEmpty() &&
subdivision.country &&
this.isBroadcastInCountry(subdivision.country)
)
return true
return this.broadcastSubdivisionCodes.includes(subdivision.code) return false
} }
isBroadcastInCountry(country: Country): boolean { isBroadcastInCountry(country: Country): boolean {

View File

@@ -1,6 +1,6 @@
import { Storage, Collection, File } from '@freearhey/core' import { Storage, Collection, File } from '@freearhey/core'
import { HTMLTable, LogParser, LogItem } from '../core' import { HTMLTable, LogParser, LogItem } from '../core'
import { Country, Subdivision } from '../models' import { Country } from '../models'
import { DATA_DIR, LOGS_DIR, README_DIR } from '../constants' import { DATA_DIR, LOGS_DIR, README_DIR } from '../constants'
import { Table } from './table' import { Table } from './table'
@@ -13,11 +13,6 @@ export class CountryTable implements Table {
const countriesContent = await dataStorage.json('countries.json') const countriesContent = await dataStorage.json('countries.json')
const countries = new Collection(countriesContent).map(data => new Country(data)) const countries = new Collection(countriesContent).map(data => new Country(data))
const countriesGroupedByCode = countries.keyBy((country: Country) => country.code) const countriesGroupedByCode = countries.keyBy((country: Country) => country.code)
const subdivisionsContent = await dataStorage.json('subdivisions.json')
const subdivisions = new Collection(subdivisionsContent).map(data => new Subdivision(data))
const subdivisionsGroupedByCode = subdivisions.keyBy(
(subdivision: Subdivision) => subdivision.code
)
const parser = new LogParser() const parser = new LogParser()
const logsStorage = new Storage(LOGS_DIR) const logsStorage = new Storage(LOGS_DIR)
@@ -26,27 +21,6 @@ export class CountryTable implements Table {
let data = new Collection() let data = new Collection()
parsed
.filter((logItem: LogItem) => logItem.type === 'subdivision')
.forEach((logItem: LogItem) => {
const file = new File(logItem.filepath)
const code = file.name().toUpperCase()
const [countryCode, subdivisionCode] = code.split('-') || ['', '']
const country = countriesGroupedByCode.get(countryCode)
if (country && subdivisionCode) {
const subdivision = subdivisionsGroupedByCode.get(code)
if (subdivision) {
data.add([
`${country.name}/${subdivision.name}`,
`&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${subdivision.name}`,
logItem.count,
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
])
}
}
})
parsed parsed
.filter((logItem: LogItem) => logItem.type === 'country') .filter((logItem: LogItem) => logItem.type === 'country')
.forEach((logItem: LogItem) => { .forEach((logItem: LogItem) => {

View File

@@ -2,3 +2,4 @@ export * from './categoryTable'
export * from './countryTable' export * from './countryTable'
export * from './languageTable' export * from './languageTable'
export * from './regionTable' export * from './regionTable'
export * from './subdivisionTable'

View File

@@ -0,0 +1,72 @@
import { Storage, Collection, File } from '@freearhey/core'
import { HTMLTable, LogParser, LogItem } from '../core'
import { Country, Subdivision } from '../models'
import { DATA_DIR, LOGS_DIR, README_DIR } from '../constants'
import { Table } from './table'
export class SubdivisionTable implements Table {
constructor() {}
async make() {
const dataStorage = new Storage(DATA_DIR)
const countriesContent = await dataStorage.json('countries.json')
const countries = new Collection(countriesContent).map(data => new Country(data))
const countriesGroupedByCode = countries.keyBy((country: Country) => country.code)
const subdivisionsContent = await dataStorage.json('subdivisions.json')
const subdivisions = new Collection(subdivisionsContent).map(data => new Subdivision(data))
const subdivisionsGroupedByCode = subdivisions.keyBy(
(subdivision: Subdivision) => subdivision.code
)
const parser = new LogParser()
const logsStorage = new Storage(LOGS_DIR)
const generatorsLog = await logsStorage.load('generators.log')
const parsed = parser.parse(generatorsLog)
const parsedSubdivisions = parsed.filter((logItem: LogItem) => logItem.type === 'subdivision')
let output = ''
countries.forEach((country: Country) => {
const parsedCountrySubdivisions = parsedSubdivisions.filter((logItem: LogItem) =>
logItem.filepath.includes(`subdivisions/${country.code.toLowerCase()}`)
)
if (!parsedCountrySubdivisions.length) return
output += `\r\n<details>\r\n\<summary>${country.name}</summary>\r\n`
let data = new Collection()
parsedCountrySubdivisions.forEach((logItem: LogItem) => {
const file = new File(logItem.filepath)
const code = file.name().toUpperCase()
const [countryCode, subdivisionCode] = code.split('-') || ['', '']
const country = countriesGroupedByCode.get(countryCode)
if (country && subdivisionCode) {
const subdivision = subdivisionsGroupedByCode.get(code)
if (subdivision) {
data.add([
subdivision.name,
logItem.count,
`<code>https://iptv-org.github.io/iptv/${logItem.filepath}</code>`
])
}
}
})
const table = new HTMLTable(data.all(), [
{ name: 'Subdivision' },
{ name: 'Channels', align: 'right' },
{ name: 'Playlist', nowrap: true }
])
output += table.toString()
output += '\r\n</details>'
})
const readmeStorage = new Storage(README_DIR)
await readmeStorage.save('_subdivisions.md', output.trim())
}
}