Update scripts

This commit is contained in:
freearhey
2026-05-25 13:29:39 +03:00
parent b7cd2a1d5a
commit 254458135a
6 changed files with 86 additions and 36 deletions
+6 -1
View File
@@ -14,6 +14,7 @@ const data = {
feedsKeyByStreamId: new Dictionary<sdk.Models.Feed>(),
feedsGroupedByChannel: new Dictionary<sdk.Models.Feed[]>(),
blocklistRecordsGroupedByChannel: new Dictionary<sdk.Models.BlocklistRecord[]>(),
guidesGroupedByStreamId: new Dictionary<sdk.Models.Guide[]>(),
categories: new Collection<sdk.Models.Category>(),
countries: new Collection<sdk.Models.Country>(),
subdivisions: new Collection<sdk.Models.Subdivision>(),
@@ -37,7 +38,8 @@ async function loadData() {
subdivisions,
cities,
regions,
blocklist
blocklist,
guides
} = dataManager.getProcessedData()
const searchableData = channels.map((channel: sdk.Models.Channel) => channel.getSearchable())
@@ -57,6 +59,9 @@ async function loadData() {
data.blocklistRecordsGroupedByChannel = blocklist.groupBy(
(blocklistRecord: sdk.Models.BlocklistRecord) => blocklistRecord.channel
)
data.guidesGroupedByStreamId = guides
.filter((guide: sdk.Models.Guide) => !!guide.sources.length)
.groupBy((guide: sdk.Models.Guide) => guide.getStreamId())
data.categories = categories
data.countries = countries
data.subdivisions = subdivisions
+5 -1
View File
@@ -5,8 +5,8 @@ import { Storage } from '@freearhey/storage-js'
import { STREAMS_DIR } from '../../constants'
import { PlaylistParser } from '../../core'
import { getStreamInfo } from '../../utils'
import { loadData, data } from '../../api'
import cliProgress from 'cli-progress'
import { loadData } from '../../api'
import { eachLimit } from 'async'
import path from 'node:path'
import os from 'node:os'
@@ -44,6 +44,10 @@ async function main() {
let files = program.args.length ? program.args : await streamsStorage.list('**/*.m3u')
files = files.map((filepath: string) => path.basename(filepath))
let streams = await parser.parse(files)
streams = streams.map((stream: Stream) => {
stream.setGuides(data.guidesGroupedByStreamId.get(stream.getId()))
return stream
})
logger.info(`found ${streams.count()} streams`)
+9 -24
View File
@@ -34,6 +34,10 @@ async function main() {
})
const files = await streamsStorage.list('**/*.m3u')
let streams = await parser.parse(files)
streams = streams.map((stream: Stream) => {
stream.setGuides(data.guidesGroupedByStreamId.get(stream.getId()))
return stream
})
const totalStreams = streams.count()
logger.info(`found ${totalStreams} streams`)
@@ -62,32 +66,16 @@ async function main() {
await new LanguagesGenerator({ streams, logFile }).generate()
logger.info('generating countries/...')
await new CountriesGenerator({
countries,
streams,
logFile
}).generate()
await new CountriesGenerator({ countries, streams, logFile }).generate()
logger.info('generating subdivisions/...')
await new SubdivisionsGenerator({
subdivisions,
streams,
logFile
}).generate()
await new SubdivisionsGenerator({ subdivisions, streams, logFile }).generate()
logger.info('generating cities/...')
await new CitiesGenerator({
cities,
streams,
logFile
}).generate()
await new CitiesGenerator({ cities, streams, logFile }).generate()
logger.info('generating regions/...')
await new RegionsGenerator({
streams,
regions,
logFile
}).generate()
await new RegionsGenerator({ streams, regions, logFile }).generate()
logger.info('generating sources/...')
await new SourcesGenerator({ streams, logFile }).generate()
@@ -99,10 +87,7 @@ async function main() {
await new IndexCategoryGenerator({ streams, logFile }).generate()
logger.info('generating index.country.m3u...')
await new IndexCountryGenerator({
streams,
logFile
}).generate()
await new IndexCountryGenerator({ streams, logFile }).generate()
logger.info('generating index.language.m3u...')
await new IndexLanguageGenerator({ streams, logFile }).generate()
+9 -1
View File
@@ -81,6 +81,10 @@ async function loadStreams() {
const files = await streamsStorage.list('**/*.m3u')
streams = await parser.parse(files)
streams = streams.map((stream: Stream) => {
stream.setGuides(apiData.guidesGroupedByStreamId.get(stream.getId()))
return stream
})
}
async function processIssues(issues: Collection<Issue>) {
@@ -132,7 +136,7 @@ async function removeStream(issue: Issue) {
if (changed) {
processedIssues.add(issue)
} else {
log.error(`None of the URLs specified in the request were found in the playlists`)
log.error('None of the URLs specified in the request were found in the playlists')
skippedIssues.add(issue)
}
}
@@ -162,6 +166,8 @@ async function editStream(issue: Issue) {
stream.updateWithIssue(data)
stream.setGuides(apiData.guidesGroupedByStreamId.get(stream.getId()))
const errors = new Collection<Error>()
errors.concat(stream.validate())
if (errors.isNotEmpty()) {
@@ -260,6 +266,8 @@ async function addStream(issue: Issue) {
stream.updateTitle().updateFilepath()
stream.setGuides(apiData.guidesGroupedByStreamId.get(stream.getId()))
streams.add(stream)
const errors = new Collection<Error>()
+46 -7
View File
@@ -1,26 +1,65 @@
import { Collection } from '@freearhey/core'
import * as sdk from '@iptv-org/sdk'
import { Stream } from '../models'
type PlaylistOptions = {
public: boolean
public?: boolean
}
export class Playlist {
streams: Collection<Stream>
options: {
public: boolean
}
public: boolean
constructor(streams: Collection<Stream>, options?: PlaylistOptions) {
this.streams = streams
this.options = options || { public: false }
this.public = options?.public === true
}
getGuides(): Collection<sdk.Models.Guide> {
const guides = new Collection<sdk.Models.Guide>()
this.streams.forEach(stream => {
guides.concat(stream.getGuides())
})
return guides
}
getGuideUrls(): Collection<string> {
function byFormat(source: sdk.Types.GuideSource) {
if (source.format === 'GZIP') return 2
if (source.format === 'XML') return 1
return 0
}
const urls = new Collection<string>()
this.getGuides().forEach((guide: sdk.Models.Guide) => {
const sources = new Collection(guide.sources)
const source = sources
.filter((source: sdk.Types.GuideSource) => ['GZIP', 'XML'].includes(source.format))
.sortBy([byFormat], ['desc'])
.first()
if (source) urls.add(source.url)
})
return urls.uniq()
}
toString() {
let output = '#EXTM3U\r\n'
let output = '#EXTM3U'
const guideUrls = this.getGuideUrls()
if (guideUrls.count()) {
output += ` x-tvg-url="${guideUrls.join(',')}"`
}
output += '\r\n'
this.streams.forEach((stream: Stream) => {
output += stream.toString(this.options) + '\r\n'
output += stream.toString({ public: this.public }) + '\r\n'
})
return output
+11 -2
View File
@@ -13,6 +13,15 @@ export class Stream extends sdk.Models.Stream {
removed: boolean = false
tvgId?: string
statusCode?: string
guides = new Collection<sdk.Models.Guide>()
setGuides(guides?: sdk.Models.Guide[]) {
this.guides = new Collection(guides)
}
getGuides(): Collection<sdk.Models.Guide> {
return this.guides
}
validate(): Collection<Error> {
const errors = new Collection<Error>()
@@ -80,12 +89,12 @@ export class Stream extends sdk.Models.Stream {
quality: quality || null,
url: data.url,
referrer: data.http.referrer || null,
user_agent: data.http['user-agent'] || null
user_agent: data.http['user-agent'] || null,
label: label || null
})
stream.tvgId = data.tvg.id
stream.line = data.line
stream.label = label || null
return stream
}