support for moviebox

This commit is contained in:
tapframe 2025-09-13 16:13:54 +05:30
parent 591bdfeb77
commit b03f550765
5 changed files with 128 additions and 25 deletions

Binary file not shown.

@ -1 +1 @@
Subproject commit 0a273ba5eb2632979a6678e005314c5b3ffb70eb
Subproject commit 37b9ae4298bd38b8119d45e8670f40bec2780a8b

15
package-lock.json generated
View file

@ -30,6 +30,7 @@
"axios": "^1.11.0",
"axios-cookiejar-support": "^6.0.4",
"cheerio-without-node-native": "^0.20.2",
"crypto-js": "^4.2.0",
"date-fns": "^4.1.0",
"eventemitter3": "^5.0.1",
"expo": "~52.0.47",
@ -76,6 +77,7 @@
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@types/crypto-js": "^4.2.2",
"@types/react": "~18.3.12",
"@types/react-native": "^0.72.8",
"babel-plugin-transform-remove-console": "^6.9.4",
@ -5001,6 +5003,13 @@
"@babel/types": "^7.28.2"
}
},
"node_modules/@types/crypto-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz",
"integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/graceful-fs": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
@ -6756,6 +6765,12 @@
"node": "*"
}
},
"node_modules/crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
"license": "MIT"
},
"node_modules/crypto-random-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",

View file

@ -30,12 +30,15 @@
"axios": "^1.11.0",
"axios-cookiejar-support": "^6.0.4",
"cheerio-without-node-native": "^0.20.2",
"crypto-js": "^4.2.0",
"date-fns": "^4.1.0",
"eventemitter3": "^5.0.1",
"expo": "~52.0.47",
"expo-application": "~6.0.2",
"expo-auth-session": "~6.0.3",
"expo-blur": "~14.0.3",
"expo-brightness": "~13.0.3",
"expo-crypto": "~14.0.2",
"expo-dev-client": "~5.0.20",
"expo-device": "~7.0.3",
"expo-file-system": "~18.0.12",
@ -70,12 +73,11 @@
"react-native-video": "^6.12.0",
"react-native-vlc-media-player": "^1.0.87",
"react-native-web": "~0.19.13",
"react-native-wheel-color-picker": "^1.3.1",
"expo-brightness": "~13.0.3",
"expo-crypto": "~14.0.2"
"react-native-wheel-color-picker": "^1.3.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@types/crypto-js": "^4.2.2",
"@types/react": "~18.3.12",
"@types/react-native": "^0.72.8",
"babel-plugin-transform-remove-console": "^6.9.4",

View file

@ -4,6 +4,7 @@ import { Platform } from 'react-native';
import { logger } from '../utils/logger';
import { Stream } from '../types/streams';
import { cacheService } from './cacheService';
import CryptoJS from 'crypto-js';
// Types for local scrapers
export interface ScraperManifest {
@ -1043,6 +1044,10 @@ class LocalScraperService {
}
}
// MovieBox constants - hardcoded for security
const MOVIEBOX_PRIMARY_KEY = '76iRl07s0xSN9jqmEWAt79EBJZulIQIsV64FZr2O';
const MOVIEBOX_TMDB_API_KEY = '439c478a771f35c05022f9feabcca01c';
const sandbox = {
console: {
log: (...args: any[]) => logger.log('[Scraper]', ...args),
@ -1068,32 +1073,106 @@ class LocalScraperService {
case 'react-native-cheerio':
if (cheerio) return cheerio;
throw new Error('react-native-cheerio not available');
case 'crypto-js':
return CryptoJS;
default:
throw new Error(`Module '${moduleName}' is not available in sandbox`);
}
},
// Add fetch for HTTP requests (using axios as polyfill)
// Add fetch for HTTP requests (using native fetch for MovieBox, axios for others)
fetch: async (url: string, options: any = {}) => {
const axiosConfig = {
url,
method: options.method || 'GET',
headers: options.headers || {},
data: options.body,
timeout: 30000
};
const isMovieBoxRequest = url.includes('api.inmoviebox.com') || url.includes('themoviedb.org');
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)
if (isMovieBoxRequest) {
// Always use native fetch for MovieBox requests
try {
logger.log(`[Sandbox] Using native fetch for MovieBox request: ${url}`, {
method: options.method || 'GET',
hasBody: !!options.body
});
const nativeResponse = await fetch(url, {
method: options.method || 'GET',
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': 'application/json',
...options.headers
},
body: options.body
});
const responseData = await nativeResponse.text();
logger.log(`[Sandbox] Native fetch successful for MovieBox:`, {
status: nativeResponse.status,
ok: nativeResponse.ok
});
return {
ok: nativeResponse.ok,
status: nativeResponse.status,
statusText: nativeResponse.statusText || 'OK',
headers: nativeResponse.headers,
json: async () => {
try {
return JSON.parse(responseData);
} catch (e) {
logger.error(`[Sandbox] Failed to parse JSON from native fetch: ${e}`);
throw e;
}
},
text: async () => responseData
};
} catch (error: any) {
logger.error(`[Sandbox] Native fetch failed for MovieBox ${url}:`, error.message);
throw new Error(`Fetch failed: ${error.message}`);
}
} else {
// Use axios for other requests
const axiosConfig = {
url,
method: options.method || 'GET',
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': 'application/json',
...options.headers
},
data: options.body,
timeout: 30000,
validateStatus: () => true // Don't throw on HTTP error status codes
};
} catch (error: any) {
throw new Error(`Fetch failed: ${error.message}`);
try {
logger.log(`[Sandbox] Using axios for request: ${url}`, {
method: axiosConfig.method,
headers: axiosConfig.headers,
hasBody: !!axiosConfig.data
});
const response = await axios(axiosConfig);
logger.log(`[Sandbox] Axios response received:`, {
status: response.status,
statusText: response.statusText,
dataType: typeof response.data
});
return {
ok: response.status >= 200 && response.status < 300,
status: response.status,
statusText: response.statusText || 'OK',
headers: response.headers,
json: async () => {
try {
return typeof response.data === 'string' ? JSON.parse(response.data) : response.data;
} catch (e) {
logger.error(`[Sandbox] Failed to parse JSON response: ${e}`);
throw e;
}
},
text: async () => typeof response.data === 'string' ? response.data : JSON.stringify(response.data)
};
} catch (error: any) {
logger.error(`[Sandbox] Axios error for ${url}:`, error.message);
throw new Error(`Fetch failed: ${error.message}`);
}
}
},
// Add axios for HTTP requests
@ -1118,8 +1197,15 @@ class LocalScraperService {
const executionPromise = new Promise<LocalScraperResult[]>((resolve, reject) => {
try {
// Create function from code
const func = new Function('sandbox', 'params', `
const func = new Function('sandbox', 'params', 'PRIMARY_KEY', 'TMDB_API_KEY', `
const { console, setTimeout, clearTimeout, Promise, JSON, Date, Math, parseInt, parseFloat, encodeURIComponent, decodeURIComponent, require, axios, fetch, module, exports, global, URL_VALIDATION_ENABLED } = sandbox;
// Inject MovieBox constants into global scope
global.PRIMARY_KEY = PRIMARY_KEY;
global.TMDB_API_KEY = TMDB_API_KEY;
window.PRIMARY_KEY = PRIMARY_KEY;
window.TMDB_API_KEY = TMDB_API_KEY;
${code}
// Call the main function (assuming it's exported)
@ -1134,7 +1220,7 @@ class LocalScraperService {
}
`);
const result = func(sandbox, params);
const result = func(sandbox, params, MOVIEBOX_PRIMARY_KEY, MOVIEBOX_TMDB_API_KEY);
// Handle both sync and async results
if (result && typeof result.then === 'function') {