@@ -9,6 +9,9 @@ const path = require('path');
99const DOMAINS_URL = 'https://raw.githubusercontent.com/phisher98/TVVVV/refs/heads/main/domains.json' ;
1010let cachedDomains = null ;
1111
12+ // Permanent policy: block r2.dev links (previously optional via env flag)
13+ console . log ( '[4KHDHub] r2.dev links will be removed (permanent policy)' ) ;
14+
1215// --- Caching Configuration ---
1316const CACHE_ENABLED = process . env . DISABLE_CACHE !== 'true' ;
1417console . log ( `[4KHDHub] Internal cache is ${ CACHE_ENABLED ? 'enabled' : 'disabled' } .` ) ;
@@ -61,8 +64,7 @@ function validateUrl(url) {
6164
6265 // Skip validation for known reliable hosting services
6366 const trustedHosts = [
64- 'pixeldrain.dev' ,
65- 'r2.dev'
67+ 'pixeldrain.dev'
6668 ] ;
6769
6870 const isTrustedHost = trustedHosts . some ( host => urlObj . hostname . includes ( host ) ) ;
@@ -74,11 +76,21 @@ function validateUrl(url) {
7476
7577 const protocol = urlObj . protocol === 'https:' ? https : http ;
7678
79+ // Add referer/origin for r2.dev validation attempts
80+ const extraHeaders = { } ;
81+ if ( / r 2 \. d e v $ / i. test ( urlObj . hostname ) ) {
82+ const origin = `${ urlObj . protocol } //${ urlObj . hostname } ` ;
83+ extraHeaders [ 'Referer' ] = origin + '/' ;
84+ extraHeaders [ 'Origin' ] = origin ;
85+ console . log ( `[4KHDHub] Adding Referer/Origin headers for validation of r2.dev URL: ${ url } ` ) ;
86+ }
87+
7788 const options = {
7889 method : 'HEAD' ,
7990 timeout : 15000 ,
8091 headers : {
81- 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
92+ 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' ,
93+ ...extraHeaders
8294 }
8395 } ;
8496
@@ -751,14 +763,22 @@ function extractHubCloudLinks(url, referer) {
751763 if ( displayFilename ) titleParts . push ( displayFilename ) ;
752764 if ( size ) titleParts . push ( size ) ;
753765 const finalTitle = titleParts . join ( '\n' ) ;
766+ let headers = { } ;
767+ try {
768+ const host = new URL ( link ) . hostname ;
769+ if ( / r 2 \. d e v $ / i. test ( host ) ) {
770+ headers = { Referer : baseUrl + '/' , Origin : baseUrl } ;
771+ console . log ( '[4KHDHub] Added Referer/Origin headers for r2.dev FSL link' ) ;
772+ }
773+ } catch { }
754774
755775 resolve ( {
756776 name : `4KHDHub - FSL Server${ qualityLabel } ` ,
757777 title : finalTitle ,
758778 url : link ,
759779 quality : quality ,
760780 provider : '4khdhub' ,
761- headers : { }
781+ headers
762782 } ) ;
763783 } )
764784 . catch ( ( ) => {
@@ -767,14 +787,22 @@ function extractHubCloudLinks(url, referer) {
767787 if ( displayFilename ) titleParts . push ( displayFilename ) ;
768788 if ( size ) titleParts . push ( size ) ;
769789 const finalTitle = titleParts . join ( '\n' ) ;
790+ let headers = { } ;
791+ try {
792+ const host = new URL ( link ) . hostname ;
793+ if ( / r 2 \. d e v $ / i. test ( host ) ) {
794+ headers = { Referer : baseUrl + '/' , Origin : baseUrl } ;
795+ console . log ( '[4KHDHub] Added Referer/Origin headers for r2.dev FSL link (fallback)' ) ;
796+ }
797+ } catch { }
770798
771799 resolve ( {
772800 name : `4KHDHub - FSL Server${ qualityLabel } ` ,
773801 title : finalTitle ,
774802 url : link ,
775803 quality : quality ,
776804 provider : '4khdhub' ,
777- headers : { }
805+ headers
778806 } ) ;
779807 } ) ;
780808 } else if ( text . includes ( 'Download File' ) ) {
@@ -1306,12 +1334,22 @@ function extractStreamingLinks(downloadLinks) {
13061334 . then ( results => {
13071335 const validResults = results . filter ( result => result !== null ) ;
13081336 const flatResults = validResults . flat ( ) ;
1309- // Filter out .zip files
1310- const filteredResults = flatResults . filter ( link => {
1311- return link && link . url && ! link . url . toLowerCase ( ) . endsWith ( '.zip' ) ;
1312- } ) ;
1337+ // Keep .zip links but strip the trailing .zip extension (attempt direct file URL)
1338+ const transformedResults = flatResults
1339+ . filter ( link => link && link . url )
1340+ . map ( link => {
1341+ try {
1342+ const lower = link . url . toLowerCase ( ) ;
1343+ if ( lower . endsWith ( '.zip' ) ) {
1344+ const newUrl = link . url . slice ( 0 , - 4 ) ; // remove .zip
1345+ console . log ( `[4KHDHub] Converted zip URL to non-zip: ${ link . url } -> ${ newUrl } ` ) ;
1346+ return { ...link , url : newUrl } ;
1347+ }
1348+ } catch { }
1349+ return link ;
1350+ } ) ;
13131351 // Note: Link count will be logged after validation completes
1314- return filteredResults ;
1352+ return transformedResults ;
13151353 } ) ;
13161354}
13171355
@@ -1778,7 +1816,7 @@ async function get4KHDHubStreams(tmdbId, type, season = null, episode = null) {
17781816 }
17791817
17801818 // Normalize to generic stream object format
1781- const streams = validatedLinks . map ( link => ( {
1819+ let streams = validatedLinks . map ( link => ( {
17821820 name : link . name , // Don't add prefix since it's already included
17831821 title : link . title || link . name ,
17841822 url : link . url ,
@@ -1787,6 +1825,28 @@ async function get4KHDHubStreams(tmdbId, type, season = null, episode = null) {
17871825 headers : { }
17881826 } ) ) ;
17891827
1828+ // Always remove r2.dev links
1829+ {
1830+ const before = streams . length ;
1831+ streams = streams . filter ( s => {
1832+ try { return ! new URL ( s . url ) . hostname . endsWith ( 'r2.dev' ) ; } catch { return true ; }
1833+ } ) ;
1834+ const removed = before - streams . length ;
1835+ if ( removed > 0 ) console . log ( `[4KHDHub] Removed ${ removed } r2.dev streams (permanent policy)` ) ;
1836+ }
1837+
1838+ // Host distribution instrumentation
1839+ try {
1840+ const hostCounts = streams . reduce ( ( acc , s ) => {
1841+ try {
1842+ const h = new URL ( s . url ) . hostname ;
1843+ acc [ h ] = ( acc [ h ] || 0 ) + 1 ;
1844+ } catch { }
1845+ return acc ;
1846+ } , { } ) ;
1847+ console . log ( '[4KHDHub] Final host distribution:' , hostCounts ) ;
1848+ } catch { }
1849+
17901850 console . log ( `[4KHDHub] Returning ${ streams . length } streams` ) ;
17911851 return streams ;
17921852
0 commit comments