mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-28 21:38:46 +00:00
removed the stream/MKV/URL-validation HEAD probes;
This commit is contained in:
parent
a4548c69e9
commit
9d0163b4eb
9 changed files with 1 additions and 155 deletions
|
|
@ -116,12 +116,7 @@ export const usePlayerSetup = (
|
|||
const restoreBrightness = async () => {
|
||||
try {
|
||||
if (Platform.OS === 'android') {
|
||||
if (originalSystemBrightnessModeRef.current !== null) {
|
||||
await (Brightness as any).setSystemBrightnessModeAsync?.(originalSystemBrightnessModeRef.current);
|
||||
}
|
||||
if (originalSystemBrightnessRef.current !== null) {
|
||||
await (Brightness as any).setSystemBrightnessAsync?.(originalSystemBrightnessRef.current);
|
||||
}
|
||||
|
||||
}
|
||||
if (originalAppBrightnessRef.current !== null) {
|
||||
await Brightness.setBrightnessAsync(originalAppBrightnessRef.current);
|
||||
|
|
|
|||
|
|
@ -3,48 +3,6 @@ import { logger } from '../utils/logger';
|
|||
import { TMDBService } from '../services/tmdbService';
|
||||
import { isTmdbUrl } from '../utils/logoUtils';
|
||||
import FastImage from '@d11/react-native-fast-image';
|
||||
import { mmkvStorage } from '../services/mmkvStorage';
|
||||
|
||||
// Cache for image availability checks
|
||||
const imageAvailabilityCache: Record<string, boolean> = {};
|
||||
|
||||
// Helper function to check image availability with caching
|
||||
const checkImageAvailability = async (url: string): Promise<boolean> => {
|
||||
// Check memory cache first
|
||||
if (imageAvailabilityCache[url] !== undefined) {
|
||||
return imageAvailabilityCache[url];
|
||||
}
|
||||
|
||||
// Check AsyncStorage cache
|
||||
try {
|
||||
const cachedResult = await mmkvStorage.getItem(`image_available:${url}`);
|
||||
if (cachedResult !== null) {
|
||||
const isAvailable = cachedResult === 'true';
|
||||
imageAvailabilityCache[url] = isAvailable;
|
||||
return isAvailable;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore AsyncStorage errors
|
||||
}
|
||||
|
||||
// Perform actual check
|
||||
try {
|
||||
const response = await fetch(url, { method: 'HEAD' });
|
||||
const isAvailable = response.ok;
|
||||
|
||||
// Update caches
|
||||
imageAvailabilityCache[url] = isAvailable;
|
||||
try {
|
||||
await mmkvStorage.setItem(`image_available:${url}`, isAvailable ? 'true' : 'false');
|
||||
} catch (error) {
|
||||
// Ignore AsyncStorage errors
|
||||
}
|
||||
|
||||
return isAvailable;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const useMetadataAssets = (
|
||||
metadata: any,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ export interface AppSettings {
|
|||
scraperRepositoryUrl: string; // URL to the scraper repository
|
||||
enableLocalScrapers: boolean; // Enable/disable local scraper functionality
|
||||
scraperTimeout: number; // Timeout for scraper execution in seconds
|
||||
enableScraperUrlValidation: boolean; // Enable/disable URL validation for scrapers
|
||||
streamDisplayMode: 'separate' | 'grouped'; // How to display streaming links - separately by provider or grouped under one name
|
||||
streamSortMode: 'scraper-then-quality' | 'quality-then-scraper'; // How to sort streams - by scraper first or quality first
|
||||
showScraperLogos: boolean; // Show scraper logos next to streaming links
|
||||
|
|
@ -138,7 +137,6 @@ export const DEFAULT_SETTINGS: AppSettings = {
|
|||
scraperRepositoryUrl: '',
|
||||
enableLocalScrapers: true,
|
||||
scraperTimeout: 60, // 60 seconds timeout
|
||||
enableScraperUrlValidation: true, // Enable URL validation by default
|
||||
streamDisplayMode: 'separate', // Default to separate display by provider
|
||||
streamSortMode: 'scraper-then-quality', // Default to current behavior (scraper first, then quality)
|
||||
showScraperLogos: true, // Show scraper logos by default
|
||||
|
|
|
|||
|
|
@ -1443,10 +1443,6 @@ const PluginsScreen: React.FC = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const handleToggleUrlValidation = async (enabled: boolean) => {
|
||||
await updateSetting('enableScraperUrlValidation', enabled);
|
||||
};
|
||||
|
||||
const handleToggleQualityExclusion = async (quality: string) => {
|
||||
const currentExcluded = settings.excludedQualities || [];
|
||||
const isExcluded = currentExcluded.includes(quality);
|
||||
|
|
@ -1971,22 +1967,6 @@ const PluginsScreen: React.FC = () => {
|
|||
colors={colors}
|
||||
styles={styles}
|
||||
>
|
||||
<View style={styles.settingRow}>
|
||||
<View style={styles.settingInfo}>
|
||||
<Text style={styles.settingTitle}>{t('plugins.enable_url_validation')}</Text>
|
||||
<Text style={styles.settingDescription}>
|
||||
{t('plugins.url_validation_desc')}
|
||||
</Text>
|
||||
</View>
|
||||
<Switch
|
||||
value={settings.enableScraperUrlValidation && settings.enableLocalScrapers}
|
||||
onValueChange={handleToggleUrlValidation}
|
||||
trackColor={{ false: colors.elevation3, true: colors.primary }}
|
||||
thumbColor={settings.enableScraperUrlValidation && settings.enableLocalScrapers ? colors.white : '#f4f3f4'}
|
||||
disabled={!settings.enableLocalScrapers}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.settingRow}>
|
||||
<View style={styles.settingInfo}>
|
||||
<Text style={styles.settingTitle}>{t('plugins.group_streams')}</Text>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import {
|
|||
filterStreamsByQuality,
|
||||
filterStreamsByLanguage,
|
||||
getQualityNumeric,
|
||||
detectMkvViaHead,
|
||||
inferVideoTypeFromUrl,
|
||||
sortStreamsByQuality,
|
||||
} from './utils';
|
||||
|
|
@ -37,7 +36,6 @@ import {
|
|||
TMDBEpisodeOverride,
|
||||
AlertAction,
|
||||
} from './types';
|
||||
import { MKV_HEAD_TIMEOUT_MS } from './constants';
|
||||
|
||||
// Cache for scraper logos
|
||||
const scraperLogoCache = new Map<string, string>();
|
||||
|
|
@ -469,36 +467,6 @@ export const useStreamsScreen = () => {
|
|||
return;
|
||||
}
|
||||
|
||||
// iOS MKV detection
|
||||
if (Platform.OS === 'ios' && settings.preferredPlayer === 'internal') {
|
||||
const lowerUrl = (stream.url || '').toLowerCase();
|
||||
const isMkvByPath =
|
||||
lowerUrl.includes('.mkv') ||
|
||||
/[?&]ext=mkv\b/i.test(lowerUrl) ||
|
||||
/format=mkv\b/i.test(lowerUrl) ||
|
||||
/container=mkv\b/i.test(lowerUrl);
|
||||
const isHttp = lowerUrl.startsWith('http://') || lowerUrl.startsWith('https://');
|
||||
|
||||
if (!isMkvByPath && isHttp) {
|
||||
try {
|
||||
const mkvDetected = await Promise.race<boolean>([
|
||||
detectMkvViaHead(stream.url, (stream.headers as any) || undefined),
|
||||
new Promise<boolean>(res => setTimeout(() => res(false), MKV_HEAD_TIMEOUT_MS)),
|
||||
]);
|
||||
if (mkvDetected) {
|
||||
const mergedHeaders = {
|
||||
...(stream.headers || {}),
|
||||
'Content-Type': 'video/x-matroska',
|
||||
} as Record<string, string>;
|
||||
navigateToPlayer(stream, { headers: mergedHeaders });
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn('[StreamsScreen] MKV detection failed:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iOS external player
|
||||
if (Platform.OS === 'ios' && settings.preferredPlayer !== 'internal') {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Stream } from '../../types/metadata';
|
||||
import { MKV_HEAD_TIMEOUT_MS } from './constants';
|
||||
|
||||
/**
|
||||
* Language variations for filtering
|
||||
|
|
@ -150,30 +149,6 @@ export const sortStreamsByQuality = (streams: Stream[]): Stream[] => {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Detect MKV format via HEAD request
|
||||
*/
|
||||
export const detectMkvViaHead = async (
|
||||
url: string,
|
||||
headers?: Record<string, string>
|
||||
): Promise<boolean> => {
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), MKV_HEAD_TIMEOUT_MS);
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
method: 'HEAD',
|
||||
headers,
|
||||
signal: controller.signal as any,
|
||||
} as any);
|
||||
const contentType = res.headers.get('content-type') || '';
|
||||
return /matroska|x-matroska/i.test(contentType);
|
||||
} catch (_e) {
|
||||
return false;
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Infer video type from URL
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1164,10 +1164,6 @@ class LocalScraperService {
|
|||
|
||||
private async executePlugin(code: string, params: any, consoleOverride?: any): Promise<LocalScraperResult[]> {
|
||||
try {
|
||||
const settingsData = await mmkvStorage.getItem('app_settings');
|
||||
const settings = settingsData ? JSON.parse(settingsData) : {};
|
||||
const urlValidationEnabled = settings.enableScraperUrlValidation ?? true;
|
||||
|
||||
const allScraperSettingsRaw = await mmkvStorage.getItem(this.SCRAPER_SETTINGS_KEY);
|
||||
const allScraperSettings = allScraperSettingsRaw ? JSON.parse(allScraperSettingsRaw) : {};
|
||||
let perScraperSettings = (params && params.scraperId && allScraperSettings[params.scraperId])
|
||||
|
|
@ -1299,7 +1295,6 @@ class LocalScraperService {
|
|||
'params',
|
||||
'PRIMARY_KEY',
|
||||
'TMDB_API_KEY',
|
||||
'URL_VALIDATION_ENABLED',
|
||||
'SCRAPER_SETTINGS',
|
||||
'SCRAPER_ID',
|
||||
`
|
||||
|
|
@ -1311,7 +1306,6 @@ class LocalScraperService {
|
|||
globalScope.TMDB_API_KEY = TMDB_API_KEY;
|
||||
globalScope.SCRAPER_SETTINGS = SCRAPER_SETTINGS;
|
||||
globalScope.SCRAPER_ID = SCRAPER_ID;
|
||||
globalScope.URL_VALIDATION_ENABLED = URL_VALIDATION_ENABLED;
|
||||
} else {
|
||||
logger.error('[Plugin Sandbox] Could not find global scope to inject settings');
|
||||
}
|
||||
|
|
@ -1346,7 +1340,6 @@ class LocalScraperService {
|
|||
params,
|
||||
MOVIEBOX_PRIMARY_KEY,
|
||||
MOVIEBOX_TMDB_API_KEY,
|
||||
urlValidationEnabled,
|
||||
perScraperSettings,
|
||||
params?.scraperId
|
||||
);
|
||||
|
|
|
|||
|
|
@ -149,26 +149,6 @@ class StreamCacheService {
|
|||
return episodeId ? `${baseKey}:${episodeId}` : baseKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if a stream URL is still accessible
|
||||
*/
|
||||
private async validateStreamUrl(url: string): Promise<boolean> {
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), 3000); // 3 second timeout
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'HEAD',
|
||||
signal: controller.signal as any,
|
||||
} as any);
|
||||
|
||||
clearTimeout(timeout);
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache info for debugging
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
import { Platform } from 'react-native';
|
||||
import { isMkvStream } from './mkvDetection';
|
||||
|
||||
export interface PlayerSelectionOptions {
|
||||
uri: string;
|
||||
|
|
|
|||
Loading…
Reference in a new issue