|
|
|
|
@@ -33,6 +33,7 @@ export interface CloudConfig {
|
|
|
|
|
is_active: number;
|
|
|
|
|
promotion_account?: string;
|
|
|
|
|
is_transfer_enabled: number;
|
|
|
|
|
is_primary: number;
|
|
|
|
|
storage_used?: string;
|
|
|
|
|
storage_total?: string;
|
|
|
|
|
checkin_status: string; // 'none'|'success'|'failed'|'pending'|'skipped'
|
|
|
|
|
@@ -70,7 +71,7 @@ function extractQuarkUid(cookie: string): string | null {
|
|
|
|
|
export function getCloudConfigs(): CloudConfig[] {
|
|
|
|
|
const db = getDb();
|
|
|
|
|
return db.prepare(
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, storage_used, storage_total,
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, is_primary, storage_used, storage_total,
|
|
|
|
|
cloud_type_uid,
|
|
|
|
|
checkin_status, last_checkin_at, checkin_message, consecutive_failures,
|
|
|
|
|
last_used_at, total_saves, created_at, updated_at, verification_status
|
|
|
|
|
@@ -81,7 +82,7 @@ export function getCloudConfigs(): CloudConfig[] {
|
|
|
|
|
export function getAvailableClouds(): CloudConfig[] {
|
|
|
|
|
const db = getDb();
|
|
|
|
|
return db.prepare(
|
|
|
|
|
`SELECT id, cloud_type, nickname, is_active, promotion_account, is_transfer_enabled, storage_used, storage_total,
|
|
|
|
|
`SELECT id, cloud_type, nickname, is_active, promotion_account, is_transfer_enabled, is_primary, storage_used, storage_total,
|
|
|
|
|
cloud_type_uid,
|
|
|
|
|
checkin_status, last_checkin_at, checkin_message, consecutive_failures,
|
|
|
|
|
last_used_at, total_saves, created_at, updated_at
|
|
|
|
|
@@ -93,7 +94,7 @@ export function getAvailableClouds(): CloudConfig[] {
|
|
|
|
|
export function getCloudConfigByType(cloudType: string): CloudConfig | undefined {
|
|
|
|
|
const db = getDb();
|
|
|
|
|
return db.prepare(
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, storage_used, storage_total,
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, is_primary, storage_used, storage_total,
|
|
|
|
|
cloud_type_uid,
|
|
|
|
|
checkin_status, last_checkin_at, checkin_message, consecutive_failures,
|
|
|
|
|
last_used_at, total_saves, created_at, updated_at, verification_status
|
|
|
|
|
@@ -105,7 +106,7 @@ export function getCloudConfigByType(cloudType: string): CloudConfig | undefined
|
|
|
|
|
export function getCloudConfigById(id: number): CloudConfig | undefined {
|
|
|
|
|
const db = getDb();
|
|
|
|
|
return db.prepare(
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, storage_used, storage_total,
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, is_primary, storage_used, storage_total,
|
|
|
|
|
cloud_type_uid,
|
|
|
|
|
checkin_status, last_checkin_at, checkin_message, consecutive_failures,
|
|
|
|
|
last_used_at, total_saves, created_at, updated_at, verification_status
|
|
|
|
|
@@ -117,7 +118,7 @@ export function getCloudConfigById(id: number): CloudConfig | undefined {
|
|
|
|
|
export function getActiveCloudConfigs(): CloudConfig[] {
|
|
|
|
|
const db = getDb();
|
|
|
|
|
return db.prepare(
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, storage_used, storage_total,
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, is_primary, storage_used, storage_total,
|
|
|
|
|
cloud_type_uid,
|
|
|
|
|
checkin_status, last_checkin_at, checkin_message, consecutive_failures,
|
|
|
|
|
last_used_at, total_saves, created_at, updated_at
|
|
|
|
|
@@ -126,6 +127,31 @@ export function getActiveCloudConfigs(): CloudConfig[] {
|
|
|
|
|
).all() as CloudConfig[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Toggle the is_primary flag for a cloud config.
|
|
|
|
|
* Enforces max 2 primary accounts per cloud type.
|
|
|
|
|
*/
|
|
|
|
|
export function togglePrimary(id: number, setPrimary: boolean): CloudConfig {
|
|
|
|
|
const db = getDb();
|
|
|
|
|
const config = getCloudConfigById(id);
|
|
|
|
|
if (!config) throw new Error(`Cloud config ${id} not found`);
|
|
|
|
|
|
|
|
|
|
if (setPrimary) {
|
|
|
|
|
// Check how many primary accounts already exist for this cloud type
|
|
|
|
|
const primaryCount = db.prepare(
|
|
|
|
|
`SELECT COUNT(*) as c FROM cloud_configs WHERE cloud_type = ? AND is_primary = 1 AND id != ?`
|
|
|
|
|
).get(config.cloud_type, id) as { c: number };
|
|
|
|
|
if (primaryCount.c >= 2) {
|
|
|
|
|
throw new Error(`同类型网盘最多只能设置 2 个默认账号(已存在 ${primaryCount.c} 个)`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
db.prepare(`UPDATE cloud_configs SET is_primary = ?, updated_at = datetime('now', 'localtime') WHERE id = ?`)
|
|
|
|
|
.run(setPrimary ? 1 : 0, id);
|
|
|
|
|
|
|
|
|
|
return getCloudConfigById(id)!;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function saveCloudConfig(data: {
|
|
|
|
|
id?: number;
|
|
|
|
|
cloud_type: string;
|
|
|
|
|
@@ -199,7 +225,7 @@ export function saveCloudConfig(data: {
|
|
|
|
|
// Re-read savedId for return
|
|
|
|
|
const savedId = existing.id;
|
|
|
|
|
return db.prepare(
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, storage_used, storage_total,
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, is_primary, storage_used, storage_total,
|
|
|
|
|
cloud_type_uid,
|
|
|
|
|
checkin_status, last_checkin_at, checkin_message, consecutive_failures,
|
|
|
|
|
last_used_at, total_saves, created_at, updated_at
|
|
|
|
|
@@ -215,7 +241,7 @@ export function saveCloudConfig(data: {
|
|
|
|
|
|
|
|
|
|
const savedId = data.id || (db.prepare('SELECT last_insert_rowid() as id').get() as any).id;
|
|
|
|
|
return db.prepare(
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, storage_used, storage_total,
|
|
|
|
|
`SELECT id, cloud_type, cookie, nickname, is_active, promotion_account, is_transfer_enabled, is_primary, storage_used, storage_total,
|
|
|
|
|
cloud_type_uid,
|
|
|
|
|
checkin_status, last_checkin_at, checkin_message, consecutive_failures,
|
|
|
|
|
last_used_at, total_saves, created_at, updated_at
|
|
|
|
|
@@ -408,7 +434,7 @@ export async function getAndValidateCredential(cloudType: string, ipAddress?: st
|
|
|
|
|
`SELECT * FROM cloud_configs
|
|
|
|
|
WHERE cloud_type = ? AND is_active = 1
|
|
|
|
|
AND consecutive_failures < 5
|
|
|
|
|
ORDER BY last_used_at ASC NULLS FIRST
|
|
|
|
|
ORDER BY is_primary DESC, last_used_at ASC NULLS FIRST
|
|
|
|
|
LIMIT 1`
|
|
|
|
|
).get(cloudType) as CloudConfig | undefined;
|
|
|
|
|
} else {
|
|
|
|
|
@@ -429,12 +455,12 @@ export async function getAndValidateCredential(cloudType: string, ipAddress?: st
|
|
|
|
|
const ipTodayCount = ipCountRow?.total || 0;
|
|
|
|
|
|
|
|
|
|
if (ipTodayCount < 3) {
|
|
|
|
|
// First 2 saves — use the primary account (least recently used, healthy)
|
|
|
|
|
// First 2 saves — use a primary account (is_primary=1), fallback to any healthy
|
|
|
|
|
config = db.prepare(
|
|
|
|
|
`SELECT * FROM cloud_configs
|
|
|
|
|
WHERE cloud_type = ? AND is_active = 1
|
|
|
|
|
AND consecutive_failures < 5
|
|
|
|
|
ORDER BY last_used_at ASC NULLS FIRST
|
|
|
|
|
ORDER BY is_primary DESC, last_used_at ASC NULLS FIRST
|
|
|
|
|
LIMIT 1`
|
|
|
|
|
).get(cloudType) as CloudConfig | undefined;
|
|
|
|
|
} else {
|
|
|
|
|
@@ -464,7 +490,7 @@ export async function getAndValidateCredential(cloudType: string, ipAddress?: st
|
|
|
|
|
`SELECT * FROM cloud_configs
|
|
|
|
|
WHERE cloud_type = ? AND is_active = 1
|
|
|
|
|
AND consecutive_failures < 5
|
|
|
|
|
ORDER BY last_used_at ASC NULLS FIRST
|
|
|
|
|
ORDER BY is_primary DESC, last_used_at ASC NULLS FIRST
|
|
|
|
|
LIMIT 1`
|
|
|
|
|
).get(cloudType) as CloudConfig | undefined;
|
|
|
|
|
}
|
|
|
|
|
|