Files
MoonTVPlus/src/app/api/admin/openlist/route.ts
T

215 lines
6.7 KiB
TypeScript

/* eslint-disable no-console */
import { NextRequest, NextResponse } from 'next/server';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { db } from '@/lib/db';
import { OpenListClient } from '@/lib/openlist.client';
export const runtime = 'nodejs';
/**
* 清理字符串中的 BOM 和其他不可见字符
*/
function cleanPath(path: string): string {
// 移除 UTF-8 BOM (U+FEFF) 和其他零宽度字符
let cleaned = path
.replace(/^\uFEFF/, '') // 移除开头的 BOM
.replace(/\uFEFF/g, '') // 移除所有 BOM
.replace(/[\u200B-\u200D\uFEFF]/g, '') // 移除零宽度字符
.trim(); // 移除首尾空白
// 移除末尾的 /(除非路径就是 /)
if (cleaned.length > 1 && cleaned.endsWith('/')) {
cleaned = cleaned.slice(0, -1);
}
return cleaned;
}
/**
* POST /api/admin/openlist
* 保存 OpenList 配置
*/
export async function POST(request: NextRequest) {
const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
return NextResponse.json(
{
error: '不支持本地存储进行管理员配置',
},
{ status: 400 }
);
}
try {
const body = await request.json();
const {
action,
Enabled,
URL,
Username,
Password,
RootPaths,
OfflineDownloadPath,
OfflineDownloadUseCustomSource,
OfflineDownloadURL,
OfflineDownloadUsername,
OfflineDownloadPassword,
ScanInterval,
ScanMode,
DisableVideoPreview,
} = body;
const authInfo = getAuthInfoFromCookie(request);
if (!authInfo || !authInfo.username) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const username = authInfo.username;
// 获取配置
const adminConfig = await getConfig();
// 权限检查 - 使用v2用户系统
if (username !== process.env.USERNAME) {
const userInfo = await db.getUserInfoV2(username);
if (!userInfo || userInfo.role !== 'admin' || userInfo.banned) {
return NextResponse.json({ error: '权限不足' }, { status: 401 });
}
}
if (action === 'save') {
// 如果功能未启用,允许保存空配置
if (!Enabled) {
adminConfig.OpenListConfig = {
Enabled: false,
URL: URL || '',
Username: Username || '',
Password: Password || '',
RootPaths: RootPaths || ['/'],
OfflineDownloadPath: OfflineDownloadPath || '/',
OfflineDownloadUseCustomSource: OfflineDownloadUseCustomSource || false,
OfflineDownloadURL: OfflineDownloadURL || '',
OfflineDownloadUsername: OfflineDownloadUsername || '',
OfflineDownloadPassword: OfflineDownloadPassword || '',
LastRefreshTime: adminConfig.OpenListConfig?.LastRefreshTime,
ResourceCount: adminConfig.OpenListConfig?.ResourceCount,
ScanInterval: 0,
ScanMode: ScanMode || 'hybrid',
DisableVideoPreview: DisableVideoPreview || false,
};
await db.saveAdminConfig(adminConfig);
return NextResponse.json({
success: true,
message: '保存成功',
});
}
// 功能启用时,验证必填字段
if (!URL || !Username || !Password) {
return NextResponse.json(
{ error: '请提供 URL、账号和密码' },
{ status: 400 }
);
}
if (
OfflineDownloadUseCustomSource &&
(!OfflineDownloadURL || !OfflineDownloadUsername || !OfflineDownloadPassword)
) {
return NextResponse.json(
{ error: '请提供离线下载 OpenList URL、账号和密码' },
{ status: 400 }
);
}
// 验证 RootPaths
if (!Array.isArray(RootPaths) || RootPaths.length === 0) {
return NextResponse.json(
{ error: '请至少提供一个根目录' },
{ status: 400 }
);
}
// 清理 RootPaths 中的 BOM 和不可见字符
const cleanedRootPaths = RootPaths.map(cleanPath);
// 验证扫描间隔
const scanInterval = parseInt(ScanInterval) || 0;
if (scanInterval > 0 && scanInterval < 60) {
return NextResponse.json(
{ error: '定时扫描间隔最低为 60 分钟' },
{ status: 400 }
);
}
// 验证账号密码是否正确
try {
console.log('[OpenList Config] 验证账号密码');
await OpenListClient.login(URL, Username, Password);
console.log('[OpenList Config] 账号密码验证成功');
} catch (error) {
console.error('[OpenList Config] 账号密码验证失败:', error);
return NextResponse.json(
{ error: '账号密码验证失败: ' + (error as Error).message },
{ status: 400 }
);
}
if (OfflineDownloadUseCustomSource) {
try {
console.log('[OpenList Config] 验证离线下载 OpenList 账号密码');
await OpenListClient.login(
OfflineDownloadURL,
OfflineDownloadUsername,
OfflineDownloadPassword
);
console.log('[OpenList Config] 离线下载 OpenList 账号密码验证成功');
} catch (error) {
console.error('[OpenList Config] 离线下载 OpenList 账号密码验证失败:', error);
return NextResponse.json(
{ error: '离线下载 OpenList 账号密码验证失败: ' + (error as Error).message },
{ status: 400 }
);
}
}
adminConfig.OpenListConfig = {
Enabled: true,
URL,
Username,
Password,
RootPaths: cleanedRootPaths,
OfflineDownloadPath: OfflineDownloadPath || '/',
OfflineDownloadUseCustomSource: OfflineDownloadUseCustomSource || false,
OfflineDownloadURL: OfflineDownloadURL || '',
OfflineDownloadUsername: OfflineDownloadUsername || '',
OfflineDownloadPassword: OfflineDownloadPassword || '',
LastRefreshTime: adminConfig.OpenListConfig?.LastRefreshTime,
ResourceCount: adminConfig.OpenListConfig?.ResourceCount,
ScanInterval: scanInterval,
ScanMode: ScanMode || 'hybrid',
DisableVideoPreview: DisableVideoPreview || false,
};
await db.saveAdminConfig(adminConfig);
return NextResponse.json({
success: true,
message: '保存成功',
});
}
return NextResponse.json({ error: '未知操作' }, { status: 400 });
} catch (error) {
console.error('OpenList 配置操作失败:', error);
return NextResponse.json(
{ error: '操作失败', details: (error as Error).message },
{ status: 500 }
);
}
}