From bad1170421298ef6aa5f1c69a6214065fe184773 Mon Sep 17 00:00:00 2001 From: WebStreamr <210764791+webstreamr@users.noreply.github.com> Date: Thu, 15 Jan 2026 13:38:27 +0000 Subject: [PATCH] feat: introduce fallback sources and mark VidSrc and RgShows as such fallback sources are only considered when not enough results are found. the idea is to use it for sources which are very useful as fallback but not everytime either because the quality is not good or querying them is resource intensive. --- src/extractor/VixSrc.ts | 4 +- .../__snapshots__/VixSrc.test.ts.snap | 2 + src/index.ts | 2 +- src/source/FourKHDHub.ts | 4 +- src/source/RgShows.ts | 2 + src/source/Source.ts | 2 + src/source/VidSrc.ts | 2 + .../__snapshots__/FourKHDHub.test.ts.snap | 49 + src/source/index.ts | 5 +- src/utils/StreamResolver.test.ts | 22 +- src/utils/StreamResolver.ts | 67 +- .../StreamResolver/head-https:4khdhub.dad | 1 + ...ercent20Knivespercent20Outpercent20Mystery | 342 +++ ...p-dead-man-a-knives-out-mystery-movie-4860 | 2125 +++++++++++++++++ .../https:api.themoviedb.org3movie812583 | 1 + ...estra.com-0c8acb0a3f7236028f194565b1af79b3 | 145 ++ ...estra.com-bc18cccb96a2e04e8e4615e2576ac261 | 942 ++++++++ ...Q3N5aU9GbkNMbkdjd2RPZDJqMHVlSk9CNlQ4MkE9PQ | 20 + ...ei95ckVmeXhnUVp6cHlyZVN3VFFIR0hQR0dvTlE9PQ | 20 + ...NnlVSC8xTjJueVpzOXpOeXcxVFZJZmg1ckoxT0E9PQ | 20 + ...RC9KS3BJa3EzTHRJMXgzZVEwV3RSK3h5czBSZmc9PQ | 20 + ...S1hqVEhPZE4vZDUrMU13M1F4S3MzOEIvdS9kUHc9PQ | 20 + ...c0t2VSthNTZ3cWR3L2QyTWpHV29FNGdJNk0wTUE9PQ | 20 + ...1RMeTZaRU4zalJmWityRk5wbHlRb1NqNmczMHZhQT0 | 376 +++ ...mc0b1l0eVM3anJjWmRLZlhZRkwybmJpeGplM3c0UT0 | 376 +++ ...EFxTm5yNUJ2eWdEWFMvK2ZhdVgxNWJMSlQwOXJsMD0 | 376 +++ ...2YrMjZ6T0NUTWh4THVjUTJWbW5PQk1DVmxqQlNmWT0 | 378 +++ ...1ZDdnJMNTNuNmFjTzhLNW1TLzhjM0lnK2xncEN0OD0 | 373 +++ ...E5sUjhkZWQ0ZnliVklxWGZlaDAyekwvK2ZxaHlLQT0 | 376 +++ .../https:hubcloud.foodrive4bttg4jurgo151w | 328 +++ .../https:hubcloud.foodrive6w6tm1hfcsmshwk | 328 +++ .../https:hubcloud.foodrivea55vjuuwj4vbtha | 328 +++ .../https:hubcloud.foodrivemvsevbmwskarnmy | 328 +++ .../https:hubcloud.foodrivetskphjtms4ovpkl | 328 +++ .../https:hubcloud.foodrivexoun4ifeynizfs9 | 328 +++ ...estra.com-218ec81a9b9bd0339f6550a292a93989 | 8 + .../https:vidsrc-embed.ruembedmovie812583 | 274 +++ .../__snapshots__/StreamResolver.test.ts.snap | 141 ++ src/utils/__snapshots__/manifest.test.ts.snap | 12 +- src/utils/language.ts | 16 +- src/utils/manifest.ts | 2 + 41 files changed, 8486 insertions(+), 27 deletions(-) create mode 100644 src/utils/__fixtures__/StreamResolver/head-https:4khdhub.dad create mode 100644 src/utils/__fixtures__/StreamResolver/https:4khdhub.dadsWakepercent20Uppercent20Deadpercent20Manpercent3Apercent20Apercent20Knivespercent20Outpercent20Mystery create mode 100644 src/utils/__fixtures__/StreamResolver/https:4khdhub.dadwake-up-dead-man-a-knives-out-mystery-movie-4860 create mode 100644 src/utils/__fixtures__/StreamResolver/https:api.themoviedb.org3movie812583 create mode 100644 src/utils/__fixtures__/StreamResolver/https:cloudnestra.com-0c8acb0a3f7236028f194565b1af79b3 create mode 100644 src/utils/__fixtures__/StreamResolver/https:cloudnestra.com-bc18cccb96a2e04e8e4615e2576ac261 create mode 100644 src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnYzJ3QkJQM1lXVlpSYjREQ3N5aU9GbkNMbkdjd2RPZDJqMHVlSk9CNlQ4MkE9PQ create mode 100644 src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZURBd2FuM2JaTS9Nblcrei95ckVmeXhnUVp6cHlyZVN3VFFIR0hQR0dvTlE9PQ create mode 100644 src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZUlZeUtKM2tHc0J2bEp5NnlVSC8xTjJueVpzOXpOeXcxVFZJZmg1ckoxT0E9PQ create mode 100644 src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZitGdU5NcEhjYk8wZWxzRC9KS3BJa3EzTHRJMXgzZVEwV3RSK3h5czBSZmc9PQ create mode 100644 src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZkl4ekFYVUZJVHBaNjUvS1hqVEhPZE4vZDUrMU13M1F4S3MzOEIvdS9kUHc9PQ create mode 100644 src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZnNxVEE4dEo3WUVSOTU4c0t2VSthNTZ3cWR3L2QyTWpHV29FNGdJNk0wTUE9PQ create mode 100644 src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandid4bttg4jurgo151wandtokenYksveTVQSkpSOGJRd1RMeTZaRU4zalJmWityRk5wbHlRb1NqNmczMHZhQT0 create mode 100644 src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandid6w6tm1hfcsmshwkandtokenZmVqK0pteE9QemNSbmc0b1l0eVM3anJjWmRLZlhZRkwybmJpeGplM3c0UT0 create mode 100644 src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandida55vjuuwj4vbthaandtokenNlgvb1l0TVNtUlNqbEFxTm5yNUJ2eWdEWFMvK2ZhdVgxNWJMSlQwOXJsMD0 create mode 100644 src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidmvsevbmwskarnmyandtokenQjFHOGo1MXB1OFI0Q2YrMjZ6T0NUTWh4THVjUTJWbW5PQk1DVmxqQlNmWT0 create mode 100644 src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidtskphjtms4ovpklandtokenVmRkcG5seHh3K3crb1ZDdnJMNTNuNmFjTzhLNW1TLzhjM0lnK2xncEN0OD0 create mode 100644 src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidxoun4ifeynizfs9andtokendEF5YnQ5NUpzWFhjOE5sUjhkZWQ0ZnliVklxWGZlaDAyekwvK2ZxaHlLQT0 create mode 100644 src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrive4bttg4jurgo151w create mode 100644 src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrive6w6tm1hfcsmshwk create mode 100644 src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivea55vjuuwj4vbtha create mode 100644 src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivemvsevbmwskarnmy create mode 100644 src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivetskphjtms4ovpkl create mode 100644 src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivexoun4ifeynizfs9 create mode 100644 src/utils/__fixtures__/StreamResolver/https:tmstr4.cloudnestra.com-218ec81a9b9bd0339f6550a292a93989 create mode 100644 src/utils/__fixtures__/StreamResolver/https:vidsrc-embed.ruembedmovie812583 diff --git a/src/extractor/VixSrc.ts b/src/extractor/VixSrc.ts index fcab676..14720e7 100644 --- a/src/extractor/VixSrc.ts +++ b/src/extractor/VixSrc.ts @@ -28,7 +28,7 @@ export class VixSrc extends Extractor { playlistUrl.searchParams.append('expires', expiresMatch[1] as string); playlistUrl.searchParams.append('h', '1'); - const countryCodes = meta.countryCodes ?? await this.determineCountryCodesFromPlaylist(ctx, playlistUrl, { headers }); + const countryCodes = meta.countryCodes ?? [CountryCode.multi, ...(await this.determineCountryCodesFromPlaylist(ctx, playlistUrl, { headers }))]; if (!hasMultiEnabled(ctx.config) && !countryCodes.some(countryCode => countryCode in ctx.config)) { return []; @@ -42,7 +42,7 @@ export class VixSrc extends Extractor { ttl: this.ttl, meta: { ...meta, - countryCodes: countryCodes.length ? countryCodes : [CountryCode.multi], + countryCodes, height: meta.height ?? await guessHeightFromPlaylist(ctx, this.fetcher, playlistUrl, { headers }), }, }, diff --git a/src/extractor/__snapshots__/VixSrc.test.ts.snap b/src/extractor/__snapshots__/VixSrc.test.ts.snap index 9bf12ef..9965e64 100644 --- a/src/extractor/__snapshots__/VixSrc.test.ts.snap +++ b/src/extractor/__snapshots__/VixSrc.test.ts.snap @@ -7,6 +7,7 @@ exports[`VixSrc Black Mirror 1`] = ` "label": "VixSrc", "meta": { "countryCodes": [ + "multi", "en", "it", ], @@ -28,6 +29,7 @@ exports[`VixSrc Full Metal Jacket 1`] = ` "label": "VixSrc", "meta": { "countryCodes": [ + "multi", "en", "it", ], diff --git a/src/index.ts b/src/index.ts index 52319bd..4df1fac 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,7 +50,7 @@ const addon = express(); addon.set('trust proxy', true); if (envIsProd()) { - addon.use(rateLimit({ windowMs: 60 * 1000, limit: 10 })); + addon.use(rateLimit({ windowMs: 60 * 1000, limit: 30 })); } addon.use((req: Request, res: Response, next: NextFunction) => { diff --git a/src/source/FourKHDHub.ts b/src/source/FourKHDHub.ts index 69651fe..e811dfd 100644 --- a/src/source/FourKHDHub.ts +++ b/src/source/FourKHDHub.ts @@ -50,7 +50,7 @@ export class FourKHDHub extends Source { $(`.episode-item`) .filter((_i, el) => $('.episode-title', el).text().includes(`S${String(tmdbId.season).padStart(2, '0')}`)) .map((_i, el) => ({ - countryCodes: findCountryCodes($(el).html() as string), + countryCodes: [CountryCode.multi, ...findCountryCodes($(el).html() as string)], downloadItem: $('.episode-download-item', el) .filter((_i, el) => $(el).text().includes(`Episode-${String(tmdbId.episode).padStart(2, '0')}`)) .get(0), @@ -62,7 +62,7 @@ export class FourKHDHub extends Source { return Promise.all( $(`.download-item`) - .map(async (_i, el) => await this.extractSourceResults(ctx, $, el, findCountryCodes($(el).html() as string))) + .map(async (_i, el) => await this.extractSourceResults(ctx, $, el, [CountryCode.multi, ...findCountryCodes($(el).html() as string)])) .toArray(), ); }; diff --git a/src/source/RgShows.ts b/src/source/RgShows.ts index 516805d..2147480 100644 --- a/src/source/RgShows.ts +++ b/src/source/RgShows.ts @@ -8,6 +8,8 @@ export class RgShows extends Source { public readonly label = 'RgShows'; + public override readonly isFallback = true; + public readonly contentTypes: ContentType[] = ['movie', 'series']; public readonly countryCodes: CountryCode[] = [CountryCode.multi]; diff --git a/src/source/Source.ts b/src/source/Source.ts index 86364aa..bca53b1 100644 --- a/src/source/Source.ts +++ b/src/source/Source.ts @@ -27,6 +27,8 @@ export abstract class Source { public readonly ttl: number = 43200000; // 12h + public readonly isFallback: boolean = false; // fallback sources are only considered if we don't have enough URLs from others already + public abstract readonly contentTypes: ContentType[]; public abstract readonly countryCodes: CountryCode[]; diff --git a/src/source/VidSrc.ts b/src/source/VidSrc.ts index 017010b..0ca4688 100644 --- a/src/source/VidSrc.ts +++ b/src/source/VidSrc.ts @@ -8,6 +8,8 @@ export class VidSrc extends Source { public readonly label = 'VidSrc'; + public override readonly isFallback = true; + public readonly contentTypes: ContentType[] = ['movie', 'series']; public readonly countryCodes: CountryCode[] = [CountryCode.multi]; diff --git a/src/source/__snapshots__/FourKHDHub.test.ts.snap b/src/source/__snapshots__/FourKHDHub.test.ts.snap index 0aaa42f..c6f7088 100644 --- a/src/source/__snapshots__/FourKHDHub.test.ts.snap +++ b/src/source/__snapshots__/FourKHDHub.test.ts.snap @@ -6,6 +6,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 67645734912, "countryCodes": [ + "multi", "en", "hi", ], @@ -18,6 +19,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 50036368998, "countryCodes": [ + "multi", "en", "hi", ], @@ -30,6 +32,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 37795712204, "countryCodes": [ + "multi", "en", "hi", ], @@ -42,6 +45,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 26736171417, "countryCodes": [ + "multi", "en", "hi", ], @@ -54,6 +58,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 20615843020, "countryCodes": [ + "multi", "en", "hi", ], @@ -66,6 +71,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 17824114278, "countryCodes": [ + "multi", "en", "hi", ], @@ -78,6 +84,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 15998753177, "countryCodes": [ + "multi", "en", "hi", ], @@ -90,6 +97,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 9126805504, "countryCodes": [ + "multi", "en", "hi", ], @@ -102,6 +110,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 8321499136, "countryCodes": [ + "multi", "en", "hi", ], @@ -114,6 +123,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 8010114007, "countryCodes": [ + "multi", "en", "hi", ], @@ -126,6 +136,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 7730941132, "countryCodes": [ + "multi", "en", "hi", ], @@ -138,6 +149,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 7000796692, "countryCodes": [ + "multi", "en", "hi", ], @@ -150,6 +162,7 @@ exports[`FourKHDHub handle avengers: endgame 1`] = ` "meta": { "bytes": 4015794421, "countryCodes": [ + "multi", "en", "hi", ], @@ -167,6 +180,7 @@ exports[`FourKHDHub handle crank 2006 1`] = ` "meta": { "bytes": 17255031111, "countryCodes": [ + "multi", "en", "hi", ], @@ -179,6 +193,7 @@ exports[`FourKHDHub handle crank 2006 1`] = ` "meta": { "bytes": 10479720202, "countryCodes": [ + "multi", "en", "hi", ], @@ -191,6 +206,7 @@ exports[`FourKHDHub handle crank 2006 1`] = ` "meta": { "bytes": 4176855695, "countryCodes": [ + "multi", "en", "hi", ], @@ -208,6 +224,7 @@ exports[`FourKHDHub handle crayon shin-chan 1993 1`] = ` "meta": { "bytes": 28550795100, "countryCodes": [ + "multi", "hi", "ja", ], @@ -220,6 +237,7 @@ exports[`FourKHDHub handle crayon shin-chan 1993 1`] = ` "meta": { "bytes": 10383083438, "countryCodes": [ + "multi", "hi", "ja", ], @@ -232,6 +250,7 @@ exports[`FourKHDHub handle crayon shin-chan 1993 1`] = ` "meta": { "bytes": 5776731013, "countryCodes": [ + "multi", "hi", "ja", ], @@ -251,6 +270,7 @@ exports[`FourKHDHub handle dark 2017 s01e02 1`] = ` "meta": { "bytes": 2126008811, "countryCodes": [ + "multi", "de", "en", ], @@ -263,6 +283,7 @@ exports[`FourKHDHub handle dark 2017 s01e02 1`] = ` "meta": { "bytes": 4348654387, "countryCodes": [ + "multi", "de", "en", ], @@ -280,6 +301,7 @@ exports[`FourKHDHub handle dexter original sin 2024 s01e01 1`] = ` "meta": { "bytes": 5733781340, "countryCodes": [ + "multi", "en", ], "height": 2160, @@ -291,6 +313,7 @@ exports[`FourKHDHub handle dexter original sin 2024 s01e01 1`] = ` "meta": { "bytes": 5143223336, "countryCodes": [ + "multi", "en", ], "height": 2160, @@ -302,6 +325,7 @@ exports[`FourKHDHub handle dexter original sin 2024 s01e01 1`] = ` "meta": { "bytes": 5046586572, "countryCodes": [ + "multi", "en", ], "height": 2160, @@ -313,6 +337,7 @@ exports[`FourKHDHub handle dexter original sin 2024 s01e01 1`] = ` "meta": { "bytes": 5057323991, "countryCodes": [ + "multi", "en", ], "height": 2160, @@ -329,6 +354,7 @@ exports[`FourKHDHub handle dexter resurrection 2025 s01e01 1`] = ` "meta": { "bytes": 6012954214, "countryCodes": [ + "multi", "en", ], "height": 2160, @@ -340,6 +366,7 @@ exports[`FourKHDHub handle dexter resurrection 2025 s01e01 1`] = ` "meta": { "bytes": 3285649981, "countryCodes": [ + "multi", "en", ], "height": 1080, @@ -351,6 +378,7 @@ exports[`FourKHDHub handle dexter resurrection 2025 s01e01 1`] = ` "meta": { "bytes": 935109591, "countryCodes": [ + "multi", "en", ], "height": 1080, @@ -367,6 +395,7 @@ exports[`FourKHDHub handle f1 1`] = ` "meta": { "bytes": 71296457113, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -381,6 +410,7 @@ exports[`FourKHDHub handle f1 1`] = ` "meta": { "bytes": 41414222151, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -395,6 +425,7 @@ exports[`FourKHDHub handle f1 1`] = ` "meta": { "bytes": 30096983326, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -409,6 +440,7 @@ exports[`FourKHDHub handle f1 1`] = ` "meta": { "bytes": 29785598197, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -423,6 +455,7 @@ exports[`FourKHDHub handle f1 1`] = ` "meta": { "bytes": 21496311316, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -437,6 +470,7 @@ exports[`FourKHDHub handle f1 1`] = ` "meta": { "bytes": 19520626360, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -451,6 +485,7 @@ exports[`FourKHDHub handle f1 1`] = ` "meta": { "bytes": 11424613007, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -470,6 +505,7 @@ exports[`FourKHDHub handle lovely runner 2024 s01e01 1`] = ` "meta": { "bytes": 3586297692, "countryCodes": [ + "multi", "hi", "ko", ], @@ -482,6 +518,7 @@ exports[`FourKHDHub handle lovely runner 2024 s01e01 1`] = ` "meta": { "bytes": 10340133765, "countryCodes": [ + "multi", "hi", "ko", ], @@ -596,6 +633,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 65326452572, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -610,6 +648,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 36335423324, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -624,6 +663,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 26940182364, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -638,6 +678,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 26671746908, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -652,6 +693,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 26661009489, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -666,6 +708,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 23665269800, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -680,6 +723,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 21775484190, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -694,6 +738,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 20862803640, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -708,6 +753,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 16943645982, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -722,6 +768,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 10307921510, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -736,6 +783,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 9384503541, "countryCodes": [ + "multi", "en", "hi", "ta", @@ -750,6 +798,7 @@ exports[`FourKHDHub handle superman 2025 1`] = ` "meta": { "bytes": 7451768258, "countryCodes": [ + "multi", "en", "hi", "ta", diff --git a/src/source/index.ts b/src/source/index.ts index 9d31170..2cf1b5b 100644 --- a/src/source/index.ts +++ b/src/source/index.ts @@ -28,12 +28,11 @@ export const createSources = (fetcher: Fetcher): Source[] => { return [ // multi new FourKHDHub(fetcher), - new RgShows(fetcher), new VixSrc(fetcher), + new VidSrc(), + new RgShows(fetcher), // AL new Kokoshka(fetcher), - // EN - new VidSrc(), // ES / MX new CineHDPlus(fetcher), new Cuevana(fetcher), diff --git a/src/utils/StreamResolver.test.ts b/src/utils/StreamResolver.test.ts index 974e2fc..5985193 100644 --- a/src/utils/StreamResolver.test.ts +++ b/src/utils/StreamResolver.test.ts @@ -2,21 +2,27 @@ import { ContentType } from 'stremio-addon-sdk'; import winston from 'winston'; import { BlockedError, HttpError, NotFoundError, QueueIsFullError, TimeoutError, TooManyRequestsError, TooManyTimeoutsError } from '../error'; import { createExtractors, Extractor, ExtractorRegistry } from '../extractor'; +import { HubCloud } from '../extractor/HubCloud'; +import { VidSrc as VidSrcExtractor } from '../extractor/VidSrc'; import { Source, SourceResult } from '../source'; +import { FourKHDHub } from '../source/FourKHDHub'; import { MeineCloud } from '../source/MeineCloud'; import { MostraGuarda } from '../source/MostraGuarda'; +import { VidSrc } from '../source/VidSrc'; import { createTestContext } from '../test'; import { BlockedReason, CountryCode, Format, UrlResult } from '../types'; import { FetcherMock } from './FetcherMock'; -import { ImdbId } from './id'; +import { ImdbId, TmdbId } from './id'; import { StreamResolver } from './StreamResolver'; const logger = winston.createLogger({ transports: [new winston.transports.Console({ level: 'nope' })] }); const fetcher = new FetcherMock(`${__dirname}/__fixtures__/StreamResolver`); const ctx = createTestContext({ de: 'on', it: 'on' }); +const fourKhdHub = new FourKHDHub(fetcher); const meineCloud = new MeineCloud(fetcher); const mostraGuarda = new MostraGuarda(fetcher); +const vidSrc = new VidSrc(); describe('resolve', () => { test('returns info as stream if no sources were configured', async () => { @@ -68,6 +74,20 @@ describe('resolve', () => { expect(streamsWithExternalUrls.streams).toMatchSnapshot(); }); + test('skips fallback sources if possible', async () => { + const streamResolver = new StreamResolver(logger, new ExtractorRegistry(logger, [new HubCloud(fetcher), new VidSrcExtractor(fetcher, ['vidsrc-embed.ru'])])); + + const streams = await streamResolver.resolve(createTestContext(), [fourKhdHub, vidSrc], 'movie', new TmdbId(812583, undefined, undefined)); + expect(streams.streams).toMatchSnapshot(); + }); + + test('keeps fallback sources if needed', async () => { + const streamResolver = new StreamResolver(logger, new ExtractorRegistry(logger, [new HubCloud(fetcher), new VidSrcExtractor(fetcher, ['vidsrc-embed.ru'])])); + + const streams = await streamResolver.resolve(createTestContext(), [vidSrc], 'movie', new TmdbId(812583, undefined, undefined)); + expect(streams.streams).toMatchSnapshot(); + }); + test('adds error info', async () => { class MockSource extends Source { public readonly id = 'mocksource'; diff --git a/src/utils/StreamResolver.ts b/src/utils/StreamResolver.ts index 8955c43..5ccf121 100644 --- a/src/utils/StreamResolver.ts +++ b/src/utils/StreamResolver.ts @@ -1,14 +1,15 @@ +import { Mutex } from 'async-mutex'; import bytes from 'bytes'; import { ContentType, Stream } from 'stremio-addon-sdk'; import winston from 'winston'; import { logErrorAndReturnNiceString } from '../error'; import { ExtractorRegistry } from '../extractor'; import { Source } from '../source'; -import { Context, Format, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; import { showErrors, showExternalUrls } from './config'; import { envGetAppName } from './env'; import { Id } from './id'; -import { flagFromCountryCode } from './language'; +import { countryCodesFromConfig, flagFromCountryCode } from './language'; interface ResolveResponse { streams: Stream[]; @@ -40,22 +41,39 @@ export class StreamResolver { const streams: Stream[] = []; let sourceErrorCount = 0; - const urlResults: UrlResult[] = []; - const sourcePromises = sources.map(async (source) => { - if (!source.contentTypes.includes(type)) { - return; - } + const sourceErrorCountMutex = new Mutex(); + const urlResults: UrlResult[] = []; + + const urlResultsCountByCountryCode = new Map(); + const urlResultsCountByCountryCodeMutex = new Mutex(); + + const skippedFallbackSources: Source[] = []; + + const handleSource = async (source: Source) => { try { const sourceResults = await source.handle(ctx, type, id); - const sourceUrlResults = await Promise.all( sourceResults.map(({ url, meta }) => this.extractorRegistry.handle(ctx, url, { ...meta, sourceLabel: source.label, sourceId: source.id }, true)), ); - urlResults.push(...sourceUrlResults.flat()); + const urlResultsToAdd = sourceUrlResults.flat(); + for (const urlResult of urlResultsToAdd) { + if (urlResult.error) { + continue; + } + + await urlResultsCountByCountryCodeMutex.runExclusive(() => { + urlResult.meta?.countryCodes?.forEach((countryCode) => { + urlResultsCountByCountryCode.set(countryCode, (urlResultsCountByCountryCode.get(countryCode) ?? 0) + 1); + }); + }); + } + urlResults.push(...urlResultsToAdd); } catch (error) { - sourceErrorCount++; + await sourceErrorCountMutex.runExclusive(() => { + sourceErrorCount++; + }); if (showErrors(ctx.config)) { streams.push({ @@ -65,9 +83,34 @@ export class StreamResolver { }); } } + }; + + // Resolve non-fallback sources in parallel extracting all their results + const sourcePromises = sources.map(async (source) => { + if (!source.contentTypes.includes(type)) { + return; + } + + if (source.isFallback) { + skippedFallbackSources.push(source); + return; + } + + await handleSource(source); }); await Promise.all(sourcePromises); + // Resolve fallback sources if we didn't get enough results already + for (const skippedFallbackSource of skippedFallbackSources) { + const configCountryCodes = countryCodesFromConfig(ctx.config); + const resultCount = urlResults.reduce((accumulator, urlResult) => accumulator + Number(this.arraysIntersect(urlResult.meta?.countryCodes as CountryCode[], configCountryCodes)), 0); + if (resultCount > 2) { + continue; + } + + await handleSource(skippedFallbackSource); + } + urlResults.sort((a, b) => { if (a.error || b.error) { return a.isExternal ? -1 : 1; @@ -119,6 +162,10 @@ export class StreamResolver { }; }; + private arraysIntersect(arr1: T[], arr2: T[]): boolean { + return arr1.filter(item => arr2.includes(item)).length > 0; + } + private determineTtl(urlResults: UrlResult[]): number | undefined { if (!urlResults.length) { return 900000; // 15m diff --git a/src/utils/__fixtures__/StreamResolver/head-https:4khdhub.dad b/src/utils/__fixtures__/StreamResolver/head-https:4khdhub.dad new file mode 100644 index 0000000..0b0cdb7 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/head-https:4khdhub.dad @@ -0,0 +1 @@ +{"date":"Thu, 15 Jan 2026 13:33:06 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=tCHWJJ%2FBuH3jYaypQEgAWtVWsve%2BjP83m%2BuZ4jMQRk%2BLOAoSGca22nV3HU5gzVHQW%2B7DI5AVcaPJSrCqJK4fkN%2FaCvWKm4KoVOzG\"}]}","vary":"Accept-Encoding","cf-cache-status":"MISS","last-modified":"Thu, 15 Jan 2026 13:33:06 GMT","cf-ray":"9be5be30da220ac2-FRA","alt-svc":"h3=\":443\"; ma=86400"} \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:4khdhub.dadsWakepercent20Uppercent20Deadpercent20Manpercent3Apercent20Apercent20Knivespercent20Outpercent20Mystery b/src/utils/__fixtures__/StreamResolver/https:4khdhub.dadsWakepercent20Uppercent20Deadpercent20Manpercent3Apercent20Apercent20Knivespercent20Outpercent20Mystery new file mode 100644 index 0000000..17c01d4 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:4khdhub.dadsWakepercent20Uppercent20Deadpercent20Manpercent3Apercent20Apercent20Knivespercent20Outpercent20Mystery @@ -0,0 +1,342 @@ + + + + + + + Search - Wake Up Dead Man: A Knives Out Mystery - 4KHDHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +
+ + + + +
+ + + + + +
+ + + + + +
+
+
+ + + + + + + + + +
+ + +
+ +
+ +
+
+
+
+

4KHDHub

+

+ Your one-stop destination for high-quality movies and TV shows in various formats. +

+
+ +
+

Quick Links

+ +
+ +
+

Connect

+

Stay updated with the latest releases and news.

+
+
+ +
+

© 2025 4KHDHub - All rights reserved.

+
+
+
+ + +
+ + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:4khdhub.dadwake-up-dead-man-a-knives-out-mystery-movie-4860 b/src/utils/__fixtures__/StreamResolver/https:4khdhub.dadwake-up-dead-man-a-knives-out-mystery-movie-4860 new file mode 100644 index 0000000..c4b2665 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:4khdhub.dadwake-up-dead-man-a-knives-out-mystery-movie-4860 @@ -0,0 +1,2125 @@ + + + + + + Wake Up Dead Man: A Knives Out Mystery (2025) - 4K-HDHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ +
+ + + + +
+ + + + + +
+ + + + + +
+
+
+ + + + + + + + + +
+ + +
+
+ + +
+ +
+
+

Wake Up Dead Man: A Knives Out Mystery (2025)

+ + + + +

He works in mysterious ways.

+ +
+ +
+ + 7.4 +
+ + + Comedy + + Crime + + Mystery + + Movies + + 1080p + + 2160p + + Dual Language + + DV HDR + + English + + HEVC + + Hindi + + SDR + + +
+ +
+ +
+
+ + + + +
+ +

+ When young priest Jud Duplenticy is sent to assist charismatic firebrand Monsignor Jefferson Wicks, it’s clear that all is not well in the pews. After a sudden and seemingly impossible murder rocks the town, the lack of an obvious suspect prompts local police chief Geraldine Scott to join forces with renowned detective Benoit Blanc to unravel a mystery that defies all logic.

+ + + + + + +
+ +
+ +

Download Links

+ + + +
+ + +
+
+ +
+ + Wake Up Dead Man: A Knives Out Mystery (2160p WEB-DL HDR DV HEVC) +
20.89 GB + Hindi, English + WEB-DL + +
+ + + + +
+ +
+ +
+
+ +
+ + Wake Up Dead Man: A Knives Out Mystery (2160p WEB-DL HEVC) +
17.97 GB + Hindi, English + WEB-DL + +
+ + + + +
+ +
+ +
+
+ +
+ + Wake Up Dead Man: A Knives Out Mystery (1080p WEB-DL HEVC) +
9.33 GB + Hindi, English + WEB-DL + +
+ + + + +
+ +
+ +
+
+ +
+ + Wake Up Dead Man: A Knives Out Mystery (1080p WEB-DL x264) +
9.3 GB + Hindi, English + WEB-DL + +
+ + + + +
+ +
+ +
+
+ +
+ + Wake Up Dead Man: A Knives Out Mystery (1080p WEB-DL HDR DV HEVC) +
5.32 GB + Hindi, English + WEB-DL + +
+ + + + +
+ +
+ +
+
+ +
+ + Wake Up Dead Man: A Knives Out Mystery (1080p WEB-DL AV1) +
1.28 GB + Hindi, English + WEB-DL + +
+ + + + +
+ +
+ + +
+
+ +
+
+ + + + + +

How to Download

+
+
    +
  1. Click on the download link of your choice.
  2. +
  3. Wait for the page to load and bypass any ads if necessary.
  4. +
  5. Click on the download button on the file hosting site.
  6. +
  7. Enjoy your high-quality movie!
  8. +
+
+ + +
+
+
+
+ +
+
+
+
+

4K-HDHub

+

+ Your one-stop destination for high-quality movies and TV shows in various formats. +

+
+ + +
+

Quick Links

+ +
+ +
+

Connect

+

Stay updated with the latest releases and news.

+
+
+ + +
+

© 2025 4K-HDHub - All rights reserved.

+
+
+
+ + + + + + + + + + + +
+ + + + + diff --git a/src/utils/__fixtures__/StreamResolver/https:api.themoviedb.org3movie812583 b/src/utils/__fixtures__/StreamResolver/https:api.themoviedb.org3movie812583 new file mode 100644 index 0000000..99fe5e2 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:api.themoviedb.org3movie812583 @@ -0,0 +1 @@ +{"adult":false,"backdrop_path":"/fiRDzpcJe7qz3yIR43hdXIE3NHv.jpg","belongs_to_collection":{"id":722971,"name":"Knives Out Collection","poster_path":"/pkjW3K0UDnwYWDcUR83VzfHNQA4.jpg","backdrop_path":"/G7qYINSq5xyDd0I0zn3DpAssA0.jpg"},"budget":210000000,"genres":[{"id":53,"name":"Thriller"},{"id":9648,"name":"Mystery"},{"id":35,"name":"Comedy"}],"homepage":"https://www.wakeupdeadmanfilm.com/home","id":812583,"imdb_id":"tt14364480","origin_country":["US"],"original_language":"en","original_title":"Wake Up Dead Man: A Knives Out Mystery","overview":"When young priest Jud Duplenticy is sent to assist charismatic firebrand Monsignor Jefferson Wicks, it’s clear that all is not well in the pews. After a sudden and seemingly impossible murder rocks the town, the lack of an obvious suspect prompts local police chief Geraldine Scott to join forces with renowned detective Benoit Blanc to unravel a mystery that defies all logic.","popularity":41.1958,"poster_path":"/qCOGGi8JBVEZMc3DVby8rUivyXz.jpg","production_companies":[{"id":37871,"logo_path":"/aUOo1S2AabqQnRrXK6XuObWPDyK.png","name":"T-Street","origin_country":"US"}],"production_countries":[{"iso_3166_1":"US","name":"United States of America"}],"release_date":"2025-11-26","revenue":4000000,"runtime":145,"spoken_languages":[{"english_name":"English","iso_639_1":"en","name":"English"}],"status":"Released","tagline":"He works in mysterious ways.","title":"Wake Up Dead Man: A Knives Out Mystery","video":false,"vote_average":7.211,"vote_count":1767} \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:cloudnestra.com-0c8acb0a3f7236028f194565b1af79b3 b/src/utils/__fixtures__/StreamResolver/https:cloudnestra.com-0c8acb0a3f7236028f194565b1af79b3 new file mode 100644 index 0000000..d83b0ba --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:cloudnestra.com-0c8acb0a3f7236028f194565b1af79b3 @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + +
+
+
+ Wake Up Dead Man: A Knives Out Mystery (2025)
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + diff --git a/src/utils/__fixtures__/StreamResolver/https:cloudnestra.com-bc18cccb96a2e04e8e4615e2576ac261 b/src/utils/__fixtures__/StreamResolver/https:cloudnestra.com-bc18cccb96a2e04e8e4615e2576ac261 new file mode 100644 index 0000000..574b0c7 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:cloudnestra.com-bc18cccb96a2e04e8e4615e2576ac261 @@ -0,0 +1,942 @@ + + + +Wake Up Dead Man: A Knives Out Mystery (2025) + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnYzJ3QkJQM1lXVlpSYjREQ3N5aU9GbkNMbkdjd2RPZDJqMHVlSk9CNlQ4MkE9PQ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnYzJ3QkJQM1lXVlpSYjREQ3N5aU9GbkNMbkdjd2RPZDJqMHVlSk9CNlQ4MkE9PQ new file mode 100644 index 0000000..f34be1b --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnYzJ3QkJQM1lXVlpSYjREQ3N5aU9GbkNMbkdjd2RPZDJqMHVlSk9CNlQ4MkE9PQ @@ -0,0 +1,20 @@ + + +Redirecting ... + + + + + + + + + +Redirecting .. + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZURBd2FuM2JaTS9Nblcrei95ckVmeXhnUVp6cHlyZVN3VFFIR0hQR0dvTlE9PQ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZURBd2FuM2JaTS9Nblcrei95ckVmeXhnUVp6cHlyZVN3VFFIR0hQR0dvTlE9PQ new file mode 100644 index 0000000..7b09451 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZURBd2FuM2JaTS9Nblcrei95ckVmeXhnUVp6cHlyZVN3VFFIR0hQR0dvTlE9PQ @@ -0,0 +1,20 @@ + + +Redirecting ... + + + + + + + + + +Redirecting .. + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZUlZeUtKM2tHc0J2bEp5NnlVSC8xTjJueVpzOXpOeXcxVFZJZmg1ckoxT0E9PQ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZUlZeUtKM2tHc0J2bEp5NnlVSC8xTjJueVpzOXpOeXcxVFZJZmg1ckoxT0E9PQ new file mode 100644 index 0000000..3b55c38 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZUlZeUtKM2tHc0J2bEp5NnlVSC8xTjJueVpzOXpOeXcxVFZJZmg1ckoxT0E9PQ @@ -0,0 +1,20 @@ + + +Redirecting ... + + + + + + + + + +Redirecting .. + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZitGdU5NcEhjYk8wZWxzRC9KS3BJa3EzTHRJMXgzZVEwV3RSK3h5czBSZmc9PQ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZitGdU5NcEhjYk8wZWxzRC9KS3BJa3EzTHRJMXgzZVEwV3RSK3h5czBSZmc9PQ new file mode 100644 index 0000000..e9611f5 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZitGdU5NcEhjYk8wZWxzRC9KS3BJa3EzTHRJMXgzZVEwV3RSK3h5czBSZmc9PQ @@ -0,0 +1,20 @@ + + +Redirecting ... + + + + + + + + + +Redirecting .. + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZkl4ekFYVUZJVHBaNjUvS1hqVEhPZE4vZDUrMU13M1F4S3MzOEIvdS9kUHc9PQ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZkl4ekFYVUZJVHBaNjUvS1hqVEhPZE4vZDUrMU13M1F4S3MzOEIvdS9kUHc9PQ new file mode 100644 index 0000000..19b2761 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZkl4ekFYVUZJVHBaNjUvS1hqVEhPZE4vZDUrMU13M1F4S3MzOEIvdS9kUHc9PQ @@ -0,0 +1,20 @@ + + +Redirecting ... + + + + + + + + + +Redirecting .. + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZnNxVEE4dEo3WUVSOTU4c0t2VSthNTZ3cWR3L2QyTWpHV29FNGdJNk0wTUE9PQ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZnNxVEE4dEo3WUVSOTU4c0t2VSthNTZ3cWR3L2QyTWpHV29FNGdJNk0wTUE9PQ new file mode 100644 index 0000000..6c8e8a4 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gadgetsweb.xyzidQ1dxTzFnbjhrQm5kMG5lL01tQzcvZzhmMjZOTkNrdktvSEp1VXBaU3FnZnNxVEE4dEo3WUVSOTU4c0t2VSthNTZ3cWR3L2QyTWpHV29FNGdJNk0wTUE9PQ @@ -0,0 +1,20 @@ + + +Redirecting ... + + + + + + + + + +Redirecting .. + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandid4bttg4jurgo151wandtokenYksveTVQSkpSOGJRd1RMeTZaRU4zalJmWityRk5wbHlRb1NqNmczMHZhQT0 b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandid4bttg4jurgo151wandtokenYksveTVQSkpSOGJRd1RMeTZaRU4zalJmWityRk5wbHlRb1NqNmczMHZhQT0 new file mode 100644 index 0000000..0f90e65 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandid4bttg4jurgo151wandtokenYksveTVQSkpSOGJRd1RMeTZaRU4zalJmWityRk5wbHlRb1NqNmczMHZhQT0 @@ -0,0 +1,376 @@ + + + + + + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.265-4kHdHub.Com.mkv + + + + + + + + + + + + + + + + + + + + +
+
+
+HubCloud | Login +
+ +
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.265-4kHdHub.Com.mkv
+ +
+
    +
  • File Size9.33 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:21:55
  • +
+ +
+
+ + +
+

Download Link Generated

+
+ +
+ Copy Share Link +
+
+ + + + + + + + + +
+ + +
+ + + + + + Download [FSL Server] + + + + + + + + + + Download [Server : 10Gbps] + +

+ Resume Not Supported in 10Gbps So Use only if you have stable internet (: +

+ + + + + + + Download [PixelServer : 2] + + + + + + + + + + + + + + + + + + + +

+ + + + + + +
+ + + +
+
+ +
+ +
+
+
+

+
+Msc + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandid6w6tm1hfcsmshwkandtokenZmVqK0pteE9QemNSbmc0b1l0eVM3anJjWmRLZlhZRkwybmJpeGplM3c0UT0 b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandid6w6tm1hfcsmshwkandtokenZmVqK0pteE9QemNSbmc0b1l0eVM3anJjWmRLZlhZRkwybmJpeGplM3c0UT0 new file mode 100644 index 0000000..d8a1c2b --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandid6w6tm1hfcsmshwkandtokenZmVqK0pteE9QemNSbmc0b1l0eVM3anJjWmRLZlhZRkwybmJpeGplM3c0UT0 @@ -0,0 +1,376 @@ + + + + + + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.HDR-DV.H.265-4kHdHub.Com.mkv + + + + + + + + + + + + + + + + + + + + +
+
+
+HubCloud | Login +
+ +
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.HDR-DV.H.265-4kHdHub.Com.mkv
+ +
+
    +
  • File Size5.32 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:21:00
  • +
+ +
+
+ + +
+

Download Link Generated

+
+ +
+ Copy Share Link +
+
+ + + + + + + + + +
+ + +
+ + + + + + Download [FSL Server] + + + + + + + + + + Download [Server : 10Gbps] + +

+ Resume Not Supported in 10Gbps So Use only if you have stable internet (: +

+ + + + + + + Download [PixelServer : 2] + + + + + + + + + + + + + + + + + + + +

+ + + + + + +
+ + + +
+
+ +
+ +
+
+
+

+
+Msc + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandida55vjuuwj4vbthaandtokenNlgvb1l0TVNtUlNqbEFxTm5yNUJ2eWdEWFMvK2ZhdVgxNWJMSlQwOXJsMD0 b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandida55vjuuwj4vbthaandtokenNlgvb1l0TVNtUlNqbEFxTm5yNUJ2eWdEWFMvK2ZhdVgxNWJMSlQwOXJsMD0 new file mode 100644 index 0000000..01825d7 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandida55vjuuwj4vbthaandtokenNlgvb1l0TVNtUlNqbEFxTm5yNUJ2eWdEWFMvK2ZhdVgxNWJMSlQwOXJsMD0 @@ -0,0 +1,376 @@ + + + + + + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.H.265-4kHDHub.Com.mkv + + + + + + + + + + + + + + + + + + + + +
+
+
+HubCloud | Login +
+ +
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.H.265-4kHDHub.Com.mkv
+ +
+
    +
  • File Size17.97 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:59:40
  • +
+ +
+
+ + +
+

Download Link Generated

+
+ +
+ Copy Share Link +
+
+ + + + + + + + + +
+ + +
+ + + + + + Download [FSL Server] + + + + + + + + + + Download [Server : 10Gbps] + +

+ Resume Not Supported in 10Gbps So Use only if you have stable internet (: +

+ + + + + + + Download [PixelServer : 2] + + + + + + + + + + + + + + + + + + + +

+ + + + + + +
+ + + +
+
+ +
+ +
+
+
+

+
+Msc + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidmvsevbmwskarnmyandtokenQjFHOGo1MXB1OFI0Q2YrMjZ6T0NUTWh4THVjUTJWbW5PQk1DVmxqQlNmWT0 b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidmvsevbmwskarnmyandtokenQjFHOGo1MXB1OFI0Q2YrMjZ6T0NUTWh4THVjUTJWbW5PQk1DVmxqQlNmWT0 new file mode 100644 index 0000000..40e6bc8 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidmvsevbmwskarnmyandtokenQjFHOGo1MXB1OFI0Q2YrMjZ6T0NUTWh4THVjUTJWbW5PQk1DVmxqQlNmWT0 @@ -0,0 +1,378 @@ + + + + + + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.AAC5.1-English.AAC5.1.AV1-4kHdHub.Com.mkv + + + + + + + + + + + + + + + + + + + + +
+
+
+HubCloud | Login +
+ +
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.AAC5.1-English.AAC5.1.AV1-4kHdHub.Com.mkv
+ +
+
    +
  • File Size1.28 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:20:28
  • +
+ +
+
+ + +
+

Download Link Generated

+
+ +
+ Copy Share Link +
+
+ + + + + + + + + +
+ + +
+ + + + + + Download [FSL Server] + + + + + + + + + + Download [Server : 10Gbps] + +

+ Resume Not Supported in 10Gbps So Use only if you have stable internet (: +

+ + + + + + + Download [PixelServer : 2] + + + + + + + + + + + + + + +
+ Downoad From Telegram + + + + + +

+ + + + + + +
+ + + +
+
+ +
+ +
+
+
+

+
+Msc + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidtskphjtms4ovpklandtokenVmRkcG5seHh3K3crb1ZDdnJMNTNuNmFjTzhLNW1TLzhjM0lnK2xncEN0OD0 b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidtskphjtms4ovpklandtokenVmRkcG5seHh3K3crb1ZDdnJMNTNuNmFjTzhLNW1TLzhjM0lnK2xncEN0OD0 new file mode 100644 index 0000000..302716b --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidtskphjtms4ovpklandtokenVmRkcG5seHh3K3crb1ZDdnJMNTNuNmFjTzhLNW1TLzhjM0lnK2xncEN0OD0 @@ -0,0 +1,373 @@ + + + + + + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.DV.HDR.H.265-4kHDHub.Com.mkv + + + + + + + + + + + + + + + + + + + + +
+
+
+HubCloud | Login +
+ +
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.DV.HDR.H.265-4kHDHub.Com.mkv
+ +
+
    +
  • File Size20.89 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:59:26
  • +
+ +
+
+ + +
+

Download Link Generated

+
+ +
+ Copy Share Link +
+
+ + + + + + + + + +
+ + +
+ + + + + + Download [FSL Server] + + + + + + + + + + Download [Server : 10Gbps] + +

+ Resume Not Supported in 10Gbps So Use only if you have stable internet (: +

+ + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + +
+ + + +
+
+ +
+ +
+
+
+

+
+Msc + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidxoun4ifeynizfs9andtokendEF5YnQ5NUpzWFhjOE5sUjhkZWQ0ZnliVklxWGZlaDAyekwvK2ZxaHlLQT0 b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidxoun4ifeynizfs9andtokendEF5YnQ5NUpzWFhjOE5sUjhkZWQ0ZnliVklxWGZlaDAyekwvK2ZxaHlLQT0 new file mode 100644 index 0000000..9da0c89 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:gamerxyt.comhubcloud.phphosthubcloudandidxoun4ifeynizfs9andtokendEF5YnQ5NUpzWFhjOE5sUjhkZWQ0ZnliVklxWGZlaDAyekwvK2ZxaHlLQT0 @@ -0,0 +1,376 @@ + + + + + + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.264-4kHdHub.Com.mkv + + + + + + + + + + + + + + + + + + + + +
+
+
+HubCloud | Login +
+ +
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.264-4kHdHub.Com.mkv
+ +
+
    +
  • File Size9.3 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:04:31
  • +
+ +
+
+ + +
+

Download Link Generated

+
+ +
+ Copy Share Link +
+
+ + + + + + + + + +
+ + +
+ + + + + + Download [FSL Server] + + + + + + + + + + Download [Server : 10Gbps] + +

+ Resume Not Supported in 10Gbps So Use only if you have stable internet (: +

+ + + + + + + Download [PixelServer : 2] + + + + + + + + + + + + + + + + + + + +

+ + + + + + +
+ + + +
+
+ +
+ +
+
+
+

+
+Msc + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrive4bttg4jurgo151w b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrive4bttg4jurgo151w new file mode 100644 index 0000000..bce5308 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrive4bttg4jurgo151w @@ -0,0 +1,328 @@ + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.265-4kHdHub.Com.mkv + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+HubCloud | Create An Account |Login +
+
+
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.265-4kHdHub.Com.mkv
+ +
+
    +
  • File Size9.33 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:21:55
  • +
+ + +
+
+ + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +

Please Wait While Page is loading

+
+
+ + + + Generate Direct Download Link + + +
+ + + +
+ + + + + +
+

+
+ + + + + +
+ + + + + +
+ + + + + + +
+
+ +
+ +
+
+
+

+
+ + + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrive6w6tm1hfcsmshwk b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrive6w6tm1hfcsmshwk new file mode 100644 index 0000000..de6c772 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrive6w6tm1hfcsmshwk @@ -0,0 +1,328 @@ + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.HDR-DV.H.265-4kHdHub.Com.mkv + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+HubCloud | Create An Account |Login +
+
+
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.HDR-DV.H.265-4kHdHub.Com.mkv
+ +
+
    +
  • File Size5.32 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:21:00
  • +
+ + +
+
+ + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +

Please Wait While Page is loading

+
+
+ + + + Generate Direct Download Link + + +
+ + + +
+ + + + + +
+

+
+ + + + + +
+ + + + + +
+ + + + + + +
+
+ +
+ +
+
+
+

+
+ + + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivea55vjuuwj4vbtha b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivea55vjuuwj4vbtha new file mode 100644 index 0000000..f3ade28 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivea55vjuuwj4vbtha @@ -0,0 +1,328 @@ + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.H.265-4kHDHub.Com.mkv + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+HubCloud | Create An Account |Login +
+
+
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.H.265-4kHDHub.Com.mkv
+ +
+
    +
  • File Size17.97 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:59:40
  • +
+ + +
+
+ + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +

Please Wait While Page is loading

+
+
+ + + + Generate Direct Download Link + + +
+ + + +
+ + + + + +
+

+
+ + + + + +
+ + + + + +
+ + + + + + +
+
+ +
+ +
+
+
+

+
+ + + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivemvsevbmwskarnmy b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivemvsevbmwskarnmy new file mode 100644 index 0000000..a0ab444 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivemvsevbmwskarnmy @@ -0,0 +1,328 @@ + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.AAC5.1-English.AAC5.1.AV1-4kHdHub.Com.mkv + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+HubCloud | Create An Account |Login +
+
+
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.AAC5.1-English.AAC5.1.AV1-4kHdHub.Com.mkv
+ +
+
    +
  • File Size1.28 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:20:28
  • +
+ + +
+
+ + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +

Please Wait While Page is loading

+
+
+ + + + Generate Direct Download Link + + +
+ + + +
+ + + + + +
+

+
+ + + + + +
+ + + + + +
+ + + + + + +
+
+ +
+ +
+
+
+

+
+ + + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivetskphjtms4ovpkl b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivetskphjtms4ovpkl new file mode 100644 index 0000000..49fe578 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivetskphjtms4ovpkl @@ -0,0 +1,328 @@ + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.DV.HDR.H.265-4kHDHub.Com.mkv + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+HubCloud | Create An Account |Login +
+
+
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.DV.HDR.H.265-4kHDHub.Com.mkv
+ +
+
    +
  • File Size20.89 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:59:26
  • +
+ + +
+
+ + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +

Please Wait While Page is loading

+
+
+ + + + Generate Direct Download Link + + +
+ + + +
+ + + + + +
+

+
+ + + + + +
+ + + + + +
+ + + + + + +
+
+ +
+ +
+
+
+

+
+ + + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivexoun4ifeynizfs9 b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivexoun4ifeynizfs9 new file mode 100644 index 0000000..010125a --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:hubcloud.foodrivexoun4ifeynizfs9 @@ -0,0 +1,328 @@ + + +Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.264-4kHdHub.Com.mkv + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+HubCloud | Create An Account |Login +
+
+
+
+

+
+ +
+ +
+ Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.264-4kHdHub.Com.mkv
+ +
+
    +
  • File Size9.3 GB
  • +
  • File Typevideo/x-matrosk
  • +
  • Share Date12-Dec-2025 08:04:31
  • +
+ + +
+
+ + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +

Please Wait While Page is loading

+
+
+ + + + Generate Direct Download Link + + +
+ + + +
+ + + + + +
+

+
+ + + + + +
+ + + + + +
+ + + + + + +
+
+ +
+ +
+
+
+

+
+ + + + + + \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:tmstr4.cloudnestra.com-218ec81a9b9bd0339f6550a292a93989 b/src/utils/__fixtures__/StreamResolver/https:tmstr4.cloudnestra.com-218ec81a9b9bd0339f6550a292a93989 new file mode 100644 index 0000000..d017ab4 --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:tmstr4.cloudnestra.com-218ec81a9b9bd0339f6550a292a93989 @@ -0,0 +1,8 @@ +#EXTM3U +#EXT-X-INDEPENDENT-SEGMENTS +#EXT-X-STREAM-INF:BANDWIDTH=956290,CODECS="mp4a.40.2,avc1.42c01e",RESOLUTION=640x360,FRAME-RATE=24,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE +/pl/H4sIAAAAAAAAAwXB0ZKCIBQA0F8CMSf3sTUrAlpQLsYbqE2jWM7WbOLX7zkk6ck2y3ybo_SW4a5zeer7bXbLvWvRBn1Vo5IsAWoPY5SP8SOJeLUQXhWRaY130aGwCEMXi.6Kl2H2JkxnUl66cZ4VoUxpxWC4pvXxFK9aBIZmCdraPiheYVgtqKH_fv_BQJkn4mBqirwu1x7U7lLQn64Ruk44FkdYvZELfwTCVv3xexn7o_7ravXUw27jcTe7cVZmAmG1iupAn3KCeE1ASNyxS6N_W1JK.Sgbvb9HV1jHCwpt9V5NIZBAtK6M3YiCRzUobJrw5Hsc6ykwF04rH8Tiy5A6Avac2MYB_dgV5f.vyM6uQQEAAA--/7a67bab9038b6ca38d13b08cead24c49/index.m3u8 +#EXT-X-STREAM-INF:BANDWIDTH=3024126,CODECS="mp4a.40.2,avc1.64001f",RESOLUTION=1280x720,FRAME-RATE=24,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE +/pl/H4sIAAAAAAAAAwXB0ZKCIBQA0F8CMSf3sTUrAlpQLsYbqE2jWM7WbOLX7zkk6ck2y3ybo_SW4a5zeer7bXbLvWvRBn1Vo5IsAWoPY5SP8SOJeLUQXhWRaY130aGwCEMXi.6Kl2H2JkxnUl66cZ4VoUxpxWC4pvXxFK9aBIZmCdraPiheYVgtqKH_fv_BQJkn4mBqirwu1x7U7lLQn64Ruk44FkdYvZELfwTCVv3xexn7o_7ravXUw27jcTe7cVZmAmG1iupAn3KCeE1ASNyxS6N_W1JK.Sgbvb9HV1jHCwpt9V5NIZBAtK6M3YiCRzUobJrw5Hsc6ykwF04rH8Tiy5A6Avac2MYB_dgV5f.vyM6uQQEAAA--/7e39f90815d0cbca3fcb1178fb9fa803/index.m3u8 +#EXT-X-STREAM-INF:BANDWIDTH=5679378,CODECS="mp4a.40.2,avc1.640028",RESOLUTION=1920x1080,FRAME-RATE=24,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE +/pl/H4sIAAAAAAAAAwXB0ZKCIBQA0F8CMSf3sTUrAlpQLsYbqE2jWM7WbOLX7zkk6ck2y3ybo_SW4a5zeer7bXbLvWvRBn1Vo5IsAWoPY5SP8SOJeLUQXhWRaY130aGwCEMXi.6Kl2H2JkxnUl66cZ4VoUxpxWC4pvXxFK9aBIZmCdraPiheYVgtqKH_fv_BQJkn4mBqirwu1x7U7lLQn64Ruk44FkdYvZELfwTCVv3xexn7o_7ravXUw27jcTe7cVZmAmG1iupAn3KCeE1ASNyxS6N_W1JK.Sgbvb9HV1jHCwpt9V5NIZBAtK6M3YiCRzUobJrw5Hsc6ykwF04rH8Tiy5A6Avac2MYB_dgV5f.vyM6uQQEAAA--/9e523ae15b61dc766f5c818726881ecf/index.m3u8 \ No newline at end of file diff --git a/src/utils/__fixtures__/StreamResolver/https:vidsrc-embed.ruembedmovie812583 b/src/utils/__fixtures__/StreamResolver/https:vidsrc-embed.ruembedmovie812583 new file mode 100644 index 0000000..e7cc44f --- /dev/null +++ b/src/utils/__fixtures__/StreamResolver/https:vidsrc-embed.ruembedmovie812583 @@ -0,0 +1,274 @@ + + + +Wake Up Dead Man: A Knives Out Mystery (2025) + + + + + + + + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + diff --git a/src/utils/__snapshots__/StreamResolver.test.ts.snap b/src/utils/__snapshots__/StreamResolver.test.ts.snap index 57f4bc5..157b9b7 100644 --- a/src/utils/__snapshots__/StreamResolver.test.ts.snap +++ b/src/utils/__snapshots__/StreamResolver.test.ts.snap @@ -167,6 +167,21 @@ exports[`resolve ignores not found errors 1`] = ` } `; +exports[`resolve keeps fallback sources if needed 1`] = ` +[ + { + "behaviorHints": { + "bingeGroup": "webstreamr-vidsrc-vidsrc-multi", + "notWebReady": true, + }, + "name": "WebStreamr 🌐 1080p", + "title": "Wake Up Dead Man: A Knives Out Mystery (2025) +🔗 CloudStream Pro from VidSrc", + "url": "https://tmstr4.cloudnestra.com/pl/H4sIAAAAAAAAAwXB0ZKCIBQA0F8CMSf3sTUrAlpQLsYbqE2jWM7WbOLX7zkk6ck2y3ybo_SW4a5zeer7bXbLvWvRBn1Vo5IsAWoPY5SP8SOJeLUQXhWRaY130aGwCEMXi.6Kl2H2JkxnUl66cZ4VoUxpxWC4pvXxFK9aBIZmCdraPiheYVgtqKH_fv_BQJkn4mBqirwu1x7U7lLQn64Ruk44FkdYvZELfwTCVv3xexn7o_7ravXUw27jcTe7cVZmAmG1iupAn3KCeE1ASNyxS6N_W1JK.Sgbvb9HV1jHCwpt9V5NIZBAtK6M3YiCRzUobJrw5Hsc6ykwF04rH8Tiy5A6Avac2MYB_dgV5f.vyM6uQQEAAA--/master.m3u8", + }, +] +`; + exports[`resolve returns empty array if no source found anything 1`] = ` { "streams": [], @@ -391,3 +406,129 @@ exports[`resolve returns source errors as stream 2`] = ` ], } `; + +exports[`resolve skips fallback sources if possible 1`] = ` +[ + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_fsl-multi_en_hi", + "notWebReady": true, + "videoSize": 22430466703, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 2160p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.DV.HDR.H.265-4kHDHub.Com.mkv +💾 20.89 GB 🔗 HubCloud (FSL) from 4KHDHub", + "url": "https://fsl.master.surf/03ee346a29b2b13afa1935bfbd6d05e8?token=1768483596", + }, + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_fsl-multi_en_hi", + "notWebReady": true, + "videoSize": 19295140577, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 2160p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.H.265-4kHDHub.Com.mkv +💾 17.97 GB 🔗 HubCloud (FSL) from 4KHDHub", + "url": "https://fsl.master.surf/e25e157cd10b4c203ad281a9280d5931?token=1768483596", + }, + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_pixelserver-multi_en_hi", + "notWebReady": true, + "videoSize": 19295140577, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 2160p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.2160p.NF.WEB-DL.DUAL.DDP5.1.Atmos.H.265-4kHDHub.Com.mkv +💾 17.97 GB 🔗 HubCloud (PixelServer) from 4KHDHub", + "url": "https://pixeldrain.dev/api/file/Kd5MqbDS", + }, + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_fsl-multi_en_hi", + "notWebReady": true, + "videoSize": 10018011217, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 1080p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.265-4kHdHub.Com.mkv +💾 9.33 GB 🔗 HubCloud (FSL) from 4KHDHub", + "url": "https://fsl.master.surf/7a5fb128b139c4170291e04f0f6cd729?token=1768483596", + }, + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_pixelserver-multi_en_hi", + "notWebReady": true, + "videoSize": 10018011217, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 1080p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.265-4kHdHub.Com.mkv +💾 9.33 GB 🔗 HubCloud (PixelServer) from 4KHDHub", + "url": "https://pixeldrain.dev/api/file/h7hpWDSW", + }, + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_fsl-multi_en_hi", + "notWebReady": true, + "videoSize": 9985798963, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 1080p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.264-4kHdHub.Com.mkv +💾 9.3 GB 🔗 HubCloud (FSL) from 4KHDHub", + "url": "https://fsl.master.surf/f956e46a610fa88657d505d07be917e9?token=1768483435", + }, + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_pixelserver-multi_en_hi", + "notWebReady": true, + "videoSize": 9985798963, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 1080p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.H.264-4kHdHub.Com.mkv +💾 9.3 GB 🔗 HubCloud (PixelServer) from 4KHDHub", + "url": "https://pixeldrain.dev/api/file/yzyxiGzC", + }, + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_fsl-multi_en_hi", + "notWebReady": true, + "videoSize": 5712306503, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 1080p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.HDR-DV.H.265-4kHdHub.Com.mkv +💾 5.32 GB 🔗 HubCloud (FSL) from 4KHDHub", + "url": "https://fsl.master.surf/27df6ba61996f9a2e1725d5faa4a0cbb?token=1768483596", + }, + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_pixelserver-multi_en_hi", + "notWebReady": true, + "videoSize": 5712306503, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 1080p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.DDP5.1.Atmos-English.DDP5.1.Atmos.HDR-DV.H.265-4kHdHub.Com.mkv +💾 5.32 GB 🔗 HubCloud (PixelServer) from 4KHDHub", + "url": "https://pixeldrain.dev/api/file/gPsPz3B7", + }, + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_fsl-multi_en_hi", + "notWebReady": true, + "videoSize": 1374389534, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 1080p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.AAC5.1-English.AAC5.1.AV1-4kHdHub.Com.mkv +💾 1.28 GB 🔗 HubCloud (FSL) from 4KHDHub", + "url": "https://fsl.master.surf/f391f8beec927157dc784b261af950c2?token=1768483596", + }, + { + "behaviorHints": { + "bingeGroup": "webstreamr-4khdhub-hubcloud_pixelserver-multi_en_hi", + "notWebReady": true, + "videoSize": 1374389534, + }, + "name": "WebStreamr 🌐 🇺🇸 🇮🇳 1080p", + "title": "Wake.Up.Dead.Man.A.Knives.Out.Mystery.2025.1080p.NF.WEB-DL.Hindi.AAC5.1-English.AAC5.1.AV1-4kHdHub.Com.mkv +💾 1.28 GB 🔗 HubCloud (PixelServer) from 4KHDHub", + "url": "https://pixeldrain.dev/api/file/XsNetT2P", + }, +] +`; diff --git a/src/utils/__snapshots__/manifest.test.ts.snap b/src/utils/__snapshots__/manifest.test.ts.snap index 7982062..0a31055 100644 --- a/src/utils/__snapshots__/manifest.test.ts.snap +++ b/src/utils/__snapshots__/manifest.test.ts.snap @@ -86,7 +86,7 @@ exports[`buildManifest default manifest 1`] = ` Supported languages: Albanian, German, Castilian Spanish, French, Hindi, Italian, Latin American Spanish, Tamil, Telugu -Supported sources: 4KHDHub, RgShows, VixSrc, Kokoshka, VidSrc, CineHDPlus, Cuevana, HomeCine, VerHdLink, Einschalten, KinoGer, MegaKino, MeineCloud, StreamKiste, Frembed, FrenchCloud, Movix, Eurostreaming, MostraGuarda +Supported sources: 4KHDHub, CineHDPlus, Cuevana, Einschalten, Eurostreaming, Frembed, FrenchCloud, HomeCine, KinoGer, Kokoshka, MegaKino, MeineCloud, MostraGuarda, Movix, RgShows, StreamKiste, VerHdLink, VidSrc, VixSrc Supported extractors: ", "id": "webstreamr", @@ -251,11 +251,6 @@ exports[`buildManifest has checked source with appropriate config 1`] = ` exports[`buildManifest has unchecked source without a config 1`] = ` [ - { - "key": "multi", - "title": "Multi 🌐 (VixSrc)", - "type": "checkbox", - }, { "key": "de", "title": "German 🇩🇪 (MeineCloud, StreamKiste)", @@ -266,6 +261,11 @@ exports[`buildManifest has unchecked source without a config 1`] = ` "title": "Castilian Spanish 🇪🇸 (VerHdLink)", "type": "checkbox", }, + { + "key": "multi", + "title": "Multi 🌐 (VixSrc)", + "type": "checkbox", + }, { "key": "it", "title": "Italian 🇮🇹 (VixSrc)", diff --git a/src/utils/language.ts b/src/utils/language.ts index bb4294f..9e0173b 100644 --- a/src/utils/language.ts +++ b/src/utils/language.ts @@ -1,4 +1,4 @@ -import { CountryCode } from '../types'; +import { Config, CountryCode } from '../types'; const countryCodeMap: Record = { multi: { language: 'Multi', flag: '🌐', iso639: undefined }, @@ -64,7 +64,19 @@ export const findCountryCodes = (value: string): CountryCode[] => { const countryCodes: CountryCode[] = []; for (const countryCode in countryCodeMap) { - if (value.includes(countryCodeMap[countryCode as CountryCode]['language'])) { + if (!countryCodes.includes(countryCode as CountryCode) && value.includes(countryCodeMap[countryCode as CountryCode]['language'])) { + countryCodes.push(countryCode as CountryCode); + } + } + + return countryCodes; +}; + +export const countryCodesFromConfig = (config: Config): CountryCode[] => { + const countryCodes: CountryCode[] = []; + + for (const countryCode in countryCodeMap) { + if (countryCode in config) { countryCodes.push(countryCode as CountryCode); } } diff --git a/src/utils/manifest.ts b/src/utils/manifest.ts index 6eed930..b9761e9 100644 --- a/src/utils/manifest.ts +++ b/src/utils/manifest.ts @@ -35,6 +35,8 @@ export const buildManifest = (sources: Source[], extractors: Extractor[], config }, }; + sources.sort((sourceA, sourceB) => sourceA.label.localeCompare(sourceB.label)); + const countryCodeSources: Partial> = {}; sources.forEach(source => source.countryCodes