fix: cookie加密后cloud.service.ts未解密导致API 401; 更新版本号至2.1.1/1.1.9
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { getDb } from '../database/database';
|
||||
import { localTimestamp, formatLocalDateTime } from '../utils/time';
|
||||
import { getSystemConfig } from '../admin/system-config.service';
|
||||
import { decrypt } from '../utils/crypto';
|
||||
import { QuarkDriver } from './drivers/quark.driver';
|
||||
import { BaiduDriver } from './drivers/baidu.driver';
|
||||
import { CloudConfig, getAndValidateCredential, getActiveCloudConfigs } from './credential.service';
|
||||
@@ -159,12 +160,12 @@ async function doSaveFromShare(shareUrl: string, cloudType: string, sourceTitle?
|
||||
|
||||
switch (cloudType) {
|
||||
case 'quark': {
|
||||
const driver = new QuarkDriver({ cookie: config.cookie!, nickname: config.nickname });
|
||||
const driver = new QuarkDriver({ cookie: decrypt(config.cookie!), nickname: config.nickname });
|
||||
driverResult = await driver.saveFromShare(shareUrl, sourceTitle);
|
||||
break;
|
||||
}
|
||||
case 'baidu': {
|
||||
const driver = new BaiduDriver({ cookie: config.cookie!, nickname: config.nickname });
|
||||
const driver = new BaiduDriver({ cookie: decrypt(config.cookie!), nickname: config.nickname });
|
||||
driverResult = await driver.saveFromShare(shareUrl, sourceTitle);
|
||||
break;
|
||||
}
|
||||
@@ -174,6 +175,21 @@ async function doSaveFromShare(shareUrl: string, cloudType: string, sourceTitle?
|
||||
return { success: false, message: `暂不支持 ${cloudType} 的保存功能` };
|
||||
}
|
||||
|
||||
// ── If save failed, get actual error reason from PanSou validation ──
|
||||
let actualError: string | null = null;
|
||||
if (!driverResult.success) {
|
||||
try {
|
||||
const { LinkValidator } = await import('../validation/link-validator.service');
|
||||
const validator = new LinkValidator();
|
||||
const validation = await validator.validate(shareUrl, cloudType);
|
||||
if (validation.message) {
|
||||
actualError = validation.message;
|
||||
}
|
||||
} catch {
|
||||
// PanSou unreachable
|
||||
}
|
||||
}
|
||||
|
||||
const durationMs = Date.now() - startTime;
|
||||
|
||||
if (driverResult.success) {
|
||||
@@ -196,7 +212,7 @@ async function doSaveFromShare(shareUrl: string, cloudType: string, sourceTitle?
|
||||
driverResult.shareUrl || null, driverResult.sharePwd || null,
|
||||
driverResult.fileSize == null ? null : String(driverResult.fileSize), driverResult.fileCount || 0, driverResult.folderCount || 0,
|
||||
durationMs, driverResult.success ? 'success' : 'failed',
|
||||
driverResult.success ? null : driverResult.message,
|
||||
driverResult.success ? null : (actualError ? `${driverResult.message} | ${actualError}` : driverResult.message),
|
||||
driverResult.folderName || null, driverResult.originalFolderName || null,
|
||||
ipAddress || null, ipLocation, localTimestamp(), config.id
|
||||
);
|
||||
@@ -312,7 +328,7 @@ export async function refreshAllStorageInfo(): Promise<void> {
|
||||
for (const cfg of configs) {
|
||||
try {
|
||||
const { QuarkDriver } = require('./drivers/quark.driver');
|
||||
const driver = new QuarkDriver({ cookie: cfg.cookie, nickname: cfg.nickname });
|
||||
const driver = new QuarkDriver({ cookie: decrypt(cfg.cookie!), nickname: cfg.nickname });
|
||||
const storage = await driver.getStorageInfo();
|
||||
if (storage.totalBytes > 0 || storage.usedBytes > 0) {
|
||||
const db = getDb();
|
||||
@@ -324,4 +340,4 @@ export async function refreshAllStorageInfo(): Promise<void> {
|
||||
console.error(`[Storage] Failed to refresh quark#${cfg.id}:`, err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,7 +189,7 @@ export function saveCloudConfig(data: {
|
||||
consecutive_failures = 0,
|
||||
updated_at = ?
|
||||
WHERE id = ?`
|
||||
).run(data.cloud_type, encryptedCookie || null, data.nickname || null, data.is_active ?? 1, data.promotion_account ?? '', data.is_transfer_enabled ?? 1, data.storage_used || null, data.storage_total || null, cloudTypeUid || null, localTimestamp(), data.id);
|
||||
).run(data.cloud_type, encryptedCookie || null, data.nickname || null, data.is_active == null ? 1 : Number(data.is_active), data.promotion_account ?? '', data.is_transfer_enabled == null ? 1 : Number(data.is_transfer_enabled), data.storage_used || null, data.storage_total || null, cloudTypeUid || null, localTimestamp(), data.id);
|
||||
} else {
|
||||
// Try to find existing config by cloud_type + cloud_type_uid
|
||||
let existing: any = null;
|
||||
@@ -220,7 +220,7 @@ export function saveCloudConfig(data: {
|
||||
consecutive_failures = 0,
|
||||
updated_at = ?
|
||||
WHERE id = ?`
|
||||
).run(encryptedCookie || null, data.nickname || null, data.is_active ?? 1, data.promotion_account ?? '', data.is_transfer_enabled ?? 1, data.storage_used || null, data.storage_total || null, cloudTypeUid || null, localTimestamp(), existing.id);
|
||||
).run(encryptedCookie || null, data.nickname || null, data.is_active == null ? 1 : Number(data.is_active), data.promotion_account ?? '', data.is_transfer_enabled == null ? 1 : Number(data.is_transfer_enabled), data.storage_used || null, data.storage_total || null, cloudTypeUid || null, localTimestamp(), existing.id);
|
||||
|
||||
// Re-read savedId for return
|
||||
const savedId = existing.id;
|
||||
@@ -236,7 +236,7 @@ export function saveCloudConfig(data: {
|
||||
// No existing config found — insert new
|
||||
db.prepare(
|
||||
'INSERT INTO cloud_configs (cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, storage_used, storage_total, cloud_type_uid, consecutive_failures) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 0)'
|
||||
).run(data.cloud_type, encryptedCookie || null, data.nickname || null, data.is_active ?? 1, data.promotion_account ?? '', data.is_transfer_enabled ?? 1, data.storage_used || null, data.storage_total || null, cloudTypeUid || null);
|
||||
).run(data.cloud_type, encryptedCookie || null, data.nickname || null, data.is_active == null ? 1 : Number(data.is_active), data.promotion_account ?? '', data.is_transfer_enabled == null ? 1 : Number(data.is_transfer_enabled), data.storage_used || null, data.storage_total || null, cloudTypeUid || null);
|
||||
}
|
||||
|
||||
const savedId = data.id || (db.prepare('SELECT last_insert_rowid() as id').get() as any).id;
|
||||
|
||||
@@ -89,14 +89,8 @@ export async function getStorageInfoQuick(cookie: string, fallbackTotal?: string
|
||||
*/
|
||||
export async function getStorageInfo(cookie: string): Promise<{ used: string; total: string; usedBytes: number; totalBytes: number }> {
|
||||
try {
|
||||
const mparam = getMparam(cookie);
|
||||
let totalBytes = 0;
|
||||
const params = new URLSearchParams({
|
||||
...getCommonParams(),
|
||||
kps: mparam.kps || '',
|
||||
sign: mparam.sign || '',
|
||||
vcode: mparam.vcode || '',
|
||||
});
|
||||
const params = new URLSearchParams(getCommonParams());
|
||||
const response = await fetch(`${BASE_URL}/1/clouddrive/capacity/detail?${params.toString()}`, {
|
||||
headers: getHeaders(cookie),
|
||||
signal: AbortSignal.timeout(10000),
|
||||
|
||||
@@ -321,6 +321,8 @@ function seedSystemConfigs(db: Database.Database): void {
|
||||
{ key: 'quark_ad_keywords', value: '广告,推广,福利,加V,加微,联系,客服,赚钱,兼职', description: '夸克转存广告关键词(一行一个,匹配文件名/文件夹名即删除)' },
|
||||
{ key: 'quark_warning_folder_names', value: '⚠️ 网盘内除您所需资源外', description: '夸克转存后自动创建的警示文件夹名(一行一个,自动加上 ⚠️ 前缀)' },
|
||||
{ key: 'quark_sus_extensions', value: 'bat\nexe\nvbs\nscr\ncmd\ncom\npif\njs\njar\nmsi\nreg\ninf\nps1', description: '夸克转存可疑文件后缀(一行一个,不写点号,匹配即删除)' },
|
||||
{ key: 'link_valid_keywords', value: '链接有效', description: 'PanSou 链接有效关键词(一行一条)' },
|
||||
{ key: 'link_invalid_keywords', value: '链接失效', description: 'PanSou 链接失效关键词和本地验证失效关键词(一行一条)' },
|
||||
];
|
||||
const insert = db.prepare(
|
||||
'INSERT OR IGNORE INTO system_configs (key, value, description) VALUES (?, ?, ?)'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cloudsearch-frontend",
|
||||
"version": "1.1.8",
|
||||
"version": "1.1.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -351,7 +351,7 @@ async function handleToggleTransfer(row: CloudConfig, enabled: boolean) {
|
||||
nickname: row.nickname || '',
|
||||
promotion_account: row.promotion_account || '',
|
||||
is_transfer_enabled: newVal,
|
||||
is_active: row.is_active !== 0,
|
||||
is_active: row.is_active,
|
||||
cookie: undefined, // don't send cookie on toggle-only
|
||||
})
|
||||
row.is_transfer_enabled = newVal
|
||||
@@ -503,9 +503,9 @@ async function handleSave() {
|
||||
cloud_type: form.cloud_type as CloudType,
|
||||
nickname: form.nickname,
|
||||
promotion_account: form.promotion_account,
|
||||
is_transfer_enabled: form.is_transfer_enabled,
|
||||
is_transfer_enabled: form.is_transfer_enabled ? 1 : 0,
|
||||
cookie: form.cookie || undefined,
|
||||
is_active: true,
|
||||
is_active: 1,
|
||||
storage_used: form._storageUsed || undefined,
|
||||
storage_total: form._storageTotal || undefined,
|
||||
})
|
||||
@@ -515,9 +515,9 @@ async function handleSave() {
|
||||
cloud_type: form.cloud_type as CloudType,
|
||||
nickname: form.nickname,
|
||||
promotion_account: form.promotion_account,
|
||||
is_transfer_enabled: form.is_transfer_enabled,
|
||||
is_transfer_enabled: form.is_transfer_enabled ? 1 : 0,
|
||||
cookie: form.cookie,
|
||||
is_active: true,
|
||||
is_active: 1,
|
||||
storage_used: form._storageUsed || undefined,
|
||||
storage_total: form._storageTotal || undefined,
|
||||
})
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
</div>
|
||||
<div class="detail-cell" v-if="row.file_size">
|
||||
<span class="detail-label">文件大小</span>
|
||||
<code class="detail-code">{{ formatFileSize(row.file_size) }}</code>
|
||||
<code class="detail-code">{{ row.file_size ? (function(n){if(n==null||n==='')return'-';var v=typeof n==='string'?parseInt(n,10):n;if(!v||v<=0)return'-';var u=['B','KB','MB','GB','TB'];var i=0,s=v;while(s>=1024&&i<4){s/=1024;i++}return s.toFixed(i===0?0:2)+' '+u[i]})(row.file_size) : '-' }}</code>
|
||||
</div>
|
||||
<div class="detail-cell" v-if="row.status !== 'reused' && (row.folder_count > 0 || row.file_count > 0)">
|
||||
<span class="detail-label">文件夹</span>
|
||||
@@ -157,7 +157,13 @@
|
||||
<div class="detail-row" v-if="row.status === 'failed' && row.error_message">
|
||||
<div class="detail-cell detail-full">
|
||||
<span class="detail-label">错误信息</span>
|
||||
<pre class="detail-error">{{ row.error_message }}</pre>
|
||||
<pre class="detail-error">{{ row.error_message.includes(' | ') ? row.error_message.split(' | ')[1] : row.error_message.split(' | ')[0] }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-row" v-if="row.status === 'failed' && row.error_message && row.error_message.includes(' | ')">
|
||||
<div class="detail-cell detail-full">
|
||||
<span class="detail-label">友好提示</span>
|
||||
<pre class="detail-error">{{ row.error_message.split(' | ')[0] }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user