openlist和小雅增加禁用预览
This commit is contained in:
@@ -2781,6 +2781,7 @@ const OpenListConfigComponent = ({
|
|||||||
const [offlineDownloadPath, setOfflineDownloadPath] = useState('/');
|
const [offlineDownloadPath, setOfflineDownloadPath] = useState('/');
|
||||||
const [scanInterval, setScanInterval] = useState(0);
|
const [scanInterval, setScanInterval] = useState(0);
|
||||||
const [scanMode, setScanMode] = useState<'torrent' | 'name' | 'hybrid'>('hybrid');
|
const [scanMode, setScanMode] = useState<'torrent' | 'name' | 'hybrid'>('hybrid');
|
||||||
|
const [disableVideoPreview, setDisableVideoPreview] = useState(false);
|
||||||
const [videos, setVideos] = useState<any[]>([]);
|
const [videos, setVideos] = useState<any[]>([]);
|
||||||
const [refreshing, setRefreshing] = useState(false);
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
const [scanProgress, setScanProgress] = useState<{
|
const [scanProgress, setScanProgress] = useState<{
|
||||||
@@ -2801,6 +2802,7 @@ const OpenListConfigComponent = ({
|
|||||||
setOfflineDownloadPath(config.OpenListConfig.OfflineDownloadPath || '/');
|
setOfflineDownloadPath(config.OpenListConfig.OfflineDownloadPath || '/');
|
||||||
setScanInterval(config.OpenListConfig.ScanInterval || 0);
|
setScanInterval(config.OpenListConfig.ScanInterval || 0);
|
||||||
setScanMode(config.OpenListConfig.ScanMode || 'hybrid');
|
setScanMode(config.OpenListConfig.ScanMode || 'hybrid');
|
||||||
|
setDisableVideoPreview(config.OpenListConfig.DisableVideoPreview || false);
|
||||||
}
|
}
|
||||||
}, [config]);
|
}, [config]);
|
||||||
|
|
||||||
@@ -2842,6 +2844,7 @@ const OpenListConfigComponent = ({
|
|||||||
OfflineDownloadPath: offlineDownloadPath,
|
OfflineDownloadPath: offlineDownloadPath,
|
||||||
ScanInterval: scanInterval,
|
ScanInterval: scanInterval,
|
||||||
ScanMode: scanMode,
|
ScanMode: scanMode,
|
||||||
|
DisableVideoPreview: disableVideoPreview,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -3218,6 +3221,30 @@ const OpenListConfigComponent = ({
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='flex items-center justify-between py-3 border-b border-gray-200 dark:border-gray-700'>
|
||||||
|
<div>
|
||||||
|
<h3 className='text-sm font-medium text-gray-900 dark:text-white'>
|
||||||
|
禁用预览视频
|
||||||
|
</h3>
|
||||||
|
<p className='text-xs text-gray-500 dark:text-gray-400 mt-1'>
|
||||||
|
开启后将直接返回直连链接,不使用视频预览流
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => setDisableVideoPreview(!disableVideoPreview)}
|
||||||
|
disabled={!enabled}
|
||||||
|
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
|
||||||
|
disableVideoPreview ? 'bg-blue-600' : 'bg-gray-200 dark:bg-gray-700'
|
||||||
|
} ${!enabled ? 'opacity-50 cursor-not-allowed' : ''}`}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||||||
|
disableVideoPreview ? 'translate-x-6' : 'translate-x-1'
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='flex gap-3'>
|
<div className='flex gap-3'>
|
||||||
<button
|
<button
|
||||||
onClick={handleCheckConnectivity}
|
onClick={handleCheckConnectivity}
|
||||||
@@ -8605,6 +8632,7 @@ const XiaoyaConfigComponent = ({
|
|||||||
const [token, setToken] = useState('');
|
const [token, setToken] = useState('');
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
|
const [disableVideoPreview, setDisableVideoPreview] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (config?.XiaoyaConfig) {
|
if (config?.XiaoyaConfig) {
|
||||||
@@ -8613,6 +8641,7 @@ const XiaoyaConfigComponent = ({
|
|||||||
setToken(config.XiaoyaConfig.Token || '');
|
setToken(config.XiaoyaConfig.Token || '');
|
||||||
setUsername(config.XiaoyaConfig.Username || '');
|
setUsername(config.XiaoyaConfig.Username || '');
|
||||||
setPassword(config.XiaoyaConfig.Password || '');
|
setPassword(config.XiaoyaConfig.Password || '');
|
||||||
|
setDisableVideoPreview(config.XiaoyaConfig.DisableVideoPreview || false);
|
||||||
}
|
}
|
||||||
}, [config]);
|
}, [config]);
|
||||||
|
|
||||||
@@ -8629,6 +8658,7 @@ const XiaoyaConfigComponent = ({
|
|||||||
Token: token,
|
Token: token,
|
||||||
Username: username,
|
Username: username,
|
||||||
Password: password,
|
Password: password,
|
||||||
|
DisableVideoPreview: disableVideoPreview,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -8741,6 +8771,29 @@ const XiaoyaConfigComponent = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='flex items-center justify-between py-3 border-b border-gray-200 dark:border-gray-700'>
|
||||||
|
<div>
|
||||||
|
<h3 className='text-sm font-medium text-gray-900 dark:text-white'>
|
||||||
|
禁用预览视频
|
||||||
|
</h3>
|
||||||
|
<p className='text-xs text-gray-500 dark:text-gray-400 mt-1'>
|
||||||
|
开启后将直接返回直连链接,不使用视频预览流
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => setDisableVideoPreview(!disableVideoPreview)}
|
||||||
|
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
|
||||||
|
disableVideoPreview ? 'bg-blue-600' : 'bg-gray-200 dark:bg-gray-700'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||||||
|
disableVideoPreview ? 'translate-x-6' : 'translate-x-1'
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='grid grid-cols-2 gap-4'>
|
<div className='grid grid-cols-2 gap-4'>
|
||||||
<div>
|
<div>
|
||||||
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2'>
|
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2'>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
const { action, Enabled, URL, Username, Password, RootPaths, OfflineDownloadPath, ScanInterval, ScanMode } = body;
|
const { action, Enabled, URL, Username, Password, RootPaths, OfflineDownloadPath, ScanInterval, ScanMode, DisableVideoPreview } = body;
|
||||||
|
|
||||||
const authInfo = getAuthInfoFromCookie(request);
|
const authInfo = getAuthInfoFromCookie(request);
|
||||||
if (!authInfo || !authInfo.username) {
|
if (!authInfo || !authInfo.username) {
|
||||||
@@ -59,6 +59,7 @@ export async function POST(request: NextRequest) {
|
|||||||
ResourceCount: adminConfig.OpenListConfig?.ResourceCount,
|
ResourceCount: adminConfig.OpenListConfig?.ResourceCount,
|
||||||
ScanInterval: 0,
|
ScanInterval: 0,
|
||||||
ScanMode: ScanMode || 'hybrid',
|
ScanMode: ScanMode || 'hybrid',
|
||||||
|
DisableVideoPreview: DisableVideoPreview || false,
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.saveAdminConfig(adminConfig);
|
await db.saveAdminConfig(adminConfig);
|
||||||
@@ -118,6 +119,7 @@ export async function POST(request: NextRequest) {
|
|||||||
ResourceCount: adminConfig.OpenListConfig?.ResourceCount,
|
ResourceCount: adminConfig.OpenListConfig?.ResourceCount,
|
||||||
ScanInterval: scanInterval,
|
ScanInterval: scanInterval,
|
||||||
ScanMode: ScanMode || 'hybrid',
|
ScanMode: ScanMode || 'hybrid',
|
||||||
|
DisableVideoPreview: DisableVideoPreview || false,
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.saveAdminConfig(adminConfig);
|
await db.saveAdminConfig(adminConfig);
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export async function POST(request: NextRequest) {
|
|||||||
Token: configData.Token,
|
Token: configData.Token,
|
||||||
Username: configData.Username,
|
Username: configData.Username,
|
||||||
Password: configData.Password,
|
Password: configData.Password,
|
||||||
|
DisableVideoPreview: configData.DisableVideoPreview || false,
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.saveAdminConfig(config);
|
await db.saveAdminConfig(config);
|
||||||
|
|||||||
@@ -102,6 +102,43 @@ export async function GET(request: NextRequest) {
|
|||||||
openListConfig.Password
|
openListConfig.Password
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 如果启用了禁用预览视频,直接使用直连方法
|
||||||
|
if (openListConfig.DisableVideoPreview) {
|
||||||
|
const fileResponse = await client.getFile(filePath);
|
||||||
|
|
||||||
|
if (fileResponse.code !== 200 || !fileResponse.data.raw_url) {
|
||||||
|
console.error('[OpenList Play] 获取播放URL失败:', {
|
||||||
|
fileName,
|
||||||
|
code: fileResponse.code,
|
||||||
|
message: fileResponse.message,
|
||||||
|
});
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: '获取播放链接失败' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果指定了 format=json,使用 getFinalUrl 并返回 JSON
|
||||||
|
if (format === 'json') {
|
||||||
|
const finalUrl = await getFinalUrl(fileResponse.data.raw_url);
|
||||||
|
|
||||||
|
// 检查URL是否为空
|
||||||
|
if (!finalUrl || finalUrl.trim() === '') {
|
||||||
|
throw new Error('获取到的播放链接为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ url: finalUrl });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查URL是否为空
|
||||||
|
if (!fileResponse.data.raw_url || fileResponse.data.raw_url.trim() === '') {
|
||||||
|
throw new Error('获取到的播放链接为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认返回重定向(用于 tvbox)
|
||||||
|
return NextResponse.redirect(fileResponse.data.raw_url);
|
||||||
|
}
|
||||||
|
|
||||||
// 优先尝试视频预览流方法
|
// 优先尝试视频预览流方法
|
||||||
try {
|
try {
|
||||||
const data = await client.getVideoPreview(filePath);
|
const data = await client.getVideoPreview(filePath);
|
||||||
|
|||||||
@@ -101,6 +101,31 @@ export async function GET(request: NextRequest) {
|
|||||||
xiaoyaConfig.Token
|
xiaoyaConfig.Token
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 如果启用了禁用预览视频,直接使用直连方法
|
||||||
|
if (xiaoyaConfig.DisableVideoPreview) {
|
||||||
|
const playUrl = await client.getDownloadUrl(path);
|
||||||
|
|
||||||
|
// 如果指定了 format=json,使用 getFinalUrl 并返回 JSON
|
||||||
|
if (format === 'json') {
|
||||||
|
const finalUrl = await getFinalUrl(playUrl);
|
||||||
|
|
||||||
|
// 检查URL是否为空
|
||||||
|
if (!finalUrl || finalUrl.trim() === '') {
|
||||||
|
throw new Error('获取到的播放链接为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ url: finalUrl });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查URL是否为空
|
||||||
|
if (!playUrl || playUrl.trim() === '') {
|
||||||
|
throw new Error('获取到的播放链接为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认返回重定向(用于 tvbox)
|
||||||
|
return NextResponse.redirect(playUrl);
|
||||||
|
}
|
||||||
|
|
||||||
// 优先尝试视频预览流方法
|
// 优先尝试视频预览流方法
|
||||||
try {
|
try {
|
||||||
const token = await client.getToken();
|
const token = await client.getToken();
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ export interface AdminConfig {
|
|||||||
ResourceCount?: number; // 资源数量
|
ResourceCount?: number; // 资源数量
|
||||||
ScanInterval?: number; // 定时扫描间隔(分钟),0表示关闭,最低60分钟
|
ScanInterval?: number; // 定时扫描间隔(分钟),0表示关闭,最低60分钟
|
||||||
ScanMode?: 'torrent' | 'name' | 'hybrid'; // 扫描模式:torrent=种子库匹配,name=名字匹配,hybrid=混合模式(默认)
|
ScanMode?: 'torrent' | 'name' | 'hybrid'; // 扫描模式:torrent=种子库匹配,name=名字匹配,hybrid=混合模式(默认)
|
||||||
|
DisableVideoPreview?: boolean; // 禁用预览视频,直接返回直连链接
|
||||||
};
|
};
|
||||||
AIConfig?: {
|
AIConfig?: {
|
||||||
Enabled: boolean; // 是否启用AI问片功能
|
Enabled: boolean; // 是否启用AI问片功能
|
||||||
@@ -203,6 +204,7 @@ export interface AdminConfig {
|
|||||||
Token?: string; // Token 认证(推荐)
|
Token?: string; // Token 认证(推荐)
|
||||||
Username?: string; // 用户名认证(备选)
|
Username?: string; // 用户名认证(备选)
|
||||||
Password?: string; // 密码认证(备选)
|
Password?: string; // 密码认证(备选)
|
||||||
|
DisableVideoPreview?: boolean; // 禁用预览视频,直接返回直连链接
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user