Skip to content

Commit 17079e1

Browse files
author
Inside4ndroid
committed
chore: provider updates (4khdhub permanent r2.dev block + zip strip, moviesclub vidora headers)
1 parent 25cc596 commit 17079e1

5 files changed

Lines changed: 100 additions & 23 deletions

File tree

CHANGELOG.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,30 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [1.0.5] - 2025-09-19
6+
7+
### Improved
8+
- 4khdhub provider: Permanently block `r2.dev` FSL links (previous optional flag removed).
9+
- Added Referer/Origin headers automatically for FSL Server links during validation (prior to block enforcement ensured proper behavior).
10+
- Tightened URL validation: removed unconditional trust for `r2.dev`; validation logic now consistent across hosts.
11+
- Host distribution instrumentation logs final hostname counts for easier diagnostics.
12+
- Preserved HubCloud worker `.zip` links by stripping the `.zip` extension instead of discarding them (enables direct playback attempts).
13+
- MoviesClub provider: Added automatic `Origin`/`Referer` headers for `vidora.stream` sources to prevent 403 responses.
14+
15+
### Notes
16+
- `r2.dev` links are always removed from final output; no env flag required.
17+
18+
### Documentation
19+
- README: Updated Providers section, unified schema example, MoviesClub listed, registry mapping instructions, and badge version.
20+
521
## [1.0.4] - 2025-09-18
622

723
### Added
8-
- New provider: `moviesclub` with registry mapping (`moviesclub.js``getMoviesClubStreams`).
924

1025
### Changed
11-
- Unified provider stream schema across all providers:
1226
```json
1327
{ "title": "", "url": "", "quality": "", "provider": "", "headers": { } }
1428
```
15-
- Provider integration docs: When adding a provider, also add its exported function to `providerFunctionMap` in `providers/registry.js`.
16-
- README Docker quick run snippet updated to: `docker run -it -p 8787:8787 inside4ndroid/tmdb-embed-api:latest`.
17-
18-
### Documentation
19-
- README: Updated Providers section, unified schema example, MoviesClub listed, registry mapping instructions, and badge version.
2029

2130
## [1.0.3] - 2025-09-17
2231

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<img src="https://img.shields.io/badge/Node.js-18%2B-brightgreen?style=flat" />
77
<img src="https://img.shields.io/badge/Status-Active-success?style=flat" />
88
<img src="https://img.shields.io/badge/License-MIT-blue?style=flat" />
9-
<img src="https://img.shields.io/badge/Version-1.0.4-informational?style=flat" />
9+
<img src="https://img.shields.io/badge/Version-1.0.5-informational?style=flat" />
1010
<img src="https://img.shields.io/docker/pulls/inside4ndroid/tmdb-embed-api?label=Docker%20Pulls&style=flat" />
1111
</p>
1212

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tmdb-embed-api",
3-
"version": "1.0.4",
3+
"version": "1.0.5",
44
"description": "Standalone streaming embed source aggregation API (TMDB ID in, streams out)",
55
"main": "apiServer.js",
66
"scripts": {

providers/4khdhub.js

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ const path = require('path');
99
const DOMAINS_URL = 'https://raw.githubusercontent.com/phisher98/TVVVV/refs/heads/main/domains.json';
1010
let 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 ---
1316
const CACHE_ENABLED = process.env.DISABLE_CACHE !== 'true';
1417
console.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 (/r2\.dev$/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 (/r2\.dev$/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 (/r2\.dev$/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

providers/moviesclub.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,15 @@ async function handleSingleServer(embedUrl, mediaType, season, episode, tmdbId)
309309
title: playerConfig.title || `${mediaType === 'movie' ? 'Movie' : `S${season.toString().padStart(2, '0')}E${episode.toString().padStart(2, '0')}`} ${tmdbId} - MoviesClub`,
310310
url: playerConfig.file,
311311
quality: extractQualityFromUrl(playerConfig.file) || '720p',
312-
headers: {}
312+
headers: (() => {
313+
if (playerConfig.file.includes('vidora.stream')) {
314+
return {
315+
Origin: 'https://vidora.stream',
316+
Referer: 'https://vidora.stream/'
317+
};
318+
}
319+
return {};
320+
})()
313321
};
314322

315323
// Add poster if available
@@ -384,7 +392,7 @@ function extractStreamsFromServer(serverData, serverName, mediaType, season, epi
384392
title: `${mediaType === 'movie' ? 'Movie' : `S${season.toString().padStart(2, '0')}E${episode.toString().padStart(2, '0')}`} ${tmdbId} - ${serverName}`,
385393
url: serverData,
386394
quality: extractQualityFromUrl(serverData) || '720p',
387-
headers: {}
395+
headers: serverData.includes('vidora.stream') ? { Origin: 'https://vidora.stream', Referer: 'https://vidora.stream/' } : {}
388396
};
389397
streams.push(stream);
390398
}
@@ -406,7 +414,7 @@ function extractStreamsFromServer(serverData, serverName, mediaType, season, epi
406414
title: `${mediaType === 'movie' ? 'Movie' : `S${season.toString().padStart(2, '0')}E${episode.toString().padStart(2, '0')}`} ${tmdbId} - ${serverName}`,
407415
url: serverData[key],
408416
quality: extractQualityFromUrl(serverData[key]) || '720p',
409-
headers: {}
417+
headers: serverData[key].includes('vidora.stream') ? { Origin: 'https://vidora.stream', Referer: 'https://vidora.stream/' } : {}
410418
};
411419

412420
// Add poster if available

0 commit comments

Comments
 (0)