app / src-tauri /src /models /account.rs
AZILS's picture
Upload 323 files
a21c316 verified
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use super::{token::TokenData, quota::QuotaData};
/// 账号数据结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Account {
pub id: String,
pub email: String,
pub name: Option<String>,
pub token: TokenData,
/// 可选的设备指纹,用于切换账号时固定机器信息
#[serde(default, skip_serializing_if = "Option::is_none")]
pub device_profile: Option<DeviceProfile>,
/// 设备指纹历史(生成/采集时记录),不含基线
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub device_history: Vec<DeviceProfileVersion>,
pub quota: Option<QuotaData>,
/// Disabled accounts are ignored by the proxy token pool (e.g. revoked refresh_token -> invalid_grant).
#[serde(default)]
pub disabled: bool,
/// Optional human-readable reason for disabling.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub disabled_reason: Option<String>,
/// Unix timestamp when the account was disabled.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub disabled_at: Option<i64>,
/// User manually disabled proxy feature (does not affect app usage).
#[serde(default)]
pub proxy_disabled: bool,
/// Optional human-readable reason for proxy disabling.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub proxy_disabled_reason: Option<String>,
/// Unix timestamp when the proxy was disabled.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub proxy_disabled_at: Option<i64>,
/// 受配额保护禁用的模型列表 [NEW #621]
#[serde(default, skip_serializing_if = "HashSet::is_empty")]
pub protected_models: HashSet<String>,
/// [NEW] 403 验证阻止状态 (VALIDATION_REQUIRED)
#[serde(default)]
pub validation_blocked: bool,
/// [NEW] 验证阻止截止时间戳
#[serde(default, skip_serializing_if = "Option::is_none")]
pub validation_blocked_until: Option<i64>,
/// [NEW] 验证阻止原因
#[serde(default, skip_serializing_if = "Option::is_none")]
pub validation_blocked_reason: Option<String>,
/// [NEW] 验证链接 URL (#1522)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub validation_url: Option<String>,
pub created_at: i64,
pub last_used: i64,
/// 绑定的代理 ID (None = 使用全局代理池)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub proxy_id: Option<String>,
/// 代理绑定时间
#[serde(default, skip_serializing_if = "Option::is_none")]
pub proxy_bound_at: Option<i64>,
/// 用户自定义标签
#[serde(default, skip_serializing_if = "Option::is_none")]
pub custom_label: Option<String>,
}
impl Account {
pub fn new(id: String, email: String, token: TokenData) -> Self {
let now = chrono::Utc::now().timestamp();
Self {
id,
email,
name: None,
token,
device_profile: None,
device_history: Vec::new(),
quota: None,
disabled: false,
disabled_reason: None,
disabled_at: None,
proxy_disabled: false,
proxy_disabled_reason: None,
proxy_disabled_at: None,
protected_models: HashSet::new(),
validation_blocked: false,
validation_blocked_until: None,
validation_blocked_reason: None,
validation_url: None,
created_at: now,
last_used: now,
proxy_id: None,
proxy_bound_at: None,
custom_label: None,
}
}
pub fn update_last_used(&mut self) {
self.last_used = chrono::Utc::now().timestamp();
}
pub fn update_quota(&mut self, quota: QuotaData) {
self.quota = Some(quota);
}
}
/// 账号索引数据(accounts.json)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccountIndex {
pub version: String,
pub accounts: Vec<AccountSummary>,
pub current_account_id: Option<String>,
}
/// 账号摘要信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccountSummary {
pub id: String,
pub email: String,
pub name: Option<String>,
#[serde(default)]
pub disabled: bool,
#[serde(default)]
pub proxy_disabled: bool,
/// 受保护的模型列表 [NEW] 供 UI 显示锁定图标
#[serde(default, skip_serializing_if = "HashSet::is_empty")]
pub protected_models: HashSet<String>,
pub created_at: i64,
pub last_used: i64,
}
impl AccountIndex {
pub fn new() -> Self {
Self {
version: "2.0".to_string(),
accounts: Vec::new(),
current_account_id: None,
}
}
}
impl Default for AccountIndex {
fn default() -> Self {
Self::new()
}
}
/// 设备指纹(storage.json 中 telemetry 相关字段)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceProfile {
pub machine_id: String,
pub mac_machine_id: String,
pub dev_device_id: String,
pub sqm_id: String,
}
/// 指纹历史版本
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceProfileVersion {
pub id: String,
pub created_at: i64,
pub label: String,
pub profile: DeviceProfile,
#[serde(default)]
pub is_current: bool,
}
/// 导出账号项(用于备份/迁移)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccountExportItem {
pub email: String,
pub refresh_token: String,
}
/// 导出账号响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccountExportResponse {
pub accounts: Vec<AccountExportItem>,
}