added hdhub, frost and watchout ( ty movieslay )

This commit is contained in:
Devin Bot
2026-10-25 18:56:22 -07:00
parent 6b238cbc45
commit c7c4cb48f4
5 changed files with 165 additions and 0 deletions

View File

@@ -187,6 +187,18 @@ export const SOURCES = [
}],
},
{
key: 'frost',
label: 'FrostStream',
sourceFile: 'frost',
proxyParam: 'fst',
timeout: 25000,
jitter: 500,
retries: 2,
multiUrl: true,
skipProxy: true,
},
{
key: 'fsonline',
label: 'FSOnline',
@@ -199,6 +211,18 @@ export const SOURCES = [
skipProxy: true,
},
{
key: 'hdhub',
label: 'HDHub',
sourceFile: 'hdhub',
proxyParam: 'hdh',
timeout: 25000,
jitter: 500,
retries: 2,
multiUrl: true,
skipProxy: true,
},
{
key: 'hexa',
label: 'Hexa',
@@ -608,6 +632,18 @@ export const SOURCES = [
},
},
{
key: 'watchout',
label: 'Watchout',
sourceFile: 'watchout',
proxyParam: 'wo',
timeout: 25000,
jitter: 500,
retries: 2,
multiUrl: true,
skipProxy: true,
},
{
key: 'xdownloader',
label: 'XDownloader',

30
src/sources/frost.js Normal file
View File

@@ -0,0 +1,30 @@
import { fetchJson, resolveImdbId } from '../utils/helpers.js';
export async function getStream({ id, s, e, tmdbApiKey, sdk }) {
const isTv = s != null && e != null;
const type = isTv ? 'series' : 'movie';
const imdb = await resolveImdbId(id, isTv, tmdbApiKey || sdk?.tmdbApiKey);
if (!imdb) return null;
const url = isTv
? `https://froststream.cloutteam.com/stream/series/${imdb}:${s}:${e}.json`
: `https://froststream.cloutteam.com/stream/movie/${imdb}.json`;
const res = await fetchJson(url).catch(() => null);
if (!res || !Array.isArray(res.streams) || !res.streams.length) return null;
const allUrls = res.streams.filter(st => st.url).map(st => ({
url: st.url,
server: `Frost - ${st.name || 'Server'} ${st.title ? `- ${st.title}` : ''}`,
headers: st.behaviorHints?.proxyHeaders?.request || undefined,
skipProxy: st.behaviorHints?.notWebReady === false
}));
if (!allUrls.length) return null;
return {
url: allUrls[0].url,
headers: allUrls[0].headers,
allUrls
};
}

36
src/sources/hdhub.js Normal file
View File

@@ -0,0 +1,36 @@
import { fetchJson, resolveImdbId } from '../utils/helpers.js';
export async function getStream({ id, s, e, tmdbApiKey, sdk }) {
const isTv = s != null && e != null;
const type = isTv ? 'series' : 'movie';
const imdb = await resolveImdbId(id, isTv, tmdbApiKey || sdk?.tmdbApiKey);
if (!imdb) return null;
const CONFIG = btoa(JSON.stringify({ "torbox": "unset", "qualities": "2160p,1080p,720p", "sort": "desc", "catalogs": "featured,popular" }));
const url = `https://hdhub.thevolecitor.qzz.io/${CONFIG}/stream/${type}/${imdb}${isTv ? `:${s}:${e}` : ""}.json`;
const res = await fetchJson(url).catch(() => null);
if (!res || !Array.isArray(res.streams) || !res.streams.length) return null;
const validStreams = res.streams.filter(st => {
if (!st.url || !st.url.trim()) return false;
const lower = st.url.toLowerCase();
if (lower.includes('hubcloud') || lower.includes('pixeldrain.dev') || lower.endsWith('.zip')) return false;
return true;
});
if (!validStreams.length) return null;
const allUrls = validStreams.map(st => ({
url: st.url,
server: `HDHub - ${st.name || 'Server'}`,
headers: st.behaviorHints?.proxyHeaders?.request || undefined,
skipProxy: st.behaviorHints?.notWebReady === false
}));
return {
url: allUrls[0].url,
headers: allUrls[0].headers,
allUrls
};
}

46
src/sources/watchout.js Normal file
View File

@@ -0,0 +1,46 @@
import { fetchJson, fetchText } from '../utils/helpers.js';
const API_URL = "https://raw.githubusercontent.com/Watchout2025/api/refs/heads/main/hls/";
export async function getStream({ id, s, e }) {
const isTv = s != null && e != null;
const type = isTv ? 'tv' : 'movie';
const targetUrl = isTv
? `${API_URL}tv/${id}/S${s}.json`
: `${API_URL}movie/${id}`;
const headers = {
'Origin': 'https://vidout.pages.dev',
'Referer': 'https://vidout.pages.dev'
};
if (type === 'movie') {
const data = await fetchText(targetUrl).catch(() => null);
if (!data || !data.includes('://')) return null;
return {
url: data.trim(),
headers,
allUrls: [{
url: data.trim(),
server: 'Watchout - Direct',
headers
}]
};
} else {
const data = await fetchJson(targetUrl).catch(() => null);
const streamUrl = data?.[String(e)] || null;
if (!streamUrl) return null;
return {
url: streamUrl,
headers,
allUrls: [{
url: streamUrl,
server: 'Watchout - Direct',
headers
}]
};
}
}

View File

@@ -52,6 +52,23 @@ function pruneHelperCache(cache) {
}
}
export async function resolveImdbId(id, isTv, tmdbApiKey) {
if (typeof id === 'string' && id.startsWith('tt')) return id;
const apiKey = tmdbApiKey || process.env.TMDB_API_KEY;
if (!apiKey) return `tt${id}`;
const type = isTv ? 'tv' : 'movie';
try {
const res = await fetch(`https://api.themoviedb.org/3/${type}/${id}?api_key=${apiKey}&append_to_response=external_ids`, {
signal: AbortSignal.timeout(5000),
});
if (!res.ok) return `tt${id}`;
const data = await res.json();
return data.imdb_id || data.external_ids?.imdb_id || `tt${id}`;
} catch {
return `tt${id}`;
}
}
setInterval(() => {
pruneHelperCache(tmdbValidationCache);
pruneHelperCache(tmdbInfoCache);