From f8f62db174eaa4acc8dbce1ff9f44a0318e99a7a Mon Sep 17 00:00:00 2001 From: WebStreamr <210764791+webstreamr@users.noreply.github.com> Date: Fri, 2 Jan 2026 09:15:30 +0000 Subject: [PATCH] chore(source): determine latest 4KHDHub domain more dynamically --- src/source/FourKHDHub.ts | 14 ++++++++++++-- .../__fixtures__/FourKHDHub/head-https:4khdhub.dad | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 src/source/__fixtures__/FourKHDHub/head-https:4khdhub.dad diff --git a/src/source/FourKHDHub.ts b/src/source/FourKHDHub.ts index d1a4155..f0777c7 100644 --- a/src/source/FourKHDHub.ts +++ b/src/source/FourKHDHub.ts @@ -3,6 +3,7 @@ import * as cheerio from 'cheerio'; import { BasicAcceptedElems, CheerioAPI } from 'cheerio'; import { AnyNode } from 'domhandler'; import levenshtein from 'fast-levenshtein'; +import memoize from 'memoizee'; import rot13Cipher from 'rot13-cipher'; import { ContentType } from 'stremio-addon-sdk'; import { Context, CountryCode, Meta } from '../types'; @@ -26,6 +27,11 @@ export class FourKHDHub extends Source { super(); this.fetcher = fetcher; + + this.getBaseUrl = memoize(this.getBaseUrl, { + maxAge: 3600000, // 1 hour + normalizer: () => 'baseUrl', + }); } public async handleInternal(ctx: Context, _type: string, id: Id): Promise { @@ -64,7 +70,7 @@ export class FourKHDHub extends Source { private readonly fetchPageUrl = async (ctx: Context, tmdbId: TmdbId): Promise => { const [name, year] = await getTmdbNameAndYear(ctx, this.fetcher, tmdbId); - const searchUrl = new URL(`/?s=${encodeURIComponent(`${name} ${year}`)}`, this.baseUrl); + const searchUrl = new URL(`/?s=${encodeURIComponent(`${name} ${year}`)}`, await this.getBaseUrl(ctx)); const html = await this.fetcher.text(ctx, searchUrl); const $ = cheerio.load(html); @@ -83,7 +89,7 @@ export class FourKHDHub extends Source { return levenshtein.get(movieCardTitle, name, { useCollator: true }) < 5; }) - .map((_i, el) => new URL($(el).attr('href') as string, this.baseUrl)) + .map(async (_i, el) => new URL($(el).attr('href') as string, await this.getBaseUrl(ctx))) .get(0); }; @@ -127,4 +133,8 @@ export class FourKHDHub extends Source { return new URL(atob(redirectData['o'])); } + + private readonly getBaseUrl = async (ctx: Context): Promise => { + return await this.fetcher.getFinalRedirectUrl(ctx, new URL(this.baseUrl)); + }; } diff --git a/src/source/__fixtures__/FourKHDHub/head-https:4khdhub.dad b/src/source/__fixtures__/FourKHDHub/head-https:4khdhub.dad new file mode 100644 index 0000000..57ec746 --- /dev/null +++ b/src/source/__fixtures__/FourKHDHub/head-https:4khdhub.dad @@ -0,0 +1 @@ +{"date":"Fri, 02 Jan 2026 09:15:12 GMT","content-type":"text/html; charset=UTF-8","connection":"close","server":"cloudflare","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","x-turbo-charged-by":"LiteSpeed","expires":"Thu, 19 Nov 1981 08:52:00 GMT","cache-control":"no-store, must-revalidate","pragma":"no-cache","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=vaTDhRUw77BBpC46sTicG0HdV0%2FfymKjEvNMlQnbEfzogqB4wV0MJCfpxlJM3SG1CQYrHlLmxJTZ0y%2FqjIQ5bMs4W3%2FkMTKoCX97\"}]}","vary":"Accept-Encoding","age":"2950","cf-cache-status":"HIT","last-modified":"Fri, 02 Jan 2026 08:26:02 GMT","cf-ray":"9b79268d5ef99b9b-FRA","alt-svc":"h3=\":443\"; ma=86400"} \ No newline at end of file