移除openlist token的输入
This commit is contained in:
@@ -2541,7 +2541,6 @@ const OpenListConfigComponent = ({
|
|||||||
const { alertModal, showAlert, hideAlert } = useAlertModal();
|
const { alertModal, showAlert, hideAlert } = useAlertModal();
|
||||||
const { isLoading, withLoading } = useLoadingState();
|
const { isLoading, withLoading } = useLoadingState();
|
||||||
const [url, setUrl] = useState('');
|
const [url, setUrl] = useState('');
|
||||||
const [token, setToken] = useState('');
|
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [rootPath, setRootPath] = useState('/');
|
const [rootPath, setRootPath] = useState('/');
|
||||||
@@ -2558,7 +2557,6 @@ const OpenListConfigComponent = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (config?.OpenListConfig) {
|
if (config?.OpenListConfig) {
|
||||||
setUrl(config.OpenListConfig.URL || '');
|
setUrl(config.OpenListConfig.URL || '');
|
||||||
setToken(config.OpenListConfig.Token || '');
|
|
||||||
setUsername(config.OpenListConfig.Username || '');
|
setUsername(config.OpenListConfig.Username || '');
|
||||||
setPassword(config.OpenListConfig.Password || '');
|
setPassword(config.OpenListConfig.Password || '');
|
||||||
setRootPath(config.OpenListConfig.RootPath || '/');
|
setRootPath(config.OpenListConfig.RootPath || '/');
|
||||||
@@ -2566,7 +2564,7 @@ const OpenListConfigComponent = ({
|
|||||||
}, [config]);
|
}, [config]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (config?.OpenListConfig?.URL && config?.OpenListConfig?.Token) {
|
if (config?.OpenListConfig?.URL && config?.OpenListConfig?.Username && config?.OpenListConfig?.Password) {
|
||||||
fetchVideos();
|
fetchVideos();
|
||||||
}
|
}
|
||||||
}, [config]);
|
}, [config]);
|
||||||
@@ -2595,7 +2593,6 @@ const OpenListConfigComponent = ({
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
action: 'save',
|
action: 'save',
|
||||||
URL: url,
|
URL: url,
|
||||||
Token: token,
|
|
||||||
Username: username,
|
Username: username,
|
||||||
Password: password,
|
Password: password,
|
||||||
RootPath: rootPath,
|
RootPath: rootPath,
|
||||||
@@ -2731,26 +2728,10 @@ const OpenListConfigComponent = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2'>
|
|
||||||
OpenList Token
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type='password'
|
|
||||||
value={token}
|
|
||||||
onChange={(e) => setToken(e.target.value)}
|
|
||||||
placeholder='your-token'
|
|
||||||
className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-transparent'
|
|
||||||
/>
|
|
||||||
<p className='mt-1 text-xs text-gray-500 dark:text-gray-400'>
|
|
||||||
可以直接填写Token,或使用下方账号密码登录获取
|
|
||||||
</p>
|
|
||||||
</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'>
|
||||||
账号(可选)
|
账号
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type='text'
|
type='text'
|
||||||
@@ -2762,7 +2743,7 @@ const OpenListConfigComponent = ({
|
|||||||
</div>
|
</div>
|
||||||
<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'>
|
||||||
密码(可选)
|
密码
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type='password'
|
type='password'
|
||||||
@@ -2802,7 +2783,7 @@ const OpenListConfigComponent = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 视频列表区域 */}
|
{/* 视频列表区域 */}
|
||||||
{config?.OpenListConfig?.URL && config?.OpenListConfig?.Token && (
|
{config?.OpenListConfig?.URL && config?.OpenListConfig?.Username && config?.OpenListConfig?.Password && (
|
||||||
<div className='space-y-4'>
|
<div className='space-y-4'>
|
||||||
<div className='flex items-center justify-between'>
|
<div className='flex items-center justify-between'>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
const { action, URL, Token, Username, Password, RootPath } = body;
|
const { action, URL, Username, Password, RootPath } = body;
|
||||||
|
|
||||||
const authInfo = getAuthInfoFromCookie(request);
|
const authInfo = getAuthInfoFromCookie(request);
|
||||||
if (!authInfo || !authInfo.username) {
|
if (!authInfo || !authInfo.username) {
|
||||||
@@ -49,40 +49,30 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
if (action === 'save') {
|
if (action === 'save') {
|
||||||
// 保存配置
|
// 保存配置
|
||||||
if (!URL) {
|
if (!URL || !Username || !Password) {
|
||||||
return NextResponse.json({ error: '缺少URL参数' }, { status: 400 });
|
|
||||||
}
|
|
||||||
|
|
||||||
let finalToken = Token;
|
|
||||||
|
|
||||||
// 如果没有Token但有账号密码,尝试登录获取Token
|
|
||||||
if (!finalToken && Username && Password) {
|
|
||||||
try {
|
|
||||||
console.log('[OpenList Config] 使用账号密码登录获取Token');
|
|
||||||
finalToken = await OpenListClient.login(URL, Username, Password);
|
|
||||||
console.log('[OpenList Config] 登录成功,获取到Token');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[OpenList Config] 登录失败:', error);
|
|
||||||
return NextResponse.json(
|
|
||||||
{ error: '使用账号密码登录失败: ' + (error as Error).message },
|
|
||||||
{ status: 400 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否有Token
|
|
||||||
if (!finalToken) {
|
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: '请提供Token或账号密码' },
|
{ error: '请提供 URL、账号和密码' },
|
||||||
|
{ 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 }
|
{ status: 400 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
adminConfig.OpenListConfig = {
|
adminConfig.OpenListConfig = {
|
||||||
URL,
|
URL,
|
||||||
Token: finalToken,
|
Username,
|
||||||
Username: Username || undefined,
|
Password,
|
||||||
Password: Password || undefined,
|
|
||||||
RootPath: RootPath || '/',
|
RootPath: RootPath || '/',
|
||||||
LastRefreshTime: adminConfig.OpenListConfig?.LastRefreshTime,
|
LastRefreshTime: adminConfig.OpenListConfig?.LastRefreshTime,
|
||||||
ResourceCount: adminConfig.OpenListConfig?.ResourceCount,
|
ResourceCount: adminConfig.OpenListConfig?.ResourceCount,
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ async function handleOpenListProxy(request: NextRequest) {
|
|||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const openListConfig = config.OpenListConfig;
|
const openListConfig = config.OpenListConfig;
|
||||||
|
|
||||||
if (!openListConfig || !openListConfig.URL || !openListConfig.Token) {
|
if (!openListConfig || !openListConfig.URL || !openListConfig.Username || !openListConfig.Password) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ code: 0, msg: 'OpenList 未配置', list: [] },
|
{ code: 0, msg: 'OpenList 未配置', list: [] },
|
||||||
{ status: 200 }
|
{ status: 200 }
|
||||||
@@ -272,7 +272,11 @@ async function handleOpenListProxy(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const rootPath = openListConfig.RootPath || '/';
|
const rootPath = openListConfig.RootPath || '/';
|
||||||
const client = new OpenListClient(openListConfig.URL, openListConfig.Token);
|
const client = new OpenListClient(
|
||||||
|
openListConfig.URL,
|
||||||
|
openListConfig.Username,
|
||||||
|
openListConfig.Password
|
||||||
|
);
|
||||||
|
|
||||||
// 读取 metainfo (从数据库或缓存)
|
// 读取 metainfo (从数据库或缓存)
|
||||||
let metaInfo: MetaInfo | null = getCachedMetaInfo(rootPath);
|
let metaInfo: MetaInfo | null = getCachedMetaInfo(rootPath);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export async function GET(request: NextRequest) {
|
|||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const openListConfig = config.OpenListConfig;
|
const openListConfig = config.OpenListConfig;
|
||||||
|
|
||||||
if (!openListConfig || !openListConfig.URL || !openListConfig.Token) {
|
if (!openListConfig || !openListConfig.URL || !openListConfig.Username || !openListConfig.Password) {
|
||||||
throw new Error('OpenList 未配置');
|
throw new Error('OpenList 未配置');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const openListConfig = config.OpenListConfig;
|
const openListConfig = config.OpenListConfig;
|
||||||
|
|
||||||
if (!openListConfig || !openListConfig.URL || !openListConfig.Token) {
|
if (!openListConfig || !openListConfig.URL || !openListConfig.Username || !openListConfig.Password) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: 'OpenList 未配置' },
|
{ error: 'OpenList 未配置' },
|
||||||
{ status: 400 }
|
{ status: 400 }
|
||||||
@@ -49,7 +49,6 @@ export async function POST(request: NextRequest) {
|
|||||||
const rootPath = openListConfig.RootPath || '/';
|
const rootPath = openListConfig.RootPath || '/';
|
||||||
const client = new OpenListClient(
|
const client = new OpenListClient(
|
||||||
openListConfig.URL,
|
openListConfig.URL,
|
||||||
openListConfig.Token,
|
|
||||||
openListConfig.Username,
|
openListConfig.Username,
|
||||||
openListConfig.Password
|
openListConfig.Password
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export async function GET(request: NextRequest) {
|
|||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const openListConfig = config.OpenListConfig;
|
const openListConfig = config.OpenListConfig;
|
||||||
|
|
||||||
if (!openListConfig || !openListConfig.URL || !openListConfig.Token) {
|
if (!openListConfig || !openListConfig.URL || !openListConfig.Username || !openListConfig.Password) {
|
||||||
return NextResponse.json({ error: 'OpenList 未配置' }, { status: 400 });
|
return NextResponse.json({ error: 'OpenList 未配置' }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,6 @@ export async function GET(request: NextRequest) {
|
|||||||
const folderPath = `${rootPath}${rootPath.endsWith('/') ? '' : '/'}${folderName}`;
|
const folderPath = `${rootPath}${rootPath.endsWith('/') ? '' : '/'}${folderName}`;
|
||||||
const client = new OpenListClient(
|
const client = new OpenListClient(
|
||||||
openListConfig.URL,
|
openListConfig.URL,
|
||||||
openListConfig.Token,
|
|
||||||
openListConfig.Username,
|
openListConfig.Username,
|
||||||
openListConfig.Password
|
openListConfig.Password
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export async function GET(request: NextRequest) {
|
|||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const openListConfig = config.OpenListConfig;
|
const openListConfig = config.OpenListConfig;
|
||||||
|
|
||||||
if (!openListConfig || !openListConfig.URL || !openListConfig.Token) {
|
if (!openListConfig || !openListConfig.URL || !openListConfig.Username || !openListConfig.Password) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: 'OpenList 未配置', list: [], total: 0 },
|
{ error: 'OpenList 未配置', list: [], total: 0 },
|
||||||
{ status: 200 }
|
{ status: 200 }
|
||||||
@@ -44,7 +44,6 @@ export async function GET(request: NextRequest) {
|
|||||||
const rootPath = openListConfig.RootPath || '/';
|
const rootPath = openListConfig.RootPath || '/';
|
||||||
const client = new OpenListClient(
|
const client = new OpenListClient(
|
||||||
openListConfig.URL,
|
openListConfig.URL,
|
||||||
openListConfig.Token,
|
|
||||||
openListConfig.Username,
|
openListConfig.Username,
|
||||||
openListConfig.Password
|
openListConfig.Password
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export async function GET(request: NextRequest) {
|
|||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const openListConfig = config.OpenListConfig;
|
const openListConfig = config.OpenListConfig;
|
||||||
|
|
||||||
if (!openListConfig || !openListConfig.URL || !openListConfig.Token) {
|
if (!openListConfig || !openListConfig.URL || !openListConfig.Username || !openListConfig.Password) {
|
||||||
return NextResponse.json({ error: 'OpenList 未配置' }, { status: 400 });
|
return NextResponse.json({ error: 'OpenList 未配置' }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,6 @@ export async function GET(request: NextRequest) {
|
|||||||
|
|
||||||
const client = new OpenListClient(
|
const client = new OpenListClient(
|
||||||
openListConfig.URL,
|
openListConfig.URL,
|
||||||
openListConfig.Token,
|
|
||||||
openListConfig.Username,
|
openListConfig.Username,
|
||||||
openListConfig.Password
|
openListConfig.Password
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const openListConfig = config.OpenListConfig;
|
const openListConfig = config.OpenListConfig;
|
||||||
|
|
||||||
if (!openListConfig || !openListConfig.URL || !openListConfig.Token) {
|
if (!openListConfig || !openListConfig.URL || !openListConfig.Username || !openListConfig.Password) {
|
||||||
return NextResponse.json({ error: 'OpenList 未配置' }, { status: 400 });
|
return NextResponse.json({ error: 'OpenList 未配置' }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,6 @@ export async function POST(request: NextRequest) {
|
|||||||
const folderPath = `${rootPath}${rootPath.endsWith('/') ? '' : '/'}${folder}`;
|
const folderPath = `${rootPath}${rootPath.endsWith('/') ? '' : '/'}${folder}`;
|
||||||
const client = new OpenListClient(
|
const client = new OpenListClient(
|
||||||
openListConfig.URL,
|
openListConfig.URL,
|
||||||
openListConfig.Token,
|
|
||||||
openListConfig.Username,
|
openListConfig.Username,
|
||||||
openListConfig.Password
|
openListConfig.Password
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
const openListConfig = config.OpenListConfig;
|
const openListConfig = config.OpenListConfig;
|
||||||
|
|
||||||
if (!openListConfig || !openListConfig.URL || !openListConfig.Token) {
|
if (!openListConfig || !openListConfig.URL || !openListConfig.Username || !openListConfig.Password) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: 'OpenList 未配置' },
|
{ error: 'OpenList 未配置' },
|
||||||
{ status: 400 }
|
{ status: 400 }
|
||||||
@@ -66,7 +66,6 @@ export async function POST(request: NextRequest) {
|
|||||||
performScan(
|
performScan(
|
||||||
taskId,
|
taskId,
|
||||||
openListConfig.URL,
|
openListConfig.URL,
|
||||||
openListConfig.Token,
|
|
||||||
openListConfig.RootPath || '/',
|
openListConfig.RootPath || '/',
|
||||||
tmdbApiKey,
|
tmdbApiKey,
|
||||||
tmdbProxy,
|
tmdbProxy,
|
||||||
@@ -97,20 +96,18 @@ export async function POST(request: NextRequest) {
|
|||||||
async function performScan(
|
async function performScan(
|
||||||
taskId: string,
|
taskId: string,
|
||||||
url: string,
|
url: string,
|
||||||
token: string,
|
|
||||||
rootPath: string,
|
rootPath: string,
|
||||||
tmdbApiKey: string,
|
tmdbApiKey: string,
|
||||||
tmdbProxy?: string,
|
tmdbProxy?: string,
|
||||||
username?: string,
|
username?: string,
|
||||||
password?: string
|
password?: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const client = new OpenListClient(url, token, username, password);
|
const client = new OpenListClient(url, username!, password!);
|
||||||
|
|
||||||
console.log('[OpenList Refresh] 开始扫描:', {
|
console.log('[OpenList Refresh] 开始扫描:', {
|
||||||
taskId,
|
taskId,
|
||||||
rootPath,
|
rootPath,
|
||||||
url,
|
url,
|
||||||
hasToken: !!token,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 立即更新进度,确保任务可被查询
|
// 立即更新进度,确保任务可被查询
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export async function GET(request: NextRequest) {
|
|||||||
const apiSites = await getAvailableApiSites(authInfo.username);
|
const apiSites = await getAvailableApiSites(authInfo.username);
|
||||||
|
|
||||||
// 检查是否配置了 OpenList
|
// 检查是否配置了 OpenList
|
||||||
const hasOpenList = !!(config.OpenListConfig?.URL && config.OpenListConfig?.Token);
|
const hasOpenList = !!(config.OpenListConfig?.URL && config.OpenListConfig?.Username && config.OpenListConfig?.Password);
|
||||||
|
|
||||||
// 共享状态
|
// 共享状态
|
||||||
let streamClosed = false;
|
let streamClosed = false;
|
||||||
|
|||||||
@@ -90,7 +90,9 @@ export default async function RootLayout({
|
|||||||
tmdbApiKey = config.SiteConfig.TMDBApiKey || '';
|
tmdbApiKey = config.SiteConfig.TMDBApiKey || '';
|
||||||
// 检查是否配置了 OpenList
|
// 检查是否配置了 OpenList
|
||||||
openListEnabled = !!(
|
openListEnabled = !!(
|
||||||
config.OpenListConfig?.URL && config.OpenListConfig?.Token
|
config.OpenListConfig?.URL &&
|
||||||
|
config.OpenListConfig?.Username &&
|
||||||
|
config.OpenListConfig?.Password
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,9 +93,8 @@ export interface AdminConfig {
|
|||||||
};
|
};
|
||||||
OpenListConfig?: {
|
OpenListConfig?: {
|
||||||
URL: string; // OpenList 服务器地址
|
URL: string; // OpenList 服务器地址
|
||||||
Token: string; // 认证 Token
|
Username: string; // 账号(用于登录获取Token)
|
||||||
Username?: string; // 账号(可选,用于登录获取Token)
|
Password: string; // 密码(用于登录获取Token)
|
||||||
Password?: string; // 密码(可选,用于登录获取Token)
|
|
||||||
RootPath: string; // 根目录路径,默认 "/"
|
RootPath: string; // 根目录路径,默认 "/"
|
||||||
LastRefreshTime?: number; // 上次刷新时间戳
|
LastRefreshTime?: number; // 上次刷新时间戳
|
||||||
ResourceCount?: number; // 资源数量
|
ResourceCount?: number; // 资源数量
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
|
// Token 内存缓存
|
||||||
|
const tokenCache = new Map<string, { token: string; expiresAt: number }>();
|
||||||
|
|
||||||
export interface OpenListFile {
|
export interface OpenListFile {
|
||||||
name: string;
|
name: string;
|
||||||
size: number;
|
size: number;
|
||||||
@@ -30,11 +33,12 @@ export interface OpenListGetResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class OpenListClient {
|
export class OpenListClient {
|
||||||
|
private token: string = '';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private baseURL: string,
|
private baseURL: string,
|
||||||
private token: string,
|
private username: string,
|
||||||
private username?: string,
|
private password: string
|
||||||
private password?: string
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,60 +73,81 @@ export class OpenListClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新Token(如果配置了账号密码)
|
* 获取缓存的 Token 或重新登录
|
||||||
*/
|
*/
|
||||||
private async refreshToken(): Promise<boolean> {
|
private async getToken(): Promise<string> {
|
||||||
if (!this.username || !this.password) {
|
const cacheKey = `${this.baseURL}:${this.username}`;
|
||||||
return false;
|
const cached = tokenCache.get(cacheKey);
|
||||||
|
|
||||||
|
// 如果有缓存且未过期,直接返回
|
||||||
|
if (cached && cached.expiresAt > Date.now()) {
|
||||||
|
this.token = cached.token;
|
||||||
|
return this.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// 否则重新登录
|
||||||
console.log('[OpenListClient] Token可能失效,尝试使用账号密码重新登录');
|
console.log('[OpenListClient] Token 不存在或已过期,重新登录');
|
||||||
this.token = await OpenListClient.login(
|
this.token = await OpenListClient.login(
|
||||||
this.baseURL,
|
this.baseURL,
|
||||||
this.username,
|
this.username,
|
||||||
this.password
|
this.password
|
||||||
);
|
);
|
||||||
console.log('[OpenListClient] Token刷新成功');
|
|
||||||
return true;
|
// 缓存 Token,设置 1 小时过期
|
||||||
} catch (error) {
|
tokenCache.set(cacheKey, {
|
||||||
console.error('[OpenListClient] Token刷新失败:', error);
|
token: this.token,
|
||||||
return false;
|
expiresAt: Date.now() + 60 * 60 * 1000,
|
||||||
}
|
});
|
||||||
|
|
||||||
|
console.log('[OpenListClient] 登录成功,Token 已缓存');
|
||||||
|
return this.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行请求,如果401则尝试刷新Token后重试
|
* 清除 Token 缓存(当 Token 失效时调用)
|
||||||
|
*/
|
||||||
|
private clearTokenCache(): void {
|
||||||
|
const cacheKey = `${this.baseURL}:${this.username}`;
|
||||||
|
tokenCache.delete(cacheKey);
|
||||||
|
console.log('[OpenListClient] Token 缓存已清除');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行请求,如果401则清除缓存并重新登录后重试
|
||||||
*/
|
*/
|
||||||
private async fetchWithRetry(
|
private async fetchWithRetry(
|
||||||
url: string,
|
url: string,
|
||||||
options: RequestInit,
|
options: RequestInit,
|
||||||
retried = false
|
retried = false
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
const response = await fetch(url, options);
|
// 获取 Token
|
||||||
|
const token = await this.getToken();
|
||||||
|
|
||||||
// 如果是401且未重试过且有账号密码,尝试刷新Token后重试
|
// 更新请求头中的 Token
|
||||||
if (response.status === 401 && !retried && this.username && this.password) {
|
const requestOptions = {
|
||||||
const refreshed = await this.refreshToken();
|
...options,
|
||||||
if (refreshed) {
|
headers: {
|
||||||
// 更新请求头中的Token
|
...options.headers,
|
||||||
const newOptions = {
|
Authorization: token,
|
||||||
...options,
|
},
|
||||||
headers: {
|
};
|
||||||
...options.headers,
|
|
||||||
Authorization: this.token,
|
const response = await fetch(url, requestOptions);
|
||||||
},
|
|
||||||
};
|
// 如果是401且未重试过,清除缓存并重新登录后重试
|
||||||
return this.fetchWithRetry(url, newOptions, true);
|
if (response.status === 401 && !retried) {
|
||||||
}
|
console.log('[OpenListClient] 收到 401,清除 Token 缓存并重试');
|
||||||
|
this.clearTokenCache();
|
||||||
|
return this.fetchWithRetry(url, options, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getHeaders() {
|
private async getHeaders() {
|
||||||
|
const token = await this.getToken();
|
||||||
return {
|
return {
|
||||||
Authorization: this.token, // 不带 bearer
|
Authorization: token, // 不带 bearer
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -135,7 +160,7 @@ export class OpenListClient {
|
|||||||
): Promise<OpenListListResponse> {
|
): Promise<OpenListListResponse> {
|
||||||
const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/list`, {
|
const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/list`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: this.getHeaders(),
|
headers: await this.getHeaders(),
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
path,
|
path,
|
||||||
password: '',
|
password: '',
|
||||||
@@ -156,7 +181,7 @@ export class OpenListClient {
|
|||||||
async getFile(path: string): Promise<OpenListGetResponse> {
|
async getFile(path: string): Promise<OpenListGetResponse> {
|
||||||
const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/get`, {
|
const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/get`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: this.getHeaders(),
|
headers: await this.getHeaders(),
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
path,
|
path,
|
||||||
password: '',
|
password: '',
|
||||||
@@ -172,10 +197,11 @@ export class OpenListClient {
|
|||||||
|
|
||||||
// 上传文件
|
// 上传文件
|
||||||
async uploadFile(path: string, content: string): Promise<void> {
|
async uploadFile(path: string, content: string): Promise<void> {
|
||||||
|
const token = await this.getToken();
|
||||||
const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/put`, {
|
const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/put`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: this.token,
|
Authorization: token,
|
||||||
'Content-Type': 'text/plain; charset=utf-8',
|
'Content-Type': 'text/plain; charset=utf-8',
|
||||||
'File-Path': encodeURIComponent(path),
|
'File-Path': encodeURIComponent(path),
|
||||||
'As-Task': 'false',
|
'As-Task': 'false',
|
||||||
@@ -198,7 +224,7 @@ export class OpenListClient {
|
|||||||
try {
|
try {
|
||||||
const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/list`, {
|
const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/list`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: this.getHeaders(),
|
headers: await this.getHeaders(),
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
path,
|
path,
|
||||||
password: '',
|
password: '',
|
||||||
@@ -223,7 +249,7 @@ export class OpenListClient {
|
|||||||
|
|
||||||
const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/remove`, {
|
const response = await this.fetchWithRetry(`${this.baseURL}/api/fs/remove`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: this.getHeaders(),
|
headers: await this.getHeaders(),
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
names: [fileName],
|
names: [fileName],
|
||||||
dir: dir,
|
dir: dir,
|
||||||
|
|||||||
Reference in New Issue
Block a user