From 50a7e5559bfa98305e006f8b7833aa2952d65029 Mon Sep 17 00:00:00 2001 From: WebStreamr <210764791+webstreamr@users.noreply.github.com> Date: Mon, 26 Jan 2026 13:47:55 +0000 Subject: [PATCH] refactor(extractor): introduce internal type to reduce common code --- src/extractor/DoodStream.ts | 6 ++---- src/extractor/Dropload.ts | 6 ++---- src/extractor/ExternalUrl.ts | 5 ++--- src/extractor/Extractor.ts | 10 +++++++--- src/extractor/Fastream.ts | 6 ++---- src/extractor/FileLions.ts | 6 ++---- src/extractor/FileMoon.ts | 6 ++---- src/extractor/Fsst.ts | 6 ++---- src/extractor/HubCloud.ts | 6 ++---- src/extractor/HubDrive.ts | 4 ++-- src/extractor/KinoGer.ts | 6 ++---- src/extractor/LuluStream.ts | 6 ++---- src/extractor/Mixdrop.ts | 6 ++---- src/extractor/RgShows.ts | 6 ++---- src/extractor/SaveFiles.ts | 6 ++---- src/extractor/StreamEmbed.ts | 6 ++---- src/extractor/StreamUp.ts | 6 ++---- src/extractor/Streamtape.ts | 11 +++-------- src/extractor/SuperVideo.ts | 6 ++---- src/extractor/Uqload.ts | 6 ++---- src/extractor/VidSrc.ts | 7 +++---- src/extractor/Vidora.ts | 6 ++---- src/extractor/VixSrc.ts | 6 ++---- src/extractor/Voe.ts | 6 ++---- src/extractor/YouTube.ts | 6 ++---- src/types.ts | 11 +++++++++++ 26 files changed, 68 insertions(+), 100 deletions(-) diff --git a/src/extractor/DoodStream.ts b/src/extractor/DoodStream.ts index f03356b..9600df4 100644 --- a/src/extractor/DoodStream.ts +++ b/src/extractor/DoodStream.ts @@ -1,7 +1,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { buildMediaFlowProxyExtractorRedirectUrl, supportsMediaFlowProxy } from '../utils'; import { Extractor } from './Extractor'; @@ -25,7 +25,7 @@ export class DoodStream extends Extractor { return new URL(`http://dood.to/e/${videoId}`); }; - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const html = await this.fetcher.text(ctx, url, { headers }); @@ -44,8 +44,6 @@ export class DoodStream extends Extractor { { url: buildMediaFlowProxyExtractorRedirectUrl(ctx, 'Doodstream', url, headers), format: Format.mp4, - label: this.label, - ttl: this.ttl, meta: { ...meta, title, diff --git a/src/extractor/Dropload.ts b/src/extractor/Dropload.ts index 34aed4d..bf25128 100644 --- a/src/extractor/Dropload.ts +++ b/src/extractor/Dropload.ts @@ -1,7 +1,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { extractUrlFromPacked, guessHeightFromPlaylist } from '../utils'; import { Extractor } from './Extractor'; @@ -18,7 +18,7 @@ export class Dropload extends Extractor { public override readonly normalize = (url: URL): URL => new URL(url.href.replace('/d/', '/').replace('/e/', '/').replace('/embed-', '/')); - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const html = await this.fetcher.text(ctx, url, { headers }); @@ -44,8 +44,6 @@ export class Dropload extends Extractor { { url: playlistUrl, format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, title, diff --git a/src/extractor/ExternalUrl.ts b/src/extractor/ExternalUrl.ts index 2323f6f..7efd4b3 100644 --- a/src/extractor/ExternalUrl.ts +++ b/src/extractor/ExternalUrl.ts @@ -1,4 +1,4 @@ -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { showExternalUrls } from '../utils'; import { Extractor } from './Extractor'; @@ -13,14 +13,13 @@ export class ExternalUrl extends Extractor { return showExternalUrls(ctx.config) && null !== url.host.match(/.*/); } - protected async extractInternal(_ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(_ctx: Context, url: URL, meta: Meta): Promise { return [ { url: url, format: Format.unknown, isExternal: true, label: `${url.host}`, - ttl: this.ttl, meta, }, ]; diff --git a/src/extractor/Extractor.ts b/src/extractor/Extractor.ts index 0ac5b0a..ba1b8f3 100644 --- a/src/extractor/Extractor.ts +++ b/src/extractor/Extractor.ts @@ -1,5 +1,5 @@ import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta, UrlResult } from '../types'; import { Fetcher } from '../utils'; export abstract class Extractor { @@ -23,12 +23,16 @@ export abstract class Extractor { return url; }; - protected abstract extractInternal(ctx: Context, url: URL, meta: Meta): Promise; + protected abstract extractInternal(ctx: Context, url: URL, meta: Meta): Promise; public async extract(ctx: Context, url: URL, meta: Meta): Promise { try { return (await this.extractInternal(ctx, url, meta)).map( - urlResult => ({ ...urlResult, label: this.formatLabel(urlResult.label) }), + urlResult => ({ + ...urlResult, + label: this.formatLabel(urlResult.label ?? this.label), + ttl: this.ttl, + }), ); } catch (error) { if (error instanceof NotFoundError) { diff --git a/src/extractor/Fastream.ts b/src/extractor/Fastream.ts index 6d45042..1b1eead 100644 --- a/src/extractor/Fastream.ts +++ b/src/extractor/Fastream.ts @@ -1,6 +1,6 @@ import bytes from 'bytes'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { buildMediaFlowProxyExtractorStreamUrl, supportsMediaFlowProxy } from '../utils'; import { Extractor } from './Extractor'; @@ -19,7 +19,7 @@ export class Fastream extends Extractor { return new URL(url.href.replace('/e/', '/embed-').replace('/d/', '/embed-')); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const downloadUrl = new URL(url.href.replace('/embed-', '/d/')); @@ -38,8 +38,6 @@ export class Fastream extends Extractor { { url: playlistUrl, format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, bytes: bytes.parse(heightAndSizeMatch[2] as string) as number, diff --git a/src/extractor/FileLions.ts b/src/extractor/FileLions.ts index 378187a..91e3b55 100644 --- a/src/extractor/FileLions.ts +++ b/src/extractor/FileLions.ts @@ -1,7 +1,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { buildMediaFlowProxyExtractorStreamUrl, supportsMediaFlowProxy, unpackEval } from '../utils'; import { Extractor } from './Extractor'; @@ -62,7 +62,7 @@ export class FileLions extends Extractor { return new URL(url.href.replace('/v/', '/f/').replace('/download/', '/f/').replace('/file/', '/f/')); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const html = await this.fetcher.text(ctx, url, { headers }); @@ -87,8 +87,6 @@ export class FileLions extends Extractor { { url: await buildMediaFlowProxyExtractorStreamUrl(ctx, this.fetcher, 'FileLions', url, headers), format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, height: parseInt(heightMatch[1] as string), diff --git a/src/extractor/FileMoon.ts b/src/extractor/FileMoon.ts index d8bc8b4..8601926 100644 --- a/src/extractor/FileMoon.ts +++ b/src/extractor/FileMoon.ts @@ -1,6 +1,6 @@ import * as cheerio from 'cheerio'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { buildMediaFlowProxyExtractorStreamUrl, supportsMediaFlowProxy, @@ -45,7 +45,7 @@ export class FileMoon extends Extractor { return new URL(url.href.replace('/e/', '/d/')); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta, originalUrl?: URL): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta, originalUrl?: URL): Promise { const headers = { Referer: meta.referer ?? url.href }; const html = await this.fetcher.text(ctx, url, { headers }); @@ -72,8 +72,6 @@ export class FileMoon extends Extractor { { url: playlistUrl, format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, ...(heightMatch && { height: parseInt(heightMatch[1] as string) }), diff --git a/src/extractor/Fsst.ts b/src/extractor/Fsst.ts index b800ae3..24ca2f1 100644 --- a/src/extractor/Fsst.ts +++ b/src/extractor/Fsst.ts @@ -1,5 +1,5 @@ import * as cheerio from 'cheerio'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { Extractor } from './Extractor'; export class Fsst extends Extractor { @@ -11,7 +11,7 @@ export class Fsst extends Extractor { return null !== url.host.match(/fsst/); }; - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const html = await this.fetcher.text(ctx, url, { headers, noProxyHeaders: true }); @@ -29,8 +29,6 @@ export class Fsst extends Extractor { return [{ url: await this.fetcher.getFinalRedirectUrl(ctx, new URL(fileHref), { headers, noProxyHeaders: true }, 1), format: Format.mp4, - label: this.label, - ttl: this.ttl, meta: { ...meta, height: parseInt(heightAndUrlMatch[1] as string), diff --git a/src/extractor/HubCloud.ts b/src/extractor/HubCloud.ts index 1db2105..8a1a33f 100644 --- a/src/extractor/HubCloud.ts +++ b/src/extractor/HubCloud.ts @@ -1,6 +1,6 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { Extractor } from './Extractor'; export class HubCloud extends Extractor { @@ -14,7 +14,7 @@ export class HubCloud extends Extractor { return null !== url.host.match(/hubcloud/); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const redirectHtml = await this.fetcher.text(ctx, url, { headers }); @@ -36,7 +36,6 @@ export class HubCloud extends Extractor { url, format: Format.unknown, label: `${this.label} (FSL)`, - ttl: this.ttl, meta: { ...meta, bytes: bytes.parse($('#size').text()) as number, @@ -53,7 +52,6 @@ export class HubCloud extends Extractor { url, format: Format.unknown, label: `${this.label} (PixelServer)`, - ttl: this.ttl, meta: { ...meta, bytes: bytes.parse($('#size').text()) as number, diff --git a/src/extractor/HubDrive.ts b/src/extractor/HubDrive.ts index 457895e..8276dc5 100644 --- a/src/extractor/HubDrive.ts +++ b/src/extractor/HubDrive.ts @@ -1,5 +1,5 @@ import * as cheerio from 'cheerio'; -import { Context, Meta, UrlResult } from '../types'; +import { Context, InternalUrlResult, Meta } from '../types'; import { Fetcher } from '../utils'; import { Extractor } from './Extractor'; import { HubCloud } from './HubCloud'; @@ -23,7 +23,7 @@ export class HubDrive extends Extractor { return null !== url.host.match(/hubdrive/); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const html = await this.fetcher.text(ctx, url, { headers }); diff --git a/src/extractor/KinoGer.ts b/src/extractor/KinoGer.ts index 83fd603..cef4480 100644 --- a/src/extractor/KinoGer.ts +++ b/src/extractor/KinoGer.ts @@ -1,5 +1,5 @@ import crypto from 'crypto'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { guessHeightFromPlaylist } from '../utils'; import { Extractor } from './Extractor'; @@ -43,7 +43,7 @@ export class KinoGer extends Extractor { return new URL(`${url.origin}/api/v1/video?id=${url.hash.slice(1)}`); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { 'Origin': url.origin, 'Referer': url.origin + '/', @@ -66,8 +66,6 @@ export class KinoGer extends Extractor { { url: m3u8Url, format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, height: meta.height ?? await guessHeightFromPlaylist(ctx, this.fetcher, m3u8Url, { headers }), diff --git a/src/extractor/LuluStream.ts b/src/extractor/LuluStream.ts index e927a59..eddb449 100644 --- a/src/extractor/LuluStream.ts +++ b/src/extractor/LuluStream.ts @@ -1,7 +1,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { buildMediaFlowProxyExtractorStreamUrl, supportsMediaFlowProxy, @@ -34,7 +34,7 @@ export class LuluStream extends Extractor { return new URL(`/e/${videoId}`, url); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const fileUrl = new URL(url.href.replace('/e/', '/d/')); @@ -55,8 +55,6 @@ export class LuluStream extends Extractor { { url: playlistUrl, format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, title, diff --git a/src/extractor/Mixdrop.ts b/src/extractor/Mixdrop.ts index 6f39aaf..151440c 100644 --- a/src/extractor/Mixdrop.ts +++ b/src/extractor/Mixdrop.ts @@ -1,7 +1,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { buildMediaFlowProxyExtractorRedirectUrl, supportsMediaFlowProxy } from '../utils'; import { Extractor } from './Extractor'; @@ -18,7 +18,7 @@ export class Mixdrop extends Extractor { public override readonly normalize = (url: URL): URL => new URL(url.href.replace('/f/', '/e/')); - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const fileUrl = new URL(url.href.replace('/e/', '/f/')); const html = await this.fetcher.text(ctx, fileUrl); @@ -35,8 +35,6 @@ export class Mixdrop extends Extractor { { url: buildMediaFlowProxyExtractorRedirectUrl(ctx, 'Mixdrop', url), format: Format.mp4, - label: this.label, - ttl: this.ttl, meta: { ...meta, bytes: bytes.parse((sizeMatch[1] as string).replace(',', '')) as number, diff --git a/src/extractor/RgShows.ts b/src/extractor/RgShows.ts index 5f15c03..e26597c 100644 --- a/src/extractor/RgShows.ts +++ b/src/extractor/RgShows.ts @@ -1,5 +1,5 @@ import { BlockedError } from '../error'; -import { BlockedReason, Context, Format, Meta, UrlResult } from '../types'; +import { BlockedReason, Context, Format, InternalUrlResult, Meta } from '../types'; import { guessHeightFromPlaylist } from '../utils'; import { Extractor } from './Extractor'; @@ -20,7 +20,7 @@ export class RgShows extends Extractor { return null !== url.host.match(/rgshows/); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { 'Referer': 'https://www.rgshows.ru/', 'Origin': 'https://www.rgshows.ru', 'User-Agent': 'Mozilla' }; const data = await this.fetcher.json(ctx, url, { headers }) as RgShowsApiData; @@ -38,8 +38,6 @@ export class RgShows extends Extractor { { url: streamUrl, format: isMp4 ? Format.mp4 : (isHls ? Format.hls : /* istanbul ignore next */ Format.unknown), - label: this.label, - ttl: this.ttl, meta: { ...meta, ...(isHls && { height: meta.height ?? await guessHeightFromPlaylist(ctx, this.fetcher, streamUrl, { headers }) }), diff --git a/src/extractor/SaveFiles.ts b/src/extractor/SaveFiles.ts index 0a4f2e9..0efb1d6 100644 --- a/src/extractor/SaveFiles.ts +++ b/src/extractor/SaveFiles.ts @@ -1,6 +1,6 @@ import * as cheerio from 'cheerio'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { Extractor } from './Extractor'; export class SaveFiles extends Extractor { @@ -18,7 +18,7 @@ export class SaveFiles extends Extractor { return new URL(url.href.replace('/e/', '/').replace('/d/', '/')); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const html = await this.fetcher.text(ctx, url, { headers }); @@ -37,8 +37,6 @@ export class SaveFiles extends Extractor { { url: new URL(fileMatch[1] as string), format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, title, diff --git a/src/extractor/StreamEmbed.ts b/src/extractor/StreamEmbed.ts index 4d1b593..c7d3d6c 100644 --- a/src/extractor/StreamEmbed.ts +++ b/src/extractor/StreamEmbed.ts @@ -1,5 +1,5 @@ import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { Extractor } from './Extractor'; export class StreamEmbed extends Extractor { @@ -11,7 +11,7 @@ export class StreamEmbed extends Extractor { return null !== url.host.match(/bullstream|mp4player|watch\.gxplayer/); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const html = await this.fetcher.text(ctx, url, { headers }); @@ -26,8 +26,6 @@ export class StreamEmbed extends Extractor { { url: new URL(`/m3u8/${video.uid}/${video.md5}/master.txt?s=1&id=${video.id}&cache=${video.status}`, url.origin), format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, height: parseInt(JSON.parse(video.quality)[0]), diff --git a/src/extractor/StreamUp.ts b/src/extractor/StreamUp.ts index 4f23812..bd4b663 100644 --- a/src/extractor/StreamUp.ts +++ b/src/extractor/StreamUp.ts @@ -1,5 +1,5 @@ import * as cheerio from 'cheerio'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { guessHeightFromPlaylist } from '../utils'; import { Extractor } from './Extractor'; @@ -21,7 +21,7 @@ export class StreamUp extends Extractor { ].includes(url.host); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: `${url.origin}/`, Origin: url.origin }; const html = await this.fetcher.text(ctx, url, { headers }); @@ -36,8 +36,6 @@ export class StreamUp extends Extractor { { url: playlistUrl, format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, height: meta.height ?? await guessHeightFromPlaylist(ctx, this.fetcher, playlistUrl), diff --git a/src/extractor/Streamtape.ts b/src/extractor/Streamtape.ts index 2b1d67f..4a3dcbe 100644 --- a/src/extractor/Streamtape.ts +++ b/src/extractor/Streamtape.ts @@ -1,10 +1,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; -import { Context, Format, Meta, UrlResult } from '../types'; -import { - buildMediaFlowProxyExtractorRedirectUrl, - supportsMediaFlowProxy, -} from '../utils'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; +import { buildMediaFlowProxyExtractorRedirectUrl, supportsMediaFlowProxy } from '../utils'; import { Extractor } from './Extractor'; export class Streamtape extends Extractor { @@ -45,7 +42,7 @@ export class Streamtape extends Extractor { return new URL(url.href.replace('/e/', '/v/')); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; // Only needed to properly find non-existing files via 404 response @@ -62,8 +59,6 @@ export class Streamtape extends Extractor { { url: buildMediaFlowProxyExtractorRedirectUrl(ctx, 'Streamtape', url, headers), format: Format.mp4, - label: this.label, - ttl: this.ttl, meta: { ...meta, title, diff --git a/src/extractor/SuperVideo.ts b/src/extractor/SuperVideo.ts index 019fec1..c5e905c 100644 --- a/src/extractor/SuperVideo.ts +++ b/src/extractor/SuperVideo.ts @@ -1,7 +1,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { extractUrlFromPacked, guessHeightFromPlaylist } from '../utils'; import { Extractor } from './Extractor'; @@ -20,7 +20,7 @@ export class SuperVideo extends Extractor { return new URL(url.href.replace('/e/', '/').replace('/k/', '/').replace('/embed-', '/')); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const html = await this.fetcher.text(ctx, url, { headers }); @@ -48,8 +48,6 @@ export class SuperVideo extends Extractor { { url: m3u8Url, format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, title, diff --git a/src/extractor/Uqload.ts b/src/extractor/Uqload.ts index b853475..433f2a7 100644 --- a/src/extractor/Uqload.ts +++ b/src/extractor/Uqload.ts @@ -1,6 +1,6 @@ import * as cheerio from 'cheerio'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { buildMediaFlowProxyExtractorRedirectUrl, supportsMediaFlowProxy } from '../utils'; import { Extractor } from './Extractor'; @@ -19,7 +19,7 @@ export class Uqload extends Extractor { return new URL(url.href.replace('/embed-', '/')); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const html = await this.fetcher.text(ctx, url); if (/File Not Found/.test(html)) { @@ -35,8 +35,6 @@ export class Uqload extends Extractor { { url: buildMediaFlowProxyExtractorRedirectUrl(ctx, 'Uqload', url), format: Format.mp4, - label: this.label, - ttl: this.ttl, meta: { ...meta, title, diff --git a/src/extractor/VidSrc.ts b/src/extractor/VidSrc.ts index e0b811d..da33306 100644 --- a/src/extractor/VidSrc.ts +++ b/src/extractor/VidSrc.ts @@ -1,6 +1,6 @@ import * as cheerio from 'cheerio'; import { BlockedError, TooManyRequestsError } from '../error'; -import { Context, Format, Meta, NonEmptyArray, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta, NonEmptyArray } from '../types'; import { Fetcher, guessHeightFromPlaylist } from '../utils'; import { Extractor } from './Extractor'; @@ -23,7 +23,7 @@ export class VidSrc extends Extractor { return null !== url.host.match(/vidsrc|vsrc/); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { // While this is a crappy thing to do, they seem to be blocking overly strict IMO const randomIp = `${Math.floor(Math.random() * 223) + 1}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}`; const newCtx = { ...ctx, ip: randomIp }; @@ -31,7 +31,7 @@ export class VidSrc extends Extractor { return this.extractUsingRandomDomain(newCtx, url, meta, [...this.domains]); }; - private async extractUsingRandomDomain(ctx: Context, url: URL, meta: Meta, domains: string[]): Promise { + private async extractUsingRandomDomain(ctx: Context, url: URL, meta: Meta, domains: string[]): Promise { const domainIndex = Math.floor(Math.random() * domains.length); const [domain] = domains.splice(domainIndex, 1) as [string]; @@ -74,7 +74,6 @@ export class VidSrc extends Extractor { url: m3u8Url, format: Format.hls, label: serverName, - ttl: this.ttl, meta: { ...meta, height: await guessHeightFromPlaylist(ctx, this.fetcher, m3u8Url, { headers: { Referer: iframeUrl.href } }), diff --git a/src/extractor/Vidora.ts b/src/extractor/Vidora.ts index 6af588c..9dc3bd2 100644 --- a/src/extractor/Vidora.ts +++ b/src/extractor/Vidora.ts @@ -1,5 +1,5 @@ import * as cheerio from 'cheerio'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { extractUrlFromPacked, guessHeightFromPlaylist } from '../utils'; import { Extractor } from './Extractor'; @@ -18,7 +18,7 @@ export class Vidora extends Extractor { return new URL(url.href.replace('/embed/', '/')); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const html = await this.fetcher.text(ctx, url); const $ = cheerio.load(html); @@ -31,8 +31,6 @@ export class Vidora extends Extractor { { url: m3u8Url, format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, height: meta.height ?? await guessHeightFromPlaylist(ctx, this.fetcher, m3u8Url, { headers }), diff --git a/src/extractor/VixSrc.ts b/src/extractor/VixSrc.ts index 14720e7..c49bd1f 100644 --- a/src/extractor/VixSrc.ts +++ b/src/extractor/VixSrc.ts @@ -1,4 +1,4 @@ -import { Context, CountryCode, Format, Meta, UrlResult } from '../types'; +import { Context, CountryCode, Format, InternalUrlResult, Meta } from '../types'; import { CustomRequestConfig, guessHeightFromPlaylist, hasMultiEnabled, iso639FromCountryCode } from '../utils'; import { Extractor } from './Extractor'; @@ -13,7 +13,7 @@ export class VixSrc extends Extractor { return null !== url.host.match(/vixsrc/); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: url.href }; const html = await this.fetcher.text(ctx, url); @@ -38,8 +38,6 @@ export class VixSrc extends Extractor { { url: playlistUrl, format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, countryCodes, diff --git a/src/extractor/Voe.ts b/src/extractor/Voe.ts index ab9012f..73e8a61 100644 --- a/src/extractor/Voe.ts +++ b/src/extractor/Voe.ts @@ -1,7 +1,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { NotFoundError } from '../error'; -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { buildMediaFlowProxyExtractorStreamUrl, guessHeightFromPlaylist, supportsMediaFlowProxy, @@ -125,7 +125,7 @@ export class Voe extends Extractor { return new URL(`/${url.pathname.replace(/\/+$/, '').split('/').at(-1)}`, url); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; let html: string; @@ -167,8 +167,6 @@ export class Voe extends Extractor { { url: playlistUrl, format: Format.hls, - label: this.label, - ttl: this.ttl, meta: { ...meta, height, diff --git a/src/extractor/YouTube.ts b/src/extractor/YouTube.ts index c98df51..55ffb99 100644 --- a/src/extractor/YouTube.ts +++ b/src/extractor/YouTube.ts @@ -1,4 +1,4 @@ -import { Context, Format, Meta, UrlResult } from '../types'; +import { Context, Format, InternalUrlResult, Meta } from '../types'; import { Extractor } from './Extractor'; export class YouTube extends Extractor { @@ -12,7 +12,7 @@ export class YouTube extends Extractor { return null !== url.host.match(/youtube/) && url.searchParams.has('v'); } - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { const headers = { Referer: meta.referer ?? url.href }; const html = await this.fetcher.text(ctx, url, { headers }); @@ -24,8 +24,6 @@ export class YouTube extends Extractor { url, format: Format.unknown, ytId: url.searchParams.get('v') as string, - label: this.label, - ttl: this.ttl, meta: { ...meta, title: titleMatch[1] as string, diff --git a/src/types.ts b/src/types.ts index d4eb231..c9f9f3d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -93,6 +93,17 @@ export enum Format { unknown = 'unknown', } +export interface InternalUrlResult { + url: URL; + format: Format; + isExternal?: boolean; + ytId?: string; + error?: unknown; + label?: string; + meta?: Meta; + requestHeaders?: Record; +} + export interface UrlResult { url: URL; format: Format;