mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-10 03:50:52 +00:00
support for moviebox
This commit is contained in:
parent
591bdfeb77
commit
b03f550765
5 changed files with 128 additions and 25 deletions
BIN
.App.tsx.swp
BIN
.App.tsx.swp
Binary file not shown.
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0a273ba5eb2632979a6678e005314c5b3ffb70eb
|
Subproject commit 37b9ae4298bd38b8119d45e8670f40bec2780a8b
|
||||||
15
package-lock.json
generated
15
package-lock.json
generated
|
|
@ -30,6 +30,7 @@
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
"axios-cookiejar-support": "^6.0.4",
|
"axios-cookiejar-support": "^6.0.4",
|
||||||
"cheerio-without-node-native": "^0.20.2",
|
"cheerio-without-node-native": "^0.20.2",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
"expo": "~52.0.47",
|
"expo": "~52.0.47",
|
||||||
|
|
@ -76,6 +77,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/react": "~18.3.12",
|
"@types/react": "~18.3.12",
|
||||||
"@types/react-native": "^0.72.8",
|
"@types/react-native": "^0.72.8",
|
||||||
"babel-plugin-transform-remove-console": "^6.9.4",
|
"babel-plugin-transform-remove-console": "^6.9.4",
|
||||||
|
|
@ -5001,6 +5003,13 @@
|
||||||
"@babel/types": "^7.28.2"
|
"@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": {
|
"node_modules/@types/graceful-fs": {
|
||||||
"version": "4.1.9",
|
"version": "4.1.9",
|
||||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
|
||||||
|
|
@ -6756,6 +6765,12 @@
|
||||||
"node": "*"
|
"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": {
|
"node_modules/crypto-random-string": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,15 @@
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
"axios-cookiejar-support": "^6.0.4",
|
"axios-cookiejar-support": "^6.0.4",
|
||||||
"cheerio-without-node-native": "^0.20.2",
|
"cheerio-without-node-native": "^0.20.2",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
"expo": "~52.0.47",
|
"expo": "~52.0.47",
|
||||||
"expo-application": "~6.0.2",
|
"expo-application": "~6.0.2",
|
||||||
"expo-auth-session": "~6.0.3",
|
"expo-auth-session": "~6.0.3",
|
||||||
"expo-blur": "~14.0.3",
|
"expo-blur": "~14.0.3",
|
||||||
|
"expo-brightness": "~13.0.3",
|
||||||
|
"expo-crypto": "~14.0.2",
|
||||||
"expo-dev-client": "~5.0.20",
|
"expo-dev-client": "~5.0.20",
|
||||||
"expo-device": "~7.0.3",
|
"expo-device": "~7.0.3",
|
||||||
"expo-file-system": "~18.0.12",
|
"expo-file-system": "~18.0.12",
|
||||||
|
|
@ -70,12 +73,11 @@
|
||||||
"react-native-video": "^6.12.0",
|
"react-native-video": "^6.12.0",
|
||||||
"react-native-vlc-media-player": "^1.0.87",
|
"react-native-vlc-media-player": "^1.0.87",
|
||||||
"react-native-web": "~0.19.13",
|
"react-native-web": "~0.19.13",
|
||||||
"react-native-wheel-color-picker": "^1.3.1",
|
"react-native-wheel-color-picker": "^1.3.1"
|
||||||
"expo-brightness": "~13.0.3",
|
|
||||||
"expo-crypto": "~14.0.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/react": "~18.3.12",
|
"@types/react": "~18.3.12",
|
||||||
"@types/react-native": "^0.72.8",
|
"@types/react-native": "^0.72.8",
|
||||||
"babel-plugin-transform-remove-console": "^6.9.4",
|
"babel-plugin-transform-remove-console": "^6.9.4",
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { Platform } from 'react-native';
|
||||||
import { logger } from '../utils/logger';
|
import { logger } from '../utils/logger';
|
||||||
import { Stream } from '../types/streams';
|
import { Stream } from '../types/streams';
|
||||||
import { cacheService } from './cacheService';
|
import { cacheService } from './cacheService';
|
||||||
|
import CryptoJS from 'crypto-js';
|
||||||
|
|
||||||
// Types for local scrapers
|
// Types for local scrapers
|
||||||
export interface ScraperManifest {
|
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 = {
|
const sandbox = {
|
||||||
console: {
|
console: {
|
||||||
log: (...args: any[]) => logger.log('[Scraper]', ...args),
|
log: (...args: any[]) => logger.log('[Scraper]', ...args),
|
||||||
|
|
@ -1068,32 +1073,106 @@ class LocalScraperService {
|
||||||
case 'react-native-cheerio':
|
case 'react-native-cheerio':
|
||||||
if (cheerio) return cheerio;
|
if (cheerio) return cheerio;
|
||||||
throw new Error('react-native-cheerio not available');
|
throw new Error('react-native-cheerio not available');
|
||||||
|
case 'crypto-js':
|
||||||
|
return CryptoJS;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Module '${moduleName}' is not available in sandbox`);
|
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 = {}) => {
|
fetch: async (url: string, options: any = {}) => {
|
||||||
const axiosConfig = {
|
const isMovieBoxRequest = url.includes('api.inmoviebox.com') || url.includes('themoviedb.org');
|
||||||
url,
|
|
||||||
method: options.method || 'GET',
|
|
||||||
headers: options.headers || {},
|
|
||||||
data: options.body,
|
|
||||||
timeout: 30000
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
if (isMovieBoxRequest) {
|
||||||
const response = await axios(axiosConfig);
|
// Always use native fetch for MovieBox requests
|
||||||
return {
|
try {
|
||||||
ok: response.status >= 200 && response.status < 300,
|
logger.log(`[Sandbox] Using native fetch for MovieBox request: ${url}`, {
|
||||||
status: response.status,
|
method: options.method || 'GET',
|
||||||
statusText: response.statusText,
|
hasBody: !!options.body
|
||||||
headers: response.headers,
|
});
|
||||||
json: async () => response.data,
|
|
||||||
text: async () => typeof response.data === 'string' ? response.data : JSON.stringify(response.data)
|
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
|
// Add axios for HTTP requests
|
||||||
|
|
@ -1118,8 +1197,15 @@ class LocalScraperService {
|
||||||
const executionPromise = new Promise<LocalScraperResult[]>((resolve, reject) => {
|
const executionPromise = new Promise<LocalScraperResult[]>((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
// Create function from code
|
// 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;
|
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}
|
${code}
|
||||||
|
|
||||||
// Call the main function (assuming it's exported)
|
// 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
|
// Handle both sync and async results
|
||||||
if (result && typeof result.then === 'function') {
|
if (result && typeof result.then === 'function') {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue