mirror of
https://github.com/Inside4ndroid/TMDB-Embed-API.git
synced 2026-10-22 09:35:11 +00:00
Huge update see changelog for details.
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
const axios = require('axios');
|
||||
const { getTmdbApiKey } = require('../utils/tmdbKey');
|
||||
|
||||
const VIDEASY_HEADERS = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'Origin': 'https://player.videasy.net',
|
||||
'Referer': 'https://player.videasy.net/'
|
||||
};
|
||||
|
||||
// Each server maps a name to its API URL. moviesOnly:true skips TV requests.
|
||||
const SERVERS = {
|
||||
'Neon': { url: 'https://api.videasy.net/myflixerzupcloud/sources-with-title' },
|
||||
'Yoru': { url: 'https://api.videasy.net/cdn/sources-with-title', moviesOnly: true },
|
||||
'Cypher': { url: 'https://api.videasy.net/moviebox/sources-with-title' },
|
||||
'Reyna': { url: 'https://api.videasy.net/primewire/sources-with-title' },
|
||||
'Omen': { url: 'https://api.videasy.net/onionplay/sources-with-title' },
|
||||
'Breach': { url: 'https://api.videasy.net/m4uhd/sources-with-title' },
|
||||
'Ghost': { url: 'https://api.videasy.net/primesrcme/sources-with-title' },
|
||||
'Sage': { url: 'https://api.videasy.net/1movies/sources-with-title' },
|
||||
'Vyse': { url: 'https://api.videasy.net/hdmovie/sources-with-title' },
|
||||
'Raze': { url: 'https://api.videasy.net/superflix/sources-with-title' }
|
||||
};
|
||||
|
||||
const DECRYPT_URL = 'https://enc-dec.app/api/dec-videasy';
|
||||
|
||||
async function getVideasyStreams(tmdbId, mediaType = 'movie', seasonNum = null, episodeNum = null) {
|
||||
console.log(`[Videasy] Fetching streams for TMDB ID: ${tmdbId}, Type: ${mediaType}`);
|
||||
|
||||
const tmdbKey = getTmdbApiKey();
|
||||
if (!tmdbKey) {
|
||||
console.error('[Videasy] No TMDB API key configured.');
|
||||
return [];
|
||||
}
|
||||
|
||||
// Step 1: Resolve title/year/imdbId from TMDB
|
||||
let details;
|
||||
try {
|
||||
const type = mediaType === 'tv' ? 'tv' : 'movie';
|
||||
const { data } = await axios.get(
|
||||
`https://api.themoviedb.org/3/${type}/${tmdbId}?api_key=${tmdbKey}&append_to_response=external_ids`,
|
||||
{ timeout: 8000 }
|
||||
);
|
||||
details = {
|
||||
title: data.title || data.name || '',
|
||||
year: (data.release_date || data.first_air_date || '').split('-')[0],
|
||||
imdbId: (data.external_ids && data.external_ids.imdb_id) || '',
|
||||
type
|
||||
};
|
||||
} catch (err) {
|
||||
console.error(`[Videasy] TMDB lookup failed: ${err.message}`);
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!details.title) {
|
||||
console.error('[Videasy] No title returned from TMDB.');
|
||||
return [];
|
||||
}
|
||||
|
||||
const allStreams = [];
|
||||
const seen = new Set();
|
||||
|
||||
// Step 2: Query each server in parallel
|
||||
await Promise.all(Object.entries(SERVERS).map(async ([name, server]) => {
|
||||
if (server.moviesOnly && mediaType === 'tv') return;
|
||||
|
||||
let apiUrl = `${server.url}?title=${encodeURIComponent(details.title)}`
|
||||
+ `&mediaType=${details.type}&year=${details.year}`
|
||||
+ `&tmdbId=${tmdbId}&imdbId=${details.imdbId || ''}`;
|
||||
if (mediaType === 'tv') apiUrl += `&seasonId=${seasonNum}&episodeId=${episodeNum}`;
|
||||
|
||||
try {
|
||||
const encRes = await axios.get(apiUrl, {
|
||||
headers: VIDEASY_HEADERS,
|
||||
timeout: 8000,
|
||||
responseType: 'text'
|
||||
});
|
||||
|
||||
const encryptedText = typeof encRes.data === 'string' ? encRes.data : JSON.stringify(encRes.data);
|
||||
if (!encryptedText || encryptedText.length < 20 || encryptedText.startsWith('<')) return;
|
||||
|
||||
// Step 3: Decrypt via enc-dec.app
|
||||
const decRes = await axios.post(DECRYPT_URL,
|
||||
{ text: encryptedText, id: String(tmdbId) },
|
||||
{ headers: { 'Content-Type': 'application/json' }, timeout: 8000 }
|
||||
);
|
||||
|
||||
const resData = (decRes.data && decRes.data.result) || decRes.data;
|
||||
if (!resData || !Array.isArray(resData.sources)) return;
|
||||
|
||||
for (const s of resData.sources) {
|
||||
if (!s.url || seen.has(s.url)) continue;
|
||||
seen.add(s.url);
|
||||
allStreams.push({
|
||||
name: `Videasy ${name}`,
|
||||
title: `Videasy ${name} - ${s.quality || 'Auto'}`,
|
||||
url: s.url,
|
||||
quality: s.quality || 'Auto',
|
||||
provider: 'Videasy',
|
||||
headers: {
|
||||
'Referer': 'https://player.videasy.net/',
|
||||
'Origin': 'https://player.videasy.net'
|
||||
}
|
||||
});
|
||||
}
|
||||
console.log(`[Videasy] Server ${name}: ${resData.sources.length} source(s)`);
|
||||
} catch {
|
||||
// server unreachable or returned no data — skip silently
|
||||
}
|
||||
}));
|
||||
|
||||
console.log(`[Videasy] Total streams: ${allStreams.length}`);
|
||||
return allStreams;
|
||||
}
|
||||
|
||||
module.exports = { getVideasyStreams };
|
||||
Reference in New Issue
Block a user