mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-20 16:22:04 +00:00
test
This commit is contained in:
parent
da0a69ab0e
commit
9006d312b8
4 changed files with 93 additions and 8 deletions
|
|
@ -29,7 +29,7 @@ async function getUHDMoviesDomain() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('[UHDMovies] Fetching latest domain...');
|
console.log('[UHDMovies] Fetching latest domain...');
|
||||||
const response = await axios.get('https://raw.githubusercontent.com/phisher98/TVVVV/refs/heads/main/domains.json', { timeout: 10000 });
|
const response = await axios.get('https://raw.githubusercontent.com/phisher98/TVVVV/refs/heads/main/domains.json');
|
||||||
if (response.data && response.data.UHDMovies) {
|
if (response.data && response.data.UHDMovies) {
|
||||||
uhdMoviesDomain = response.data.UHDMovies;
|
uhdMoviesDomain = response.data.UHDMovies;
|
||||||
domainCacheTimestamp = now;
|
domainCacheTimestamp = now;
|
||||||
|
|
@ -101,8 +101,7 @@ const axiosInstance = axios.create({
|
||||||
'Connection': 'keep-alive',
|
'Connection': 'keep-alive',
|
||||||
'Upgrade-Insecure-Requests': '1',
|
'Upgrade-Insecure-Requests': '1',
|
||||||
'Cache-Control': 'max-age=0'
|
'Cache-Control': 'max-age=0'
|
||||||
},
|
}
|
||||||
timeout: 30000
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Simple In-Memory Cache
|
// Simple In-Memory Cache
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit fa92f8cf27fc238b48697263aa48d8a2eb5a68ef
|
Subproject commit 6be646d6702a809b28eac63b7d04a453f756c402
|
||||||
|
|
@ -294,6 +294,9 @@ class LocalScraperService {
|
||||||
// This is a simplified sandbox - in production, you'd want more security
|
// This is a simplified sandbox - in production, you'd want more security
|
||||||
try {
|
try {
|
||||||
// Create a limited global context
|
// Create a limited global context
|
||||||
|
const moduleExports = {};
|
||||||
|
const moduleObj = { exports: moduleExports };
|
||||||
|
|
||||||
const sandbox = {
|
const sandbox = {
|
||||||
console: {
|
console: {
|
||||||
log: (...args: any[]) => logger.log('[Scraper]', ...args),
|
log: (...args: any[]) => logger.log('[Scraper]', ...args),
|
||||||
|
|
@ -310,13 +313,41 @@ class LocalScraperService {
|
||||||
parseFloat,
|
parseFloat,
|
||||||
encodeURIComponent,
|
encodeURIComponent,
|
||||||
decodeURIComponent,
|
decodeURIComponent,
|
||||||
|
// Add fetch for HTTP requests (using axios as polyfill)
|
||||||
|
fetch: async (url: string, options: any = {}) => {
|
||||||
|
const axiosConfig = {
|
||||||
|
url,
|
||||||
|
method: options.method || 'GET',
|
||||||
|
headers: options.headers || {},
|
||||||
|
data: options.body,
|
||||||
|
timeout: 30000
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios(axiosConfig);
|
||||||
|
return {
|
||||||
|
ok: response.status >= 200 && response.status < 300,
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
headers: response.headers,
|
||||||
|
json: async () => response.data,
|
||||||
|
text: async () => typeof response.data === 'string' ? response.data : JSON.stringify(response.data)
|
||||||
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new Error(`Fetch failed: ${error.message}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
// Add axios for HTTP requests
|
// Add axios for HTTP requests
|
||||||
axios: axios.create({
|
axios: axios.create({
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
headers: {
|
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'
|
'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'
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
|
// Node.js compatibility
|
||||||
|
module: moduleObj,
|
||||||
|
exports: moduleExports,
|
||||||
|
global: {} // Empty global object
|
||||||
};
|
};
|
||||||
|
|
||||||
// Execute the scraper code with timeout
|
// Execute the scraper code with timeout
|
||||||
|
|
@ -328,7 +359,7 @@ class LocalScraperService {
|
||||||
try {
|
try {
|
||||||
// Create function from code
|
// Create function from code
|
||||||
const func = new Function('sandbox', 'params', `
|
const func = new Function('sandbox', 'params', `
|
||||||
const { console, setTimeout, clearTimeout, Promise, JSON, Date, Math, parseInt, parseFloat, encodeURIComponent, decodeURIComponent, axios } = sandbox;
|
const { console, setTimeout, clearTimeout, Promise, JSON, Date, Math, parseInt, parseFloat, encodeURIComponent, decodeURIComponent, axios, fetch, module, exports, global } = sandbox;
|
||||||
${code}
|
${code}
|
||||||
|
|
||||||
// Call the main function (assuming it's exported)
|
// Call the main function (assuming it's exported)
|
||||||
|
|
@ -336,6 +367,8 @@ class LocalScraperService {
|
||||||
return getStreams(params.tmdbId, params.mediaType, params.season, params.episode);
|
return getStreams(params.tmdbId, params.mediaType, params.season, params.episode);
|
||||||
} else if (typeof module !== 'undefined' && module.exports && typeof module.exports.getStreams === 'function') {
|
} else if (typeof module !== 'undefined' && module.exports && typeof module.exports.getStreams === 'function') {
|
||||||
return module.exports.getStreams(params.tmdbId, params.mediaType, params.season, params.episode);
|
return module.exports.getStreams(params.tmdbId, params.mediaType, params.season, params.episode);
|
||||||
|
} else if (typeof global !== 'undefined' && global.getStreams && typeof global.getStreams === 'function') {
|
||||||
|
return global.getStreams(params.tmdbId, params.mediaType, params.season, params.episode);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('No getStreams function found in scraper');
|
throw new Error('No getStreams function found in scraper');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { logger } from '../utils/logger';
|
||||||
import EventEmitter from 'eventemitter3';
|
import EventEmitter from 'eventemitter3';
|
||||||
import { localScraperService } from './localScraperService';
|
import { localScraperService } from './localScraperService';
|
||||||
import { DEFAULT_SETTINGS, AppSettings } from '../hooks/useSettings';
|
import { DEFAULT_SETTINGS, AppSettings } from '../hooks/useSettings';
|
||||||
|
import { TMDBService } from './tmdbService';
|
||||||
|
|
||||||
// Create an event emitter for addon changes
|
// Create an event emitter for addon changes
|
||||||
export const addonEmitter = new EventEmitter();
|
export const addonEmitter = new EventEmitter();
|
||||||
|
|
@ -631,8 +632,60 @@ class StremioService {
|
||||||
if (hasScrapers) {
|
if (hasScrapers) {
|
||||||
logger.log('🔧 [getStreams] Executing local scrapers for', type, id);
|
logger.log('🔧 [getStreams] Executing local scrapers for', type, id);
|
||||||
|
|
||||||
// Execute local scrapers asynchronously
|
// Map Stremio types to local scraper types
|
||||||
localScraperService.getStreams(type, id, undefined, undefined, (streams, scraperId, scraperName, error) => {
|
const scraperType = type === 'series' ? 'tv' : type;
|
||||||
|
|
||||||
|
// Parse the Stremio ID to extract IMDb ID and season/episode info
|
||||||
|
let tmdbId: string | null = null;
|
||||||
|
let season: number | undefined = undefined;
|
||||||
|
let episode: number | undefined = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const idParts = id.split(':');
|
||||||
|
let baseImdbId: string;
|
||||||
|
|
||||||
|
// Handle different episode ID formats
|
||||||
|
if (idParts[0] === 'series') {
|
||||||
|
// Format: series:imdbId:season:episode
|
||||||
|
baseImdbId = idParts[1];
|
||||||
|
if (scraperType === 'tv' && idParts.length >= 4) {
|
||||||
|
season = parseInt(idParts[2], 10);
|
||||||
|
episode = parseInt(idParts[3], 10);
|
||||||
|
}
|
||||||
|
} else if (idParts[0].startsWith('tt')) {
|
||||||
|
// Format: imdbId:season:episode (direct IMDb ID)
|
||||||
|
baseImdbId = idParts[0];
|
||||||
|
if (scraperType === 'tv' && idParts.length >= 3) {
|
||||||
|
season = parseInt(idParts[1], 10);
|
||||||
|
episode = parseInt(idParts[2], 10);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback: assume first part is the ID
|
||||||
|
baseImdbId = idParts[0];
|
||||||
|
if (scraperType === 'tv' && idParts.length >= 3) {
|
||||||
|
season = parseInt(idParts[1], 10);
|
||||||
|
episode = parseInt(idParts[2], 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert IMDb ID to TMDB ID using TMDBService
|
||||||
|
const tmdbService = TMDBService.getInstance();
|
||||||
|
const tmdbIdNumber = await tmdbService.findTMDBIdByIMDB(baseImdbId);
|
||||||
|
|
||||||
|
if (tmdbIdNumber) {
|
||||||
|
tmdbId = tmdbIdNumber.toString();
|
||||||
|
logger.log(`🔄 [getStreams] Converted IMDb ID ${baseImdbId} to TMDB ID ${tmdbId}${scraperType === 'tv' ? ` (S${season}E${episode})` : ''}`);
|
||||||
|
} else {
|
||||||
|
logger.warn(`⚠️ [getStreams] Could not convert IMDb ID ${baseImdbId} to TMDB ID`);
|
||||||
|
return; // Skip local scrapers if we can't convert the ID
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`❌ [getStreams] Failed to parse Stremio ID or convert to TMDB ID:`, error);
|
||||||
|
return; // Skip local scrapers if ID parsing fails
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute local scrapers asynchronously with TMDB ID
|
||||||
|
localScraperService.getStreams(scraperType, tmdbId, season, episode, (streams, scraperId, scraperName, error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error(`❌ [getStreams] Local scraper ${scraperName} failed:`, error);
|
logger.error(`❌ [getStreams] Local scraper ${scraperName} failed:`, error);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue