const axios = require('axios'); const cheerio = require('cheerio'); const { URLSearchParams, URL } = require('url'); const FormData = require('form-data'); const { CookieJar } = require('tough-cookie'); const fs = require('fs').promises; const path = require('path'); // Dynamic import for axios-cookiejar-support let axiosCookieJarSupport = null; const getAxiosCookieJarSupport = async () => { if (!axiosCookieJarSupport) { axiosCookieJarSupport = await import('axios-cookiejar-support'); } return axiosCookieJarSupport; }; // --- Proxy Configuration --- const UHDMOVIES_PROXY_URL = process.env.UHDMOVIES_PROXY_URL; if (UHDMOVIES_PROXY_URL) { console.log(`[UHDMovies] Proxy support enabled: ${UHDMOVIES_PROXY_URL}`); } else { console.log('[UHDMovies] No proxy configured, using direct connections'); } // --- Domain Fetching --- let uhdMoviesDomain = 'https://uhdmovies.email'; // Fallback domain let domainCacheTimestamp = 0; const DOMAIN_CACHE_TTL = 4 * 60 * 60 * 1000; // 4 hours async function getUHDMoviesDomain() { const now = Date.now(); if (now - domainCacheTimestamp < DOMAIN_CACHE_TTL) { return uhdMoviesDomain; } try { console.log('[UHDMovies] Fetching latest domain...'); const response = await makeRequest('https://raw.githubusercontent.com/phisher98/TVVVV/refs/heads/main/domains.json', { timeout: 10000 }); if (response.data && response.data.UHDMovies) { uhdMoviesDomain = response.data.UHDMovies; domainCacheTimestamp = now; console.log(`[UHDMovies] Updated domain to: ${uhdMoviesDomain}`); } else { console.warn('[UHDMovies] Domain JSON fetched, but "UHDMovies" key was not found. Using fallback.'); } } catch (error) { console.error(`[UHDMovies] Failed to fetch latest domain, using fallback. Error: ${error.message}`); } return uhdMoviesDomain; } // Constants const { getTmdbApiKey } = require('../utils/tmdbKey'); function getUhdMoviesKey(){ const k = getTmdbApiKey(); if(!k) console.warn('[UHDMovies] TMDB API key missing; certain metadata features skipped.'); return k; } // --- Caching Configuration --- const CACHE_ENABLED = process.env.DISABLE_CACHE !== 'true'; // Set to true to disable caching for this provider console.log(`[UHDMovies] Internal cache is ${CACHE_ENABLED ? 'enabled' : 'disabled'}.`); const CACHE_DIR = process.env.VERCEL ? path.join('/tmp', '.uhd_cache') : path.join(__dirname, '.cache', 'uhdmovies'); // Cache directory inside providers/uhdmovies // Caching layer simplified: placeholders only (extend for FS persistence if needed) // --- Caching Helper Functions --- const ensureCacheDir = async () => { if (!CACHE_ENABLED) return; try { await fs.mkdir(CACHE_DIR, { recursive: true }); } catch (error) { if (error.code !== 'EEXIST') { console.error(`[UHDMovies Cache] Error creating cache directory: ${error.message}`); } } }; const getFromCache = async (key) => { if (!CACHE_ENABLED) return null; return null; // no-op }; const saveToCache = async (key, data) => { if (!CACHE_ENABLED) return; // no-op (placeholder for future FS caching) }; // Initialize cache directory on startup ensureCacheDir(); // Configure axios with headers to mimic a browser // Configure axios instance with optional proxy support const createAxiosInstance = () => { const config = { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', 'Cache-Control': 'max-age=0' }, timeout: 30000 }; // Add proxy configuration if UHDMOVIES_PROXY_URL is set if (UHDMOVIES_PROXY_URL) { console.log(`[UHDMovies] Using proxy: ${UHDMOVIES_PROXY_URL}`); // For proxy URLs that expect the destination URL as a parameter config.transformRequest = [(data, headers) => { return data; }]; } return axios.create(config); }; const axiosInstance = createAxiosInstance(); // Proxy wrapper function const makeRequest = async (url, options = {}) => { if (UHDMOVIES_PROXY_URL) { // Route through proxy const proxiedUrl = `${UHDMOVIES_PROXY_URL}${encodeURIComponent(url)}`; console.log(`[UHDMovies] Making proxied request to: ${url}`); return axiosInstance.get(proxiedUrl, options); } else { // Direct request console.log(`[UHDMovies] Making direct request to: ${url}`); return axiosInstance.get(url, options); } }; // Removed unused in-memory cache structure (uhdMoviesCache) // Function to search for movies async function searchMovies(query) { try { const baseUrl = await getUHDMoviesDomain(); console.log(`[UHDMovies] Searching for: ${query}`); const searchUrl = `${baseUrl}/search/${encodeURIComponent(query)}`; const response = await makeRequest(searchUrl); const $ = cheerio.load(response.data); const searchResults = []; // New logic for grid-based search results $('article.gridlove-post').each((index, element) => { const linkElement = $(element).find('a[href*="/download-"]'); if (linkElement.length > 0) { const link = linkElement.first().attr('href'); // Prefer the 'title' attribute, fallback to h1 text const title = linkElement.first().attr('title') || $(element).find('h1.sanket').text().trim(); if (link && title && !searchResults.some(item => item.link === link)) { searchResults.push({ title, link: link.startsWith('http') ? link : `${baseUrl}${link}` }); } } }); // Fallback for original list-based search if new logic fails if (searchResults.length === 0) { console.log('[UHDMovies] Grid search logic found no results, trying original list-based logic...'); $('a[href*="/download-"]').each((index, element) => { const link = $(element).attr('href'); // Avoid duplicates by checking if link already exists in results if (link && !searchResults.some(item => item.link === link)) { const title = $(element).text().trim(); if (title) { searchResults.push({ title, link: link.startsWith('http') ? link : `${baseUrl}${link}` }); } } }); } console.log(`[UHDMovies] Found ${searchResults.length} results`); return searchResults; } catch (error) { console.error(`[UHDMovies] Error searching movies: ${error.message}`); return []; } } // Function to extract clean quality information from verbose text function extractCleanQuality(fullQualityText) { if (!fullQualityText || fullQualityText === 'Unknown Quality') { return 'Unknown Quality'; } const cleanedFullQualityText = fullQualityText.replace(/(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/g, '').trim(); const text = cleanedFullQualityText.toLowerCase(); const quality = []; // Extract resolution if (text.includes('2160p') || text.includes('4k')) { quality.push('4K'); } else if (text.includes('1080p')) { quality.push('1080p'); } else if (text.includes('720p')) { quality.push('720p'); } else if (text.includes('480p')) { quality.push('480p'); } // Extract special features if (text.includes('hdr')) { quality.push('HDR'); } if (text.includes('dolby vision') || text.includes('dovi') || /\bdv\b/.test(text)) { quality.push('DV'); } if (text.includes('imax')) { quality.push('IMAX'); } if (text.includes('bluray') || text.includes('blu-ray')) { quality.push('BluRay'); } // If we found any quality indicators, join them if (quality.length > 0) { return quality.join(' | '); } // Fallback: try to extract a shorter version of the original text // Look for patterns like "Movie Name (Year) Resolution ..." const patterns = [ /(\d{3,4}p.*?(?:x264|x265|hevc).*?)[[(]/i, /(\d{3,4}p.*?)[[(]/i, /((?:720p|1080p|2160p|4k).*?)$/i ]; for (const pattern of patterns) { const match = cleanedFullQualityText.match(pattern); if (match && match[1].trim().length < 100) { return match[1].trim().replace(/x265/ig, 'HEVC'); } } // Final fallback: truncate if too long if (cleanedFullQualityText.length > 80) { return cleanedFullQualityText.substring(0, 77).replace(/x265/ig, 'HEVC') + '...'; } return cleanedFullQualityText.replace(/x265/ig, 'HEVC'); } // Function to extract download links for TV shows from a page async function extractTvShowDownloadLinks(showPageUrl, season, episode) { try { console.log(`[UHDMovies] Extracting TV show links from: ${showPageUrl} for S${season}E${episode}`); const response = await makeRequest(showPageUrl); const $ = cheerio.load(response.data); const showTitle = $('h1').first().text().trim(); const downloadLinks = []; // --- NEW LOGIC TO SCOPE SEARCH TO THE CORRECT SEASON --- let inTargetSeason = false; let qualityText = ''; $('.entry-content').find('*').each((index, element) => { const $el = $(element); const text = $el.text().trim(); const seasonMatch = text.match(/^SEASON\s+(\d+)/i); // Check if we are entering a new season block if (seasonMatch) { const currentSeasonNum = parseInt(seasonMatch[1], 10); if (currentSeasonNum === season) { inTargetSeason = true; console.log(`[UHDMovies] Entering Season ${season} block.`); } else if (inTargetSeason) { // We've hit the next season, so we stop. console.log(`[UHDMovies] Exiting Season ${season} block, now in Season ${currentSeasonNum}.`); inTargetSeason = false; return false; // Exit .each() loop } } if (inTargetSeason) { // This element is within the correct season's block. // Is this a quality header? (e.g., a
 or a 

with ) // It often contains resolution, release group, etc. const isQualityHeader = $el.is('pre, p:has(strong), p:has(b), h3, h4'); if (isQualityHeader) { const headerText = $el.text().trim(); // Filter out irrelevant headers. We can be more aggressive here. if (headerText.length > 5 && !/plot|download|screenshot|trailer|join|powered by|season/i.test(headerText) && !($el.find('a').length > 0)) { qualityText = headerText; // Store the most recent quality header } } // Is this a paragraph with episode links? if ($el.is('p') && $el.find('a[href*="tech.unblockedgames.world"], a[href*="tech.examzculture.in"]').length > 0) { const linksParagraph = $el; const episodeRegex = new RegExp(`^Episode\\s+0*${episode}(?!\\d)`, 'i'); const targetEpisodeLink = linksParagraph.find('a').filter((i, el) => { return episodeRegex.test($(el).text().trim()); }).first(); if (targetEpisodeLink.length > 0) { const link = targetEpisodeLink.attr('href'); if (link && !downloadLinks.some(item => item.link === link)) { const sizeMatch = qualityText.match(/\[\s*([0-9.,]+\s*[KMGT]B)/i); const size = sizeMatch ? sizeMatch[1] : 'Unknown'; const cleanQuality = extractCleanQuality(qualityText); const rawQuality = qualityText.replace(/(\r\n|\n|\r)/gm, " ").replace(/\s+/g, ' ').trim(); console.log(`[UHDMovies] Found match: Quality='${qualityText}', Link='${link}'`); downloadLinks.push({ quality: cleanQuality, size: size, link: link, rawQuality: rawQuality }); } } } // --- ENHANCED: Check for maxbutton-gdrive-episode structure --- if ($el.is('p') && $el.find('a.maxbutton-gdrive-episode').length > 0) { const episodeRegex = new RegExp(`^Episode\\s+0*${episode}(?!\\d)`, 'i'); const targetEpisodeLink = $el.find('a.maxbutton-gdrive-episode').filter((i, el) => { const episodeText = $(el).find('.mb-text').text().trim(); return episodeRegex.test(episodeText); }).first(); if (targetEpisodeLink.length > 0) { const link = targetEpisodeLink.attr('href'); if (link && !downloadLinks.some(item => item.link === link)) { const sizeMatch = qualityText.match(/\[\s*([0-9.,]+\s*[KMGT]B)/i); const size = sizeMatch ? sizeMatch[1] : 'Unknown'; const cleanQuality = extractCleanQuality(qualityText); const rawQuality = qualityText.replace(/(\r\n|\n|\r)/gm, " ").replace(/\s+/g, ' ').trim(); console.log(`[UHDMovies] Found match (maxbutton): Quality='${qualityText}', Link='${link}'`); downloadLinks.push({ quality: cleanQuality, size: size, link: link, rawQuality: rawQuality }); } } } } }); if (downloadLinks.length === 0) { console.log('[UHDMovies] Main extraction logic failed. Checking if requested season exists on page before fallback.'); // Check if the requested season exists on the page at all let seasonExists = false; const actualSeasonsOnPage = new Set(); // Track what seasons actually have content // First pass: Look for actual episode content to see what seasons are available $('.entry-content').find('a[href*="tech.unblockedgames.world"], a[href*="tech.examzculture.in"], a.maxbutton-gdrive-episode').each((index, element) => { const $el = $(element); const linkText = $el.text().trim(); const episodeText = $el.find('.mb-text').text().trim() || linkText; // Look for season indicators in episode links const seasonMatches = [ episodeText.match(/S(\d{1,2})/i), // S01, S02, etc. episodeText.match(/Season\s+(\d+)/i), // Season 1, Season 2, etc. episodeText.match(/S(\d{1,2})E(\d{1,3})/i) // S01E01 format ]; for (const match of seasonMatches) { if (match && match[1]) { const foundSeason = parseInt(match[1], 10); actualSeasonsOnPage.add(foundSeason); } } }); console.log(`[UHDMovies] Actual seasons found on page: ${Array.from(actualSeasonsOnPage).sort((a,b) => a-b).join(', ')}`); // Check if requested season is in the actual content if (actualSeasonsOnPage.has(season)) { seasonExists = true; console.log(`[UHDMovies] Season ${season} confirmed to exist in actual episode content`); } else { // Fallback: Check page descriptions/titles for season mentions $('.entry-content').find('*').each((index, element) => { const $el = $(element); const text = $el.text().trim(); // Match various season formats: "SEASON 2", "Season 2", "(Season 1 – 2)", "Season 1-2", etc. const seasonMatches = [ text.match(/^SEASON\s+(\d+)/i), text.match(/\bSeason\s+(\d+)/i), text.match(/\(Season\s+\d+\s*[–-]\s*(\d+)\)/i), // Matches "(Season 1 – 2)" text.match(/Season\s+\d+\s*[–-]\s*(\d+)/i), // Matches "Season 1-2" text.match(/\bS(\d+)/i) // Matches "S2", "S02", etc. ]; for (const match of seasonMatches) { if (match) { const currentSeasonNum = parseInt(match[1], 10); if (currentSeasonNum === season) { seasonExists = true; console.log(`[UHDMovies] Season ${season} found in page description: "${text.substring(0, 100)}..."`); return false; // Exit .each() loop } // For range formats like "Season 1 – 2", check if requested season is in range if (match[0].includes('–') || match[0].includes('-')) { const rangeMatch = match[0].match(/Season\s+(\d+)\s*[–-]\s*(\d+)/i); if (rangeMatch) { const startSeason = parseInt(rangeMatch[1], 10); const endSeason = parseInt(rangeMatch[2], 10); if (season >= startSeason && season <= endSeason) { seasonExists = true; console.log(`[UHDMovies] Season ${season} found in range ${startSeason}-${endSeason} in page description`); return false; // Exit .each() loop } } } } } }); } if (!seasonExists) { console.log(`[UHDMovies] Season ${season} not found on page. Available seasons may not include the requested season.`); // Don't use fallback if the season doesn't exist to avoid wrong episodes return { title: showTitle, links: [], seasonNotFound: true }; } console.log(`[UHDMovies] Season ${season} exists on page but episode extraction failed. Trying fallback method with season filtering.`); // --- ENHANCED FALLBACK LOGIC FOR NEW HTML STRUCTURE --- // Try the new maxbutton-gdrive-episode structure first $('.entry-content').find('a.maxbutton-gdrive-episode').each((i, el) => { const linkElement = $(el); const episodeText = linkElement.find('.mb-text').text().trim(); const episodeRegex = new RegExp(`^Episode\\s+0*${episode}(?!\\d)`, 'i'); if (episodeRegex.test(episodeText)) { const link = linkElement.attr('href'); if (link && !downloadLinks.some(item => item.link === link)) { let qualityText = 'Unknown Quality'; // Look for quality info in the preceding paragraph or heading const parentP = linkElement.closest('p, div'); const prevElement = parentP.prev(); if (prevElement.length > 0) { const prevText = prevElement.text().trim(); if (prevText && prevText.length > 5 && !prevText.toLowerCase().includes('download')) { qualityText = prevText; } } // Check if this episode belongs to the correct season // Enhanced season check - look for various season formats const seasonCheckRegexes = [ new RegExp(`\\.S0*${season}[\\.]`, 'i'), // .S01. new RegExp(`S0*${season}[\\.]`, 'i'), // S01. new RegExp(`S0*${season}\\b`, 'i'), // S01 (word boundary) new RegExp(`Season\\s+0*${season}\\b`, 'i'), // Season 1 new RegExp(`S0*${season}`, 'i') // S01 anywhere ]; const seasonMatch = seasonCheckRegexes.some(regex => regex.test(qualityText)); if (!seasonMatch) { console.log(`[UHDMovies] Skipping episode from different season: Quality='${qualityText}'`); return; // Skip this episode as it's from a different season } const sizeMatch = qualityText.match(/\[([0-9.,]+[KMGT]B[^\]]*)\]/i); const size = sizeMatch ? sizeMatch[1] : 'Unknown'; const cleanQuality = extractCleanQuality(qualityText); const rawQuality = qualityText.replace(/(\r\n|\n|\r)/gm, " ").replace(/\s+/g, ' ').trim(); console.log(`[UHDMovies] Found match via enhanced fallback (maxbutton): Quality='${qualityText}', Link='${link}'`); downloadLinks.push({ quality: cleanQuality, size: size, link: link, rawQuality: rawQuality }); } } }); // If still no results, try the original fallback logic if (downloadLinks.length === 0) { console.log(`[UHDMovies] Enhanced fallback failed, trying original fallback logic.`); $('.entry-content').find('a[href*="tech.unblockedgames.world"], a[href*="tech.examzculture.in"]').each((i, el) => { const linkElement = $(el); const episodeRegex = new RegExp(`^Episode\\s+0*${episode}(?!\\d)`, 'i'); if (episodeRegex.test(linkElement.text().trim())) { const link = linkElement.attr('href'); if (link && !downloadLinks.some(item => item.link === link)) { let qualityText = 'Unknown Quality'; const parentP = linkElement.closest('p, div'); const prevElement = parentP.prev(); if (prevElement.length > 0) { const prevText = prevElement.text().trim(); if (prevText && prevText.length > 5 && !prevText.toLowerCase().includes('download')) { qualityText = prevText; } } // Check if this episode belongs to the correct season // Enhanced season check - look for various season formats const seasonCheckRegexes = [ new RegExp(`\\.S0*${season}[\\.]`, 'i'), // .S01. new RegExp(`S0*${season}[\\.]`, 'i'), // S01. new RegExp(`S0*${season}\\b`, 'i'), // S01 (word boundary) new RegExp(`Season\\s+0*${season}\\b`, 'i'), // Season 1 new RegExp(`S0*${season}`, 'i') // S01 anywhere ]; const seasonMatch = seasonCheckRegexes.some(regex => regex.test(qualityText)); if (!seasonMatch) { console.log(`[UHDMovies] Skipping episode from different season: Quality='${qualityText}'`); return; // Skip this episode as it's from a different season } const sizeMatch = qualityText.match(/\[([0-9.,]+[KMGT]B[^\]]*)\]/i); const size = sizeMatch ? sizeMatch[1] : 'Unknown'; const cleanQuality = extractCleanQuality(qualityText); const rawQuality = qualityText.replace(/(\r\n|\n|\r)/gm, " ").replace(/\s+/g, ' ').trim(); console.log(`[UHDMovies] Found match via original fallback: Quality='${qualityText}', Link='${link}'`); downloadLinks.push({ quality: cleanQuality, size: size, link: link, rawQuality: rawQuality }); } } }); } } if (downloadLinks.length > 0) { console.log(`[UHDMovies] Found ${downloadLinks.length} links for S${season}E${episode}.`); } else { console.log(`[UHDMovies] Could not find links for S${season}E${episode}. It's possible the logic needs adjustment or the links aren't on the page.`); } return { title: showTitle, links: downloadLinks }; } catch (error) { console.error(`[UHDMovies] Error extracting TV show download links: ${error.message}`); return { title: 'Unknown', links: [] }; } } // Function to extract download links from a movie page async function extractDownloadLinks(moviePageUrl, targetYear = null) { try { console.log(`[UHDMovies] Extracting links from: ${moviePageUrl}`); const response = await makeRequest(moviePageUrl); const $ = cheerio.load(response.data); const movieTitle = $('h1').first().text().trim(); const downloadLinks = []; // Find all download links (the new SID links) and their associated quality information $('a[href*="tech.unblockedgames.world"], a[href*="tech.examzculture.in"]').each((index, element) => { const link = $(element).attr('href'); if (link && !downloadLinks.some(item => item.link === link)) { let quality = 'Unknown Quality'; let size = 'Unknown'; // Method 1: Look for quality in the closest preceding paragraph or heading const prevElement = $(element).closest('p').prev(); if (prevElement.length > 0) { const prevText = prevElement.text().trim(); if (prevText && prevText.length > 20 && !prevText.includes('Download')) { quality = prevText; } } // Method 2: Look for quality in parent's siblings if (quality === 'Unknown Quality') { const parentSiblings = $(element).parent().prevAll().first().text().trim(); if (parentSiblings && parentSiblings.length > 20) { quality = parentSiblings; } } // Method 3: Look for bold/strong text above the link if (quality === 'Unknown Quality') { const strongText = $(element).closest('p').prevAll().find('strong, b').last().text().trim(); if (strongText && strongText.length > 20) { quality = strongText; } } // Method 4: Look for the entire paragraph containing quality info if (quality === 'Unknown Quality') { let currentElement = $(element).parent(); for (let i = 0; i < 5; i++) { currentElement = currentElement.prev(); if (currentElement.length === 0) break; const text = currentElement.text().trim(); if (text && text.length > 30 && (text.includes('1080p') || text.includes('720p') || text.includes('2160p') || text.includes('4K') || text.includes('HEVC') || text.includes('x264') || text.includes('x265'))) { quality = text; break; } } } // Year-based filtering for collections if (targetYear && quality !== 'Unknown Quality') { // Check for years in quality text const yearMatches = quality.match(/\((\d{4})\)/g); let hasMatchingYear = false; if (yearMatches && yearMatches.length > 0) { for (const yearMatch of yearMatches) { const year = parseInt(yearMatch.replace(/[()]/g, '')); if (year === targetYear) { hasMatchingYear = true; break; } } if (!hasMatchingYear) { console.log(`[UHDMovies] Skipping link due to year mismatch. Target: ${targetYear}, Found: ${yearMatches.join(', ')} in "${quality}"`); return; // Skip this link } } else { // If no year in quality text, check filename and other indicators const linkText = $(element).text().trim(); const parentText = $(element).parent().text().trim(); const combinedText = `${quality} ${linkText} ${parentText}`; // Look for years in combined text const allYearMatches = combinedText.match(/\((\d{4})\)/g) || combinedText.match(/(\d{4})/g); if (allYearMatches) { let foundTargetYear = false; for (const yearMatch of allYearMatches) { const year = parseInt(yearMatch.replace(/[()]/g, '')); if (year >= 1900 && year <= 2030) { // Valid movie year range if (year === targetYear) { foundTargetYear = true; break; } } } if (!foundTargetYear && allYearMatches.length > 0) { console.log(`[UHDMovies] Skipping link due to no matching year found. Target: ${targetYear}, Found years: ${allYearMatches.join(', ')} in combined text`); return; // Skip this link } } // Additional check: if quality contains movie names that don't match target year const lowerQuality = quality.toLowerCase(); if (targetYear === 2015) { if (lowerQuality.includes('wasp') || lowerQuality.includes('quantumania')) { console.log(`[UHDMovies] Skipping link for 2015 target as it contains 'wasp' or 'quantumania': "${quality}"`); return; // Skip this link } } } } // Extract size from quality text if present const sizeMatch = quality.match(/\[([0-9.,]+\s*[KMGT]B[^\]]*)\]/); if (sizeMatch) { size = sizeMatch[1]; } // Clean up the quality information const cleanQuality = extractCleanQuality(quality); downloadLinks.push({ quality: cleanQuality, size: size, link: link, rawQuality: quality.replace(/(\r\n|\n|\r)/gm, " ").replace(/\s+/g, ' ').trim() }); } }); return { title: movieTitle, links: downloadLinks }; } catch (error) { console.error(`[UHDMovies] Error extracting download links: ${error.message}`); return { title: 'Unknown', links: [] }; } } function extractCodecs(rawQuality) { const codecs = []; const text = rawQuality.toLowerCase(); if (text.includes('hevc') || text.includes('x265')) { codecs.push('H.265'); } else if (text.includes('x264')) { codecs.push('H.264'); } if (text.includes('10bit') || text.includes('10-bit')) { codecs.push('10-bit'); } if (text.includes('atmos')) { codecs.push('Atmos'); } else if (text.includes('dts-hd')) { codecs.push('DTS-HD'); } else if (text.includes('dts')) { codecs.push('DTS'); } else if (text.includes('ddp5.1') || text.includes('dd+ 5.1') || text.includes('eac3')) { codecs.push('EAC3'); } else if (text.includes('ac3')) { codecs.push('AC3'); } if (text.includes('dovi') || text.includes('dolby vision') || /\bdv\b/.test(text)) { codecs.push('DV'); } else if (text.includes('hdr')) { codecs.push('HDR'); } return codecs; } // Function to try Instant Download method async function tryInstantDownload($) { const instantDownloadLink = $('a:contains("Instant Download")').attr('href'); if (!instantDownloadLink) { return null; } console.log('[UHDMovies] Found "Instant Download" link, attempting to extract final URL...'); try { const urlParams = new URLSearchParams(new URL(instantDownloadLink).search); const keys = urlParams.get('url'); if (keys) { const apiUrl = `${new URL(instantDownloadLink).origin}/api`; const formData = new FormData(); formData.append('keys', keys); let apiResponse; if (UHDMOVIES_PROXY_URL) { const proxiedApiUrl = `${UHDMOVIES_PROXY_URL}${encodeURIComponent(apiUrl)}`; console.log(`[UHDMovies] Making proxied POST request for Instant Download API to: ${apiUrl}`); apiResponse = await axiosInstance.post(proxiedApiUrl, formData, { headers: { ...formData.getHeaders(), 'x-token': new URL(instantDownloadLink).hostname } }); } else { apiResponse = await axiosInstance.post(apiUrl, formData, { headers: { ...formData.getHeaders(), 'x-token': new URL(instantDownloadLink).hostname } }); } if (apiResponse.data && apiResponse.data.url) { let finalUrl = apiResponse.data.url; // Fix spaces in workers.dev URLs by encoding them properly if (finalUrl.includes('workers.dev')) { const urlParts = finalUrl.split('/'); const filename = urlParts[urlParts.length - 1]; const encodedFilename = filename.replace(/ /g, '%20'); urlParts[urlParts.length - 1] = encodedFilename; finalUrl = urlParts.join('/'); } console.log('[UHDMovies] Extracted final link from API:', finalUrl); return finalUrl; } } console.log('[UHDMovies] Could not find a valid final download link from Instant Download.'); return null; } catch (error) { console.log(`[UHDMovies] Error processing "Instant Download": ${error.message}`); return null; } } // Function to try Resume Cloud method async function tryResumeCloud($) { // Look for both "Resume Cloud" and "Cloud Resume Download" buttons const resumeCloudButton = $('a:contains("Resume Cloud"), a:contains("Cloud Resume Download")'); if (resumeCloudButton.length === 0) { return null; } const resumeLink = resumeCloudButton.attr('href'); if (!resumeLink) { return null; } // Check if it's already a direct download link (workers.dev) if (resumeLink.includes('workers.dev') || resumeLink.startsWith('http')) { let directLink = resumeLink; // Fix spaces in workers.dev URLs by encoding them properly if (directLink.includes('workers.dev')) { const urlParts = directLink.split('/'); const filename = urlParts[urlParts.length - 1]; const encodedFilename = filename.replace(/ /g, '%20'); urlParts[urlParts.length - 1] = encodedFilename; directLink = urlParts.join('/'); } console.log(`[UHDMovies] Found direct "Cloud Resume Download" link: ${directLink}`); return directLink; } // Otherwise, follow the link to get the final download try { const resumeUrl = new URL(resumeLink, 'https://driveleech.net').href; console.log(`[UHDMovies] Found 'Resume Cloud' page link. Following to: ${resumeUrl}`); // "Click" the link by making another request const finalPageResponse = await makeRequest(resumeUrl, { maxRedirects: 10 }); const $$ = cheerio.load(finalPageResponse.data); // Look for direct download links let finalDownloadLink = $$('a.btn-success[href*="workers.dev"], a[href*="driveleech.net/d/"]').attr('href'); if (finalDownloadLink) { // Fix spaces in workers.dev URLs by encoding them properly if (finalDownloadLink.includes('workers.dev')) { // Split the URL at the last slash to separate the base URL from the filename const urlParts = finalDownloadLink.split('/'); const filename = urlParts[urlParts.length - 1]; // Encode spaces in the filename part only const encodedFilename = filename.replace(/ /g, '%20'); urlParts[urlParts.length - 1] = encodedFilename; finalDownloadLink = urlParts.join('/'); } console.log(`[UHDMovies] Extracted final Resume Cloud link: ${finalDownloadLink}`); return finalDownloadLink; } else { console.log('[UHDMovies] Could not find the final download link on the "Resume Cloud" page.'); return null; } } catch (error) { console.log(`[UHDMovies] Error processing "Resume Cloud": ${error.message}`); return null; } } // Environment variable to control URL validation const URL_VALIDATION_ENABLED = process.env.DISABLE_URL_VALIDATION !== 'true'; console.log(`[UHDMovies] URL validation is ${URL_VALIDATION_ENABLED ? 'enabled' : 'disabled'}.`); // Validate if a video URL is working (not 404 or broken) async function validateVideoUrl(url, timeout = 10000) { // Skip validation if disabled via environment variable if (!URL_VALIDATION_ENABLED) { console.log(`[UHDMovies] URL validation disabled, skipping validation for: ${url.substring(0, 100)}...`); return true; } try { console.log(`[UHDMovies] Validating URL: ${url.substring(0, 100)}...`); // Use proxy for URL validation if enabled let response; if (UHDMOVIES_PROXY_URL) { const proxiedUrl = `${UHDMOVIES_PROXY_URL}${encodeURIComponent(url)}`; console.log(`[UHDMovies] Making proxied HEAD request for validation to: ${url}`); response = await axiosInstance.head(proxiedUrl, { timeout, headers: { 'Range': 'bytes=0-1' // Just request first byte to test } }); } else { response = await axiosInstance.head(url, { timeout, headers: { 'Range': 'bytes=0-1' // Just request first byte to test } }); } // Check if status is OK (200-299) or partial content (206) if (response.status >= 200 && response.status < 400) { console.log(`[UHDMovies] ✓ URL validation successful (${response.status})`); return true; } else { console.log(`[UHDMovies] ✗ URL validation failed with status: ${response.status}`); return false; } } catch (error) { console.log(`[UHDMovies] ✗ URL validation failed: ${error.message}`); return false; } } // Compare media to find matching result function compareMedia(mediaInfo, searchResult) { const normalizeString = (str) => String(str || '').toLowerCase().replace(/[^a-zA-Z0-9]/g, ''); const titleWithAnd = mediaInfo.title.replace(/\s*&\s*/g, ' and '); const normalizedMediaTitle = normalizeString(titleWithAnd); const normalizedResultTitle = normalizeString(searchResult.title); console.log(`[UHDMovies] Comparing: "${mediaInfo.title}" (${mediaInfo.year}) vs "${searchResult.title}"`); console.log(`[UHDMovies] Normalized: "${normalizedMediaTitle}" vs "${normalizedResultTitle}"`); // Check if titles match or result title contains media title let titleMatches = normalizedResultTitle.includes(normalizedMediaTitle); // If direct match fails, try checking for franchise/collection matches if (!titleMatches) { const mainTitle = normalizedMediaTitle.split('and')[0]; const isCollection = normalizedResultTitle.includes('duology') || normalizedResultTitle.includes('trilogy') || normalizedResultTitle.includes('quadrilogy') || normalizedResultTitle.includes('collection') || normalizedResultTitle.includes('saga'); if (isCollection && normalizedResultTitle.includes(mainTitle)) { console.log(`[UHDMovies] Found collection match: "${mainTitle}" in collection "${searchResult.title}"`); titleMatches = true; } } if (!titleMatches) { console.log(`[UHDMovies] Title mismatch: "${normalizedResultTitle}" does not contain "${normalizedMediaTitle}"`); return false; } // NEW: Negative keyword check for spinoffs const negativeKeywords = ['challenge', 'conversation', 'story', 'in conversation']; const originalTitleLower = mediaInfo.title.toLowerCase(); for (const keyword of negativeKeywords) { if (normalizedResultTitle.includes(keyword.replace(/\s/g, '')) && !originalTitleLower.includes(keyword)) { console.log(`[UHDMovies] Rejecting spinoff due to keyword: "${keyword}"`); return false; // It's a spinoff, reject it. } } // Check year if both are available if (mediaInfo.year && searchResult.title) { const yearRegex = /\b(19[89]\d|20\d{2})\b/g; // Look for years 1980-2099 const yearMatchesInResult = searchResult.title.match(yearRegex); const yearRangeMatch = searchResult.title.match(/\((\d{4})\s*-\s*(\d{4})\)/); let hasMatchingYear = false; if (yearMatchesInResult) { console.log(`[UHDMovies] Found years in result: ${yearMatchesInResult.join(', ')}`); if (yearMatchesInResult.some(yearStr => Math.abs(parseInt(yearStr) - mediaInfo.year) <= 1)) { hasMatchingYear = true; } } if (!hasMatchingYear && yearRangeMatch) { console.log(`[UHDMovies] Found year range in result: ${yearRangeMatch[0]}`); const startYear = parseInt(yearRangeMatch[1]); const endYear = parseInt(yearRangeMatch[2]); if (mediaInfo.year >= startYear - 1 && mediaInfo.year <= endYear + 1) { hasMatchingYear = true; } } // If there are any years found in the title, one of them MUST match. if ((yearMatchesInResult || yearRangeMatch) && !hasMatchingYear) { console.log(`[UHDMovies] Year mismatch. Target: ${mediaInfo.year}, but no matching year found in result.`); return false; } } console.log(`[UHDMovies] Match successful!`); return true; } // Function to score search results based on quality keywords and season coverage function scoreResult(title, requestedSeason = null) { let score = 0; const lowerTitle = title.toLowerCase(); // Quality scoring if (lowerTitle.includes('remux')) score += 10; if (lowerTitle.includes('bluray') || lowerTitle.includes('blu-ray')) score += 8; if (lowerTitle.includes('imax')) score += 6; if (lowerTitle.includes('4k') || lowerTitle.includes('2160p')) score += 5; if (lowerTitle.includes('dovi') || lowerTitle.includes('dolby vision') || /\\bdv\\b/.test(lowerTitle)) score += 4; if (lowerTitle.includes('hdr')) score += 3; if (lowerTitle.includes('1080p')) score += 2; if (lowerTitle.includes('hevc') || lowerTitle.includes('x265')) score += 1; // Season coverage scoring (for TV shows) if (requestedSeason !== null) { // Check for season range formats like "Season 1 – 2" or "Season 1-2" const seasonRangeMatch = lowerTitle.match(/season\s+(\d+)\s*[–-]\s*(\d+)/i); if (seasonRangeMatch) { const startSeason = parseInt(seasonRangeMatch[1], 10); const endSeason = parseInt(seasonRangeMatch[2], 10); if (requestedSeason >= startSeason && requestedSeason <= endSeason) { score += 50; // High bonus for season range that includes requested season console.log(`[UHDMovies] Season range bonus (+50): ${startSeason}-${endSeason} includes requested season ${requestedSeason}`); } } // Check for specific season mentions const specificSeasonMatch = lowerTitle.match(/season\s+(\d+)/i); if (specificSeasonMatch) { const mentionedSeason = parseInt(specificSeasonMatch[1], 10); if (mentionedSeason === requestedSeason) { score += 30; // Good bonus for exact season match console.log(`[UHDMovies] Exact season bonus (+30): Season ${mentionedSeason} matches requested season ${requestedSeason}`); } else if (mentionedSeason < requestedSeason) { score -= 20; // Penalty for older season when requesting newer season console.log(`[UHDMovies] Season penalty (-20): Season ${mentionedSeason} is older than requested season ${requestedSeason}`); } } // Check for "Season X Added" or similar indicators if (lowerTitle.includes('season') && lowerTitle.includes('added')) { const addedSeasonMatch = lowerTitle.match(/season\s+(\d+)\s+added/i); if (addedSeasonMatch) { const addedSeason = parseInt(addedSeasonMatch[1], 10); if (addedSeason === requestedSeason) { score += 40; // High bonus for newly added season console.log(`[UHDMovies] Added season bonus (+40): Season ${addedSeason} was recently added`); } } } } return score; } // Function to parse size string into MB function parseSize(sizeString) { if (!sizeString || typeof sizeString !== 'string') { return 0; } const upperCaseSizeString = sizeString.toUpperCase(); // Regex to find a number (integer or float) followed by GB, MB, or KB const match = upperCaseSizeString.match(/([0-9.,]+)\s*(GB|MB|KB)/); if (!match) { return 0; } const sizeValue = parseFloat(match[1].replace(/,/g, '')); if (isNaN(sizeValue)) { return 0; } const unit = match[2]; if (unit === 'GB') { return sizeValue * 1024; } else if (unit === 'MB') { return sizeValue; } else if (unit === 'KB') { return sizeValue / 1024; } return 0; } // Helper function to extract cookies from jar for a specific URL const getCookiesForUrl = async (jar, url) => { try { const cookies = await jar.getCookies(url); if (cookies && cookies.length > 0) { return cookies.map(cookie => cookie.toString()).join('; '); } } catch (error) { console.log(`[UHDMovies] Error extracting cookies for ${url}: ${error.message}`); } return null; }; // Helper function to create a proxied session for SID resolution const createProxiedSession = async (jar) => { const { wrapper } = await getAxiosCookieJarSupport(); const sessionConfig = { jar, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', 'Accept-Language': 'en-US,en;q=0.5', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1' } }; const session = wrapper(axios.create(sessionConfig)); // If proxy is enabled, wrap the session methods to use proxy if (UHDMOVIES_PROXY_URL) { console.log(`[UHDMovies] Creating SID session with proxy: ${UHDMOVIES_PROXY_URL}`); const originalGet = session.get.bind(session); const originalPost = session.post.bind(session); session.get = async (url, options = {}) => { const proxiedUrl = `${UHDMOVIES_PROXY_URL}${encodeURIComponent(url)}`; console.log(`[UHDMovies] Making proxied SID GET request to: ${url}`); // Extract cookies from jar and add to headers const cookieString = await getCookiesForUrl(jar, url); if (cookieString) { console.log(`[UHDMovies] Adding cookies to proxied request: ${cookieString}`); options.headers = { ...options.headers, 'Cookie': cookieString }; } return originalGet(proxiedUrl, options); }; session.post = async (url, data, options = {}) => { const proxiedUrl = `${UHDMOVIES_PROXY_URL}${encodeURIComponent(url)}`; console.log(`[UHDMovies] Making proxied SID POST request to: ${url}`); // Extract cookies from jar and add to headers const cookieString = await getCookiesForUrl(jar, url); if (cookieString) { console.log(`[UHDMovies] Adding cookies to proxied request: ${cookieString}`); options.headers = { ...options.headers, 'Cookie': cookieString }; } return originalPost(proxiedUrl, data, options); }; } return session; }; // New function to resolve the tech.unblockedgames.world links async function resolveSidToDriveleech(sidUrl) { console.log(`[UHDMovies] Resolving SID link: ${sidUrl}`); const { origin } = new URL(sidUrl); const jar = new CookieJar(); // Create session with proxy support const session = await createProxiedSession(jar); try { // Step 0: Get the _wp_http value console.log(" [SID] Step 0: Fetching initial page..."); const responseStep0 = await session.get(sidUrl); let $ = cheerio.load(responseStep0.data); const initialForm = $('#landing'); const wp_http_step1 = initialForm.find('input[name="_wp_http"]').val(); const action_url_step1 = initialForm.attr('action'); if (!wp_http_step1 || !action_url_step1) { console.error(" [SID] Error: Could not find _wp_http in initial form."); return null; } // Step 1: POST to the first form's action URL console.log(" [SID] Step 1: Submitting initial form..."); const step1Data = new URLSearchParams({ '_wp_http': wp_http_step1 }); const responseStep1 = await session.post(action_url_step1, step1Data, { headers: { 'Referer': sidUrl, 'Content-Type': 'application/x-www-form-urlencoded' } }); // Step 2: Parse verification page for second form console.log(" [SID] Step 2: Parsing verification page..."); $ = cheerio.load(responseStep1.data); const verificationForm = $('#landing'); const action_url_step2 = verificationForm.attr('action'); const wp_http2 = verificationForm.find('input[name="_wp_http2"]').val(); const token = verificationForm.find('input[name="token"]').val(); if (!action_url_step2) { console.error(" [SID] Error: Could not find verification form."); return null; } // Step 3: POST to the verification URL console.log(" [SID] Step 3: Submitting verification..."); const step2Data = new URLSearchParams({ '_wp_http2': wp_http2, 'token': token }); const responseStep2 = await session.post(action_url_step2, step2Data, { headers: { 'Referer': responseStep1.request.res.responseUrl, 'Content-Type': 'application/x-www-form-urlencoded' } }); // Step 4: Find dynamic cookie and link from JavaScript console.log(" [SID] Step 4: Parsing final page for JS data..."); let finalLinkPath = null; let cookieName = null; let cookieValue = null; const scriptContent = responseStep2.data; const cookieMatch = scriptContent.match(/s_343\('([^']+)',\s*'([^']+)'/); const linkMatch = scriptContent.match(/c\.setAttribute\("href",\s*"([^"]+)"\)/); if (cookieMatch) { cookieName = cookieMatch[1].trim(); cookieValue = cookieMatch[2].trim(); } if (linkMatch) { finalLinkPath = linkMatch[1].trim(); } if (!finalLinkPath || !cookieName || !cookieValue) { console.error(" [SID] Error: Could not extract dynamic cookie/link from JS."); return null; } const finalUrl = new URL(finalLinkPath, origin).href; console.log(` [SID] Dynamic link found: ${finalUrl}`); console.log(` [SID] Dynamic cookie found: ${cookieName}`); // Step 5: Set cookie and make final request console.log(" [SID] Step 5: Setting cookie and making final request..."); await jar.setCookie(`${cookieName}=${cookieValue}`, origin); const finalResponse = await session.get(finalUrl, { headers: { 'Referer': responseStep2.request.res.responseUrl } }); // Step 6: Extract driveleech URL from meta refresh tag $ = cheerio.load(finalResponse.data); const metaRefresh = $('meta[http-equiv="refresh"]'); if (metaRefresh.length > 0) { const content = metaRefresh.attr('content'); const urlMatch = content.match(/url=(.*)/i); if (urlMatch && urlMatch[1]) { const driveleechUrl = urlMatch[1].replace(/"/g, "").replace(/'/g, ""); console.log(` [SID] SUCCESS! Resolved Driveleech URL: ${driveleechUrl}`); return driveleechUrl; } } console.error(" [SID] Error: Could not find meta refresh tag with Driveleech URL."); return null; } catch (error) { console.error(` [SID] Error during SID resolution: ${error.message}`); if (error.response) { console.error(` [SID] Status: ${error.response.status}`); } return null; } } // Main function to get streams for TMDB content async function getUHDMoviesStreams(tmdbId, mediaType = 'movie', season = null, episode = null) { console.log(`[UHDMovies] Attempting to fetch streams for TMDB ID: ${tmdbId}, Type: ${mediaType}${mediaType === 'tv' ? `, S:${season}E:${episode}` : ''}`); const cacheKey = `uhd_final_v18_${tmdbId}_${mediaType}${season ? `_s${season}e${episode}` : ''}`; try { // 1. Check cache first let cachedLinks = await getFromCache(cacheKey); if (cachedLinks && cachedLinks.length > 0) { console.log(`[UHDMovies] Cache HIT for ${cacheKey}. Using ${cachedLinks.length} cached Driveleech links.`); } else { if (cachedLinks && cachedLinks.length === 0) { console.log(`[UHDMovies] Cache contains empty data for ${cacheKey}. Refetching from source.`); } else { console.log(`[UHDMovies] Cache MISS for ${cacheKey}. Fetching from source.`); } console.log(`[UHDMovies] Cache MISS for ${cacheKey}. Fetching from source.`); // 2. If cache miss, get TMDB info to perform search const TMDB_API_KEY_UHDMOVIES = getUhdMoviesKey(); const tmdbUrl = `https://api.themoviedb.org/3/${mediaType === 'tv' ? 'tv' : 'movie'}/${tmdbId}?api_key=${TMDB_API_KEY_UHDMOVIES}`; const tmdbResponse = await axios.get(tmdbUrl); const tmdbData = tmdbResponse.data; const mediaInfo = { title: mediaType === 'tv' ? tmdbData.name : tmdbData.title, year: parseInt(((mediaType === 'tv' ? tmdbData.first_air_date : tmdbData.release_date) || '').split('-')[0], 10) }; if (!mediaInfo.title) throw new Error('Could not extract title from TMDB response.'); console.log(`[UHDMovies] TMDB Info: "${mediaInfo.title}" (${mediaInfo.year || 'N/A'})`); // 3. Search for the media on UHDMovies const searchTitle = mediaInfo.title.replace(/:/g, '').replace(/\s*&\s*/g, ' and '); let searchResults = await searchMovies(searchTitle); // If no results or only wrong year results, try fallback search with just main title if (searchResults.length === 0 || !searchResults.some(result => compareMedia(mediaInfo, result))) { console.log(`[UHDMovies] Primary search failed or no matches. Trying fallback search...`); // Extract main title (remove subtitles after colon, "and the", etc.) let fallbackTitle = mediaInfo.title.split(':')[0].trim(); if (fallbackTitle.includes('and the')) { fallbackTitle = fallbackTitle.split('and the')[0].trim(); } if (fallbackTitle !== searchTitle) { console.log(`[UHDMovies] Fallback search with: "${fallbackTitle}"`); const fallbackResults = await searchMovies(fallbackTitle); if (fallbackResults.length > 0) { searchResults = fallbackResults; } } } if (searchResults.length === 0) { console.log(`[UHDMovies] No search results found for "${mediaInfo.title}".`); // Don't cache empty results to allow retrying later return []; } // 4. Find the best matching result const matchingResults = searchResults.filter(result => compareMedia(mediaInfo, result)); if (matchingResults.length === 0) { console.log(`[UHDMovies] No matching content found for "${mediaInfo.title}" (${mediaInfo.year}).`); // Don't cache empty results to allow retrying later return []; } let matchingResult; let scoredResults = null; // Declare outside the conditional if (matchingResults.length === 1) { matchingResult = matchingResults[0]; } else { console.log(`[UHDMovies] Found ${matchingResults.length} matching results. Scoring to find the best...`); scoredResults = matchingResults.map(result => { const score = scoreResult(result.title, mediaType === 'tv' ? season : null); console.log(` - Score ${score}: ${result.title}`); return { ...result, score }; }).sort((a, b) => b.score - a.score); matchingResult = scoredResults[0]; console.log(`[UHDMovies] Best match selected with score ${matchingResult.score}: "${matchingResult.title}"`); } console.log(`[UHDMovies] Found matching content: "${matchingResult.title}"`); // 5. Extract SID links from the movie/show page let downloadInfo = await (mediaType === 'tv' ? extractTvShowDownloadLinks(matchingResult.link, season, episode) : extractDownloadLinks(matchingResult.link, mediaInfo.year)); // Check if season was not found or episode extraction failed, and we have multiple results to try if (downloadInfo.links.length === 0 && matchingResults.length > 1 && scoredResults && (downloadInfo.seasonNotFound || (mediaType === 'tv' && downloadInfo.title))) { console.log(`[UHDMovies] Season ${season} not found or episode extraction failed on best match. Trying next best match...`); // Try the next best match const nextBestMatch = scoredResults[1]; console.log(`[UHDMovies] Trying next best match: "${nextBestMatch.title}"`); downloadInfo = await (mediaType === 'tv' ? extractTvShowDownloadLinks(nextBestMatch.link, season, episode) : extractDownloadLinks(nextBestMatch.link, mediaInfo.year)); if (downloadInfo.links.length > 0) { console.log(`[UHDMovies] Successfully found links on next best match!`); } else { console.log(`[UHDMovies] Next best match also failed. No download links found.`); } } if (downloadInfo.links.length === 0) { console.log('[UHDMovies] No download links found on page.'); // Don't cache empty results to allow retrying later return []; } // 6. Resolve all SID links to driveleech redirect URLs (intermediate step) console.log(`[UHDMovies] Resolving ${downloadInfo.links.length} SID link(s) to driveleech redirect URLs...`); const resolutionPromises = downloadInfo.links.map(async (linkInfo) => { try { let driveleechUrl = null; if (linkInfo.link && (linkInfo.link.includes('tech.unblockedgames.world') || linkInfo.link.includes('tech.creativeexpressionsblog.com') || linkInfo.link.includes('tech.examzculture.in'))) { driveleechUrl = await resolveSidToDriveleech(linkInfo.link); } else if (linkInfo.link && (linkInfo.link.includes('driveseed.org') || linkInfo.link.includes('driveleech.net'))) { // If it's already a direct driveseed/driveleech link, use it driveleechUrl = linkInfo.link; } if (!driveleechUrl) return null; console.log(`[UHDMovies] Caching driveleech redirect URL for ${linkInfo.quality}: ${driveleechUrl}`); return { ...linkInfo, driveleechRedirectUrl: driveleechUrl }; } catch (error) { console.error(`[UHDMovies] Error resolving ${linkInfo.quality}: ${error.message}`); return null; } }); cachedLinks = (await Promise.all(resolutionPromises)).filter(Boolean); // 7. Save the successfully resolved driveleech redirect URLs to the cache if (cachedLinks.length > 0) { console.log(`[UHDMovies] Caching ${cachedLinks.length} resolved driveleech redirect URLs for key: ${cacheKey}`); await saveToCache(cacheKey, cachedLinks); } else { console.log(`[UHDMovies] No driveleech redirect URLs could be resolved. Not caching to allow retrying later.`); return []; } } if (!cachedLinks || cachedLinks.length === 0) { console.log('[UHDMovies] No final file page URLs found after scraping/cache check.'); return []; } // 8. Process all cached driveleech redirect URLs to get streaming links console.log(`[UHDMovies] Processing ${cachedLinks.length} cached driveleech redirect URL(s) to get streaming links.`); const streamPromises = cachedLinks.map(async (linkInfo) => { try { // First, resolve the driveleech redirect URL to get the final file page URL const response = await makeRequest(linkInfo.driveleechRedirectUrl, { maxRedirects: 10 }); let $ = cheerio.load(response.data); // Check for JavaScript redirect (window.location.replace) const scriptContent = $('script').html(); const redirectMatch = scriptContent && scriptContent.match(/window\.location\.replace\("([^"]+)"\)/); let finalFilePageUrl = linkInfo.driveleechRedirectUrl; if (redirectMatch && redirectMatch[1]) { finalFilePageUrl = new URL(redirectMatch[1], 'https://driveleech.net/').href; console.log(`[UHDMovies] Resolved redirect to final file page: ${finalFilePageUrl}`); // Load the final file page const finalResponse = await makeRequest(finalFilePageUrl, { maxRedirects: 10 }); $ = cheerio.load(finalResponse.data); } // Extract file size and name information let sizeInfo = 'Unknown'; let fileName = null; const sizeElement = $('li.list-group-item:contains("Size :")').text(); if (sizeElement) { const sizeMatch = sizeElement.match(/Size\s*:\s*([0-9.,]+\s*[KMGT]B)/); if (sizeMatch) { sizeInfo = sizeMatch[1]; } } const nameElement = $('li.list-group-item:contains("Name :")'); if (nameElement.length > 0) { fileName = nameElement.text().replace('Name :', '').trim(); } else { const h5Title = $('div.card-header h5').clone().children().remove().end().text().trim(); if (h5Title) { fileName = h5Title.replace(/\[.*\]/, '').trim(); } } // Try download methods to get final streaming URL const downloadMethods = [ { name: 'Resume Cloud', func: tryResumeCloud }, { name: 'Instant Download', func: tryInstantDownload } ]; for (const method of downloadMethods) { try { const finalUrl = await method.func($); if (finalUrl) { const isValid = await validateVideoUrl(finalUrl); if (isValid) { const rawQuality = linkInfo.rawQuality || ''; const codecs = extractCodecs(rawQuality); const cleanFileName = fileName ? fileName.replace(/\.[^/.]+$/, "").replace(/[._]/g, ' ') : (linkInfo.quality || 'Unknown'); return { name: `UHDMovies`, title: `${cleanFileName}\n${sizeInfo}`, url: finalUrl, quality: linkInfo.quality, size: sizeInfo, fileName: fileName, fullTitle: rawQuality, codecs: codecs, behaviorHints: { bingeGroup: `uhdmovies-${linkInfo.quality}` } }; } } } catch (error) { console.log(`[UHDMovies] ${method.name} failed: ${error.message}`); } } return null; } catch (error) { console.error(`[UHDMovies] Error processing cached driveleech redirect ${linkInfo.driveleechRedirectUrl}: ${error.message}`); return null; } }); const streams = (await Promise.all(streamPromises)).filter(Boolean); console.log(`[UHDMovies] Successfully processed ${streams.length} final stream links.`); // Sort final streams by size streams.sort((a, b) => { const sizeA = parseSize(a.size); const sizeB = parseSize(b.size); return sizeB - sizeA; }); return streams; } catch (error) { console.error(`[UHDMovies] A critical error occurred in getUHDMoviesStreams for ${tmdbId}: ${error.message}`); if (error.stack) console.error(error.stack); return []; } } module.exports = { getUHDMoviesStreams };