diff --git a/README.md b/README.md index eb966322..e1840292 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Options: -l, --lang Filter channels by language (ISO 639-2 code) -t, --timeout Override the default timeout for each request -d, --delay Override the default delay between request + -x, --proxy Use the specified proxy (example: "socks5://username:password@127.0.0.1:1234") --days Override the number of days for which the program will be loaded (defaults to the value from the site config) --maxConnections Limit on the number of concurrent requests (default: 1) diff --git a/SITES.md b/SITES.md index 6324c2ee..77da2441 100644 --- a/SITES.md +++ b/SITES.md @@ -28,7 +28,7 @@ berrymedia.co.kr5 / 5馃煝 cablego.com.pe100 / 20馃煝 cableplus.com.uy171 / 47馃煝 - canalplus.com11591 / 212馃煝 + canalplus.com11720 / 212馃煝 cgates.lt102 / 61馃煝 chada.ma1 / 1馃煝 chaines-tv.orange.fr296 / 147馃煝 @@ -191,7 +191,7 @@ tvcesoir.fr135 / 133馃煝 tvcubana.icrt.cu10 / 10馃煝 tvgids.nl115 / 90馃煝 - tvguide.com153 / 150馃煝 + tvguide.com153 / 150馃煛https://github.com/iptv-org/epg/issues/2644 tvguide.myjcom.jp145 / 140馃煝 tvhebdo.com317 / 215馃煝 tvheute.at53 / 53馃煝 diff --git a/package-lock.json b/package-lock.json index 31a33148..a6b4180f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@alex_neo/jest-expect-message": "^1.0.5", "@eslint/eslintrc": "^3.2.0", "@eslint/js": "^9.17.0", - "@freearhey/core": "^0.5.0", + "@freearhey/core": "^0.5.1", "@ntlab/sfetch": "^1.0.0", "@octokit/core": "^6.1.3", "@octokit/plugin-paginate-rest": "^11.3.6", @@ -38,7 +38,7 @@ "csv-parser": "^3.0.0", "cwait": "^1.1.2", "dayjs": "^1.11.10", - "epg-grabber": "^0.37.4", + "epg-grabber": "^0.37.5", "epg-parser": "^0.3.1", "eslint": "^9.17.0", "eslint-config-prettier": "^9.0.0", @@ -69,6 +69,7 @@ "serve": "^14.2.4", "signale": "^1.4.0", "skip-postinstall": "^1.0.0", + "socks-proxy-agent": "^8.0.5", "srcset": "^4.0.0", "table2array": "^0.0.2", "tabletojson": "^2.0.7", @@ -1203,9 +1204,9 @@ } }, "node_modules/@freearhey/core": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.5.0.tgz", - "integrity": "sha512-FcA5Pv9RvFvLYAwNmD/2vlSR49Rx+kihJ+xbIUgIACHY6lBUptfbNznm00DQoUyWRJG/cfT3dkYCwIxSUsdP+w==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.5.1.tgz", + "integrity": "sha512-UDKIOyrtcUXaiAeIvjNFTI6DlempiOQaRB83CqHNF1VPRHNBiNhGhERWyInHE2cjLp/cc0CA/IykOYS39kBK7Q==", "dependencies": { "@types/fs-extra": "^11.0.2", "@types/lodash": "^4.14.198", @@ -4192,9 +4193,9 @@ } }, "node_modules/epg-grabber": { - "version": "0.37.4", - "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.37.4.tgz", - "integrity": "sha512-PS104bH9tHRa9kivSwx47AKMkfHwKy51XQTx+GO6sIXvIp2Z4LBpwMEXGcfPoAsdIGxgs2Wrl0dZ/QGL+7x6YQ==", + "version": "0.37.5", + "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.37.5.tgz", + "integrity": "sha512-mkT22NU5docsw6qJByBC5oMKFYETyX/PU7Iq3MQ1MS4A+C2Ale6tm+QN7BRW/9Cd5/szfr/YdkzDUZaoyO5vvw==", "dependencies": { "axios": "^1.6.1", "axios-cache-interceptor": "^0.10.3", @@ -5247,6 +5248,23 @@ "node": ">=8" } }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -6141,6 +6159,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -7641,6 +7664,41 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -9172,9 +9230,9 @@ } }, "@freearhey/core": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.5.0.tgz", - "integrity": "sha512-FcA5Pv9RvFvLYAwNmD/2vlSR49Rx+kihJ+xbIUgIACHY6lBUptfbNznm00DQoUyWRJG/cfT3dkYCwIxSUsdP+w==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.5.1.tgz", + "integrity": "sha512-UDKIOyrtcUXaiAeIvjNFTI6DlempiOQaRB83CqHNF1VPRHNBiNhGhERWyInHE2cjLp/cc0CA/IykOYS39kBK7Q==", "requires": { "@types/fs-extra": "^11.0.2", "@types/lodash": "^4.14.198", @@ -11280,9 +11338,9 @@ "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" }, "epg-grabber": { - "version": "0.37.4", - "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.37.4.tgz", - "integrity": "sha512-PS104bH9tHRa9kivSwx47AKMkfHwKy51XQTx+GO6sIXvIp2Z4LBpwMEXGcfPoAsdIGxgs2Wrl0dZ/QGL+7x6YQ==", + "version": "0.37.5", + "resolved": "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.37.5.tgz", + "integrity": "sha512-mkT22NU5docsw6qJByBC5oMKFYETyX/PU7Iq3MQ1MS4A+C2Ale6tm+QN7BRW/9Cd5/szfr/YdkzDUZaoyO5vvw==", "requires": { "axios": "^1.6.1", "axios-cache-interceptor": "^0.10.3", @@ -12006,6 +12064,22 @@ } } }, + "ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "requires": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + } + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -12650,6 +12724,11 @@ "esprima": "^4.0.0" } }, + "jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -13776,6 +13855,30 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "requires": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "requires": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", diff --git a/package.json b/package.json index 46dcb653..df39e736 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@alex_neo/jest-expect-message": "^1.0.5", "@eslint/eslintrc": "^3.2.0", "@eslint/js": "^9.17.0", - "@freearhey/core": "^0.5.0", + "@freearhey/core": "^0.5.1", "@ntlab/sfetch": "^1.0.0", "@octokit/core": "^6.1.3", "@octokit/plugin-paginate-rest": "^11.3.6", @@ -67,7 +67,7 @@ "csv-parser": "^3.0.0", "cwait": "^1.1.2", "dayjs": "^1.11.10", - "epg-grabber": "^0.37.4", + "epg-grabber": "^0.37.5", "epg-parser": "^0.3.1", "eslint": "^9.17.0", "eslint-config-prettier": "^9.0.0", @@ -98,6 +98,7 @@ "serve": "^14.2.4", "signale": "^1.4.0", "skip-postinstall": "^1.0.0", + "socks-proxy-agent": "^8.0.5", "srcset": "^4.0.0", "table2array": "^0.0.2", "tabletojson": "^2.0.7", diff --git a/scripts/commands/channels/parse.ts b/scripts/commands/channels/parse.ts index 96c57a52..572b5ed6 100644 --- a/scripts/commands/channels/parse.ts +++ b/scripts/commands/channels/parse.ts @@ -26,7 +26,7 @@ async function main() { const logger = new Logger() const file = new File(options.config) const dir = file.dirname() - const config = (await import(pathToFileURL(options.config))).default + const config = (await import(pathToFileURL(options.config).toString())).default const outputFilepath = options.output || `${dir}/${config.site}.channels.xml` let channels = new Collection() diff --git a/scripts/commands/epg/grab.ts b/scripts/commands/epg/grab.ts index a0d63037..c38b22b9 100644 --- a/scripts/commands/epg/grab.ts +++ b/scripts/commands/epg/grab.ts @@ -16,6 +16,7 @@ program .option('-l, --lang ', 'Filter channels by language (ISO 639-2 code)') .option('-t, --timeout ', 'Override the default timeout for each request') .option('-d, --delay ', 'Override the default delay between request') + .option('-x, --proxy ', 'Use the specified proxy') .option( '--days ', 'Override the number of days for which the program will be loaded (defaults to the value from the site config)', @@ -42,6 +43,7 @@ export type GrabOptions = { lang?: string days?: number cron?: string + proxy?: string } const options: GrabOptions = program.opts() diff --git a/scripts/commands/sites/update.ts b/scripts/commands/sites/update.ts index 4b587df4..9ffc0b4b 100644 --- a/scripts/commands/sites/update.ts +++ b/scripts/commands/sites/update.ts @@ -40,19 +40,20 @@ async function main() { const data = new Collection() sites.forEach((site: Site) => { data.add([ - `${site.domain}`, - `${site.totalChannels} / ${site.markedChannels}`, - site.getStatus().emoji, - site.getIssues().all().join(', ') + { value: `${site.domain}` }, + { value: site.totalChannels, align: 'right' }, + { value: site.markedChannels, align: 'right' }, + { value: site.getStatus().emoji, align: 'center' }, + { value: site.getIssues().all().join(', ') } ]) }) logger.info('updating sites.md...') const table = new HTMLTable(data.all(), [ - { name: 'Site' }, - { name: 'Channels *', align: 'center' }, - { name: 'Status' }, - { name: 'Notes' } + { name: 'Site', align: 'left' }, + { name: 'Channels
(total / with xmltv-id)', colspan: 2, align: 'left' }, + { name: 'Status', align: 'left' }, + { name: 'Notes', align: 'left' } ]) const rootStorage = new Storage(ROOT_DIR) const sitesTemplate = await new Storage().load('scripts/templates/_sites.md') diff --git a/scripts/core/configLoader.ts b/scripts/core/configLoader.ts index 36c93d20..1beb3703 100644 --- a/scripts/core/configLoader.ts +++ b/scripts/core/configLoader.ts @@ -7,7 +7,7 @@ export class ConfigLoader { const fileUrl = pathToFileURL(filepath).toString() const config = (await import(fileUrl)).default const defaultConfig = { - days: 2, + days: 1, delay: 0, output: 'guide.xml', request: { diff --git a/scripts/core/grabber.ts b/scripts/core/grabber.ts index 4bed77a3..2248cbc5 100644 --- a/scripts/core/grabber.ts +++ b/scripts/core/grabber.ts @@ -1,8 +1,9 @@ import { EPGGrabber, GrabCallbackData, EPGGrabberMock, SiteConfig, Channel } from 'epg-grabber' import { Logger, Collection } from '@freearhey/core' -import { Queue } from './' +import { Queue, ProxyParser } from './' import { GrabOptions } from '../commands/epg/grab' import { TaskQueue, PromisyClass } from 'cwait' +import { SocksProxyAgent } from 'socks-proxy-agent' type GrabberProps = { logger: Logger @@ -14,6 +15,7 @@ export class Grabber { logger: Logger queue: Queue options: GrabOptions + grabber: EPGGrabber | EPGGrabberMock constructor({ logger, queue, options }: GrabberProps) { this.logger = logger @@ -23,6 +25,7 @@ export class Grabber { } async grab(): Promise<{ channels: Collection; programs: Collection }> { + const proxyParser = new ProxyParser() const taskQueue = new TaskQueue(Promise as PromisyClass, this.options.maxConnections) const total = this.queue.size() @@ -49,6 +52,24 @@ export class Grabber { config.delay = delay } + if (this.options.proxy !== undefined) { + const proxy = proxyParser.parse(this.options.proxy) + + if ( + proxy.protocol && + ['socks', 'socks5', 'socks5h', 'socks4', 'socks4a'].includes(String(proxy.protocol)) + ) { + const socksProxyAgent = new SocksProxyAgent(this.options.proxy) + + config.request = { + ...config.request, + ...{ httpAgent: socksProxyAgent, httpsAgent: socksProxyAgent } + } + } else { + config.request = { ...config.request, ...{ proxy } } + } + } + const _programs = await this.grabber.grab( channel, date, diff --git a/scripts/core/htmlTable.ts b/scripts/core/htmlTable.ts index 72d6bd8d..144ba01b 100644 --- a/scripts/core/htmlTable.ts +++ b/scripts/core/htmlTable.ts @@ -2,9 +2,15 @@ type Column = { name: string nowrap?: boolean align?: string + colspan?: number } -type DataItem = string[] +type DataItem = { + value: string + nowrap?: boolean + align?: string + colspan?: number +}[] export class HTMLTable { data: DataItem[] @@ -20,20 +26,23 @@ export class HTMLTable { output += ' \r\n ' for (const column of this.columns) { - output += `${column.name}` + const nowrap = column.nowrap ? ' nowrap' : '' + const align = column.align ? ` align="${column.align}"` : '' + const colspan = column.colspan ? ` colspan="${column.colspan}"` : '' + + output += `${column.name}` } output += '\r\n \r\n' output += ' \r\n' - for (const item of this.data) { + for (const row of this.data) { output += ' ' - let i = 0 - for (const prop in item) { - const column = this.columns[i] - const nowrap = column.nowrap ? ' nowrap' : '' - const align = column.align ? ` align="${column.align}"` : '' - output += `${item[prop]}` - i++ + for (const item of row) { + const nowrap = item.nowrap ? ' nowrap' : '' + const align = item.align ? ` align="${item.align}"` : '' + const colspan = item.colspan ? ` colspan="${item.colspan}"` : '' + + output += `${item.value}` } output += '\r\n' } diff --git a/scripts/core/index.ts b/scripts/core/index.ts index 2c7309ed..db3e75a5 100644 --- a/scripts/core/index.ts +++ b/scripts/core/index.ts @@ -13,3 +13,4 @@ export * from './queueCreator' export * from './issueLoader' export * from './issueParser' export * from './htmlTable' +export * from './proxyParser' diff --git a/scripts/core/proxyParser.ts b/scripts/core/proxyParser.ts new file mode 100644 index 00000000..244290d5 --- /dev/null +++ b/scripts/core/proxyParser.ts @@ -0,0 +1,27 @@ +import { URL } from 'node:url' + +type ProxyParserResult = { + protocol: string | null + auth: { + username: string | null + password: string | null + } + host: string + port: number | null +} + +export class ProxyParser { + parse(_url: string): ProxyParserResult { + const parsed = new URL(_url) + + return { + protocol: parsed.protocol.replace(':', '') || null, + auth: { + username: parsed.username || null, + password: parsed.password || null + }, + host: parsed.hostname, + port: parsed.port ? parseInt(parsed.port) : null + } + } +} diff --git a/scripts/templates/_sites.md b/scripts/templates/_sites.md index a4c4b906..46191a4e 100644 --- a/scripts/templates/_sites.md +++ b/scripts/templates/_sites.md @@ -1,5 +1,3 @@ # Sites -\* Total number of channels / with a valid `xmltv-id` - _TABLE_ diff --git a/scripts/templates/_test.js b/scripts/templates/_test.js index 2bb4cebb..6375d7e7 100644 --- a/scripts/templates/_test.js +++ b/scripts/templates/_test.js @@ -6,7 +6,7 @@ dayjs.extend(customParseFormat) dayjs.extend(utc) const date = dayjs.utc('2025-01-12', 'YYYY-MM-DD').startOf('d') -const channel = { site_id: 'bbc1', xmltv_id: 'BBCOne.uk' } +const channel = { site_id: 'bbc1' } it('can generate valid url', () => { expect(url({ channel, date })).toBe('https://example.com/api/bbc1/2025-01-12') @@ -32,11 +32,7 @@ it('can parse response', () => { }) it('can handle empty guide', () => { - const result = parser({ - date, - channel, - content: '' - }) + const results = parser({ content: '' }) - expect(result).toMatchObject([]) + expect(results).toMatchObject([]) }) diff --git a/sites/canalplus.com/canalplus.com.config.js b/sites/canalplus.com/canalplus.com.config.js index 79b75b96..d6d2679b 100644 --- a/sites/canalplus.com/canalplus.com.config.js +++ b/sites/canalplus.com/canalplus.com.config.js @@ -86,6 +86,7 @@ module.exports = { mu: 'cpmus/mu', nc: 'cpncl/nc', ne: 'cpafr/ne', + pf: 'cppyf/pf', pl: 'cppol', re: 'cpreu/re', rw: 'cpafr/rw', diff --git a/sites/canalplus.com/canalplus.com_pf.channels.xml b/sites/canalplus.com/canalplus.com_pf.channels.xml new file mode 100644 index 00000000..a1c9a113 --- /dev/null +++ b/sites/canalplus.com/canalplus.com_pf.channels.xml @@ -0,0 +1,132 @@ + + + Arte + France 2 + France 3 + France 4 + France 5 + France Info + France 24 + TF1 + M6 + LCI + BBC WORLD + INFOSPORT + + TEVA + CANAL+ CINEMA(S) + W9 + TELETOON + + CHAINE JEUNESSE 2 + GULLI + CANAL+ + PARIS PREMIERE + CANAL+ SPORT 360 + CANAL+ SPORT + CANAL+ FOOT + BEIN SPORT 1 + BEIN SPORT 2 + BEIN SPORT 3 + PLANETE+ + OCS HD + C8 + CHAINE DECOUVERTE 1 + CHAINE DECOUVERTE 2 + COMEDIE+ + LCP + DORCEL TV + Polyn茅sie 1ere + TNTV + CANAL+ Kids + CANAL+ Docs + CINE+ Frisson + CINE+ Family + CINE+ Emotion + CINE+ FESTIVAL + CINE+ Classic + BFM Business + BFM TV + 6TER + Ushuaia + TiJi + PIWI+ + C Star hits en Fr + NRJ12 + MGG + RMC Story + Seasons + Histoire TV + Cheval TV + EMCI + ABC Australia + TF1 SERIES FILMS + TMC + TFX + VIXEN + GOLF+ + CNEWS + Novelas TV + PACIFIC+ + RMC DECOUVERTE + CSTAR + NHK + EUROSPORT 1 + EUROSPORT 2 + PLANETE+ AVENTURE + STAR TVE + Cha卯ne Info Anglophone + FOX NEWS + PUNCH TV + CANAL EVENEMENT + FRANCE TV PARIS 2024 + CNN + SPORT EN FRANCE + DAZN 1 + DAZN 2 + DAZN 3 + DAZN 4 + DAZN 5 + EVANGILE TV + DISCOVERY CHANNEL + CANAL+ BOX OFFICE + CANAL+ SERIES + TCM CINEMA + CHERIE 25 + CARTOON NETWORK + BOOMERANG + PLANETE+ CRIME + TEST DROM + WARNER TV + WARNER TV NEXT + EUROSPORT 3 + EUROSPORT 4 + EUROSPORT 5 + EUROSPORT 6 + EUROSPORT 7 + EUROSPORT 8 + EUROSPORT 9 + MULTISPORT 1 + MULTISPORT 2 + MULTISPORT 3 + MULTISPORT 4 + CARTOONITO + TLC + DISCOVERY INVESTIGATION + CANAL+LIVE 1 + CANAL+LIVE 2 + CANAL+LIVE 3 + CANAL+LIVE 4 + CANAL+LIVE 5 + CANAL+LIVE 6 + CANAL+LIVE 7 + CANAL+LIVE 8 + CANAL+LIVE 9 + CANAL+LIVE 10 + CANAL+LIVE 11 + CANAL+LIVE 12 + CANAL+LIVE 13 + CANAL+LIVE 14 + CANAL+LIVE 15 + CANAL+LIVE 16 + CANAL+LIVE 17 + CANAL+LIVE 18 + diff --git a/sites/canalplus.com/readme.md b/sites/canalplus.com/readme.md index 302ed326..3ee8706a 100644 --- a/sites/canalplus.com/readme.md +++ b/sites/canalplus.com/readme.md @@ -16,6 +16,7 @@ | Equatorial Guinea | `gp` | https://www.canalplus.com/gp/programme-tv/ | | France | `fr` | https://www.canalplus.com/programme-tv/ | | French Guiana | `gf` | https://www.canalplus.com/gf/programme-tv/ | +| French Polynesia | `pf` | https://www.canalplus.com/pf/programme-tv/ | | Gabon | `ga` | https://www.canalplus.com/ga/programme-tv/ | | Gambia | `gm` | https://www.canalplus.com/gm/programme-tv/ | | Ghana | `gh` | https://www.canalplus.com/gh/programme-tv/ | diff --git a/sites/programtv.onet.pl/programtv.onet.pl.channels.xml b/sites/programtv.onet.pl/programtv.onet.pl.channels.xml index e2800456..b0435a11 100644 --- a/sites/programtv.onet.pl/programtv.onet.pl.channels.xml +++ b/sites/programtv.onet.pl/programtv.onet.pl.channels.xml @@ -1,18 +1,31 @@ + CT 1 + CT 2 + Nova + 13th Street 3SAT ARD-alpha + ATV Beate-Uhse.TV + Bibel TV Das Erste Deutsches Musik Fernsehen Discovery Channel (niem.) + DMAX + Erox HD + Eroxxx HD Eurosport 1 (niem.) Heimatkanal HISTORY HD (niem.) + HR + Kabel Eins KI.KA + Motorvision MTV Germany muenchen.tv Nitro + n-tv ONE ORF 1 ORF 2 @@ -20,7 +33,9 @@ PRO 7 QVC RBB + Redlight HD RTL + Super RTL RTLZWEI SAT.1 sixx @@ -28,8 +43,17 @@ Sky Hits Sky Comedy Sky Cinema Special + Sky Cinema + 24 Sky Krimi + Sky Sport Austria + Spiegel Geschichte + Sport 1 + SRF 1 + SRF Zwei Syfy + Tele 5 (niem.) + Vivid Touch + VOX WELT ZDF ZDF Info @@ -41,20 +65,19 @@ Bloomberg (ang.) Blue Hustler Brazzers TV Europe + Club MTV CNBC CNN - Dorcel TV - Dorcel XXX DW English Club TV - Erox HD - Eroxxx HD Euronews - EWTN + EWTN Fashion TV Fast&FunBox HD France 24 - EN + Freedom FunBox UHD + Ginx eSports TV God TV Hustler HD Hustler TV @@ -70,30 +93,40 @@ Playboy TV Private TV HD Reality Kings TV - Redlight HD SBN Sky News + Stingray Classica + Stingray CMusic + Stingray DJAZZ + Stingray iConcerts Vivid RED HD - Vivid Touch + TVE Arte + Dorcel TV + Dorcel XXX France 2 - PL France 24 + M 6 + RTS Un + RTS Deux + TV 5 Monde Europe + RAI 1 + RAI 2 + RTL 102.5 + Belgia - TV1 NPO 1 NPO 2 NPO 3 + 13 Ulica HD 2x2 2x2 HD - 4FUN KIDS - 13.tv - 13 Ulica HD 360TuneBox HD + 4FUN KIDS Active Family HD Adventure HD Al Jazeera Ale kino+ HD - Alfa TVP Animal Planet (niem.) - Antena Arte HD AXN HD AXN Spin HD @@ -115,14 +148,13 @@ CANAL+ Sport HD Cartoon Network HD Cartoon Network/Warner TV + CBS Europa CBS Europa HD CI Polsat HD - Cinemax2 HD Cinemax HD + Cinemax2 HD Stingray Classica HD Clubbing TV - Polsat Comedy Central Extra - Polsat Comedy Central Extra HD Comedy Central HD Current Time Current Time HD @@ -146,10 +178,8 @@ DR 1 DR 2 ducktv HD - E! Entertainment HD E-SPORT E-SPORT HD - Echo 24 Eleven Sports 3 HD Eleven Sports 1 HD Eleven Sports 2 HD @@ -172,7 +202,6 @@ FightTime FILMAX FilmBox Arthouse HD - FilmBox Premium HD Fokus TV HD Food Network HD - EN FX Comedy HD @@ -183,9 +212,8 @@ Goldstar TV Golf Channel HD HISTORY2 HD - HBO2 HD - HBO3 HD HBO HD + HBO2 HD HGTV HD HISTORY HD GM24 @@ -198,12 +226,10 @@ CANAL+ KUCHNIA HD Kus Kus Kvartal TV - New TV MDR METRO HD AMC HD MiniMini+ HD - MIXTAPE Motowizja HD MTV Europe MTV Polska HD @@ -217,7 +243,6 @@ National Geographic HD Nautical Channel HD NDR - News24 NICK Nick Jr. HD Nicktoons HD @@ -231,7 +256,6 @@ Nuta.TV HD ONTV ONTV HD - Planete+ HD Polonia 1 Polsat 2 HD Polsat Caf茅 HD @@ -274,95 +298,64 @@ Stingray DJAZZ HD Stingray iConcerts HD STOPKLATKA HD - StudioMED TV Sundance TV HD Super Polsat HD XTREME TV Wydarzenia 24 HD SWR TBN Polska HD - TeenNick Tele 5 HD teleTOON+ HD Telewizja Pomerania TLC HD - Warner TV HD - Top Kids - Top Kids HD JUNIOR MUSIC - JUNIOR MUSIC HD TOYA Travel Channel HD TTV HD TV 4 HD TV 6 HD - TV ASTA - TV ASTA HD TV.Berlin TV Okazje HD TV Puls HD TV Regio TV Regionalna Lubin TV Republika HD - TVN 7 HD TVN24 BiS HD TVN 24 HD + TVN 7 HD TVN Fabu艂a HD TVN HD TVN Style HD TVN Turbo HD TVP 1 HD TVP 2 HD - TVP 3 Bia艂ystok - TVP 3 Bydgoszcz - TVP 3 Gda艅sk - TVP 3 Gorz贸w Wielkopolski - TVP 3 Katowice - TVP 3 Kielce - TVP 3 Krak贸w - TVP 3 艁贸d藕 - TVP 3 Lublin - TVP 3 Olsztyn - TVP 3 Opole - TVP 3 Pozna艅 - TVP 3 Rzesz贸w - TVP 3 Szczecin - TVP 3 Warszawa - TVP 3 Wroc艂aw - TVP Dokument TVP Info HD - TVP Kobieta TVP Kultura HD - TVP Nauka TVP Sport HD - TVP Wilno HOME TV HD - tvregionalna.pl TVS HD - TVT Twoja Telewizja Morska Twoja.TV Ukraina 1 Ukraina 2 - ULTRA TV 4K Water Planet HD WDR WP HD wPolsce.pl HD - WTK XSport ZDF HD ZOOM TV HD + 13.tv + 13 Ulica 4FUN DANCE 4FUN.TV - 13th Street - 13 Ulica Active Family Adventure Ale kino+ + Alfa TVP AMC Animal Planet HD - ATV + Antena AXN Black AXN AXN Spin @@ -373,7 +366,6 @@ BBC First BBC Lifestyle Belsat TV - Bibel TV Bollywood HD Cartoonito CANAL+ 1 @@ -385,21 +377,17 @@ CANAL+ KUCHNIA CANAL+ PREMIUM CANAL+ Seriale + CANAL+ Sport CANAL+ Sport 2 CANAL+ Sport 3 CANAL+ Sport 4 - CANAL+ Sport Cartoon Network BBC CBeebies - CBS Europa CBS Reality Cinemax2 Cinemax - Club MTV Comedy Central CI Polsat - CT 1 - CT 2 Da Vinci Disco Polo Music Discovery Channel @@ -409,12 +397,12 @@ Disney Channel Disney Junior Disney XD - DMAX DocuBox HD DTX ducktv - Belgia - TV1 + Echo 24 E! Entertainment + E! Entertainment HD Eleven Sports 1 Eleven Sports 2 Eleven Sports 3 @@ -433,42 +421,43 @@ FilmBox Arthouse FilmBox Extra HD FilmBox Family + FilmBox Premium HD Fokus TV Folx TV Food Network FX FX Comedy - Freedom Gametoon HD - Ginx eSports TV Golf Channel + HBO HBO2 HBO3 - HBO + HBO3 HD HGTV - HISTORY2 HISTORY + HISTORY2 HOME TV - HR ID - Kabel Eins + JUNIOR MUSIC HD + Kabaret TV Kino Polska Kino Polska Muzyka Kino TV - M 6 MCM Top METRO Mezzo Live HD MiniMini+ - Motorvision + MIXTAPE Motowizja - MTV 00s MTV Polska + MTV 00s Music Box MyZen.tv HD Nat Geo People National Geographic National Geographic Wild + News24 + New TV Nickelodeon Nick Jr. NickMusic @@ -476,22 +465,24 @@ Novela tv Nowa TV CANAL+ Sport 5 - n-tv Nuta.TV Paramount Network Planete+ + Planete+ HD Polo TV + Polsat Polsat 1 Polsat 2 - Polsat Polsat Caf茅 + Polsat Comedy Central Extra + Polsat Comedy Central Extra HD Polsat Doku Polsat Film Polsat Games Polsat JimJam Polsat Music - Polsat News 2 Polsat News + Polsat News 2 Polsat Play Polsat Rodzina Polsat Seriale @@ -510,83 +501,93 @@ Polsat Viasat Nature HD Power TV PULS 2 - RAI 1 - RAI 2 - Record TV Red Carpet TV TV Relax RFM TV rheinmaintv Romance TV - RTL 102.5 - Super RTL - RTS Un - RTS Deux SCI FI - Sky Cinema + 24 - Sky Sport Austria - Spiegel Geschichte - Sport 1 Sportklub - SRF 1 - SRF Zwei STARS.TV - Stingray Classica - Stingray CMusic - Stingray DJAZZ - Stingray iConcerts Stingray Juicebox HD Stingray Loud HD Stingray Retro STOPKLATKA + StudioMED TV Sundance TV Super Polsat Wydarzenia 24 TBN Polska - Tele 5 (niem.) + TeenNick Tele 5 teleTOON+ TLC - Warner TV + Top Kids + Top Kids HD Travel Channel - Travelxp 4K Travelxp HD + Travelxp 4K TTV TV 4 - TV 5 Monde Europe TV 6 - TVE - TVN 7 + TV ASTA + TV ASTA HD + TVN TVN 24 TVN24 BiS - TVN + TVN 7 TVN Fabu艂a - Nova TVN Style TVN Turbo TV Okazje TVP 1 TVP 2 + TVP 3 Bia艂ystok + TVP 3 Bydgoszcz + TVP 3 Gda艅sk + TVP 3 Gorz贸w Wielkopolski + TVP 3 Katowice + TVP 3 Kielce + TVP 3 Krak贸w + TVP 3 艁贸d藕 + TVP 3 Lublin + TVP 3 Olsztyn + TVP 3 Opole + TVP 3 Pozna艅 + TVP 3 Rzesz贸w + TVP 3 Szczecin TVP 3 + TVP 3 Warszawa + TVP 3 Wroc艂aw TVP ABC + TVP Dokument TVP HD TVP Historia TVP Info + TVP Kobieta TVP Kultura + TVP Nauka TVP Polonia TVP Rozrywka TVP Seriale TVP Sport TV Puls + TVP Wilno TVP World + tvregionalna.pl TV Republika TVS + TVT TV Trwam - VOX + ULTRA TV 4K VOX Music TV + Warner TV + Warner TV HD Water Planet EinsLive wPolsce.pl WP + WTK ZOOM TV + Record TV \ No newline at end of file diff --git a/tests/__data__/expected/SITES.md b/tests/__data__/expected/SITES.md index 5f8597e3..4b99e838 100644 --- a/tests/__data__/expected/SITES.md +++ b/tests/__data__/expected/SITES.md @@ -1,14 +1,12 @@ # Sites -\* Total number of channels / with a valid `xmltv-id` - - + - - - + + +
SiteChannels *StatusNotes
SiteChannels
(total / with xmltv-id)
StatusNotes
iltalehti.fi142 / 44馃煛https://github.com/iptv-org/epg/issues/2396
indihometv.com130 / 124馃煝
kan.org.il6 / 6馃敶https://github.com/iptv-org/epg/issues/2273
iltalehti.fi14244馃煛https://github.com/iptv-org/epg/issues/2396
indihometv.com130124馃煝
kan.org.il66馃敶https://github.com/iptv-org/epg/issues/2273
diff --git a/tests/__data__/expected/custom_guide.xml b/tests/__data__/expected/custom_guide.xml index 41efdac8..a57b3322 100644 --- a/tests/__data__/expected/custom_guide.xml +++ b/tests/__data__/expected/custom_guide.xml @@ -9,9 +9,6 @@ Programme1 (example2.com) Program1 (example.com) Programme1 (example.com) -Programme1 (example2.com) Program1 (example2.com) -Program1 (example2.com) Program1 (example2.com) -Program1 (example2.com) \ No newline at end of file diff --git a/tests/__data__/expected/guide.xml b/tests/__data__/expected/guide.xml index 3de58428..66da48ee 100644 --- a/tests/__data__/expected/guide.xml +++ b/tests/__data__/expected/guide.xml @@ -9,9 +9,6 @@ Programme1 (example2.com) Program1 (example.com) Programme1 (example.com) -Programme1 (example2.com) Program1 (example2.com) -Program1 (example2.com) Program1 (example2.com) -Program1 (example2.com) \ No newline at end of file diff --git a/tests/__data__/expected/guide.xml.gz b/tests/__data__/expected/guide.xml.gz index e634dcdf..fb9654e9 100644 Binary files a/tests/__data__/expected/guide.xml.gz and b/tests/__data__/expected/guide.xml.gz differ diff --git a/tests/__data__/expected/sites/sites-init/example.com.test.js b/tests/__data__/expected/sites/sites-init/example.com.test.js index 37d2d7b3..f462b6ef 100644 --- a/tests/__data__/expected/sites/sites-init/example.com.test.js +++ b/tests/__data__/expected/sites/sites-init/example.com.test.js @@ -6,7 +6,7 @@ dayjs.extend(customParseFormat) dayjs.extend(utc) const date = dayjs.utc('2025-01-12', 'YYYY-MM-DD').startOf('d') -const channel = { site_id: 'bbc1', xmltv_id: 'BBCOne.uk' } +const channel = { site_id: 'bbc1' } it('can generate valid url', () => { expect(url({ channel, date })).toBe('https://example.com/api/bbc1/2025-01-12') @@ -32,11 +32,7 @@ it('can parse response', () => { }) it('can handle empty guide', () => { - const result = parser({ - date, - channel, - content: '' - }) + const results = parser({ content: '' }) - expect(result).toMatchObject([]) + expect(results).toMatchObject([]) }) diff --git a/tests/commands/epg/grab.test.ts b/tests/commands/epg/grab.test.ts index 8d40f16f..648d5057 100644 --- a/tests/commands/epg/grab.test.ts +++ b/tests/commands/epg/grab.test.ts @@ -97,6 +97,30 @@ describe('epg:grab', () => { expect(stdout).toContain('ERR: Connection timeout') }) + + it('can grab epg via https proxy', () => { + const cmd = `${ENV_VAR} npm run grab --- --site=example.com --proxy=https://bob:123456@proxy.com:1234 --output="${path.resolve( + 'tests/__data__/output/guide.xml' + )}"` + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + + expect(content('tests/__data__/output/guide.xml')).toEqual( + content('tests/__data__/expected/guide2.xml') + ) + }) + + it('can grab epg via socks5 proxy', () => { + const cmd = `${ENV_VAR} npm run grab --- --site=example.com --proxy=socks5://bob:123456@proxy.com:1234 --output="${path.resolve( + 'tests/__data__/output/guide.xml' + )}"` + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + + expect(content('tests/__data__/output/guide.xml')).toEqual( + content('tests/__data__/expected/guide2.xml') + ) + }) }) function content(filepath: string) { diff --git a/yarn.lock b/yarn.lock index 1ba3d3bd..de4affe8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -396,10 +396,10 @@ dependencies: levn "^0.4.1" -"@freearhey/core@^0.5.0": - version "0.5.0" - resolved "https://registry.npmjs.org/@freearhey/core/-/core-0.5.0.tgz" - integrity sha512-FcA5Pv9RvFvLYAwNmD/2vlSR49Rx+kihJ+xbIUgIACHY6lBUptfbNznm00DQoUyWRJG/cfT3dkYCwIxSUsdP+w== +"@freearhey/core@^0.5.1": + version "0.5.1" + resolved "https://registry.npmjs.org/@freearhey/core/-/core-0.5.1.tgz" + integrity sha512-UDKIOyrtcUXaiAeIvjNFTI6DlempiOQaRB83CqHNF1VPRHNBiNhGhERWyInHE2cjLp/cc0CA/IykOYS39kBK7Q== dependencies: "@types/fs-extra" "^11.0.2" "@types/lodash" "^4.14.198" @@ -1271,7 +1271,7 @@ acorn-walk@^8.1.1: resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== -agent-base@^7.1.3: +agent-base@^7.1.2, agent-base@^7.1.3: version "7.1.3" resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz" integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw== @@ -2158,10 +2158,10 @@ entities@^4.2.0, entities@^4.3.0, entities@^4.4.0: resolved "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz" integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== -epg-grabber@^0.37.4: - version "0.37.4" - resolved "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.37.4.tgz" - integrity sha512-PS104bH9tHRa9kivSwx47AKMkfHwKy51XQTx+GO6sIXvIp2Z4LBpwMEXGcfPoAsdIGxgs2Wrl0dZ/QGL+7x6YQ== +epg-grabber@^0.37.5: + version "0.37.5" + resolved "https://registry.npmjs.org/epg-grabber/-/epg-grabber-0.37.5.tgz" + integrity sha512-mkT22NU5docsw6qJByBC5oMKFYETyX/PU7Iq3MQ1MS4A+C2Ale6tm+QN7BRW/9Cd5/szfr/YdkzDUZaoyO5vvw== dependencies: axios "^1.6.1" axios-cache-interceptor "^0.10.3" @@ -2835,6 +2835,14 @@ inquirer@^8.2.6: through "^2.3.6" wrap-ansi "^6.0.1" +ip-address@^9.0.5: + version "9.0.5" + resolved "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz" + integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== + dependencies: + jsbn "1.1.0" + sprintf-js "^1.1.3" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" @@ -3373,6 +3381,11 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz" + integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" @@ -4393,6 +4406,28 @@ slash@^3.0.0: resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks-proxy-agent@^8.0.5: + version "8.0.5" + resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz" + integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== + dependencies: + agent-base "^7.1.2" + debug "^4.3.4" + socks "^2.8.3" + +socks@^2.8.3: + version "2.8.3" + resolved "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz" + integrity sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw== + dependencies: + ip-address "^9.0.5" + smart-buffer "^4.2.0" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" @@ -4406,6 +4441,11 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +sprintf-js@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"