Merge pull request #456 from paregi12/Api-key

Api key
This commit is contained in:
Nayif 2026-02-02 13:02:27 +05:30 committed by GitHub
commit 457dc9f8e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 74 additions and 7 deletions

View file

@ -9,6 +9,6 @@ export const LOCALES = [
{ code: 'es', key: 'spanish' },
{ code: 'hr', key: 'croatian' },
{ code: 'zh-CN', key: 'chinese' },
{ code: 'hi', key: 'hindi' }
{ code: 'hi', key: 'hindi' },
{ code: 'sr', key: 'serbian' }
];

View file

@ -1,5 +1,5 @@
import React, { useState, useCallback, useMemo, useRef, useEffect } from 'react';
import { View, StyleSheet, ScrollView, StatusBar, Platform, Text, TouchableOpacity, Dimensions, TextInput } from 'react-native';
import { View, StyleSheet, ScrollView, StatusBar, Platform, Text, TouchableOpacity, Dimensions, TextInput, ActivityIndicator } from 'react-native';
import { useNavigation, useFocusEffect } from '@react-navigation/native';
import { NavigationProp } from '@react-navigation/native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
@ -14,6 +14,7 @@ import { BottomSheetModal, BottomSheetScrollView, BottomSheetBackdrop } from '@g
import { useTranslation } from 'react-i18next';
import { SvgXml } from 'react-native-svg';
import { toastService } from '../../services/toastService';
import { introService } from '../../services/introService';
const { width } = Dimensions.get('window');
@ -79,14 +80,40 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
const [introDbLogoXml, setIntroDbLogoXml] = useState<string | null>(null);
const [apiKeyInput, setApiKeyInput] = useState(settings?.introDbApiKey || '');
const [isVerifyingKey, setIsVerifyingKey] = useState(false);
const isMounted = useRef(true);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);
useEffect(() => {
setApiKeyInput(settings?.introDbApiKey || '');
}, [settings?.introDbApiKey]);
const handleApiKeySubmit = () => {
updateSetting('introDbApiKey', apiKeyInput);
toastService.success(t('settings.items.api_key_saved', { defaultValue: 'API Key Saved' }));
const handleApiKeySubmit = async () => {
if (!apiKeyInput.trim()) {
updateSetting('introDbApiKey', '');
toastService.success(t('settings.items.api_key_cleared', { defaultValue: 'API Key Cleared' }));
return;
}
setIsVerifyingKey(true);
const isValid = await introService.verifyApiKey(apiKeyInput);
if (!isMounted.current) return;
setIsVerifyingKey(false);
if (isValid) {
updateSetting('introDbApiKey', apiKeyInput);
toastService.success(t('settings.items.api_key_saved', { defaultValue: 'API Key Saved' }));
} else {
toastService.error(t('settings.items.api_key_invalid', { defaultValue: 'Invalid API Key' }));
}
};
useEffect(() => {
@ -271,8 +298,13 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
<TouchableOpacity
style={styles.confirmButton}
onPress={handleApiKeySubmit}
disabled={isVerifyingKey}
>
<MaterialIcons name="check" size={24} color="black" />
{isVerifyingKey ? (
<ActivityIndicator size="small" color="black" />
) : (
<MaterialIcons name="check" size={24} color="black" />
)}
</TouchableOpacity>
</View>
</View>

View file

@ -187,6 +187,40 @@ async function fetchFromIntroDb(imdbId: string, season: number, episode: number)
}
}
/**
* Verifies an IntroDB API key
*/
export async function verifyApiKey(apiKey: string): Promise<boolean> {
try {
if (!apiKey) return false;
const response = await axios.post(`${INTRODB_API_URL}/submit`, {}, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
timeout: 5000,
validateStatus: (status) => true // Handle status codes manually
});
// 400 means Auth passed but payload was empty/invalid -> Key is Valid
if (response.status === 400) return true;
// 200/201 would also mean valid (though unexpected with empty body)
if (response.status === 200 || response.status === 201) return true;
// Explicitly handle auth failures
if (response.status === 401 || response.status === 403) return false;
// Log warning for unexpected states (500, 429, etc.) but fail safe
logger.warn(`[IntroService] Verification received unexpected status: ${response.status}`);
return false;
} catch (error: any) {
logger.log('[IntroService] API Key verification failed:', error.message);
return false;
}
}
/**
* Submits an intro timestamp to IntroDB
*/
@ -305,7 +339,8 @@ export async function getIntroTimestamps(
export const introService = {
getIntroTimestamps,
getSkipTimes,
submitIntro
submitIntro,
verifyApiKey
};
export default introService;