openlist根路径主动移除bom

This commit is contained in:
mtvpls
2026-02-06 21:28:57 +08:00
parent d148491526
commit f43bdaa9e3
9 changed files with 48 additions and 28 deletions
+16 -1
View File
@@ -9,6 +9,18 @@ import { OpenListClient } from '@/lib/openlist.client';
export const runtime = 'nodejs'; export const runtime = 'nodejs';
/**
* 清理字符串中的 BOM 和其他不可见字符
*/
function cleanPath(path: string): string {
// 移除 UTF-8 BOM (U+FEFF) 和其他零宽度字符
return path
.replace(/^\uFEFF/, '') // 移除开头的 BOM
.replace(/\uFEFF/g, '') // 移除所有 BOM
.replace(/[\u200B-\u200D\uFEFF]/g, '') // 移除零宽度字符
.trim(); // 移除首尾空白
}
/** /**
* POST /api/admin/openlist * POST /api/admin/openlist
* 保存 OpenList 配置 * 保存 OpenList 配置
@@ -86,6 +98,9 @@ export async function POST(request: NextRequest) {
); );
} }
// 清理 RootPaths 中的 BOM 和不可见字符
const cleanedRootPaths = RootPaths.map(cleanPath);
// 验证扫描间隔 // 验证扫描间隔
const scanInterval = parseInt(ScanInterval) || 0; const scanInterval = parseInt(ScanInterval) || 0;
if (scanInterval > 0 && scanInterval < 60) { if (scanInterval > 0 && scanInterval < 60) {
@@ -113,7 +128,7 @@ export async function POST(request: NextRequest) {
URL, URL,
Username, Username,
Password, Password,
RootPaths, RootPaths: cleanedRootPaths,
OfflineDownloadPath: OfflineDownloadPath || '/', OfflineDownloadPath: OfflineDownloadPath || '/',
LastRefreshTime: adminConfig.OpenListConfig?.LastRefreshTime, LastRefreshTime: adminConfig.OpenListConfig?.LastRefreshTime,
ResourceCount: adminConfig.OpenListConfig?.ResourceCount, ResourceCount: adminConfig.OpenListConfig?.ResourceCount,
+1 -1
View File
@@ -91,7 +91,7 @@ export async function GET(request: NextRequest) {
const listResponse = await client.listDirectory(folderPath, currentPage, pageSize); const listResponse = await client.listDirectory(folderPath, currentPage, pageSize);
if (listResponse.code !== 200) { if (listResponse.code !== 200) {
throw new Error('OpenList 列表获取失败'); throw new Error('OpenList 列表获取失败1');
} }
total = listResponse.data.total; total = listResponse.data.total;
@@ -279,7 +279,7 @@ async function handleDetail(
if (listResponse.code !== 200) { if (listResponse.code !== 200) {
return NextResponse.json({ return NextResponse.json({
code: 0, code: 0,
msg: 'OpenList 列表获取失败', msg: 'OpenList 列表获取失败2',
page: 1, page: 1,
pagecount: 0, pagecount: 0,
limit: 0, limit: 0,
+1 -1
View File
@@ -90,7 +90,7 @@ export async function GET(request: NextRequest) {
if (listResponse.code !== 200) { if (listResponse.code !== 200) {
return NextResponse.json( return NextResponse.json(
{ error: 'OpenList 列表获取失败' }, { error: 'OpenList 列表获取失败3' },
{ status: 500 } { status: 500 }
); );
} }
+1 -1
View File
@@ -293,7 +293,7 @@ export async function GET(request: NextRequest) {
const listResponse = await client.listDirectory(folderPath, currentPage, pageSize); const listResponse = await client.listDirectory(folderPath, currentPage, pageSize);
if (listResponse.code !== 200) { if (listResponse.code !== 200) {
throw new Error('OpenList 列表获取失败'); throw new Error('OpenList 列表获取失败4');
} }
total = listResponse.data.total; total = listResponse.data.total;
+7 -13
View File
@@ -1805,19 +1805,13 @@ function PlayPageClient() {
clearRefreshTimer(); // 清除旧的定时器 clearRefreshTimer(); // 清除旧的定时器
isInitialLoadRef.current = true; // 重置为首次加载 isInitialLoadRef.current = true; // 重置为首次加载
// 动态设置 referrer policy只在小雅源时不发送 Referer // 动态设置 referrer policy:不发送 Referer
const existingMeta = document.querySelector('meta[name="referrer"]'); const existingMeta = document.querySelector('meta[name="referrer"]');
if (detailData?.source === 'xiaoya') { if (!existingMeta) {
if (!existingMeta) { const meta = document.createElement('meta');
const meta = document.createElement('meta'); meta.name = 'referrer';
meta.name = 'referrer'; meta.content = 'no-referrer';
meta.content = 'no-referrer'; document.head.appendChild(meta);
document.head.appendChild(meta);
}
} else {
if (existingMeta) {
existingMeta.remove();
}
} }
if ( if (
@@ -4847,7 +4841,7 @@ function PlayPageClient() {
moreVideoAttr: { moreVideoAttr: {
playsInline: true, playsInline: true,
'webkit-playsinline': 'true', 'webkit-playsinline': 'true',
...(detail?.source === 'xiaoya' ? { referrerpolicy: 'no-referrer' } : {}), referrerpolicy: 'no-referrer',
} as any, } as any,
// HLS 支持配置 // HLS 支持配置
customType: { customType: {
+19 -7
View File
@@ -25,19 +25,31 @@ import { getTVSeasonDetails,searchTMDB } from '@/lib/tmdb.search';
/** /**
* 获取根目录列表(兼容新旧配置) * 获取根目录列表(兼容新旧配置)
*/ */
/**
* 清理字符串中的 BOM 和其他不可见字符
*/
function cleanPath(path: string): string {
// 移除 UTF-8 BOM (U+FEFF) 和其他零宽度字符
return path
.replace(/^\uFEFF/, '') // 移除开头的 BOM
.replace(/\uFEFF/g, '') // 移除所有 BOM
.replace(/[\u200B-\u200D\uFEFF]/g, '') // 移除零宽度字符
.trim(); // 移除首尾空白
}
function getRootPaths(openListConfig: AdminConfig['OpenListConfig']): string[] { function getRootPaths(openListConfig: AdminConfig['OpenListConfig']): string[] {
if (!openListConfig) { if (!openListConfig) {
return ['/']; return ['/'];
} }
// 如果有新字段 RootPaths,直接使用 // 如果有新字段 RootPaths,直接使用并清理
if (openListConfig.RootPaths && openListConfig.RootPaths.length > 0) { if (openListConfig.RootPaths && openListConfig.RootPaths.length > 0) {
return openListConfig.RootPaths; return openListConfig.RootPaths.map(cleanPath);
} }
// 如果只tPath,返回单元素数组 // 如果只有 RootPath,返回单元素数组并清理
if (openListConfig.RootPath) { if (openListConfig.RootPath) {
return [openListConfig.RootPath]; return [cleanPath(openListConfig.RootPath)];
} }
// 默认值 // 默认值
@@ -155,8 +167,8 @@ async function performMultiRootScan(
): Promise<void> { ): Promise<void> {
for (let i = 0; i < rootPaths.length; i++) { for (let i = 0; i < rootPaths.length; i++) {
const rootPath = rootPaths[i]; const rootPath = rootPaths[i];
console.log(`[OpenList Refresh] 扫描根目录 (${i + 1}/${rootPaths.length}): ${rootPath}`);
console.log(`[OpenList Refresh] 扫描根目录 (${i + 1}/${rootPaths.length}): ${rootPath}`);
try { try {
await performScan( await performScan(
taskId, taskId,
@@ -233,9 +245,9 @@ async function performScan(
while (true) { while (true) {
const listResponse = await client.listDirectory(rootPath, currentPage, pageSize, true); const listResponse = await client.listDirectory(rootPath, currentPage, pageSize, true);
console.log(listResponse);
if (listResponse.code !== 200) { if (listResponse.code !== 200) {
throw new Error('OpenList 列表获取失败'); throw new Error('OpenList 列表获取失败5');
} }
total = listResponse.data.total; total = listResponse.data.total;
+1 -2
View File
@@ -158,7 +158,6 @@ export class OpenListClient {
console.warn('[OpenListClient] 解析响应 JSON 失败:', error); console.warn('[OpenListClient] 解析响应 JSON 失败:', error);
} }
} }
return response; return response;
} }
@@ -166,7 +165,7 @@ export class OpenListClient {
const token = await this.getToken(); const token = await this.getToken();
return { return {
Authorization: token, // 不带 bearer Authorization: token, // 不带 bearer
'Content-Type': 'application/json', 'Content-Type': 'application/json'
}; };
} }
+1 -1
View File
@@ -178,7 +178,7 @@ export async function getOpenListDetail(
); );
if (listResponse.code !== 200) { if (listResponse.code !== 200) {
throw new Error('OpenList 列表获取失败'); throw new Error('OpenList 列表获取失败6');
} }
total = listResponse.data.total; total = listResponse.data.total;