chore(extractor): simplify type and passing of height

This commit is contained in:
WebStreamr 2025-06-30 18:51:21 +00:00
parent ac78e6831b
commit b88eba017d
No known key found for this signature in database
17 changed files with 25 additions and 22 deletions

View file

@ -1,7 +1,7 @@
import randomstring from 'randomstring';
import * as cheerio from 'cheerio';
import { Extractor } from './Extractor';
import { Fetcher, guessFromTitle } from '../utils';
import { Fetcher, guessHeightFromTitle } from '../utils';
import { Context, CountryCode, Format, UrlResult } from '../types';
import { NotFoundError } from '../error';
@ -43,7 +43,6 @@ export class DoodStream extends Extractor {
const $ = cheerio.load(html);
const title = $('title').text().trim().replace(/ - DoodStream$/, '').trim();
const height = guessFromTitle(title);
const mp4Url = new URL(`${baseUrl}${randomstring.generate(10)}?token=${token}&expiry=${Date.now()}`);
@ -58,9 +57,9 @@ export class DoodStream extends Extractor {
ttl: this.ttl,
meta: {
countryCodes: [countryCode],
height: guessHeightFromTitle(title),
title,
...(mp4Head['content-length'] && { bytes: parseInt(mp4Head['content-length'] as string) }),
...(height && { height }),
},
requestHeaders: {
Referer: url.origin,

View file

@ -48,7 +48,7 @@ export class Dropload extends Extractor {
meta: {
bytes: bytes.parse(sizeMatch[1] as string) as number,
countryCodes: [countryCode],
height: parseInt(heightMatch[1] as string) as number,
height: parseInt(heightMatch[1] as string),
title,
},
},

View file

@ -39,7 +39,7 @@ export class ExternalUrl extends Extractor {
ttl: this.ttl,
meta: {
countryCodes: [countryCode],
...(title && { title }),
title,
},
},
];

View file

@ -1,6 +1,6 @@
import crypto from 'crypto';
import { Extractor } from './Extractor';
import { Fetcher, guessFromTitle } from '../utils';
import { Fetcher, guessHeightFromTitle } from '../utils';
import { Context, CountryCode, Format, UrlResult } from '../types';
/** @see https://github.com/Gujal00/ResolveURL/blob/master/script.module.resolveurl/lib/resolveurl/plugins/kinoger.py */
@ -36,8 +36,6 @@ export class KinoGer extends Extractor {
const { cf, title } = JSON.parse(decrypted) as { cf: string; title: string };
const height = guessFromTitle(title);
return [
{
url: new URL(cf),
@ -47,8 +45,8 @@ export class KinoGer extends Extractor {
ttl: this.ttl,
meta: {
countryCodes: [countryCode],
height: guessHeightFromTitle(title),
title,
...(height && { height }),
},
requestHeaders: {
Referer: url.origin,

View file

@ -1,7 +1,7 @@
import bytes from 'bytes';
import * as cheerio from 'cheerio';
import { Extractor } from './Extractor';
import { buildMediaFlowProxyExtractorRedirectUrl, Fetcher, supportsMediaFlowProxy } from '../utils';
import { buildMediaFlowProxyExtractorRedirectUrl, Fetcher, guessHeightFromTitle, supportsMediaFlowProxy } from '../utils';
import { Context, CountryCode, Format, UrlResult } from '../types';
import { NotFoundError } from '../error';
@ -48,6 +48,7 @@ export class Mixdrop extends Extractor {
ttl: this.ttl,
meta: {
countryCodes: [countryCode],
height: guessHeightFromTitle(title),
title,
...(sizeMatch && {
bytes: bytes.parse((sizeMatch[1] as string).replace(',', '')) as number,

View file

@ -1,5 +1,5 @@
import { Extractor } from './Extractor';
import { Fetcher, guessFromPlaylist } from '../utils';
import { Fetcher, guessHeightFromPlaylist } from '../utils';
import { Context, CountryCode, Format, UrlResult } from '../types';
interface SoaperInfoResponsePartial {
@ -48,7 +48,6 @@ export class Soaper extends Extractor {
const jsonResponse = JSON.parse(response) as SoaperInfoResponsePartial;
const m3u8Url = new URL(jsonResponse['val'], url.origin);
const height = await guessFromPlaylist(ctx, this.fetcher, m3u8Url);
return [
{
@ -59,8 +58,8 @@ export class Soaper extends Extractor {
ttl: this.ttl,
meta: {
countryCodes: [countryCode],
height: await guessHeightFromPlaylist(ctx, this.fetcher, m3u8Url),
title: `${title}`,
...(height && { height }),
},
},
];

View file

@ -54,7 +54,7 @@ export class SuperVideo extends Extractor {
title,
...(heightAndSizeMatch && {
bytes: bytes.parse(heightAndSizeMatch[2] as string) as number,
height: parseInt(heightAndSizeMatch[1] as string) as number,
height: parseInt(heightAndSizeMatch[1] as string),
}),
},
},

View file

@ -47,7 +47,7 @@ export class Uqload extends Extractor {
countryCodes: [countryCode],
title,
...(heightMatch && {
height: parseInt(heightMatch[1] as string) as number,
height: parseInt(heightMatch[1] as string),
}),
},
},

View file

@ -1,7 +1,7 @@
import * as cheerio from 'cheerio';
import slugify from 'slugify';
import { Extractor } from './Extractor';
import { Fetcher, guessFromPlaylist } from '../utils';
import { Fetcher, guessHeightFromPlaylist } from '../utils';
import { Context, CountryCode, Format, UrlResult } from '../types';
import { NotFoundError } from '../error';
@ -46,7 +46,6 @@ export class VidSrc extends Extractor {
}
const m3u8Url = new URL(fileMatch[1] as string);
const height = await guessFromPlaylist(ctx, this.fetcher, m3u8Url);
return {
url: m3u8Url,
@ -56,8 +55,8 @@ export class VidSrc extends Extractor {
ttl: this.ttl,
meta: {
countryCodes: [countryCode],
height: await guessHeightFromPlaylist(ctx, this.fetcher, m3u8Url),
title,
...(height && { height }),
},
};
}),

View file

@ -32,6 +32,7 @@ exports[`DoodStream dood.to 1`] = `
"countryCodes": [
"de",
],
"height": undefined,
"title": "des-teufels-bad-2024",
},
"requestHeaders": {
@ -53,6 +54,7 @@ exports[`DoodStream doodster 1`] = `
"countryCodes": [
"de",
],
"height": undefined,
"title": "Brokeback Mountain 2005",
},
"requestHeaders": {

View file

@ -31,6 +31,7 @@ exports[`ExternalUrl netu.fanstream.us 1`] = `
"countryCodes": [
"fr",
],
"title": undefined,
},
"sourceId": "external_fr",
"ttl": 3600000,

View file

@ -12,6 +12,7 @@ exports[`ExtractorRegistry returns external URLs if enabled by config 1`] = `
"countryCodes": [
"de",
],
"title": undefined,
},
"sourceId": "external_de",
"ttl": 3600000,

View file

@ -9,6 +9,7 @@ exports[`KinoGer Blood & Sinners 1`] = `
"countryCodes": [
"de",
],
"height": undefined,
"title": "Blood.and.Sinners.2025.mkv",
},
"requestHeaders": {

View file

@ -12,6 +12,7 @@ exports[`Mixdrop mixdrop.my /e/ 1`] = `
"countryCodes": [
"de",
],
"height": undefined,
"title": "28_giorni_dopo_2002_HD_-_Altadefinizione01.mp4",
},
"sourceId": "mixdrop_de",

View file

@ -47,6 +47,7 @@ exports[`Soaper last of us s2e3 1`] = `
"countryCodes": [
"de",
],
"height": undefined,
"title": "The Last of Us 2x3",
},
"sourceId": "soaper_de",

View file

@ -31,8 +31,8 @@ export enum BlockedReason {
export interface Meta {
bytes?: number;
countryCodes: CountryCode[];
height?: number;
title?: string;
height?: number | undefined;
title?: string | undefined;
}
export enum Format {

View file

@ -1,7 +1,7 @@
import { CustomRequestInit, Fetcher } from './Fetcher';
import { Context } from '../types';
export const guessFromTitle = (title: string): number | undefined => {
export const guessHeightFromTitle = (title: string): number | undefined => {
const heightMatch = title.match(/([0-9]+)p/);
if (heightMatch && heightMatch[1]) {
return parseInt(heightMatch[1]);
@ -10,7 +10,7 @@ export const guessFromTitle = (title: string): number | undefined => {
return undefined;
};
export const guessFromPlaylist = async (ctx: Context, fetcher: Fetcher, url: URL, init?: CustomRequestInit): Promise<number | undefined> => {
export const guessHeightFromPlaylist = async (ctx: Context, fetcher: Fetcher, url: URL, init?: CustomRequestInit): Promise<number | undefined> => {
const m3u8Data = await fetcher.text(ctx, url, init);
const heights = Array.from(m3u8Data.matchAll(/\d+x(\d+)|(\d+)p/g))