import { Collection, Dictionary } from '@freearhey/core' import { DATA_DIR } from './constants' import cliProgress from 'cli-progress' import * as sdk from '@iptv-org/sdk' const data = { categoriesKeyById: new Dictionary(), countriesKeyByCode: new Dictionary(), subdivisionsKeyByCode: new Dictionary(), citiesKeyByCode: new Dictionary(), regionsKeyByCode: new Dictionary(), languagesKeyByCode: new Dictionary(), channelsKeyById: new Dictionary(), feedsKeyByStreamId: new Dictionary(), feedsGroupedByChannel: new Dictionary(), blocklistRecordsGroupedByChannel: new Dictionary(), categories: new Collection(), countries: new Collection(), subdivisions: new Collection(), cities: new Collection(), regions: new Collection() } let searchIndex async function loadData() { const dataManager = new sdk.DataManager({ dataDir: DATA_DIR }) await dataManager.loadFromDisk() dataManager.processData() const { channels, feeds, categories, languages, countries, subdivisions, cities, regions, blocklist } = dataManager.getProcessedData() searchIndex = sdk.SearchEngine.createIndex(channels) data.categoriesKeyById = categories.keyBy((category: sdk.Models.Category) => category.id) data.countriesKeyByCode = countries.keyBy((country: sdk.Models.Country) => country.code) data.subdivisionsKeyByCode = subdivisions.keyBy( (subdivision: sdk.Models.Subdivision) => subdivision.code ) data.citiesKeyByCode = cities.keyBy((city: sdk.Models.City) => city.code) data.regionsKeyByCode = regions.keyBy((region: sdk.Models.Region) => region.code) data.languagesKeyByCode = languages.keyBy((language: sdk.Models.Language) => language.code) data.channelsKeyById = channels.keyBy((channel: sdk.Models.Channel) => channel.id) data.feedsKeyByStreamId = feeds.keyBy((feed: sdk.Models.Feed) => feed.getStreamId()) data.feedsGroupedByChannel = feeds.groupBy((feed: sdk.Models.Feed) => feed.channel) data.blocklistRecordsGroupedByChannel = blocklist.groupBy( (blocklistRecord: sdk.Models.BlocklistRecord) => blocklistRecord.channel ) data.categories = categories data.countries = countries data.subdivisions = subdivisions data.cities = cities data.regions = regions } async function downloadData() { function formatBytes(bytes: number) { if (bytes === 0) return '0 B' const k = 1024 const sizes = ['B', 'KB', 'MB', 'GB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i] } const files = [ 'blocklist', 'categories', 'channels', 'cities', 'countries', 'feeds', 'guides', 'languages', 'logos', 'regions', 'streams', 'subdivisions', 'timezones' ] const multiBar = new cliProgress.MultiBar({ stopOnComplete: true, hideCursor: true, forceRedraw: true, barsize: 36, format(options, params, payload) { const filename = payload.filename.padEnd(18, ' ') const barsize = options.barsize || 40 const percent = (params.progress * 100).toFixed(2) const speed = payload.speed ? formatBytes(payload.speed) + '/s' : 'N/A' const total = formatBytes(params.total) const completeSize = Math.round(params.progress * barsize) const incompleteSize = barsize - completeSize const bar = options.barCompleteString && options.barIncompleteString ? options.barCompleteString.substr(0, completeSize) + options.barGlue + options.barIncompleteString.substr(0, incompleteSize) : '-'.repeat(barsize) return `${filename} [${bar}] ${percent}% | ETA: ${params.eta}s | ${total} | ${speed}` } }) const dataManager = new sdk.DataManager({ dataDir: DATA_DIR }) const requests: Promise[] = [] for (const basename of files) { const filename = `${basename}.json` const progressBar = multiBar.create(0, 0, { filename }) const request = dataManager.downloadFileToDisk(basename, { onDownloadProgress({ total, loaded, rate }) { if (total) progressBar.setTotal(total) progressBar.update(loaded, { speed: rate }) } }) requests.push(request) } await Promise.allSettled(requests).catch(console.error) } function searchChannels(query: string): Collection { if (!searchIndex) return new Collection() const results = searchIndex.search(query) const channels = new Collection() new Collection(results).forEach( (item: sdk.Types.ChannelSearchableData) => { const channel = data.channelsKeyById.get(item.id) if (channel) channels.add(channel) } ) return channels } export { data, loadData, downloadData, searchChannels }