Change tokenk Axios wrapper to multifetch, config changes

This commit is contained in:
theofficialomega
2026-04-21 19:01:37 +02:00
parent 87b10bc6ec
commit c77b184bea
24 changed files with 778 additions and 670 deletions

813
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -43,12 +43,12 @@
"@freearhey/search-js": "^0.2.1", "@freearhey/search-js": "^0.2.1",
"@freearhey/storage-js": "^0.2.0", "@freearhey/storage-js": "^0.2.0",
"@iptv-org/sdk": "^1.3.0", "@iptv-org/sdk": "^1.3.0",
"@ntlab/sfetch": "^1.2.0", "@inquirer/prompts": "^8.4.2",
"@octokit/core": "^7.0.6", "@octokit/core": "^7.0.6",
"@octokit/plugin-paginate-rest": "^14.0.0", "@octokit/plugin-paginate-rest": "^14.0.0",
"@octokit/plugin-rest-endpoint-methods": "^17.0.0", "@octokit/plugin-rest-endpoint-methods": "^17.0.0",
"@stylistic/eslint-plugin": "^5.10.0", "@stylistic/eslint-plugin": "^5.10.0",
"@swc/core": "^1.15.26", "@swc/core": "^1.15.30",
"@swc/jest": "^0.2.39", "@swc/jest": "^0.2.39",
"@types/cli-progress": "^3.11.6", "@types/cli-progress": "^3.11.6",
"@types/fs-extra": "^11.0.4", "@types/fs-extra": "^11.0.4",
@@ -81,7 +81,6 @@
"globals": "^17.5.0", "globals": "^17.5.0",
"husky": "^9.1.7", "husky": "^9.1.7",
"iconv-lite": "^0.7.2", "iconv-lite": "^0.7.2",
"inquirer": "^13.4.1",
"jest": "^30.3.0", "jest": "^30.3.0",
"langs": "^2.0.0", "langs": "^2.0.0",
"libxml2-wasm": "^0.7.1", "libxml2-wasm": "^0.7.1",
@@ -99,10 +98,9 @@
"srcset": "^5.0.3", "srcset": "^5.0.3",
"table2array": "^0.0.2", "table2array": "^0.0.2",
"tabletojson": "^4.1.10", "tabletojson": "^4.1.10",
"tough-cookie": "^6.0.1",
"tsx": "^4.21.0", "tsx": "^4.21.0",
"typescript": "^6.0.3", "typescript": "^6.0.3",
"typescript-eslint": "^8.58.2", "typescript-eslint": "^8.59.0",
"uuid": "^13.0.0" "uuid": "^14.0.0"
} }
} }

View File

@@ -1,2 +1,3 @@
export * from './htmlTable' export * from './htmlTable'
export * from './utils' export * from './utils'
export { default as multifetch } from './multifetch'

243
scripts/core/multifetch.ts Normal file
View File

@@ -0,0 +1,243 @@
/**
* Multifetch, adapted from "@ntlab/sfetch" by BellezaEmporium.
* Multiple concurrent fetch with a callback to process the result of each request.
* The maximum number of concurrent workers can be configured with `setMaxWorker()`.
* By default, the callback will only be called if the request is successful and returns a result.
* This behavior can be changed with `setCheckResult()`.
* A custom debug function can be set with `setDebugger()`.
* Native mock support via `setMocks()` for testing without axios.
*/
import axios, { AxiosRequestConfig } from 'axios'
import fs from 'fs'
import path from 'path'
interface QueueItem {
url: string;
method?: string;
params?: Record<string, unknown>;
}
type QueueEntry = string | QueueItem;
type Callback = (queue: QueueEntry, data: unknown, headers?: unknown) => void;
type DebugFn = (format: string, url: string, config: string) => void;
type MockHandler = (url: string, config?: AxiosRequestConfig) => unknown;
interface MockRoute {
handler: MockHandler | string;
dataDir?: string;
}
let nworker = 25
let checkResult = true
let debug: DebugFn | undefined
const mocks = new Map<string, MockRoute>()
/**
* Process a mock route and return response
*/
const processMockRoute = (url: string, config: AxiosRequestConfig | undefined, route: MockRoute): unknown => {
const { handler, dataDir } = route
if (typeof handler === 'function') {
return handler(url, config)
}
if (typeof handler === 'string') {
// If it looks like a file path, read from disk
if (handler.includes('.') || handler.includes('/')) {
const filePath = dataDir ? path.join(dataDir, handler) : handler
const content = fs.readFileSync(filePath, 'utf8')
if (handler.endsWith('.json')) {
try {
return JSON.parse(content)
} catch {
return content
}
}
return content
}
// Otherwise return as-is
return handler
}
return handler
}
/**
* Check if a URL matches any mock pattern
*/
const findMock = (url: string): MockRoute | undefined => {
// Try exact match first
if (mocks.has(url)) return mocks.get(url)
// Try pattern matching (prefix match)
for (const [pattern, route] of mocks) {
if (url.startsWith(pattern)) return route
}
return undefined
}
async function doFetch(queues: QueueEntry[], cb: Callback) {
if (!queues.length) return
let resolveFinish: (() => void) | undefined
const workers = new Set<() => void>()
let activeWorkers = 0
const processQueue = () => {
if (queues.length > 0 && activeWorkers < nworker) {
const queue = queues.shift()
if (queue === undefined) return
activeWorkers++
const processRequest = async () => {
try {
const isQueueObject = typeof queue === 'object' && queue !== null
const url = isQueueObject ? queue.url : (queue as string)
const method = (isQueueObject && queue.method) ? queue.method : 'get'
const params = (isQueueObject && queue.params) ? queue.params : {}
const requestConfig: AxiosRequestConfig = method === 'request'
? { ...params, url }
: { ...params, url, method: method as AxiosRequestConfig['method'] }
if (debug) {
debug('fetch %s with %s', url, JSON.stringify(requestConfig))
}
// Check if there's a mock for this URL
const mock = findMock(url)
let response: unknown
if (mock) {
const mockResponse = processMockRoute(url, requestConfig, mock)
const isObj = typeof mockResponse === 'object' && mockResponse !== null
if (debug) {
const hasData = isObj && 'data' in mockResponse
const keys = isObj ? Object.keys(mockResponse).join(',') : ''
debug(`mock response type: ${typeof mockResponse}, has data: ${hasData}, keys: ${keys}`, url, JSON.stringify(requestConfig))
}
// Check if response looks like it's already formatted (has 'data' and optionally 'status'/'headers')
const isFormatted = isObj && 'data' in mockResponse && 'status' in mockResponse
response = isFormatted ? mockResponse : { data: mockResponse, status: 200, headers: {} }
} else if (mocks.size > 0) {
// If mocks are set up but this URL doesn't match, return 404
response = { data: '', status: 404, headers: {} }
} else {
// No mocks set up, use real axios
const axMethod = (requestConfig.method || 'get').toLowerCase()
if (axMethod === 'get' && typeof axios.get === 'function') {
response = await axios.get(url, requestConfig)
} else if (axMethod === 'post' && typeof axios.post === 'function') {
response = await axios.post(url, requestConfig.data, requestConfig)
} else {
response = await axios.request(requestConfig)
}
}
const res = response as { data?: unknown; headers?: unknown } | undefined
if ((checkResult && res?.data) || !checkResult) {
cb(queue, res?.data, res?.headers)
}
} catch (err: unknown) {
const url = typeof queue === 'object' ? queue.url : queue
const errorMessage = err instanceof Error ? err.message : String(err)
console.error(`Unable to fetch ${url}: ${errorMessage}!`)
if (!checkResult) {
cb(queue, undefined)
}
} finally {
activeWorkers--
workers.delete(processRequest)
processQueue()
if (activeWorkers === 0 && queues.length === 0 && resolveFinish) {
resolveFinish()
}
}
}
workers.add(processRequest)
processRequest()
}
}
// Start initial workers
const initialWorkers = Math.min(nworker, queues.length)
for (let i = 0; i < initialWorkers; i++) {
processQueue()
}
// Wait for all to complete
if (workers.size > 0 || activeWorkers > 0) {
await new Promise<void>(resolve => {
resolveFinish = resolve
})
}
}
Object.assign(doFetch, {
getMaxWorker() {
return nworker
},
setMaxWorker(n: number) {
nworker = n
return doFetch
},
getCheckResult() {
return checkResult
},
setCheckResult(enabled: boolean) {
checkResult = enabled
return doFetch
},
setDebugger(dbg: (arg0: string, arg1: unknown, arg2: string) => void) {
debug = dbg
return doFetch
},
/**
* Set mocks for URLs (for testing)
* @param mockConfig - Object with URL patterns as keys and handlers as values
* @param dataDir - Optional directory for resolving file paths in handlers
*
* Usage:
* multifetch.setMocks({
* 'https://example.com/api': (url) => ({ data: 'response' }),
* 'https://example.com/file': 'response.json'
* }, __dirname)
*/
setMocks(mockConfig: Record<string, MockHandler | string>, dataDir?: string) {
mocks.clear()
for (const [url, handler] of Object.entries(mockConfig)) {
mocks.set(url, { handler, dataDir })
}
return doFetch
},
/**
* Add a single mock route
*/
addMock(url: string, handler: MockHandler | string, dataDir?: string) {
mocks.set(url, { handler, dataDir })
return doFetch
},
/**
* Clear all mocks
*/
clearMocks() {
mocks.clear()
return doFetch
},
/**
* Get registered mock URLs for debugging
*/
getMocks() {
return Array.from(mocks.keys())
}
})
export default doFetch
module.exports = doFetch

View File

@@ -113,4 +113,4 @@ export function parseNumber(value: string): number {
export function parseList(value: string): string[] { export function parseList(value: string): string[] {
return value.split(',') return value.split(',')
} }

View File

@@ -1,103 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<channels> <channels>
<channel site="dsmart.com.tr" site_id="5b9fb1eecfef0b35341b7eb7" lang="tr" xmltv_id="APara.tr@SD">A Para</channel>
<channel site="dsmart.com.tr" site_id="5bac7dedcfef0b02fac035fd" lang="tr" xmltv_id="HaberGlobal.tr@SD">Haber Global</channel>
<channel site="dsmart.com.tr" site_id="5c6e8e0ecfef0b613d9ff782" lang="tr" xmltv_id="Ekoturk.tr@SD">Ekotürk</channel>
<channel site="dsmart.com.tr" site_id="5ccfd6adcfef0b6021816941" lang="tr" xmltv_id="TV100.tr@SD">Tv 100</channel>
<channel site="dsmart.com.tr" site_id="5da87214cfef0b4df9157780" lang="tr" xmltv_id="TRTSporYildiz.tr@SD">Trt Spor Yıldız</channel>
<channel site="dsmart.com.tr" site_id="5dfc9faacfef0b201d2246b5" lang="tr" xmltv_id="LoveNature.ca@SD">Love Nature</channel>
<channel site="dsmart.com.tr" site_id="5fcb6bd2cfef0b15931fcdf8" lang="tr" xmltv_id="SporSmart2.tr@SD">SPOR SMART 2</channel>
<channel site="dsmart.com.tr" site_id="5fe07d7acfef0b1593275751" lang="tr" xmltv_id="SinemaTV.tr@SD">Sinema TV</channel>
<channel site="dsmart.com.tr" site_id="5fe07d9fcfef0b1593275754" lang="tr" xmltv_id="Sinema2.tr@SD">Sinema TV 2</channel>
<channel site="dsmart.com.tr" site_id="5fe07dd5cfef0b1593275758" lang="tr" xmltv_id="SinemaAksiyon.tr@SD">Sinema TV Aksiyon</channel>
<channel site="dsmart.com.tr" site_id="5fe07e23cfef0b15932757a1" lang="tr" xmltv_id="SinemaAksiyon2.tr@SD">Sinema TV Aksiyon 2</channel>
<channel site="dsmart.com.tr" site_id="5fe07e42cfef0b15932757a3" lang="tr" xmltv_id="SinemaAile.tr@SD">Sinema TV Aile</channel>
<channel site="dsmart.com.tr" site_id="5fe07eabcfef0b15932757a6" lang="tr" xmltv_id="SinemaAile2.tr@SD">Sinema TV Aile 2</channel>
<channel site="dsmart.com.tr" site_id="5fe07f5dcfef0b1593275822" lang="tr" xmltv_id="Sinema1001.tr@SD">Sinema TV 1001</channel>
<channel site="dsmart.com.tr" site_id="5fe07f29cfef0b1593275800" lang="tr" xmltv_id="SinemaKomedi.tr@SD">Sinema TV Comedy</channel>
<channel site="dsmart.com.tr" site_id="5fe07f45cfef0b159327581f" lang="tr" xmltv_id="SinemaKomedi2.tr@SD">Sinema TV Comedy 2</channel>
<channel site="dsmart.com.tr" site_id="5fe07f72cfef0b159327585a" lang="tr" xmltv_id="Sinema1002.tr@SD">Sinema TV 1002</channel>
<channel site="dsmart.com.tr" site_id="5fedddcecfef0b159330996e" lang="tr" xmltv_id="DisneyJr.tr@SD">Disney Junior</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062a0" lang="tr" xmltv_id="NOWTV.tr@SD">NOW</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062a1" lang="tr" xmltv_id="Teve2.tr@SD">teve2</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062a4" lang="tr" xmltv_id="NationalGeographic.tr@SD">National Geographic</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062a5" lang="tr" xmltv_id="NationalGeographicWild.tr@SD">National Geographic WILD</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062a8" lang="tr" xmltv_id="TRTBelgesel.tr@SD">TRT Belgesel</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062a9" lang="tr" xmltv_id="TRTSpor.tr@SD">TRT Spor</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062aa" lang="tr" xmltv_id="">Eurosport</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062aa" lang="tr" xmltv_id="">Eurosport</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062ae" lang="tr" xmltv_id="TV8.tr@SD">TV8</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b2" lang="tr" xmltv_id="">a Spor</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b4" lang="tr" xmltv_id="">CosmoSports</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b4" lang="tr" xmltv_id="">CosmoSports</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b6" lang="tr" xmltv_id="DaVinci.de@SD">Da Vinci Learning</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b5" lang="tr" xmltv_id="">Çocuk Smart</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b7" lang="tr" xmltv_id="BabyTV.uk@France">Baby TV</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b8" lang="tr" xmltv_id="CNNInternational.us@MENA">CNN International</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b9" lang="tr" xmltv_id="Cartoonito.uk@SD">Cartoonito</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062ba" lang="tr" xmltv_id="">FilmScreen</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062ba" lang="tr" xmltv_id="">FilmScreen</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062bc" lang="tr" xmltv_id="">BBC Earth</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062bc" lang="tr" xmltv_id="">BBC Earth</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062bd" lang="tr" xmltv_id="ViasatHistory.tr@SD">Viasat History</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062bf" lang="tr" xmltv_id="">Azoomee</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062bf" lang="tr" xmltv_id="">Azoomee</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062c5" lang="tr" xmltv_id="DreamTurk.tr@SD">Dream Tv</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062c6" lang="tr" xmltv_id="BBCNews.uk@Europe">BBC World News</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062c8" lang="tr" xmltv_id="CartoonNetwork.tr@SD">Cartoon Network</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062cb" lang="tr" xmltv_id="TV85.tr@SD">TV 8,5</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062cc" lang="tr" xmltv_id="">TRT World</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60622e" lang="tr" xmltv_id="24TV.tr@SD">24</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60623a" lang="tr" xmltv_id="NTV.tr@SD">NTV</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60623d" lang="tr" xmltv_id="TGRTHaber.tr@SD">TGRT Haber</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60623e" lang="tr" xmltv_id="BloombergHT.tr@SD">Bloomberg HT</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60624a" lang="tr" xmltv_id="TRTKurdi.tr@SD">TRT Kurdi</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60624b" lang="tr" xmltv_id="TRTAvaz.tr@SD">TRT Avaz</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60624c" lang="tr" xmltv_id="TRTTurk.tr@SD">TRT Türk</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60624f" lang="tr" xmltv_id="">NHK World English</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60624f" lang="tr" xmltv_id="">NHK World English</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60625a" lang="tr" xmltv_id="DiziSmartPremium.tr@SD">Dizi Smart Premium</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60625e" lang="tr" xmltv_id="">a Haber</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60626d" lang="tr" xmltv_id="">Minika Çocuk</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60626d" lang="tr" xmltv_id="">Minika Çocuk</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60626e" lang="tr" xmltv_id="NBATV.us@SD">NBA TV</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60628d" lang="tr" xmltv_id="">Dream Türk</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60628a" lang="tr" xmltv_id="SporSmart.tr@SD">Spor Smart</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60628e" lang="tr" xmltv_id="InvestigationDiscoveryEurope.us@SD">Discovery ID</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629a" lang="tr" xmltv_id="MovieSmartClassic.tr@SD">MovieSmart Classic</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629b" lang="tr" xmltv_id="ShowTV.tr@SD">Show TV</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629c" lang="tr" xmltv_id="Kanal7.tr@SD">Kanal 7</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629d" lang="tr" xmltv_id="HaberturkTV.tr@SD">Haber Türk</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629e" lang="tr" xmltv_id="TVNET.tr@SD">TV Net</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629f" lang="tr" xmltv_id="UlkeTV.tr@SD">Ülke TV</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606231" lang="tr" xmltv_id="">TRT 3 Spor</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606236" lang="tr" xmltv_id="360.tr@SD">360</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606248" lang="tr" xmltv_id="DiscoveryChannel.tr@SD">Discovery</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606255" lang="tr" xmltv_id="TRTCocuk.tr@SD">TRT Çocuk</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606257" lang="tr" xmltv_id="MinikaGo.tr@SD">Minika GO</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606258" lang="tr" xmltv_id="KanalD.tr@SD">Kanal D</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606259" lang="tr" xmltv_id="StarTV.tr@SD">Star</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606263" lang="tr" xmltv_id="TRT2.tr@SD">trt 2</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606266" lang="tr" xmltv_id="TRTMuzik.tr@SD">TRT Müzik</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606269" lang="tr" xmltv_id="FX.us@East">FX</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606274" lang="tr" xmltv_id="TRT1.tr@SD">TRT 1</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606278" lang="tr" xmltv_id="DiziSmartMax.tr@SD">Dizi Smart Max</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606281" lang="tr" xmltv_id="">Eurosport 2</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606281" lang="tr" xmltv_id="">Eurosport 2</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606289" lang="tr" xmltv_id="TRTHaber.tr@SD">TRT Haber</channel> <channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606298" lang="tr" xmltv_id="">Beyaz TV</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606299" lang="tr" xmltv_id="MovieSmartTurk.tr@SD">MovieSmart Türk</channel>
<channel site="dsmart.com.tr" site_id="59dca1f3cfef0b4d80a47a5f" lang="tr" xmltv_id="CNNTurk.tr@SD">CNN Türk SD</channel>
<channel site="dsmart.com.tr" site_id="59dca3b2cfef0b4d80a47b77" lang="tr" xmltv_id="FashionTVEurope.fr@SD">Fashion TV</channel>
<channel site="dsmart.com.tr" site_id="59dca29fcfef0b4d80a47a61" lang="tr" xmltv_id="">Nature Escape</channel> <channel site="dsmart.com.tr" site_id="59dca29fcfef0b4d80a47a61" lang="tr" xmltv_id="">Nature Escape</channel>
<channel site="dsmart.com.tr" site_id="59dca577cfef0b4d80a47b7c" lang="tr" xmltv_id="TV4.tr@SD">TV4</channel>
<channel site="dsmart.com.tr" site_id="59dcbddccfef0b4d80a49642" lang="tr" xmltv_id="Tele1.tr@SD">Tele 1</channel>
<channel site="dsmart.com.tr" site_id="59dcbe14cfef0b4d80a49646" lang="tr" xmltv_id="A2TV.tr@SD">a2</channel>
<channel site="dsmart.com.tr" site_id="59dcbee1cfef0b4d80a49650" lang="tr" xmltv_id="TRT4K.tr@SD">TRT 4K</channel>
<channel site="dsmart.com.tr" site_id="59dcbfdccfef0b4d80a4974a" lang="tr" xmltv_id="EuroD.tr@SD">Euro D</channel>
<channel site="dsmart.com.tr" site_id="61a408d7cfef0b1593ed2812" lang="tr" xmltv_id="">History Channel</channel>
<channel site="dsmart.com.tr" site_id="63ecd91acfef0b02d2687aed" lang="tr" xmltv_id="SozcuTV.tr@SD">SZC</channel>
<channel site="dsmart.com.tr" site_id="64edfc67cfef0b02d2c038c5" lang="tr" xmltv_id="TarihTV.tr@SD">Tarih Tv</channel>
<channel site="dsmart.com.tr" site_id="66d839a0cfef0b37445c6db1" lang="tr" xmltv_id="HTSporTV.tr@SD">HT Spor</channel>
<channel site="dsmart.com.tr" site_id="67a3521bcfef0b3744abd66d" lang="tr" xmltv_id="">Docu Screen</channel> <channel site="dsmart.com.tr" site_id="67a3521bcfef0b3744abd66d" lang="tr" xmltv_id="">Docu Screen</channel>
<channel site="dsmart.com.tr" site_id="67c063a6cfef0b3744b5ff9e" lang="tr" xmltv_id="">TRT Diyanet Çocuk</channel> <channel site="dsmart.com.tr" site_id="68c161eccfef0b37441e3af2" lang="tr" xmltv_id="">Sıfır Tv</channel>
<channel site="dsmart.com.tr" site_id="69b279d6cfef0b02ec9a77d4" lang="tr" xmltv_id="">CosmoEn</channel>
<channel site="dsmart.com.tr" site_id="679b51bdcfef0b3744a77893" lang="tr" xmltv_id="">Tmb</channel> <channel site="dsmart.com.tr" site_id="679b51bdcfef0b3744a77893" lang="tr" xmltv_id="">Tmb</channel>
<channel site="dsmart.com.tr" site_id="683d6eafcfef0b3744e79132" lang="tr" xmltv_id="">RT International</channel> <channel site="dsmart.com.tr" site_id="683d6eafcfef0b3744e79132" lang="tr" xmltv_id="">RT International</channel>
<channel site="dsmart.com.tr" site_id="6071fb3bcfef0b159373a531" lang="tr" xmltv_id="">Vav Tv</channel>
<channel site="dsmart.com.tr" site_id="6481bce5cfef0b02d29e23d1" lang="tr" xmltv_id="">Bi Kanal</channel>
<channel site="dsmart.com.tr" site_id="6540d968cfef0b02d2dbb177" lang="tr" xmltv_id="">Moonbug</channel> <channel site="dsmart.com.tr" site_id="6540d968cfef0b02d2dbb177" lang="tr" xmltv_id="">Moonbug</channel>
<channel site="dsmart.com.tr" site_id="66630f98cfef0b02d797d815" lang="tr" xmltv_id="CNBCEurope.uk@SD">CNBC-e</channel>
<channel site="dsmart.com.tr" site_id="67e5c4c6cfef0b3744c556fa" lang="tr" xmltv_id="">DMAX</channel> <channel site="dsmart.com.tr" site_id="67e5c4c6cfef0b3744c556fa" lang="tr" xmltv_id="">DMAX</channel>
<channel site="dsmart.com.tr" site_id="67e5c246cfef0b3744c53a83" lang="tr" xmltv_id="">TLC</channel> <channel site="dsmart.com.tr" site_id="67e5c246cfef0b3744c53a83" lang="tr" xmltv_id="">TLC</channel>
<channel site="dsmart.com.tr" site_id="66337391cfef0b02d78776c8" lang="tr" xmltv_id="">Ekol Tv</channel> <channel site="dsmart.com.tr" site_id="69963435cfef0b02ec88cbb0" lang="tr" xmltv_id="">Meltemtv</channel>
<channel site="dsmart.com.tr" site_id="66e7e5cdcfef0b374461c45b" lang="tr" xmltv_id="">Spor Çoklu Ekran</channel> <channel site="dsmart.com.tr" site_id="66e7e5cdcfef0b374461c45b" lang="tr" xmltv_id="">Spor Çoklu Ekran</channel>
<channel site="dsmart.com.tr" site_id="66e7e50dcfef0b374461c36e" lang="tr" xmltv_id="">Ulusal Çoklu Ekran</channel> <channel site="dsmart.com.tr" site_id="66e7e50dcfef0b374461c36e" lang="tr" xmltv_id="">Ulusal Çoklu Ekran</channel>
<channel site="dsmart.com.tr" site_id="66e7e54ccfef0b374461c370" lang="tr" xmltv_id="">Haber Çoklu Ekran</channel> <channel site="dsmart.com.tr" site_id="66e7e54ccfef0b374461c370" lang="tr" xmltv_id="">Haber Çoklu Ekran</channel>
<channel site="dsmart.com.tr" site_id="68e77d8fcfef0b374432906d" lang="tr" xmltv_id="">Spacetoon</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60622e" lang="tr" xmltv_id="24TV.tr@SD">24</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606236" lang="tr" xmltv_id="360.tr@SD">360</channel>
<channel site="dsmart.com.tr" site_id="59638e5fcfef0b43f0fd31b5" lang="tr" xmltv_id="ANews.tr@SD">a News</channel> <channel site="dsmart.com.tr" site_id="59638e5fcfef0b43f0fd31b5" lang="tr" xmltv_id="ANews.tr@SD">a News</channel>
<channel site="dsmart.com.tr" site_id="5e75c923cfef0b15938bc9cc" lang="tr" xmltv_id="">TRT EBA TV</channel> <channel site="dsmart.com.tr" site_id="5b9fb1eecfef0b35341b7eb7" lang="tr" xmltv_id="APara.tr@SD">A Para</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b7" lang="tr" xmltv_id="BabyTV.uk@France">Baby TV</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062c6" lang="tr" xmltv_id="BBCNews.uk@Europe">BBC World News</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60623e" lang="tr" xmltv_id="BloombergHT.tr@SD">Bloomberg HT</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b9" lang="tr" xmltv_id="Cartoonito.uk@SD">Cartoonito</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062c8" lang="tr" xmltv_id="CartoonNetwork.tr@SD">Cartoon Network</channel>
<channel site="dsmart.com.tr" site_id="66630f98cfef0b02d797d815" lang="tr" xmltv_id="CNBCEurope.uk@SD">CNBC-e</channel>
<channel site="dsmart.com.tr" site_id="59dca1f3cfef0b4d80a47a5f" lang="tr" xmltv_id="CNNTurk.tr@SD">CNN Türk SD</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062b6" lang="tr" xmltv_id="DaVinci.de@SD">Da Vinci Learning</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606248" lang="tr" xmltv_id="DiscoveryChannel.tr@SD">Discovery</channel>
<channel site="dsmart.com.tr" site_id="5fedddcecfef0b159330996e" lang="tr" xmltv_id="DisneyJr.tr@SD">Disney Junior</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606278" lang="tr" xmltv_id="DiziSmartMax.tr@SD">Dizi Smart Max</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60625a" lang="tr" xmltv_id="DiziSmartPremium.tr@SD">Dizi Smart Premium</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062c5" lang="tr" xmltv_id="DreamTurk.tr@SD">Dream Tv</channel>
<channel site="dsmart.com.tr" site_id="5c6e8e0ecfef0b613d9ff782" lang="tr" xmltv_id="Ekoturk.tr@SD">Ekotürk</channel>
<channel site="dsmart.com.tr" site_id="59dcbfdccfef0b4d80a4974a" lang="tr" xmltv_id="EuroD.tr@SD">Euro D</channel>
<channel site="dsmart.com.tr" site_id="59dca3b2cfef0b4d80a47b77" lang="tr" xmltv_id="FashionTVEurope.fr@SD">Fashion TV</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606269" lang="tr" xmltv_id="FX.us@East">FX</channel>
<channel site="dsmart.com.tr" site_id="5bac7dedcfef0b02fac035fd" lang="tr" xmltv_id="HaberGlobal.tr@SD">Haber Global</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629d" lang="tr" xmltv_id="HaberturkTV.tr@SD">Haber Türk</channel>
<channel site="dsmart.com.tr" site_id="66d839a0cfef0b37445c6db1" lang="tr" xmltv_id="HTSporTV.tr@SD">HT Spor</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60628e" lang="tr" xmltv_id="InvestigationDiscoveryEurope.us@SD">Discovery ID</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629c" lang="tr" xmltv_id="Kanal7.tr@SD">Kanal 7</channel>
<channel site="dsmart.com.tr" site_id="5dfc9faacfef0b201d2246b5" lang="tr" xmltv_id="LoveNature.ca@SD">Love Nature</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606257" lang="tr" xmltv_id="MinikaGo.tr@SD">Minika GO</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629a" lang="tr" xmltv_id="MovieSmartClassic.tr@SD">MovieSmart Classic</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606299" lang="tr" xmltv_id="MovieSmartTurk.tr@SD">MovieSmart Türk</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062a4" lang="tr" xmltv_id="NationalGeographic.tr@SD">National Geographic</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062a5" lang="tr" xmltv_id="NationalGeographicWild.tr@SD">National Geographic WILD</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062a0" lang="tr" xmltv_id="NOWTV.tr@SD">NOW</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60623a" lang="tr" xmltv_id="NTV.tr@SD">NTV</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629b" lang="tr" xmltv_id="ShowTV.tr@SD">Show TV</channel>
<channel site="dsmart.com.tr" site_id="5fe07d9fcfef0b1593275754" lang="tr" xmltv_id="Sinema2.tr@SD">Sinema TV 2</channel>
<channel site="dsmart.com.tr" site_id="5fe07f5dcfef0b1593275822" lang="tr" xmltv_id="Sinema1001.tr@SD">Sinema TV 1001</channel>
<channel site="dsmart.com.tr" site_id="5fe07f72cfef0b159327585a" lang="tr" xmltv_id="Sinema1002.tr@SD">Sinema TV 1002</channel>
<channel site="dsmart.com.tr" site_id="5fe07eabcfef0b15932757a6" lang="tr" xmltv_id="SinemaAile2.tr@SD">Sinema TV Aile 2</channel>
<channel site="dsmart.com.tr" site_id="5fe07e42cfef0b15932757a3" lang="tr" xmltv_id="SinemaAile.tr@SD">Sinema TV Aile</channel>
<channel site="dsmart.com.tr" site_id="5fe07e23cfef0b15932757a1" lang="tr" xmltv_id="SinemaAksiyon2.tr@SD">Sinema TV Aksiyon 2</channel>
<channel site="dsmart.com.tr" site_id="5fe07dd5cfef0b1593275758" lang="tr" xmltv_id="SinemaAksiyon.tr@SD">Sinema TV Aksiyon</channel>
<channel site="dsmart.com.tr" site_id="5fe07f45cfef0b159327581f" lang="tr" xmltv_id="SinemaKomedi2.tr@SD">Sinema TV Comedy 2</channel>
<channel site="dsmart.com.tr" site_id="5fe07f29cfef0b1593275800" lang="tr" xmltv_id="SinemaKomedi.tr@SD">Sinema TV Comedy</channel>
<channel site="dsmart.com.tr" site_id="5fe07d7acfef0b1593275751" lang="tr" xmltv_id="SinemaTV.tr@SD">Sinema TV</channel>
<channel site="dsmart.com.tr" site_id="63ecd91acfef0b02d2687aed" lang="tr" xmltv_id="SozcuTV.tr@SD">SZC</channel>
<channel site="dsmart.com.tr" site_id="5fcb6bd2cfef0b15931fcdf8" lang="tr" xmltv_id="SporSmart2.tr@SD">SPOR SMART 2</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60628a" lang="tr" xmltv_id="SporSmart.tr@SD">Spor Smart</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c606259" lang="tr" xmltv_id="StarTV.tr@SD">Star</channel>
<channel site="dsmart.com.tr" site_id="64edfc67cfef0b02d2c038c5" lang="tr" xmltv_id="TarihTV.tr@SD">Tarih Tv</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062a1" lang="tr" xmltv_id="Teve2.tr@SD">teve2</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60623d" lang="tr" xmltv_id="TGRTHaber.tr@SD">TGRT Haber</channel>
<channel site="dsmart.com.tr" site_id="59dca577cfef0b4d80a47b7c" lang="tr" xmltv_id="TV4.tr@SD">TV4</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062ae" lang="tr" xmltv_id="TV8.tr@SD">TV8</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062cb" lang="tr" xmltv_id="TV85.tr@SD">TV 8,5</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629e" lang="tr" xmltv_id="TVNET.tr@SD">TV Net</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c60629f" lang="tr" xmltv_id="UlkeTV.tr@SD">Ülke TV</channel>
<channel site="dsmart.com.tr" site_id="58d29bb0eefad3db9c6062bd" lang="tr" xmltv_id="ViasatHistory.tr@SD">Viasat History</channel>
</channels> </channels>

View File

@@ -2,7 +2,7 @@ const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const customParseFormat = require('dayjs/plugin/customParseFormat') const customParseFormat = require('dayjs/plugin/customParseFormat')
const duration = require('dayjs/plugin/duration') const duration = require('dayjs/plugin/duration')
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const debug = require('debug')('site:dsmart.com.tr') const debug = require('debug')('site:dsmart.com.tr')
dayjs.extend(utc) dayjs.extend(utc)

View File

@@ -1,38 +1,31 @@
const { parser, url } = require('./dsmart.com.tr.config.js') const { parser, url } = require('./dsmart.com.tr.config.js')
const axios = require('axios')
const dayjs = require('dayjs') const dayjs = require('dayjs')
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const customParseFormat = require('dayjs/plugin/customParseFormat') const customParseFormat = require('dayjs/plugin/customParseFormat')
const multifetch = require('../../scripts/core/multifetch')
dayjs.extend(customParseFormat) dayjs.extend(customParseFormat)
dayjs.extend(utc) dayjs.extend(utc)
jest.mock('axios')
const date = dayjs.utc('2025-01-13', 'YYYY-MM-DD').startOf('d') const date = dayjs.utc('2025-01-13', 'YYYY-MM-DD').startOf('d')
const channel = { const channel = {
site_id: '5fe07f5dcfef0b1593275822', site_id: '5fe07f5dcfef0b1593275822',
xmltv_id: 'Sinema1001.tr' xmltv_id: 'Sinema1001.tr'
} }
axios.get.mockImplementation(url => { beforeEach(() => {
const result = {} multifetch.setMocks({
const urls = {
'https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=1&limit=10&day=2025-01-13': 'https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=1&limit=10&day=2025-01-13':
'content1.json', 'content1.json',
'https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=2&limit=10&day=2025-01-13': 'https://www.dsmart.com.tr/api/v1/public/epg/schedules?page=2&limit=10&day=2025-01-13':
'content2.json', 'content2.json',
} }, __dirname + '/__data__')
if (urls[url] !== undefined) { })
result.data = fs.readFileSync(path.join(__dirname, '__data__', urls[url])).toString()
if (!urls[url].startsWith('content1')) {
result.data = JSON.parse(result.data)
}
}
return Promise.resolve(result) afterEach(() => {
multifetch.clearMocks()
}) })

View File

@@ -1,5 +1,6 @@
const dayjs = require('dayjs') const dayjs = require('dayjs')
const axios = require('axios') const axios = require('axios')
const parseDuration = require('parse-duration').default
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const timezone = require('dayjs/plugin/timezone') const timezone = require('dayjs/plugin/timezone')
const customParseFormat = require('dayjs/plugin/customParseFormat') const customParseFormat = require('dayjs/plugin/customParseFormat')
@@ -65,7 +66,7 @@ module.exports = {
} }
items.forEach(item => { items.forEach(item => {
const { start, stop } = parseDuration(date, item) const { start, stop } = parseTimes(date, item)
if (!start.isValid() || !stop.isValid()) return if (!start.isValid() || !stop.isValid()) return
// Can contain Season and Episode in title, but not always. If title is missing, skip the program // Can contain Season and Episode in title, but not always. If title is missing, skip the program
if (!item?.content?.title) return if (!item?.content?.title) return
@@ -124,32 +125,20 @@ module.exports = {
} }
} }
function parseDuration(date, item) { function parseTimes(date, item) {
const current_date = date.format('YYYY-MM-DD')
const time = item.content?.broadcastBeginDate const time = item.content?.broadcastBeginDate
const duration = item.content?.duration // e.g. "11 min 45 s", "1 h 30 min", "30 min" const durationStr = item.content?.duration // e.g. "11 min 45 s", "1 h 30 min", "30 min"
if (!time) return { start: dayjs(null), stop: dayjs(null) } if (!time) return { start: dayjs(null), stop: dayjs(null) }
const timeParts = time.split('h') const timeParts = time.split('h')
const start = dayjs.utc(`${date.format('YYYY-MM-DD')} ${timeParts[0]}:${timeParts[1]}`, 'YYYY-MM-DD HH:mm')
let durationInSeconds = 0
if (duration) { let stop = start
const durationParts = duration.split(' ') if (durationStr) {
for (let i = 0; i < durationParts.length; i++) { stop = start.add(parseDuration(durationStr) || 0, 'ms')
const part = durationParts[i]
if (part === 'h' && i > 0) {
durationInSeconds += parseInt(durationParts[i - 1]) * 3600
} else if (part === 'min' && i > 0) {
durationInSeconds += parseInt(durationParts[i - 1]) * 60
} else if (part === 's' && i > 0) {
durationInSeconds += parseInt(durationParts[i - 1])
}
}
} }
const start = dayjs.utc(`${current_date} ${timeParts[0]}:${timeParts[1]}`, 'YYYY-MM-DD HH:mm')
const stop = start.add(durationInSeconds, 'second')
return { start, stop } return { start, stop }
} }

View File

@@ -4,7 +4,7 @@ const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const timezone = require('dayjs/plugin/timezone') const timezone = require('dayjs/plugin/timezone')
const customParseFormat = require('dayjs/plugin/customParseFormat') const customParseFormat = require('dayjs/plugin/customParseFormat')
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const debug = require('debug')('site:mncvision.id') const debug = require('debug')('site:mncvision.id')
dayjs.extend(utc) dayjs.extend(utc)
@@ -150,10 +150,14 @@ async function parseItems(content, date, cookies) {
function loadLangCookies(channel) { function loadLangCookies(channel) {
const url = `https://www.mncvision.id/language_switcher/setlang/${languages[channel.lang]}/` const url = `https://www.mncvision.id/language_switcher/setlang/${languages[channel.lang]}/`
return axios return new Promise(resolve => {
.get(url, { timeout }) doFetch([{ url, method: 'get' }], (queue, data, headers) => {
.then(r => parseCookies(r.headers)) resolve(parseCookies(headers))
.catch(error => console.error(error.message)) }).catch(error => {
console.error(error.message)
resolve(null)
})
})
} }
function parseCookies(headers) { function parseCookies(headers) {

View File

@@ -1,10 +1,10 @@
const { parser, url, request } = require('./mncvision.id.config.js') const { parser, url, request } = require('./mncvision.id.config.js')
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
const axios = require('axios')
const dayjs = require('dayjs') const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const customParseFormat = require('dayjs/plugin/customParseFormat') const customParseFormat = require('dayjs/plugin/customParseFormat')
const multifetch = require('../../scripts/core/multifetch')
dayjs.extend(customParseFormat) dayjs.extend(customParseFormat)
dayjs.extend(utc) dayjs.extend(utc)
@@ -28,38 +28,34 @@ const englishHeaders = {
] ]
} }
axios.get.mockImplementation((url, opts) => { beforeEach(() => {
if (url === 'https://www.mncvision.id/language_switcher/setlang/indonesia/') { const getCookie = headers => {
return Promise.resolve({ if (Array.isArray(headers['set-cookie'])) {
headers: indonesiaHeaders return headers['set-cookie'][0].split('; ')[0]
})
}
if (url === 'https://www.mncvision.id/language_switcher/setlang/english/') {
return Promise.resolve({
headers: englishHeaders
})
}
if (
url === 'https://www.mncvision.id/schedule/detail/20231119001500154/Blue-Bloods-S13-Ep-19/1'
) {
const getCookie = headers => {
if (Array.isArray(headers['set-cookie'])) {
return headers['set-cookie'][0].split('; ')[0]
}
}
if (opts.headers['Cookie'] === getCookie(indonesiaHeaders)) {
return Promise.resolve({
data: fs.readFileSync(path.resolve(__dirname, '__data__/program_id.html'))
})
}
if (opts.headers['Cookie'] === getCookie(englishHeaders)) {
return Promise.resolve({
data: fs.readFileSync(path.resolve(__dirname, '__data__/program_en.html'))
})
} }
} }
return Promise.resolve({ data: '' }) multifetch.setMocks({
'https://www.mncvision.id/language_switcher/setlang/indonesia/': () => ({
headers: indonesiaHeaders
}),
'https://www.mncvision.id/language_switcher/setlang/english/': () => ({
headers: englishHeaders
}),
'https://www.mncvision.id/schedule/detail/20231119001500154/Blue-Bloods-S13-Ep-19/1': (url, config) => {
if (config?.headers?.['Cookie'] === getCookie(indonesiaHeaders)) {
return { data: fs.readFileSync(path.resolve(__dirname, '__data__/program_id.html'), 'utf8'), status: 200 }
}
if (config?.headers?.['Cookie'] === getCookie(englishHeaders)) {
return { data: fs.readFileSync(path.resolve(__dirname, '__data__/program_en.html'), 'utf8'), status: 200 }
}
return { data: '', status: 404 }
}
})
})
afterEach(() => {
multifetch.clearMocks()
}) })
it('can generate valid url', () => { it('can generate valid url', () => {

View File

@@ -1,4 +1,4 @@
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const axios = require('axios') const axios = require('axios')
const dayjs = require('dayjs') const dayjs = require('dayjs')
const crypto = require('crypto') const crypto = require('crypto')

View File

@@ -1,4 +1,4 @@
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const dayjs = require('dayjs') const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const timezone = require('dayjs/plugin/timezone') const timezone = require('dayjs/plugin/timezone')

View File

@@ -1,13 +1,10 @@
const dayjs = require('dayjs') const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const debug = require('debug')('site:orangetv.orange.es')
dayjs.extend(utc) dayjs.extend(utc)
doFetch.setDebugger(debug) const API_PROGRAM_ENDPOINT = 'https://epg.orangetv.orange.es/epg/SmartTV_Android/1_PRO'
const API_PROGRAM_ENDPOINT = 'https://epg.orangetv.orange.es/epg/Smartphone_Android/1_PRO'
const API_CHANNEL_ENDPOINT = const API_CHANNEL_ENDPOINT =
'https://pc.orangetv.orange.es/pc/api/rtv/v1/GetChannelList?bouquet_id=1&model_external_id=PC&filter_unsupported_channels=false&client=json' 'https://pc.orangetv.orange.es/pc/api/rtv/v1/GetChannelList?bouquet_id=1&model_external_id=PC&filter_unsupported_channels=false&client=json'
const API_IMAGE_ENDPOINT = 'https://pc.orangetv.orange.es/pc/api/rtv/v1/images' const API_IMAGE_ENDPOINT = 'https://pc.orangetv.orange.es/pc/api/rtv/v1/images'

View File

@@ -20,11 +20,11 @@ const channel = {
axios.get.mockImplementation(url => { axios.get.mockImplementation(url => {
const result = {} const result = {}
const urls = { const urls = {
'https://epg.orangetv.orange.es/epg/Smartphone_Android/1_PRO/20250112_8h_1.json': 'https://epg.orangetv.orange.es/epg/SmartTV_Android/1_PRO/20250112_8h_1.json':
'data1.json', 'data1.json',
'https://epg.orangetv.orange.es/epg/Smartphone_Android/1_PRO/20250112_8h_2.json': 'https://epg.orangetv.orange.es/epg/SmartTV_Android/1_PRO/20250112_8h_2.json':
'data2.json', 'data2.json',
'https://epg.orangetv.orange.es/epg/Smartphone_Android/1_PRO/20250112_8h_3.json': 'https://epg.orangetv.orange.es/epg/SmartTV_Android/1_PRO/20250112_8h_3.json':
'data3.json', 'data3.json',
} }
if (urls[url] !== undefined) { if (urls[url] !== undefined) {
@@ -39,7 +39,7 @@ axios.get.mockImplementation(url => {
it('can generate valid url', () => { it('can generate valid url', () => {
expect(url({ date })).toBe( expect(url({ date })).toBe(
'https://epg.orangetv.orange.es/epg/Smartphone_Android/1_PRO/20250112_8h_1.json' 'https://epg.orangetv.orange.es/epg/SmartTV_Android/1_PRO/20250112_8h_1.json'
) )
}) })

View File

@@ -4,7 +4,7 @@ const dayjs = require('dayjs')
const timezone = require('dayjs/plugin/timezone') const timezone = require('dayjs/plugin/timezone')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const customParseFormat = require('dayjs/plugin/customParseFormat') const customParseFormat = require('dayjs/plugin/customParseFormat')
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const debug = require('debug')('site:rotana.net') const debug = require('debug')('site:rotana.net')
dayjs.extend(timezone) dayjs.extend(timezone)

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<channels> <channels>
<channel site="sky.com" site_id="1001" lang="en" xmltv_id="">Sky Action</channel>
<channel site="sky.com" site_id="1015" lang="en" xmltv_id="">Really+1</channel> <channel site="sky.com" site_id="1015" lang="en" xmltv_id="">Really+1</channel>
<channel site="sky.com" site_id="1022" lang="en" xmltv_id="">Sky Intro</channel> <channel site="sky.com" site_id="1022" lang="en" xmltv_id="">Sky Intro</channel>
<channel site="sky.com" site_id="1035" lang="en" xmltv_id="">SkySpBoxOffHD</channel> <channel site="sky.com" site_id="1035" lang="en" xmltv_id="">SkySpBoxOffHD</channel>
@@ -8,14 +9,28 @@
<channel site="sky.com" site_id="1084" lang="en" xmltv_id="">55250</channel> <channel site="sky.com" site_id="1084" lang="en" xmltv_id="">55250</channel>
<channel site="sky.com" site_id="1102" lang="en" xmltv_id="">Sky Intro</channel> <channel site="sky.com" site_id="1102" lang="en" xmltv_id="">Sky Intro</channel>
<channel site="sky.com" site_id="1148" lang="en" xmltv_id="">Virgin Radio</channel> <channel site="sky.com" site_id="1148" lang="en" xmltv_id="">Virgin Radio</channel>
<channel site="sky.com" site_id="1149" lang="en" xmltv_id="">TNTSports1 HD</channel>
<channel site="sky.com" site_id="1183" lang="en" xmltv_id="">Disney Jr HD</channel> <channel site="sky.com" site_id="1183" lang="en" xmltv_id="">Disney Jr HD</channel>
<channel site="sky.com" site_id="1190" lang="en" xmltv_id="">Disney+CineHD</channel> <channel site="sky.com" site_id="1190" lang="en" xmltv_id="">Disney+CineHD</channel>
<channel site="sky.com" site_id="1205" lang="en" xmltv_id="">LBC News</channel> <channel site="sky.com" site_id="1205" lang="en" xmltv_id="">LBC News</channel>
<channel site="sky.com" site_id="1218" lang="en" xmltv_id="">TNTSBoxOff2HD</channel>
<channel site="sky.com" site_id="1229" lang="en" xmltv_id="">Sky Arts</channel> <channel site="sky.com" site_id="1229" lang="en" xmltv_id="">Sky Arts</channel>
<channel site="sky.com" site_id="1261" lang="en" xmltv_id="">RTÉ Radio 1</channel> <channel site="sky.com" site_id="1261" lang="en" xmltv_id="">RTÉ Radio 1</channel>
<channel site="sky.com" site_id="1262" lang="en" xmltv_id="">RTÉ 2FM</channel> <channel site="sky.com" site_id="1262" lang="en" xmltv_id="">RTÉ 2FM</channel>
<channel site="sky.com" site_id="1263" lang="en" xmltv_id="">RTÉ R na G</channel> <channel site="sky.com" site_id="1263" lang="en" xmltv_id="">RTÉ R na G</channel>
<channel site="sky.com" site_id="1264" lang="en" xmltv_id="">RTÉ Lyric fm</channel> <channel site="sky.com" site_id="1264" lang="en" xmltv_id="">RTÉ Lyric fm</channel>
<channel site="sky.com" site_id="1281" lang="en" xmltv_id="">Sky Showcase</channel>
<channel site="sky.com" site_id="1340" lang="en" xmltv_id="">SkySp News HD</channel>
<channel site="sky.com" site_id="1341" lang="en" xmltv_id="">SkySpMainEv</channel>
<channel site="sky.com" site_id="1342" lang="en" xmltv_id="">SkySp Cricket</channel>
<channel site="sky.com" site_id="1343" lang="en" xmltv_id="">SkySp Action</channel>
<channel site="sky.com" site_id="1348" lang="en" xmltv_id="">SkySp News</channel>
<channel site="sky.com" site_id="1362" lang="en" xmltv_id="">SkySp Tennis HD</channel>
<channel site="sky.com" site_id="1400" lang="en" xmltv_id="">Sky One HD</channel>
<channel site="sky.com" site_id="1403" lang="en" xmltv_id="">Sky One</channel>
<channel site="sky.com" site_id="1701" lang="en" xmltv_id="">SkySpMainEvHD</channel>
<channel site="sky.com" site_id="1808" lang="en" xmltv_id="">Sky Family</channel>
<channel site="sky.com" site_id="1815" lang="en" xmltv_id="">Sky Greats</channel>
<channel site="sky.com" site_id="2021" lang="en" xmltv_id="">BBC R Cymru 2</channel> <channel site="sky.com" site_id="2021" lang="en" xmltv_id="">BBC R Cymru 2</channel>
<channel site="sky.com" site_id="2026" lang="en" xmltv_id="">BBC R5L</channel> <channel site="sky.com" site_id="2026" lang="en" xmltv_id="">BBC R5L</channel>
<channel site="sky.com" site_id="2034" lang="en" xmltv_id="">BBC R5SX</channel> <channel site="sky.com" site_id="2034" lang="en" xmltv_id="">BBC R5SX</channel>
@@ -48,14 +63,35 @@
<channel site="sky.com" site_id="2971" lang="en" xmltv_id="">Capital XTRA</channel> <channel site="sky.com" site_id="2971" lang="en" xmltv_id="">Capital XTRA</channel>
<channel site="sky.com" site_id="3021" lang="en" xmltv_id="">BBC ALBA HD</channel> <channel site="sky.com" site_id="3021" lang="en" xmltv_id="">BBC ALBA HD</channel>
<channel site="sky.com" site_id="3082" lang="en" xmltv_id="">Sky One HD</channel> <channel site="sky.com" site_id="3082" lang="en" xmltv_id="">Sky One HD</channel>
<channel site="sky.com" site_id="3142" lang="en" xmltv_id="">TNT Sports 4</channel>
<channel site="sky.com" site_id="3363" lang="en" xmltv_id="">Panjab Radio</channel> <channel site="sky.com" site_id="3363" lang="en" xmltv_id="">Panjab Radio</channel>
<channel site="sky.com" site_id="3371" lang="en" xmltv_id="">BFBS Radio</channel> <channel site="sky.com" site_id="3371" lang="en" xmltv_id="">BFBS Radio</channel>
<channel site="sky.com" site_id="3392" lang="en" xmltv_id="">SonLife</channel> <channel site="sky.com" site_id="3392" lang="en" xmltv_id="">SonLife</channel>
<channel site="sky.com" site_id="3470" lang="en" xmltv_id="">Classic FM</channel> <channel site="sky.com" site_id="3470" lang="en" xmltv_id="">Classic FM</channel>
<channel site="sky.com" site_id="3628" lang="en" xmltv_id="">TNTSports2 HD</channel>
<channel site="sky.com" site_id="3630" lang="en" xmltv_id="">TNTSports3 HD</channel>
<channel site="sky.com" site_id="3662" lang="en" xmltv_id="">TNT Sports 1</channel>
<channel site="sky.com" site_id="3664" lang="en" xmltv_id="">TNT Sports 2</channel>
<channel site="sky.com" site_id="3836" lang="en" xmltv_id="">SkySp F1 HD</channel>
<channel site="sky.com" site_id="3843" lang="en" xmltv_id="">SkySp F&apos;ball HD</channel>
<channel site="sky.com" site_id="3848" lang="en" xmltv_id="">SkySp F&apos;ball</channel>
<channel site="sky.com" site_id="3858" lang="en" xmltv_id="">SkySp+ HD</channel>
<channel site="sky.com" site_id="3859" lang="en" xmltv_id="">SkySp+</channel>
<channel site="sky.com" site_id="4024" lang="en" xmltv_id="">SkySp ActionHD</channel>
<channel site="sky.com" site_id="4027" lang="en" xmltv_id="">SkySp Golf HD</channel>
<channel site="sky.com" site_id="4029" lang="en" xmltv_id="">SkySp PL HD</channel>
<channel site="sky.com" site_id="4036" lang="en" xmltv_id="">SkySp News HD</channel>
<channel site="sky.com" site_id="4041" lang="en" xmltv_id="">TNTSports4 HD</channel>
<channel site="sky.com" site_id="4052" lang="en" xmltv_id="">SkySp Racing HD</channel>
<channel site="sky.com" site_id="4085" lang="en" xmltv_id="">SkySpCricket HD</channel>
<channel site="sky.com" site_id="4092" lang="en" xmltv_id="">SkySp Mix HD</channel>
<channel site="sky.com" site_id="4093" lang="en" xmltv_id="">SkySp Mix</channel>
<channel site="sky.com" site_id="4158" lang="en" xmltv_id="">WRN Europe</channel> <channel site="sky.com" site_id="4158" lang="en" xmltv_id="">WRN Europe</channel>
<channel site="sky.com" site_id="4163" lang="en" xmltv_id="">EWTN Catholic</channel> <channel site="sky.com" site_id="4163" lang="en" xmltv_id="">EWTN Catholic</channel>
<channel site="sky.com" site_id="4611" lang="en" xmltv_id="">LEGEND</channel> <channel site="sky.com" site_id="4611" lang="en" xmltv_id="">LEGEND</channel>
<channel site="sky.com" site_id="5033" lang="en" xmltv_id="">TNT Sports 3</channel>
<channel site="sky.com" site_id="5040" lang="en" xmltv_id="">Arise News</channel> <channel site="sky.com" site_id="5040" lang="en" xmltv_id="">Arise News</channel>
<channel site="sky.com" site_id="6014" lang="en" xmltv_id="">TNTSBoxOffHD</channel>
<channel site="sky.com" site_id="8040" lang="en" xmltv_id="">My Sky</channel> <channel site="sky.com" site_id="8040" lang="en" xmltv_id="">My Sky</channel>
<channel site="sky.com" site_id="8266" lang="en" xmltv_id="">My Account</channel> <channel site="sky.com" site_id="8266" lang="en" xmltv_id="">My Account</channel>
<channel site="sky.com" site_id="8301" lang="en" xmltv_id="">Program Your Remote</channel> <channel site="sky.com" site_id="8301" lang="en" xmltv_id="">Program Your Remote</channel>
@@ -319,8 +355,8 @@
<channel site="sky.com" site_id="1857" lang="en" xmltv_id="NickJr.uk@SD">Nick Jr.</channel> <channel site="sky.com" site_id="1857" lang="en" xmltv_id="NickJr.uk@SD">Nick Jr.</channel>
<channel site="sky.com" site_id="5192" lang="en" xmltv_id="NickJrToo.ie@SD">Nick Jr. Too</channel> <channel site="sky.com" site_id="5192" lang="en" xmltv_id="NickJrToo.ie@SD">Nick Jr. Too</channel>
<channel site="sky.com" site_id="4340" lang="en" xmltv_id="NickJrToo.uk@SD">Nick Jr. Too</channel> <channel site="sky.com" site_id="4340" lang="en" xmltv_id="NickJrToo.uk@SD">Nick Jr. Too</channel>
<channel site="sky.com" site_id="5527" lang="en" xmltv_id="Nicktoons.ie@SD">Nick Alvinnnn!!!</channel> <channel site="sky.com" site_id="5527" lang="en" xmltv_id="Nicktoons.ie@SD">Nick SpongeBob</channel>
<channel site="sky.com" site_id="1849" lang="en" xmltv_id="Nicktoons.uk@SD">Nick Alvinnnn!!!</channel> <channel site="sky.com" site_id="1849" lang="en" xmltv_id="Nicktoons.uk@SD">Nick SpongeBob</channel>
<channel site="sky.com" site_id="3715" lang="en" xmltv_id="NoorTV.uk@SD">Noor TV</channel> <channel site="sky.com" site_id="3715" lang="en" xmltv_id="NoorTV.uk@SD">Noor TV</channel>
<channel site="sky.com" site_id="3403" lang="en" xmltv_id="Now70s.uk@SD">NOW 70s</channel> <channel site="sky.com" site_id="3403" lang="en" xmltv_id="Now70s.uk@SD">NOW 70s</channel>
<channel site="sky.com" site_id="4541" lang="en" xmltv_id="Now80s.uk@SD">NOW 80s</channel> <channel site="sky.com" site_id="4541" lang="en" xmltv_id="Now80s.uk@SD">NOW 80s</channel>
@@ -378,7 +414,7 @@
<channel site="sky.com" site_id="4016" lang="en" xmltv_id="SkyCinemaDrama.uk@HD">Sky Drama HD</channel> <channel site="sky.com" site_id="4016" lang="en" xmltv_id="SkyCinemaDrama.uk@HD">Sky Drama HD</channel>
<channel site="sky.com" site_id="4018" lang="en" xmltv_id="SkyCinemaFamily.uk@HD">Sky Family HD</channel> <channel site="sky.com" site_id="4018" lang="en" xmltv_id="SkyCinemaFamily.uk@HD">Sky Family HD</channel>
<channel site="sky.com" site_id="4015" lang="en" xmltv_id="SkyCinemaGreats.uk@SD">Sky Greats HD</channel> <channel site="sky.com" site_id="4015" lang="en" xmltv_id="SkyCinemaGreats.uk@SD">Sky Greats HD</channel>
<channel site="sky.com" site_id="4033" lang="en" xmltv_id="SkyCinemaHits.uk@SD">Sky Box Set HD</channel> <channel site="sky.com" site_id="4033" lang="en" xmltv_id="SkyCinemaHits.uk@SD">SkyBiopicsHD</channel>
<channel site="sky.com" site_id="4021" lang="en" xmltv_id="SkyCinemaPremiere.uk@HD">SkyPremiereHD</channel> <channel site="sky.com" site_id="4021" lang="en" xmltv_id="SkyCinemaPremiere.uk@HD">SkyPremiereHD</channel>
<channel site="sky.com" site_id="4017" lang="en" xmltv_id="SkyCinemaSciFiHorror.uk@HD">Sky ScFi/HorHD</channel> <channel site="sky.com" site_id="4017" lang="en" xmltv_id="SkyCinemaSciFiHorror.uk@HD">Sky ScFi/HorHD</channel>
<channel site="sky.com" site_id="4020" lang="en" xmltv_id="SkyCinemaSelect.uk@SD">Sky5*MoviesHD</channel> <channel site="sky.com" site_id="4020" lang="en" xmltv_id="SkyCinemaSelect.uk@SD">Sky5*MoviesHD</channel>

View File

@@ -1,17 +1,13 @@
const dayjs = require('dayjs') const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const timezone = require('dayjs/plugin/timezone') const timezone = require('dayjs/plugin/timezone')
const doFetch = require('@ntlab/sfetch') const axios = require('axios')
const debug = require('debug')('site:sky.com') const doFetch = require('../../scripts/core/multifetch')
const sortBy = require('lodash.sortby') const sortBy = require('lodash.sortby')
const path = require('path')
const fs = require('fs/promises')
dayjs.extend(utc) dayjs.extend(utc)
dayjs.extend(timezone) dayjs.extend(timezone)
doFetch.setDebugger(debug)
module.exports = { module.exports = {
site: 'sky.com', site: 'sky.com',
days: 2, days: 2,
@@ -53,24 +49,15 @@ module.exports = {
return programs return programs
}, },
async channels() { async channels() {
const dataPath = path.join(__dirname, '__data__', 'content.json') const regions = await axios.get('https://epgservices.sky.com/999/api/2.0/regions/json')
let regions = [] .then(res => res.data.regions)
.then(region => region.map(region => {
try { if (!region || region.b === undefined || region.sb === undefined) return null
const raw = await fs.readFile(dataPath, 'utf8') return {
const payload = JSON.parse(raw) bouquet: region.b,
if (Array.isArray(payload.regions)) { subBouquet: region.sb
regions = payload.regions
} }
} catch (err) { }).filter(region => region !== null))
debug('Failed to read regions from %s: %o', dataPath, err)
throw err
}
if (regions.length === 0) {
debug('No regions defined in %s', dataPath)
return []
}
const uniqueRegions = new Map() const uniqueRegions = new Map()
regions.forEach(region => { regions.forEach(region => {

View File

@@ -2,7 +2,7 @@ const cheerio = require('cheerio')
const dayjs = require('dayjs') const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const customParseFormat = require('dayjs/plugin/customParseFormat') const customParseFormat = require('dayjs/plugin/customParseFormat')
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const debug = require('debug')('site:startimestv.com') const debug = require('debug')('site:startimestv.com')
dayjs.extend(utc) dayjs.extend(utc)

View File

@@ -4,7 +4,7 @@ const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const timezone = require('dayjs/plugin/timezone') const timezone = require('dayjs/plugin/timezone')
const customParseFormat = require('dayjs/plugin/customParseFormat') const customParseFormat = require('dayjs/plugin/customParseFormat')
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const debug = require('debug')('site:tivie.id') const debug = require('debug')('site:tivie.id')
dayjs.extend(utc) dayjs.extend(utc)

View File

@@ -1,4 +1,4 @@
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const cheerio = require('cheerio') const cheerio = require('cheerio')
const dayjs = require('dayjs') const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')

View File

@@ -4,7 +4,7 @@ const cheerio = require('cheerio')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const timezone = require('dayjs/plugin/timezone') const timezone = require('dayjs/plugin/timezone')
const customParseFormat = require('dayjs/plugin/customParseFormat') const customParseFormat = require('dayjs/plugin/customParseFormat')
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const FRENCH_CHANNELS = require('./__data__/frenchChannels.js') const FRENCH_CHANNELS = require('./__data__/frenchChannels.js')
dayjs.extend(utc) dayjs.extend(utc)

View File

@@ -1,6 +1,6 @@
const dayjs = require('dayjs') const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
const debug = require('debug')('site:virgintvgo.virginmedia.com') const debug = require('debug')('site:virgintvgo.virginmedia.com')
dayjs.extend(utc) dayjs.extend(utc)

View File

@@ -3,7 +3,7 @@ const axios = require('axios')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const timezone = require('dayjs/plugin/timezone') const timezone = require('dayjs/plugin/timezone')
const customParseFormat = require('dayjs/plugin/customParseFormat') const customParseFormat = require('dayjs/plugin/customParseFormat')
const doFetch = require('@ntlab/sfetch') const doFetch = require('../../scripts/core/multifetch')
dayjs.extend(utc) dayjs.extend(utc)
dayjs.extend(timezone) dayjs.extend(timezone)