import type { FormEvent } from 'react' import { useEffect, useState } from 'react' import toast from 'react-hot-toast' import { adminAPI } from '../api/admin' import { strmAPI, type GenerateSTRMResult } from '../api/strm' import type { Library } from '../types' import { inferSTRMOutputRoot, playbackStatusText, preferredSTRMBaseURL, suggestedSTRMOutputDir, type CloudPlaybackMode, } from './strmPageModel' import { apiErrorMessage, isHTTPURL } from './strmPageUtils' export function useStrmGenerateForm(libraries: Library[]) { const [generateLibraryID, setGenerateLibraryID] = useState('') const [baseURL, setBaseURL] = useState('') const [outputDir, setOutputDir] = useState('') const [outputRoot, setOutputRoot] = useState('') const [outputScope, setOutputScope] = useState('') const [outputDirTouched, setOutputDirTouched] = useState(false) const [settingsLoaded, setSettingsLoaded] = useState(false) const [cloudPlaybackMode, setCloudPlaybackMode] = useState('redirect_proxy') const [strmPlaybackEnabled, setStrmPlaybackEnabled] = useState(false) const [redirectProxyEnabled, setRedirectProxyEnabled] = useState(true) const [autoGenerate, setAutoGenerate] = useState(false) const [savingSettings, setSavingSettings] = useState(false) const [overwrite, setOverwrite] = useState(false) const [generating, setGenerating] = useState(false) const [generateResult, setGenerateResult] = useState(null) useEffect(() => { adminAPI .listSettings() .then((rows) => { const settings = Object.fromEntries(rows.map((row) => [row.key, row.value])) const savedOutputDir = settings['strm.output_dir'] || '' const mode = settings['cloud.playback_mode'] const nextMode = mode === 'strm' || mode === 'redirect_proxy' ? mode : settings['strm.enabled'] === 'true' ? 'strm' : 'redirect_proxy' setBaseURL(preferredSTRMBaseURL(settings['strm.base_url'] || settings['app.server_url'] || '')) setOutputDir(savedOutputDir) setOutputRoot(savedOutputDir) setOutputScope(settings['strm.output_scope'] || '') setOutputDirTouched(false) setCloudPlaybackMode(nextMode) setStrmPlaybackEnabled( settings['cloud.playback_strm_enabled'] != null ? settings['cloud.playback_strm_enabled'] === 'true' : settings['strm.enabled'] === 'true' || nextMode === 'strm', ) setRedirectProxyEnabled(settings['cloud.playback_redirect_proxy_enabled'] !== 'false') setAutoGenerate(settings['strm.auto_generate_enabled'] === 'true') setSettingsLoaded(true) }) .catch(() => setSettingsLoaded(true)) }, []) useEffect(() => { if (!generateLibraryID && libraries[0]) setGenerateLibraryID(libraries[0].id) }, [libraries, generateLibraryID]) useEffect(() => { if (!settingsLoaded || outputDirTouched || !generateLibraryID) return const root = outputScope === 'library' ? inferSTRMOutputRoot(outputRoot, libraries) : outputRoot if (generateLibraryID === '*') { setOutputDir(root) return } const library = libraries.find((item) => item.id === generateLibraryID) if (library) setOutputDir(suggestedSTRMOutputDir(root, library)) }, [settingsLoaded, outputDirTouched, outputRoot, outputScope, generateLibraryID, libraries]) const onOutputDirChange = (value: string) => { setOutputDir(value) setOutputRoot(value) setOutputScope('') setOutputDirTouched(true) } const onGenerate = async (event: FormEvent) => { event.preventDefault() const trimmedBaseURL = baseURL.trim() if (!generateLibraryID || !trimmedBaseURL) return if (!isHTTPURL(trimmedBaseURL)) { toast.error('域名必须以 http:// 或 https:// 开头') return } setGenerating(true) try { const result = await strmAPI.generate({ library_id: generateLibraryID, base_url: trimmedBaseURL.replace(/\/+$/, ''), output_dir: outputDir.trim(), overwrite, enabled: autoGenerate, include_local: true, }) const nextOutputDir = result.output_dir || outputDir setGenerateResult(result) setOutputDir(nextOutputDir) setOutputRoot(inferSTRMOutputRoot(nextOutputDir, libraries)) setOutputScope(generateLibraryID === '*' ? 'all' : 'library') setOutputDirTouched(false) toast.success(`生成完成:新增 ${result.generated} · 更新 ${result.updated} · 跳过 ${result.skipped}`) } catch (err: unknown) { toast.error(apiErrorMessage(err, '生成失败')) } finally { setGenerating(false) } } const saveSTRMSettings = async () => { setSavingSettings(true) try { const effectiveMode: CloudPlaybackMode = strmPlaybackEnabled && !redirectProxyEnabled ? 'strm' : !strmPlaybackEnabled && redirectProxyEnabled ? 'redirect_proxy' : cloudPlaybackMode await Promise.all([ adminAPI.updateSetting('cloud.playback_mode', effectiveMode), adminAPI.updateSetting('cloud.playback_strm_enabled', String(strmPlaybackEnabled)), adminAPI.updateSetting('cloud.playback_redirect_proxy_enabled', String(redirectProxyEnabled)), adminAPI.updateSetting('strm.enabled', String(strmPlaybackEnabled)), adminAPI.updateSetting('strm.auto_generate_enabled', String(autoGenerate)), ]) setCloudPlaybackMode(effectiveMode) toast.success( strmPlaybackEnabled || redirectProxyEnabled ? `播放设置已保存:优先 ${effectiveMode === 'strm' ? 'STRMURL' : '302/反代'}` : '播放设置已保存:云盘第三方播放已关闭', ) } catch (err: unknown) { toast.error(apiErrorMessage(err, '保存 STRM 开关失败')) } finally { setSavingSettings(false) } } return { autoGenerate, baseURL, cloudPlaybackMode, generateLibraryID, generateResult, generating, onGenerate, outputDir, overwrite, playbackStatus: playbackStatusText(strmPlaybackEnabled, redirectProxyEnabled, cloudPlaybackMode), redirectProxyEnabled, saveSTRMSettings, savingSettings, setAutoGenerate, setBaseURL, setCloudPlaybackMode, setGenerateLibraryID, setOutputDir: onOutputDirChange, setOverwrite, setRedirectProxyEnabled, setStrmPlaybackEnabled, strmPlaybackEnabled, } }