mirror of
https://github.com/iptv-org/iptv
synced 2026-04-04 18:21:51 -04:00
Update scripts
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
type BlockedProps = {
|
||||
channel: string
|
||||
reason: string
|
||||
ref: string
|
||||
}
|
||||
|
||||
export class Blocked {
|
||||
channelId: string
|
||||
reason: string
|
||||
ref: string
|
||||
|
||||
constructor(data: BlockedProps) {
|
||||
this.channelId = data.channel
|
||||
this.reason = data.reason
|
||||
this.ref = data.ref
|
||||
}
|
||||
}
|
||||
15
scripts/models/blocklistRecord.ts
Normal file
15
scripts/models/blocklistRecord.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { BlocklistRecordData } from '../types/blocklistRecord'
|
||||
|
||||
export class BlocklistRecord {
|
||||
channelId: string
|
||||
reason: string
|
||||
ref: string
|
||||
|
||||
constructor(data?: BlocklistRecordData) {
|
||||
if (!data) return
|
||||
|
||||
this.channelId = data.channel
|
||||
this.reason = data.reason
|
||||
this.ref = data.ref
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
type CategoryData = {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
import type { CategoryData, CategorySerializedData } from '../types/category'
|
||||
|
||||
export class Category {
|
||||
id: string
|
||||
@@ -11,4 +8,11 @@ export class Category {
|
||||
this.id = data.id
|
||||
this.name = data.name
|
||||
}
|
||||
|
||||
serialize(): CategorySerializedData {
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,6 @@
|
||||
import { Collection, Dictionary } from '@freearhey/core'
|
||||
import { Category, Country, Subdivision } from './index'
|
||||
|
||||
type ChannelData = {
|
||||
id: string
|
||||
name: string
|
||||
alt_names: string[]
|
||||
network: string
|
||||
owners: Collection
|
||||
country: string
|
||||
subdivision: string
|
||||
city: string
|
||||
categories: Collection
|
||||
is_nsfw: boolean
|
||||
launched: string
|
||||
closed: string
|
||||
replaced_by: string
|
||||
website: string
|
||||
logo: string
|
||||
}
|
||||
import { Category, Country, Feed, Guide, Stream, Subdivision } from './index'
|
||||
import type { ChannelData, ChannelSearchableData, ChannelSerializedData } from '../types/channel'
|
||||
|
||||
export class Channel {
|
||||
id: string
|
||||
@@ -31,15 +14,18 @@ export class Channel {
|
||||
subdivision?: Subdivision
|
||||
cityName?: string
|
||||
categoryIds: Collection
|
||||
categories?: Collection
|
||||
categories: Collection = new Collection()
|
||||
isNSFW: boolean
|
||||
launched?: string
|
||||
closed?: string
|
||||
replacedBy?: string
|
||||
website?: string
|
||||
logo: string
|
||||
feeds?: Collection
|
||||
|
||||
constructor(data?: ChannelData) {
|
||||
if (!data) return
|
||||
|
||||
constructor(data: ChannelData) {
|
||||
this.id = data.id
|
||||
this.name = data.name
|
||||
this.altNames = new Collection(data.alt_names)
|
||||
@@ -57,28 +43,34 @@ export class Channel {
|
||||
this.logo = data.logo
|
||||
}
|
||||
|
||||
withSubdivision(subdivisionsGroupedByCode: Dictionary): this {
|
||||
withSubdivision(subdivisionsKeyByCode: Dictionary): this {
|
||||
if (!this.subdivisionCode) return this
|
||||
|
||||
this.subdivision = subdivisionsGroupedByCode.get(this.subdivisionCode)
|
||||
this.subdivision = subdivisionsKeyByCode.get(this.subdivisionCode)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withCountry(countriesGroupedByCode: Dictionary): this {
|
||||
this.country = countriesGroupedByCode.get(this.countryCode)
|
||||
withCountry(countriesKeyByCode: Dictionary): this {
|
||||
this.country = countriesKeyByCode.get(this.countryCode)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withCategories(groupedCategories: Dictionary): this {
|
||||
withCategories(categoriesKeyById: Dictionary): this {
|
||||
this.categories = this.categoryIds
|
||||
.map((id: string) => groupedCategories.get(id))
|
||||
.map((id: string) => categoriesKeyById.get(id))
|
||||
.filter(Boolean)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withFeeds(feedsGroupedByChannelId: Dictionary): this {
|
||||
this.feeds = new Collection(feedsGroupedByChannelId.get(this.id))
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
getCountry(): Country | undefined {
|
||||
return this.country
|
||||
}
|
||||
@@ -102,7 +94,106 @@ export class Channel {
|
||||
)
|
||||
}
|
||||
|
||||
getFeeds(): Collection {
|
||||
if (!this.feeds) return new Collection()
|
||||
|
||||
return this.feeds
|
||||
}
|
||||
|
||||
getGuides(): Collection {
|
||||
let guides = new Collection()
|
||||
|
||||
this.getFeeds().forEach((feed: Feed) => {
|
||||
guides = guides.concat(feed.getGuides())
|
||||
})
|
||||
|
||||
return guides
|
||||
}
|
||||
|
||||
getGuideNames(): Collection {
|
||||
return this.getGuides()
|
||||
.map((guide: Guide) => guide.siteName)
|
||||
.uniq()
|
||||
}
|
||||
|
||||
getStreams(): Collection {
|
||||
let streams = new Collection()
|
||||
|
||||
this.getFeeds().forEach((feed: Feed) => {
|
||||
streams = streams.concat(feed.getStreams())
|
||||
})
|
||||
|
||||
return streams
|
||||
}
|
||||
|
||||
getStreamNames(): Collection {
|
||||
return this.getStreams()
|
||||
.map((stream: Stream) => stream.getName())
|
||||
.uniq()
|
||||
}
|
||||
|
||||
getFeedFullNames(): Collection {
|
||||
return this.getFeeds()
|
||||
.map((feed: Feed) => feed.getFullName())
|
||||
.uniq()
|
||||
}
|
||||
|
||||
isSFW(): boolean {
|
||||
return this.isNSFW === false
|
||||
}
|
||||
|
||||
getSearchable(): ChannelSearchableData {
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
altNames: this.altNames.all(),
|
||||
guideNames: this.getGuideNames().all(),
|
||||
streamNames: this.getStreamNames().all(),
|
||||
feedFullNames: this.getFeedFullNames().all()
|
||||
}
|
||||
}
|
||||
|
||||
serialize(): ChannelSerializedData {
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
altNames: this.altNames.all(),
|
||||
network: this.network,
|
||||
owners: this.owners.all(),
|
||||
countryCode: this.countryCode,
|
||||
country: this.country ? this.country.serialize() : undefined,
|
||||
subdivisionCode: this.subdivisionCode,
|
||||
subdivision: this.subdivision ? this.subdivision.serialize() : undefined,
|
||||
cityName: this.cityName,
|
||||
categoryIds: this.categoryIds.all(),
|
||||
categories: this.categories.map((category: Category) => category.serialize()).all(),
|
||||
isNSFW: this.isNSFW,
|
||||
launched: this.launched,
|
||||
closed: this.closed,
|
||||
replacedBy: this.replacedBy,
|
||||
website: this.website,
|
||||
logo: this.logo
|
||||
}
|
||||
}
|
||||
|
||||
deserialize(data: ChannelSerializedData): this {
|
||||
this.id = data.id
|
||||
this.name = data.name
|
||||
this.altNames = new Collection(data.altNames)
|
||||
this.network = data.network
|
||||
this.owners = new Collection(data.owners)
|
||||
this.countryCode = data.countryCode
|
||||
this.country = data.country ? new Country().deserialize(data.country) : undefined
|
||||
this.subdivisionCode = data.subdivisionCode
|
||||
this.cityName = data.cityName
|
||||
this.categoryIds = new Collection(data.categoryIds)
|
||||
this.isNSFW = data.isNSFW
|
||||
this.launched = data.launched
|
||||
this.closed = data.closed
|
||||
this.replacedBy = data.replacedBy
|
||||
this.website = data.website
|
||||
this.logo = data.logo
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import { Collection, Dictionary } from '@freearhey/core'
|
||||
import { Region, Language } from '.'
|
||||
|
||||
type CountryData = {
|
||||
code: string
|
||||
name: string
|
||||
lang: string
|
||||
flag: string
|
||||
}
|
||||
import { Region, Language, Subdivision } from '.'
|
||||
import type { CountryData, CountrySerializedData } from '../types/country'
|
||||
import { SubdivisionSerializedData } from '../types/subdivision'
|
||||
import { RegionSerializedData } from '../types/region'
|
||||
|
||||
export class Country {
|
||||
code: string
|
||||
@@ -17,7 +13,9 @@ export class Country {
|
||||
subdivisions?: Collection
|
||||
regions?: Collection
|
||||
|
||||
constructor(data: CountryData) {
|
||||
constructor(data?: CountryData) {
|
||||
if (!data) return
|
||||
|
||||
this.code = data.code
|
||||
this.name = data.name
|
||||
this.flag = data.flag
|
||||
@@ -38,8 +36,8 @@ export class Country {
|
||||
return this
|
||||
}
|
||||
|
||||
withLanguage(languagesGroupedByCode: Dictionary): this {
|
||||
this.language = languagesGroupedByCode.get(this.languageCode)
|
||||
withLanguage(languagesKeyByCode: Dictionary): this {
|
||||
this.language = languagesKeyByCode.get(this.languageCode)
|
||||
|
||||
return this
|
||||
}
|
||||
@@ -55,4 +53,34 @@ export class Country {
|
||||
getSubdivisions(): Collection {
|
||||
return this.subdivisions || new Collection()
|
||||
}
|
||||
|
||||
serialize(): CountrySerializedData {
|
||||
return {
|
||||
code: this.code,
|
||||
name: this.name,
|
||||
flag: this.flag,
|
||||
languageCode: this.languageCode,
|
||||
language: this.language ? this.language.serialize() : null,
|
||||
subdivisions: this.subdivisions
|
||||
? this.subdivisions.map((subdivision: Subdivision) => subdivision.serialize()).all()
|
||||
: [],
|
||||
regions: this.regions ? this.regions.map((region: Region) => region.serialize()).all() : []
|
||||
}
|
||||
}
|
||||
|
||||
deserialize(data: CountrySerializedData): this {
|
||||
this.code = data.code
|
||||
this.name = data.name
|
||||
this.flag = data.flag
|
||||
this.languageCode = data.languageCode
|
||||
this.language = data.language ? new Language().deserialize(data.language) : undefined
|
||||
this.subdivisions = new Collection(data.subdivisions).map((data: SubdivisionSerializedData) =>
|
||||
new Subdivision().deserialize(data)
|
||||
)
|
||||
this.regions = new Collection(data.regions).map((data: RegionSerializedData) =>
|
||||
new Region().deserialize(data)
|
||||
)
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
import { Collection, Dictionary } from '@freearhey/core'
|
||||
import { Country, Language, Region, Channel, Subdivision } from './index'
|
||||
|
||||
type FeedData = {
|
||||
channel: string
|
||||
id: string
|
||||
name: string
|
||||
is_main: boolean
|
||||
broadcast_area: Collection
|
||||
languages: Collection
|
||||
timezones: Collection
|
||||
video_format: string
|
||||
}
|
||||
import type { FeedData } from '../types/feed'
|
||||
|
||||
export class Feed {
|
||||
channelId: string
|
||||
@@ -30,6 +20,8 @@ export class Feed {
|
||||
timezoneIds: Collection
|
||||
timezones?: Collection
|
||||
videoFormat: string
|
||||
guides?: Collection
|
||||
streams?: Collection
|
||||
|
||||
constructor(data: FeedData) {
|
||||
this.channelId = data.channel
|
||||
@@ -61,40 +53,58 @@ export class Feed {
|
||||
})
|
||||
}
|
||||
|
||||
withChannel(channelsGroupedById: Dictionary): this {
|
||||
this.channel = channelsGroupedById.get(this.channelId)
|
||||
withChannel(channelsKeyById: Dictionary): this {
|
||||
this.channel = channelsKeyById.get(this.channelId)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withLanguages(languagesGroupedByCode: Dictionary): this {
|
||||
withStreams(streamsGroupedById: Dictionary): this {
|
||||
this.streams = new Collection(streamsGroupedById.get(`${this.channelId}@${this.id}`))
|
||||
|
||||
if (this.isMain) {
|
||||
this.streams = this.streams.concat(new Collection(streamsGroupedById.get(this.channelId)))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withGuides(guidesGroupedByStreamId: Dictionary): this {
|
||||
this.guides = new Collection(guidesGroupedByStreamId.get(`${this.channelId}@${this.id}`))
|
||||
|
||||
if (this.isMain) {
|
||||
this.guides = this.guides.concat(new Collection(guidesGroupedByStreamId.get(this.channelId)))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withLanguages(languagesKeyByCode: Dictionary): this {
|
||||
this.languages = this.languageCodes
|
||||
.map((code: string) => languagesGroupedByCode.get(code))
|
||||
.map((code: string) => languagesKeyByCode.get(code))
|
||||
.filter(Boolean)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withTimezones(timezonesGroupedById: Dictionary): this {
|
||||
this.timezones = this.timezoneIds
|
||||
.map((id: string) => timezonesGroupedById.get(id))
|
||||
.filter(Boolean)
|
||||
withTimezones(timezonesKeyById: Dictionary): this {
|
||||
this.timezones = this.timezoneIds.map((id: string) => timezonesKeyById.get(id)).filter(Boolean)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withBroadcastSubdivisions(subdivisionsGroupedByCode: Dictionary): this {
|
||||
withBroadcastSubdivisions(subdivisionsKeyByCode: Dictionary): this {
|
||||
this.broadcastSubdivisions = this.broadcastSubdivisionCodes.map((code: string) =>
|
||||
subdivisionsGroupedByCode.get(code)
|
||||
subdivisionsKeyByCode.get(code)
|
||||
)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withBroadcastCountries(
|
||||
countriesGroupedByCode: Dictionary,
|
||||
regionsGroupedByCode: Dictionary,
|
||||
subdivisionsGroupedByCode: Dictionary
|
||||
countriesKeyByCode: Dictionary,
|
||||
regionsKeyByCode: Dictionary,
|
||||
subdivisionsKeyByCode: Dictionary
|
||||
): this {
|
||||
let broadcastCountries = new Collection()
|
||||
|
||||
@@ -104,22 +114,22 @@ export class Feed {
|
||||
}
|
||||
|
||||
this.broadcastCountryCodes.forEach((code: string) => {
|
||||
broadcastCountries.add(countriesGroupedByCode.get(code))
|
||||
broadcastCountries.add(countriesKeyByCode.get(code))
|
||||
})
|
||||
|
||||
this.broadcastRegionCodes.forEach((code: string) => {
|
||||
const region: Region = regionsGroupedByCode.get(code)
|
||||
const region: Region = regionsKeyByCode.get(code)
|
||||
if (region) {
|
||||
region.countryCodes.forEach((countryCode: string) => {
|
||||
broadcastCountries.add(countriesGroupedByCode.get(countryCode))
|
||||
broadcastCountries.add(countriesKeyByCode.get(countryCode))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.broadcastSubdivisionCodes.forEach((code: string) => {
|
||||
const subdivision: Subdivision = subdivisionsGroupedByCode.get(code)
|
||||
const subdivision: Subdivision = subdivisionsKeyByCode.get(code)
|
||||
if (subdivision) {
|
||||
broadcastCountries.add(countriesGroupedByCode.get(subdivision.countryCode))
|
||||
broadcastCountries.add(countriesKeyByCode.get(subdivision.countryCode))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -197,4 +207,22 @@ export class Feed {
|
||||
|
||||
return this.getBroadcastRegions().includes((_region: Region) => _region.code === region.code)
|
||||
}
|
||||
|
||||
getGuides(): Collection {
|
||||
if (!this.guides) return new Collection()
|
||||
|
||||
return this.guides
|
||||
}
|
||||
|
||||
getStreams(): Collection {
|
||||
if (!this.streams) return new Collection()
|
||||
|
||||
return this.streams
|
||||
}
|
||||
|
||||
getFullName(): string {
|
||||
if (!this.channel) return ''
|
||||
|
||||
return `${this.channel.name} ${this.name}`
|
||||
}
|
||||
}
|
||||
|
||||
54
scripts/models/guide.ts
Normal file
54
scripts/models/guide.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import type { GuideData, GuideSerializedData } from '../types/guide'
|
||||
|
||||
export class Guide {
|
||||
channelId?: string
|
||||
feedId?: string
|
||||
siteDomain: string
|
||||
siteId: string
|
||||
siteName: string
|
||||
languageCode: string
|
||||
|
||||
constructor(data?: GuideData) {
|
||||
if (!data) return
|
||||
|
||||
this.channelId = data.channel
|
||||
this.feedId = data.feed
|
||||
this.siteDomain = data.site
|
||||
this.siteId = data.site_id
|
||||
this.siteName = data.site_name
|
||||
this.languageCode = data.lang
|
||||
}
|
||||
|
||||
getUUID(): string {
|
||||
return this.getStreamId() + this.siteId
|
||||
}
|
||||
|
||||
getStreamId(): string | undefined {
|
||||
if (!this.channelId) return undefined
|
||||
if (!this.feedId) return this.channelId
|
||||
|
||||
return `${this.channelId}@${this.feedId}`
|
||||
}
|
||||
|
||||
serialize(): GuideSerializedData {
|
||||
return {
|
||||
channelId: this.channelId,
|
||||
feedId: this.feedId,
|
||||
siteDomain: this.siteDomain,
|
||||
siteId: this.siteId,
|
||||
siteName: this.siteName,
|
||||
languageCode: this.languageCode
|
||||
}
|
||||
}
|
||||
|
||||
deserialize(data: GuideSerializedData): this {
|
||||
this.channelId = data.channelId
|
||||
this.feedId = data.feedId
|
||||
this.siteDomain = data.siteDomain
|
||||
this.siteId = data.siteId
|
||||
this.siteName = data.siteName
|
||||
this.languageCode = data.languageCode
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
export * from './issue'
|
||||
export * from './playlist'
|
||||
export * from './blocked'
|
||||
export * from './stream'
|
||||
export * from './blocklistRecord'
|
||||
export * from './broadcastArea'
|
||||
export * from './category'
|
||||
export * from './channel'
|
||||
export * from './language'
|
||||
export * from './country'
|
||||
export * from './region'
|
||||
export * from './subdivision'
|
||||
export * from './feed'
|
||||
export * from './broadcastArea'
|
||||
export * from './guide'
|
||||
export * from './issue'
|
||||
export * from './language'
|
||||
export * from './playlist'
|
||||
export * from './region'
|
||||
export * from './stream'
|
||||
export * from './subdivision'
|
||||
export * from './timezone'
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
type LanguageData = {
|
||||
code: string
|
||||
name: string
|
||||
}
|
||||
import type { LanguageData, LanguageSerializedData } from '../types/language'
|
||||
|
||||
export class Language {
|
||||
code: string
|
||||
name: string
|
||||
|
||||
constructor(data: LanguageData) {
|
||||
constructor(data?: LanguageData) {
|
||||
if (!data) return
|
||||
|
||||
this.code = data.code
|
||||
this.name = data.name
|
||||
}
|
||||
|
||||
serialize(): LanguageSerializedData {
|
||||
return {
|
||||
code: this.code,
|
||||
name: this.name
|
||||
}
|
||||
}
|
||||
|
||||
deserialize(data: LanguageSerializedData): this {
|
||||
this.code = data.code
|
||||
this.name = data.name
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
import { Collection, Dictionary } from '@freearhey/core'
|
||||
import { Subdivision } from '.'
|
||||
|
||||
type RegionData = {
|
||||
code: string
|
||||
name: string
|
||||
countries: string[]
|
||||
}
|
||||
import { Country, Subdivision } from '.'
|
||||
import type { RegionData, RegionSerializedData } from '../types/region'
|
||||
import { CountrySerializedData } from '../types/country'
|
||||
import { SubdivisionSerializedData } from '../types/subdivision'
|
||||
|
||||
export class Region {
|
||||
code: string
|
||||
name: string
|
||||
countryCodes: Collection
|
||||
countries?: Collection
|
||||
subdivisions?: Collection
|
||||
countries: Collection = new Collection()
|
||||
subdivisions: Collection = new Collection()
|
||||
|
||||
constructor(data?: RegionData) {
|
||||
if (!data) return
|
||||
|
||||
constructor(data: RegionData) {
|
||||
this.code = data.code
|
||||
this.name = data.name
|
||||
this.countryCodes = new Collection(data.countries)
|
||||
}
|
||||
|
||||
withCountries(countriesGroupedByCode: Dictionary): this {
|
||||
this.countries = this.countryCodes.map((code: string) => countriesGroupedByCode.get(code))
|
||||
withCountries(countriesKeyByCode: Dictionary): this {
|
||||
this.countries = this.countryCodes.map((code: string) => countriesKeyByCode.get(code))
|
||||
|
||||
return this
|
||||
}
|
||||
@@ -35,11 +34,11 @@ export class Region {
|
||||
}
|
||||
|
||||
getSubdivisions(): Collection {
|
||||
return this.subdivisions || new Collection()
|
||||
return this.subdivisions
|
||||
}
|
||||
|
||||
getCountries(): Collection {
|
||||
return this.countries || new Collection()
|
||||
return this.countries
|
||||
}
|
||||
|
||||
includesCountryCode(code: string): boolean {
|
||||
@@ -49,4 +48,30 @@ export class Region {
|
||||
isWorldwide(): boolean {
|
||||
return this.code === 'INT'
|
||||
}
|
||||
|
||||
serialize(): RegionSerializedData {
|
||||
return {
|
||||
code: this.code,
|
||||
name: this.name,
|
||||
countryCodes: this.countryCodes.all(),
|
||||
countries: this.countries.map((country: Country) => country.serialize()).all(),
|
||||
subdivisions: this.subdivisions
|
||||
.map((subdivision: Subdivision) => subdivision.serialize())
|
||||
.all()
|
||||
}
|
||||
}
|
||||
|
||||
deserialize(data: RegionSerializedData): this {
|
||||
this.code = data.code
|
||||
this.name = data.name
|
||||
this.countryCodes = new Collection(data.countryCodes)
|
||||
this.countries = new Collection(data.countries).map((data: CountrySerializedData) =>
|
||||
new Country().deserialize(data)
|
||||
)
|
||||
this.subdivisions = new Collection(data.subdivisions).map((data: SubdivisionSerializedData) =>
|
||||
new Subdivision().deserialize(data)
|
||||
)
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,45 @@
|
||||
import { URL, Collection, Dictionary } from '@freearhey/core'
|
||||
import { Feed, Channel, Category, Region, Subdivision, Country, Language } from './index'
|
||||
import { URL, Collection, Dictionary } from '@freearhey/core'
|
||||
import type { StreamData } from '../types/stream'
|
||||
import parser from 'iptv-playlist-parser'
|
||||
|
||||
export class Stream {
|
||||
name: string
|
||||
name?: string
|
||||
url: string
|
||||
id?: string
|
||||
groupTitle: string
|
||||
channelId?: string
|
||||
channel?: Channel
|
||||
feedId?: string
|
||||
feed?: Feed
|
||||
filepath?: string
|
||||
line: number
|
||||
line?: number
|
||||
label?: string
|
||||
verticalResolution?: number
|
||||
isInterlaced?: boolean
|
||||
httpReferrer?: string
|
||||
httpUserAgent?: string
|
||||
referrer?: string
|
||||
userAgent?: string
|
||||
groupTitle: string = 'Undefined'
|
||||
removed: boolean = false
|
||||
|
||||
constructor(data: parser.PlaylistItem) {
|
||||
constructor(data?: StreamData) {
|
||||
if (!data) return
|
||||
|
||||
const id = data.channel && data.feed ? [data.channel, data.feed].join('@') : data.channel
|
||||
const { verticalResolution, isInterlaced } = parseQuality(data.quality)
|
||||
|
||||
this.id = id || undefined
|
||||
this.channelId = data.channel || undefined
|
||||
this.feedId = data.feed || undefined
|
||||
this.name = data.name || undefined
|
||||
this.url = data.url
|
||||
this.referrer = data.referrer || undefined
|
||||
this.userAgent = data.user_agent || undefined
|
||||
this.verticalResolution = verticalResolution || undefined
|
||||
this.isInterlaced = isInterlaced || undefined
|
||||
this.label = data.label || undefined
|
||||
}
|
||||
|
||||
fromPlaylistItem(data: parser.PlaylistItem): this {
|
||||
if (!data.name) throw new Error('"name" property is required')
|
||||
if (!data.url) throw new Error('"url" property is required')
|
||||
|
||||
@@ -37,15 +56,16 @@ export class Stream {
|
||||
this.verticalResolution = verticalResolution || undefined
|
||||
this.isInterlaced = isInterlaced || undefined
|
||||
this.url = data.url
|
||||
this.httpReferrer = data.http.referrer || undefined
|
||||
this.httpUserAgent = data.http['user-agent'] || undefined
|
||||
this.groupTitle = 'Undefined'
|
||||
this.referrer = data.http.referrer || undefined
|
||||
this.userAgent = data.http['user-agent'] || undefined
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
withChannel(channelsGroupedById: Dictionary): this {
|
||||
withChannel(channelsKeyById: Dictionary): this {
|
||||
if (!this.channelId) return this
|
||||
|
||||
this.channel = channelsGroupedById.get(this.channelId)
|
||||
this.channel = channelsKeyById.get(this.channelId)
|
||||
|
||||
return this
|
||||
}
|
||||
@@ -93,18 +113,22 @@ export class Stream {
|
||||
return this
|
||||
}
|
||||
|
||||
setHttpUserAgent(httpUserAgent: string): this {
|
||||
this.httpUserAgent = httpUserAgent
|
||||
setUserAgent(userAgent: string): this {
|
||||
this.userAgent = userAgent
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
setHttpReferrer(httpReferrer: string): this {
|
||||
this.httpReferrer = httpReferrer
|
||||
setReferrer(referrer: string): this {
|
||||
this.referrer = referrer
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
getLine(): number {
|
||||
return this.line || -1
|
||||
}
|
||||
|
||||
setFilepath(filepath: string): this {
|
||||
this.filepath = filepath
|
||||
|
||||
@@ -133,12 +157,12 @@ export class Stream {
|
||||
return this.filepath || ''
|
||||
}
|
||||
|
||||
getHttpReferrer(): string {
|
||||
return this.httpReferrer || ''
|
||||
getReferrer(): string {
|
||||
return this.referrer || ''
|
||||
}
|
||||
|
||||
getHttpUserAgent(): string {
|
||||
return this.httpUserAgent || ''
|
||||
getUserAgent(): string {
|
||||
return this.userAgent || ''
|
||||
}
|
||||
|
||||
getQuality(): string {
|
||||
@@ -198,14 +222,6 @@ export class Stream {
|
||||
return Object.assign(Object.create(Object.getPrototypeOf(this)), this)
|
||||
}
|
||||
|
||||
hasName(): boolean {
|
||||
return !!this.name
|
||||
}
|
||||
|
||||
noName(): boolean {
|
||||
return !this.name
|
||||
}
|
||||
|
||||
hasChannel() {
|
||||
return !!this.channel
|
||||
}
|
||||
@@ -281,8 +297,12 @@ export class Stream {
|
||||
return this?.channel?.logo || ''
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return this.name || ''
|
||||
}
|
||||
|
||||
getTitle(): string {
|
||||
let title = `${this.name}`
|
||||
let title = `${this.getName()}`
|
||||
|
||||
if (this.getQuality()) {
|
||||
title += ` (${this.getQuality()})`
|
||||
@@ -303,30 +323,13 @@ export class Stream {
|
||||
return this.id || ''
|
||||
}
|
||||
|
||||
data() {
|
||||
return {
|
||||
id: this.id,
|
||||
channel: this.channel,
|
||||
feed: this.feed,
|
||||
filepath: this.filepath,
|
||||
label: this.label,
|
||||
name: this.name,
|
||||
verticalResolution: this.verticalResolution,
|
||||
isInterlaced: this.isInterlaced,
|
||||
url: this.url,
|
||||
httpReferrer: this.httpReferrer,
|
||||
httpUserAgent: this.httpUserAgent,
|
||||
line: this.line
|
||||
}
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
channel: this.channelId || null,
|
||||
feed: this.feedId || null,
|
||||
url: this.url,
|
||||
referrer: this.httpReferrer || null,
|
||||
user_agent: this.httpUserAgent || null,
|
||||
referrer: this.referrer || null,
|
||||
user_agent: this.userAgent || null,
|
||||
quality: this.getQuality() || null
|
||||
}
|
||||
}
|
||||
@@ -338,22 +341,22 @@ export class Stream {
|
||||
output += ` tvg-logo="${this.getLogo()}" group-title="${this.groupTitle}"`
|
||||
}
|
||||
|
||||
if (this.httpReferrer) {
|
||||
output += ` http-referrer="${this.httpReferrer}"`
|
||||
if (this.referrer) {
|
||||
output += ` http-referrer="${this.referrer}"`
|
||||
}
|
||||
|
||||
if (this.httpUserAgent) {
|
||||
output += ` http-user-agent="${this.httpUserAgent}"`
|
||||
if (this.userAgent) {
|
||||
output += ` http-user-agent="${this.userAgent}"`
|
||||
}
|
||||
|
||||
output += `,${this.getTitle()}`
|
||||
|
||||
if (this.httpReferrer) {
|
||||
output += `\n#EXTVLCOPT:http-referrer=${this.httpReferrer}`
|
||||
if (this.referrer) {
|
||||
output += `\n#EXTVLCOPT:http-referrer=${this.referrer}`
|
||||
}
|
||||
|
||||
if (this.httpUserAgent) {
|
||||
output += `\n#EXTVLCOPT:http-user-agent=${this.httpUserAgent}`
|
||||
if (this.userAgent) {
|
||||
output += `\n#EXTVLCOPT:http-user-agent=${this.userAgent}`
|
||||
}
|
||||
|
||||
output += `\n${this.url}`
|
||||
@@ -379,7 +382,11 @@ function escapeRegExp(text) {
|
||||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
|
||||
}
|
||||
|
||||
function parseQuality(quality: string): { verticalResolution: number; isInterlaced: boolean } {
|
||||
function parseQuality(quality: string | null): {
|
||||
verticalResolution: number | null
|
||||
isInterlaced: boolean | null
|
||||
} {
|
||||
if (!quality) return { verticalResolution: null, isInterlaced: null }
|
||||
let [, verticalResolutionString] = quality.match(/^(\d+)/) || [null, undefined]
|
||||
const isInterlaced = /i$/i.test(quality)
|
||||
let verticalResolution = 0
|
||||
|
||||
@@ -1,26 +1,41 @@
|
||||
import { SubdivisionData, SubdivisionSerializedData } from '../types/subdivision'
|
||||
import { Dictionary } from '@freearhey/core'
|
||||
import { Country } from '.'
|
||||
|
||||
type SubdivisionData = {
|
||||
code: string
|
||||
name: string
|
||||
country: string
|
||||
}
|
||||
|
||||
export class Subdivision {
|
||||
code: string
|
||||
name: string
|
||||
countryCode: string
|
||||
country?: Country
|
||||
|
||||
constructor(data: SubdivisionData) {
|
||||
constructor(data?: SubdivisionData) {
|
||||
if (!data) return
|
||||
|
||||
this.code = data.code
|
||||
this.name = data.name
|
||||
this.countryCode = data.country
|
||||
}
|
||||
|
||||
withCountry(countriesGroupedByCode: Dictionary): this {
|
||||
this.country = countriesGroupedByCode.get(this.countryCode)
|
||||
withCountry(countriesKeyByCode: Dictionary): this {
|
||||
this.country = countriesKeyByCode.get(this.countryCode)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
serialize(): SubdivisionSerializedData {
|
||||
return {
|
||||
code: this.code,
|
||||
name: this.name,
|
||||
countryCode: this.code,
|
||||
country: this.country ? this.country.serialize() : undefined
|
||||
}
|
||||
}
|
||||
|
||||
deserialize(data: SubdivisionSerializedData): this {
|
||||
this.code = data.code
|
||||
this.name = data.name
|
||||
this.countryCode = data.countryCode
|
||||
this.country = data.country ? new Country().deserialize(data.country) : undefined
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ export class Timezone {
|
||||
this.countryCodes = new Collection(data.countries)
|
||||
}
|
||||
|
||||
withCountries(countriesGroupedByCode: Dictionary): this {
|
||||
this.countries = this.countryCodes.map((code: string) => countriesGroupedByCode.get(code))
|
||||
withCountries(countriesKeyByCode: Dictionary): this {
|
||||
this.countries = this.countryCodes.map((code: string) => countriesKeyByCode.get(code))
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user