mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-25 13:45:03 +08:00
014a7c0e30
Split the 1446-line services/provider.rs into 5 focused modules: - gemini_auth.rs (250 lines): Gemini authentication type detection - PackyCode, Google OAuth, and generic provider detection - Security flag management for different auth types - live.rs (300 lines): Live configuration operations - LiveSnapshot backup/restore - Reading and writing live config files - Sync current provider to live config - usage.rs (150 lines): Usage script execution - Query and test usage scripts - Format usage results - Validate usage script configuration - endpoints.rs (80 lines): Custom endpoints management - CRUD operations for provider custom endpoints - Last-used timestamp tracking - mod.rs (650 lines): Core provider CRUD and service facade - ProviderService struct with all public methods - Provider add/update/delete/switch operations - Claude model key normalization - Credential extraction and validation All 107 tests pass. This improves maintainability by: - Separating concerns into cohesive modules - Making Gemini-specific logic easier to find and modify - Reducing cognitive load when working on specific features
99 lines
2.7 KiB
Rust
99 lines
2.7 KiB
Rust
//! Custom endpoints management
|
|
//!
|
|
//! Handles CRUD operations for provider custom endpoints.
|
|
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
|
|
use crate::app_config::AppType;
|
|
use crate::error::AppError;
|
|
use crate::settings::CustomEndpoint;
|
|
use crate::store::AppState;
|
|
|
|
/// Get custom endpoints list for a provider
|
|
pub fn get_custom_endpoints(
|
|
state: &AppState,
|
|
app_type: AppType,
|
|
provider_id: &str,
|
|
) -> Result<Vec<CustomEndpoint>, AppError> {
|
|
let providers = state.db.get_all_providers(app_type.as_str())?;
|
|
let Some(provider) = providers.get(provider_id) else {
|
|
return Ok(vec![]);
|
|
};
|
|
let Some(meta) = provider.meta.as_ref() else {
|
|
return Ok(vec![]);
|
|
};
|
|
if meta.custom_endpoints.is_empty() {
|
|
return Ok(vec![]);
|
|
}
|
|
|
|
let mut result: Vec<_> = meta.custom_endpoints.values().cloned().collect();
|
|
result.sort_by(|a, b| b.added_at.cmp(&a.added_at));
|
|
Ok(result)
|
|
}
|
|
|
|
/// Add a custom endpoint to a provider
|
|
pub fn add_custom_endpoint(
|
|
state: &AppState,
|
|
app_type: AppType,
|
|
provider_id: &str,
|
|
url: String,
|
|
) -> Result<(), AppError> {
|
|
let normalized = url.trim().trim_end_matches('/').to_string();
|
|
if normalized.is_empty() {
|
|
return Err(AppError::localized(
|
|
"provider.endpoint.url_required",
|
|
"URL 不能为空",
|
|
"URL cannot be empty",
|
|
));
|
|
}
|
|
|
|
state
|
|
.db
|
|
.add_custom_endpoint(app_type.as_str(), provider_id, &normalized)?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Remove a custom endpoint from a provider
|
|
pub fn remove_custom_endpoint(
|
|
state: &AppState,
|
|
app_type: AppType,
|
|
provider_id: &str,
|
|
url: String,
|
|
) -> Result<(), AppError> {
|
|
let normalized = url.trim().trim_end_matches('/').to_string();
|
|
state
|
|
.db
|
|
.remove_custom_endpoint(app_type.as_str(), provider_id, &normalized)?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Update endpoint last used timestamp
|
|
pub fn update_endpoint_last_used(
|
|
state: &AppState,
|
|
app_type: AppType,
|
|
provider_id: &str,
|
|
url: String,
|
|
) -> Result<(), AppError> {
|
|
let normalized = url.trim().trim_end_matches('/').to_string();
|
|
|
|
// Get provider, update last_used, save back
|
|
let mut providers = state.db.get_all_providers(app_type.as_str())?;
|
|
if let Some(provider) = providers.get_mut(provider_id) {
|
|
if let Some(meta) = provider.meta.as_mut() {
|
|
if let Some(endpoint) = meta.custom_endpoints.get_mut(&normalized) {
|
|
endpoint.last_used = Some(now_millis());
|
|
state.db.save_provider(app_type.as_str(), provider)?;
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Get current timestamp in milliseconds
|
|
fn now_millis() -> i64 {
|
|
SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap_or_default()
|
|
.as_millis() as i64
|
|
}
|