From f192fd0b7523094746148989e0cf06717db8152e Mon Sep 17 00:00:00 2001 From: WebStreamr <210764791+webstreamr@users.noreply.github.com> Date: Fri, 27 Mar 2026 17:59:54 +0000 Subject: [PATCH] chore(extractor): detect resolution from HubCloud title --- src/extractor/HubCloud.ts | 13 ++++++++++--- src/extractor/__snapshots__/HubCloud.test.ts.snap | 7 +++++++ src/extractor/__snapshots__/HubDrive.test.ts.snap | 1 + src/utils/resolution.ts | 8 ++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/extractor/HubCloud.ts b/src/extractor/HubCloud.ts index 2eff8af..e055e14 100644 --- a/src/extractor/HubCloud.ts +++ b/src/extractor/HubCloud.ts @@ -1,6 +1,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { Context, Format, InternalUrlResult, Meta } from '../types'; +import { findHeight } from '../utils'; import { Extractor } from './Extractor'; export class HubCloud extends Extractor { @@ -25,6 +26,9 @@ export class HubCloud extends Extractor { const linksHtml = await this.fetcher.text(ctx, new URL(redirectUrlMatch[1] as string), { headers: { Referer: url.href } }); const $ = cheerio.load(linksHtml); + const title = $('title').text().trim(); + const height = meta.height ?? findHeight(title); + return Promise.all([ ...$('a') .filter((_i, el) => { @@ -42,7 +46,8 @@ export class HubCloud extends Extractor { ...meta, bytes: bytes.parse($('#size').text()) as number, extractorId: `${this.id}_fsl`, - title: $('title').text().trim(), + height, + title, }, }; }).toArray(), @@ -62,7 +67,8 @@ export class HubCloud extends Extractor { ...meta, bytes: bytes.parse($('#size').text()) as number, extractorId: `${this.id}_fslv2`, - title: $('title').text().trim(), + height, + title, }, }; }).toArray(), @@ -81,7 +87,8 @@ export class HubCloud extends Extractor { ...meta, bytes: bytes.parse($('#size').text()) as number, extractorId: `${this.id}_pixelserver`, - title: $('title').text().trim(), + height, + title, }, requestHeaders: { Referer: userUrl.href }, }; diff --git a/src/extractor/__snapshots__/HubCloud.test.ts.snap b/src/extractor/__snapshots__/HubCloud.test.ts.snap index 6b42a97..c5c0d55 100644 --- a/src/extractor/__snapshots__/HubCloud.test.ts.snap +++ b/src/extractor/__snapshots__/HubCloud.test.ts.snap @@ -8,6 +8,7 @@ exports[`HubCloud handle crayon shin-chan 1993 1`] = ` "meta": { "bytes": 28550795100, "extractorId": "hubcloud_fsl", + "height": 1080, "title": "Crayon Shinchan Action Kamen vs Demon (1993) 1080p BluRay REMUX AVC [Hindi DD 2.0 + Japanese FLAC 2.0] (PitiPati-Ionicboy) (4kHDHub.com).mkv", }, "ttl": 43200000, @@ -24,6 +25,7 @@ exports[`HubCloud handle dark 2017 s03e08 1`] = ` "meta": { "bytes": 3382286745, "extractorId": "hubcloud_fsl", + "height": 1080, "title": "Dark.S03E08.The.Paradise.1080p.NF.WEB-DL.English.DDP5.1-German.DDP5.1.H.264-4kHdHub.Com.mkv", }, "ttl": 43200000, @@ -35,6 +37,7 @@ exports[`HubCloud handle dark 2017 s03e08 1`] = ` "meta": { "bytes": 3382286745, "extractorId": "hubcloud_pixelserver", + "height": 1080, "title": "Dark.S03E08.The.Paradise.1080p.NF.WEB-DL.English.DDP5.1-German.DDP5.1.H.264-4kHdHub.Com.mkv", }, "requestHeaders": { @@ -54,6 +57,7 @@ exports[`HubCloud handle dexter original sin 2024 s01e01 1`] = ` "meta": { "bytes": 5733781340, "extractorId": "hubcloud_fsl", + "height": 2160, "title": "Dexter.Original.Sin.S01E01.2160p.SKST.WEB-DL.H.265.DDP5.1-Tyrell.mkv", }, "ttl": 43200000, @@ -65,6 +69,7 @@ exports[`HubCloud handle dexter original sin 2024 s01e01 1`] = ` "meta": { "bytes": 5733781340, "extractorId": "hubcloud_pixelserver", + "height": 2160, "title": "Dexter.Original.Sin.S01E01.2160p.SKST.WEB-DL.H.265.DDP5.1-Tyrell.mkv", }, "requestHeaders": { @@ -84,6 +89,7 @@ exports[`HubCloud handle goat 2026 1`] = ` "meta": { "bytes": 19091129630, "extractorId": "hubcloud_fsl", + "height": 2160, "title": "Goat (2026) 2160p 10bit HDR10+ DV iTunes WEB-DL HEVC x265 [Hindi AMZN DDP 5.1 640kbps + English DDP Atmos 5.1] ESub-(BYNDR-4kHdHub).mkv", }, "ttl": 43200000, @@ -95,6 +101,7 @@ exports[`HubCloud handle goat 2026 1`] = ` "meta": { "bytes": 19091129630, "extractorId": "hubcloud_fslv2", + "height": 2160, "title": "Goat (2026) 2160p 10bit HDR10+ DV iTunes WEB-DL HEVC x265 [Hindi AMZN DDP 5.1 640kbps + English DDP Atmos 5.1] ESub-(BYNDR-4kHdHub).mkv", }, "ttl": 43200000, diff --git a/src/extractor/__snapshots__/HubDrive.test.ts.snap b/src/extractor/__snapshots__/HubDrive.test.ts.snap index 6c0b076..dc141fe 100644 --- a/src/extractor/__snapshots__/HubDrive.test.ts.snap +++ b/src/extractor/__snapshots__/HubDrive.test.ts.snap @@ -8,6 +8,7 @@ exports[`HubDrive handle avatar 1`] = ` "meta": { "bytes": 64649995223, "extractorId": "hubcloud_fsl", + "height": 2160, "title": "Avatar (2009) Extended Collector's Edition IMAX 2160p UHD BluRay REMUX DV HDR 10bit HEVC [Hindi DDP 5.1 + English DTS-HD MA 5.1] x265 (LM-LUMiX) 4KHDHUB.[Com].mkv", }, "ttl": 43200000, diff --git a/src/utils/resolution.ts b/src/utils/resolution.ts index 7323b58..d7322d2 100644 --- a/src/utils/resolution.ts +++ b/src/utils/resolution.ts @@ -22,3 +22,11 @@ export const getClosestResolution = (height: number | undefined) => { return Math.abs(curr - height) < Math.abs(prev - height) ? curr : prev; })}p`; }; + +export const findHeight = (value: string): number | undefined => { + /* istanbul ignore next */ + const height = parseInt(RESOLUTIONS.find(res => value.toLowerCase().includes(res))?.replace('p', '') ?? '', 10); + + /* istanbul ignore next */ + return isNaN(height) ? undefined : height; +};