mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-29 04:13:03 +00:00
fix showbox token not reading
This commit is contained in:
parent
7bf3a344f3
commit
f9c043ba32
5 changed files with 139 additions and 47 deletions
58
README.md
58
README.md
|
|
@ -1,3 +1,5 @@
|
|||
# 🎬 Nuvio Media Hub
|
||||
|
||||
<!-- PROJECT LOGO -->
|
||||
<div align="center">
|
||||
<a id="readme-top"></a>
|
||||
|
|
@ -8,10 +10,7 @@
|
|||
[![Issues][issues-shield]][issues-url]
|
||||
[![License][license-shield]][license-url]
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<img src="assets/titlelogo.png" alt="Nuvio Logo" width="120" />
|
||||
<h1 align="center">🎬 Nuvio Media Hub</h1>
|
||||
<p align="center">
|
||||
A modern media hub built with React Native and Expo
|
||||
<br />
|
||||
|
|
@ -31,6 +30,7 @@
|
|||
<!-- TABLE OF CONTENTS -->
|
||||
<details>
|
||||
<summary>Table of Contents</summary>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<a href="#about-the-project">About The Project</a>
|
||||
|
|
@ -40,26 +40,24 @@
|
|||
<li><a href="#getting-started">Getting Started</a></li>
|
||||
<li><a href="#contributing">Contributing</a></li>
|
||||
<li><a href="#support">Support</a></li>
|
||||
<li><a href="#support">Support</a></li>
|
||||
<li><a href="#license">License</a></li>
|
||||
<li><a href="#legal">Legal</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
<li><a href="#acknowledgments">Acknowledgments</a></li>
|
||||
<li><a href="#built-with">Built With</a></li>
|
||||
</ol>
|
||||
</details>
|
||||
</details>
|
||||
|
||||
<!-- ABOUT THE PROJECT -->
|
||||
## About The Project
|
||||
|
||||
Nuvio Media Hub is a cross‑platform app for managing, discovering, and streaming your media via a flexible addon ecosystem. Built with React Native + Expo, it integrates providers and sync services while keeping a simple, fast UI.
|
||||
|
||||
|
||||
|
||||
<!-- INSTALLATION -->
|
||||
## Installation
|
||||
|
||||
### Android
|
||||
|
||||
[](https://github.com/tapframe/NuvioStreaming/releases/latest)
|
||||
|
||||
Download the latest APK from [GitHub Releases](https://github.com/tapframe/NuvioStreaming/releases/latest)
|
||||
|
|
@ -67,20 +65,21 @@ Download the latest APK from [GitHub Releases](https://github.com/tapframe/Nuvio
|
|||
### iOS
|
||||
|
||||
#### TestFlight (Recommended)
|
||||
<img src="https://upload.wikimedia.org/wikipedia/fr/b/bc/TestFlight-icon.png" width="24" height="24" align="left"> [](https://testflight.apple.com/join/QkKMGRqp)
|
||||
|
||||
<img src="https://upload.wikimedia.org/wikipedia/fr/b/bc/TestFlight-icon.png" width="24" height="24" align="left" alt="TestFlight Icon"> [](https://testflight.apple.com/join/QkKMGRqp)
|
||||
|
||||
#### AltStore
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/20/AltStore_logo.png" width="24" height="24" align="left"> [](https://tinyurl.com/NuvioAltstore)
|
||||
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/20/AltStore_logo.png" width="24" height="24" align="left" alt="AltStore Logo"> [](https://tinyurl.com/NuvioAltstore)
|
||||
|
||||
#### SideStore
|
||||
<img src="https://github.com/SideStore/assets/blob/main/icon.png?raw=true" width="24" height="24" align="left"> [](https://tinyurl.com/NuvioSidestore)
|
||||
|
||||
<img src="https://github.com/SideStore/assets/blob/main/icon.png?raw=true" width="24" height="24" align="left" alt="SideStore Logo"> [](https://tinyurl.com/NuvioSidestore)
|
||||
|
||||
**Manual URL:** `https://raw.githubusercontent.com/tapframe/NuvioStreaming/main/nuvio-source.json`
|
||||
|
||||
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
||||
|
||||
|
||||
|
||||
<!-- GETTING STARTED -->
|
||||
## Getting Started
|
||||
|
||||
|
|
@ -89,29 +88,23 @@ Follow the steps below to run the app locally for development. For detailed setu
|
|||
### Development Build
|
||||
|
||||
<details>
|
||||
<summary>Build from Source</summary>
|
||||
<summary>Build from Source</summary>
|
||||
|
||||
```bash
|
||||
git clone https://github.com/tapframe/NuvioStreaming.git
|
||||
cd NuvioStreaming
|
||||
npm install
|
||||
# If you hit peer dependency conflicts:
|
||||
# npm install --legacy-peer-deps
|
||||
npx expo start
|
||||
```
|
||||
git clone https://github.com/tapframe/NuvioStreaming.git
|
||||
cd NuvioStreaming
|
||||
npm install
|
||||
# If you hit peer dependency conflicts:
|
||||
# npm install --legacy-peer-deps
|
||||
npx expo start
|
||||
|
||||
```bash
|
||||
npx expo prebuild
|
||||
npx expo run:android # Android
|
||||
npx expo run:ios # iOS
|
||||
```
|
||||
npx expo prebuild
|
||||
npx expo run:android # Android
|
||||
npx expo run:ios # iOS
|
||||
|
||||
</details>
|
||||
|
||||
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
||||
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions make the open‑source community amazing! Any contributions are greatly appreciated.
|
||||
|
|
@ -151,6 +144,7 @@ For comprehensive legal information, including our full disclaimer, third-party
|
|||
## Contact
|
||||
|
||||
**Project Links:**
|
||||
|
||||
* GitHub: `https://github.com/tapframe`
|
||||
* Issues: `https://github.com/tapframe/NuvioStreaming/issues`
|
||||
|
||||
|
|
@ -171,13 +165,13 @@ For comprehensive legal information, including our full disclaimer, third-party
|
|||
|
||||
<p align="left">
|
||||
<a href="https://skillicons.dev">
|
||||
<img src="https://skillicons.dev/icons?i=react,typescript,nodejs,expo,github,githubactions&theme=light&perline=6" />
|
||||
<img src="https://skillicons.dev/icons?i=react,typescript,nodejs,expo,github,githubactions&theme=light&perline=6" alt="Skills Icons" />
|
||||
</a>
|
||||
<br/>
|
||||
React Native • Expo • TypeScript
|
||||
</p>
|
||||
</p>
|
||||
|
||||
## Star History
|
||||
## Star History
|
||||
|
||||
<a href="https://www.star-history.com/#tapframe/NuvioStreaming&type=date&legend=top-left">
|
||||
<picture>
|
||||
|
|
@ -199,4 +193,4 @@ For comprehensive legal information, including our full disclaimer, third-party
|
|||
[issues-shield]: https://img.shields.io/github/issues/tapframe/NuvioStreaming.svg?style=for-the-badge
|
||||
[issues-url]: https://github.com/tapframe/NuvioStreaming/issues
|
||||
[license-shield]: https://img.shields.io/github/license/tapframe/NuvioStreaming.svg?style=for-the-badge
|
||||
[license-url]: http://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
[license-url]: http://www.gnu.org/licenses/gpl-3.0.en.html
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@ export const LOCALES = [
|
|||
{ code: 'de', key: 'german' },
|
||||
{ code: 'ar', key: 'arabic' },
|
||||
{ code: 'fr', key: 'french' },
|
||||
{ code: 'it', key: 'italian' }
|
||||
{ code: 'it', key: 'italian' },
|
||||
{ code: 'es', key: 'spanish' }
|
||||
];
|
||||
|
|
@ -1231,8 +1231,10 @@ const PluginsScreen: React.FC = () => {
|
|||
if (sb) {
|
||||
setShowboxScraperId(sb.id);
|
||||
const s = await pluginService.getScraperSettings(sb.id);
|
||||
setShowboxUiToken(s.uiToken || '');
|
||||
setShowboxSavedToken(s.uiToken || '');
|
||||
// Check for multiple possible key names for the token
|
||||
const token = s.uiToken || s.cookie || s.token || '';
|
||||
setShowboxUiToken(token);
|
||||
setShowboxSavedToken(token);
|
||||
setShowboxTokenVisible(false);
|
||||
} else {
|
||||
setShowboxScraperId(null);
|
||||
|
|
@ -1926,7 +1928,12 @@ const PluginsScreen: React.FC = () => {
|
|||
style={[styles.button, styles.primaryButton]}
|
||||
onPress={async () => {
|
||||
if (showboxScraperId) {
|
||||
await pluginService.setScraperSettings(showboxScraperId, { uiToken: showboxUiToken });
|
||||
// Save with multiple keys to ensure the scraper finds it regardless of what key it checks
|
||||
await pluginService.setScraperSettings(showboxScraperId, {
|
||||
uiToken: showboxUiToken,
|
||||
cookie: showboxUiToken,
|
||||
token: showboxUiToken
|
||||
});
|
||||
}
|
||||
setShowboxSavedToken(showboxUiToken);
|
||||
openAlert('Saved', 'ShowBox settings updated');
|
||||
|
|
|
|||
|
|
@ -389,7 +389,22 @@ const SettingsScreen: React.FC = () => {
|
|||
return <ContentDiscoverySettingsContent isTablet={isTablet} />;
|
||||
|
||||
case 'appearance':
|
||||
return <AppearanceSettingsContent isTablet={isTablet} />;
|
||||
return (
|
||||
<>
|
||||
<SettingsCard title="GENERAL" isTablet={isTablet}>
|
||||
<SettingItem
|
||||
title={t('settings.language')}
|
||||
description={t(`settings.${LOCALES.find(l => l.code === i18n.language)?.key}`)}
|
||||
icon="globe"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => languageSheetRef.current?.present()}
|
||||
isLast={true}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
</SettingsCard>
|
||||
<AppearanceSettingsContent isTablet={isTablet} />
|
||||
</>
|
||||
);
|
||||
|
||||
case 'integrations':
|
||||
return <IntegrationsSettingsContent isTablet={isTablet} />;
|
||||
|
|
@ -571,6 +586,65 @@ const SettingsScreen: React.FC = () => {
|
|||
actions={alertActions}
|
||||
onClose={() => setAlertVisible(false)}
|
||||
/>
|
||||
|
||||
<BottomSheetModal
|
||||
ref={languageSheetRef}
|
||||
index={0}
|
||||
snapPoints={['65%']}
|
||||
enablePanDownToClose={true}
|
||||
backdropComponent={renderBackdrop}
|
||||
backgroundStyle={{
|
||||
backgroundColor: currentTheme.colors.darkGray || '#0A0C0C',
|
||||
borderTopLeftRadius: 16,
|
||||
borderTopRightRadius: 16,
|
||||
}}
|
||||
handleIndicatorStyle={{
|
||||
backgroundColor: currentTheme.colors.mediumGray,
|
||||
width: 40,
|
||||
}}
|
||||
onChange={onChange(languageSheetRef)}
|
||||
onDismiss={onDismiss(languageSheetRef)}
|
||||
>
|
||||
<View style={[styles.bottomSheetHeader, { backgroundColor: currentTheme.colors.darkGray || '#0A0C0C' }]}>
|
||||
<Text style={[styles.bottomSheetTitle, { color: currentTheme.colors.white }]}>
|
||||
{t('settings.select_language')}
|
||||
</Text>
|
||||
<TouchableOpacity onPress={() => languageSheetRef.current?.dismiss()}>
|
||||
<Feather name="x" size={24} color={currentTheme.colors.lightGray} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<BottomSheetScrollView
|
||||
style={{ backgroundColor: currentTheme.colors.darkGray || '#0A0C0C' }}
|
||||
contentContainerStyle={[styles.bottomSheetContent, { paddingBottom: insets.bottom + 16 }]}
|
||||
>
|
||||
{
|
||||
LOCALES.sort((a,b) => a.key.localeCompare(b.key)).map(l =>
|
||||
<TouchableOpacity
|
||||
key={l.key}
|
||||
style={[
|
||||
styles.languageOption,
|
||||
i18n.language === l.code && { backgroundColor: currentTheme.colors.primary + '20' }
|
||||
]}
|
||||
onPress={() => {
|
||||
i18n.changeLanguage(l.code);
|
||||
languageSheetRef.current?.dismiss();
|
||||
}}
|
||||
>
|
||||
<Text style={[
|
||||
styles.languageText,
|
||||
{ color: currentTheme.colors.highEmphasis },
|
||||
i18n.language === l.code && { color: currentTheme.colors.primary, fontWeight: 'bold' }
|
||||
]}>
|
||||
{t(`settings.${l.key}`)}
|
||||
</Text>
|
||||
{i18n.language === l.code && (
|
||||
<Feather name="check" size={20} color={currentTheme.colors.primary} />
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
</BottomSheetScrollView>
|
||||
</BottomSheetModal>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1162,21 +1162,33 @@ class LocalScraperService {
|
|||
}
|
||||
|
||||
|
||||
// Execute scraper code with full access to app environment (non-sandboxed)
|
||||
private async executePlugin(code: string, params: any, consoleOverride?: any): Promise<LocalScraperResult[]> {
|
||||
try {
|
||||
// Get URL validation setting from storage
|
||||
const settingsData = await mmkvStorage.getItem('app_settings');
|
||||
const settings = settingsData ? JSON.parse(settingsData) : {};
|
||||
const urlValidationEnabled = settings.enableScraperUrlValidation ?? true;
|
||||
|
||||
// Load per-scraper settings for this run
|
||||
const allScraperSettingsRaw = await mmkvStorage.getItem(this.SCRAPER_SETTINGS_KEY);
|
||||
const allScraperSettings = allScraperSettingsRaw ? JSON.parse(allScraperSettingsRaw) : {};
|
||||
const perScraperSettings = (params && params.scraperId && allScraperSettings[params.scraperId])
|
||||
let perScraperSettings = (params && params.scraperId && allScraperSettings[params.scraperId])
|
||||
? allScraperSettings[params.scraperId]
|
||||
: (params?.settings || {});
|
||||
|
||||
if (params?.scraperId?.toLowerCase().includes('showbox')) {
|
||||
const token = perScraperSettings.uiToken || perScraperSettings.cookie || perScraperSettings.token;
|
||||
if (token) {
|
||||
perScraperSettings = {
|
||||
...perScraperSettings,
|
||||
uiToken: token,
|
||||
cookie: token,
|
||||
token: token
|
||||
};
|
||||
if (params) {
|
||||
params.settings = perScraperSettings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Module exports for CommonJS compatibility
|
||||
const moduleExports: any = {};
|
||||
const moduleObj = { exports: moduleExports };
|
||||
|
|
@ -1292,12 +1304,16 @@ class LocalScraperService {
|
|||
'SCRAPER_ID',
|
||||
`
|
||||
// Make env vars available globally for backward compatibility
|
||||
if (typeof global !== 'undefined') {
|
||||
global.PRIMARY_KEY = PRIMARY_KEY;
|
||||
global.TMDB_API_KEY = TMDB_API_KEY;
|
||||
global.SCRAPER_SETTINGS = SCRAPER_SETTINGS;
|
||||
global.SCRAPER_ID = SCRAPER_ID;
|
||||
global.URL_VALIDATION_ENABLED = URL_VALIDATION_ENABLED;
|
||||
const globalScope = typeof global !== 'undefined' ? global : (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : this));
|
||||
|
||||
if (globalScope) {
|
||||
globalScope.PRIMARY_KEY = PRIMARY_KEY;
|
||||
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');
|
||||
}
|
||||
|
||||
// Plugin code
|
||||
|
|
|
|||
Loading…
Reference in a new issue