mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-29 01:25:33 +08:00
fix: replace unsafe unwrap() calls with proper error handling
- database/dao/mcp.rs: Use map_err for serde_json serialization - database/dao/providers.rs: Use map_err for settings_config and meta serialization - commands/misc.rs: Use expect() for compile-time regex pattern - services/prompt.rs: Use unwrap_or_default() for SystemTime - deeplink/provider.rs: Replace unwrap() with is_none_or pattern for Option checks Reduces potential panic points from 26 to 1 (static regex init, safe).
This commit is contained in:
@@ -145,7 +145,8 @@ async fn fetch_npm_latest_version(client: &reqwest::Client, package: &str) -> Op
|
||||
/// 从版本输出中提取纯版本号
|
||||
fn extract_version(raw: &str) -> String {
|
||||
// 匹配 semver 格式: x.y.z 或 x.y.z-xxx
|
||||
let re = regex::Regex::new(r"\d+\.\d+\.\d+(-[\w.]+)?").unwrap();
|
||||
let re = regex::Regex::new(r"\d+\.\d+\.\d+(-[\w.]+)?")
|
||||
.expect("Invalid version regex pattern");
|
||||
re.find(raw)
|
||||
.map(|m| m.as_str().to_string())
|
||||
.unwrap_or_else(|| raw.to_string())
|
||||
|
||||
@@ -73,11 +73,13 @@ impl Database {
|
||||
params![
|
||||
server.id,
|
||||
server.name,
|
||||
serde_json::to_string(&server.server).unwrap(),
|
||||
serde_json::to_string(&server.server)
|
||||
.map_err(|e| AppError::Database(format!("Failed to serialize server config: {e}")))?,
|
||||
server.description,
|
||||
server.homepage,
|
||||
server.docs,
|
||||
serde_json::to_string(&server.tags).unwrap(),
|
||||
serde_json::to_string(&server.tags)
|
||||
.map_err(|e| AppError::Database(format!("Failed to serialize tags: {e}")))?,
|
||||
server.apps.claude,
|
||||
server.apps.codex,
|
||||
server.apps.gemini,
|
||||
|
||||
@@ -220,7 +220,8 @@ impl Database {
|
||||
WHERE id = ?13 AND app_type = ?14",
|
||||
params![
|
||||
provider.name,
|
||||
serde_json::to_string(&provider.settings_config).unwrap(),
|
||||
serde_json::to_string(&provider.settings_config)
|
||||
.map_err(|e| AppError::Database(format!("Failed to serialize settings_config: {e}")))?,
|
||||
provider.website_url,
|
||||
provider.category,
|
||||
provider.created_at,
|
||||
@@ -228,7 +229,8 @@ impl Database {
|
||||
provider.notes,
|
||||
provider.icon,
|
||||
provider.icon_color,
|
||||
serde_json::to_string(&meta_clone).unwrap(),
|
||||
serde_json::to_string(&meta_clone)
|
||||
.map_err(|e| AppError::Database(format!("Failed to serialize meta: {e}")))?,
|
||||
is_current,
|
||||
in_failover_queue,
|
||||
provider.id,
|
||||
@@ -247,7 +249,8 @@ impl Database {
|
||||
provider.id,
|
||||
app_type,
|
||||
provider.name,
|
||||
serde_json::to_string(&provider.settings_config).unwrap(),
|
||||
serde_json::to_string(&provider.settings_config)
|
||||
.map_err(|e| AppError::Database(format!("Failed to serialize settings_config: {e}")))?,
|
||||
provider.website_url,
|
||||
provider.category,
|
||||
provider.created_at,
|
||||
@@ -255,7 +258,8 @@ impl Database {
|
||||
provider.notes,
|
||||
provider.icon,
|
||||
provider.icon_color,
|
||||
serde_json::to_string(&meta_clone).unwrap(),
|
||||
serde_json::to_string(&meta_clone)
|
||||
.map_err(|e| AppError::Database(format!("Failed to serialize meta: {e}")))?,
|
||||
is_current,
|
||||
in_failover_queue,
|
||||
],
|
||||
@@ -324,7 +328,8 @@ impl Database {
|
||||
conn.execute(
|
||||
"UPDATE providers SET settings_config = ?1 WHERE id = ?2 AND app_type = ?3",
|
||||
params![
|
||||
serde_json::to_string(settings_config).unwrap(),
|
||||
serde_json::to_string(settings_config)
|
||||
.map_err(|e| AppError::Database(format!("Failed to serialize settings_config: {e}")))?,
|
||||
provider_id,
|
||||
app_type
|
||||
],
|
||||
|
||||
@@ -409,27 +409,26 @@ fn merge_claude_config(
|
||||
})?;
|
||||
|
||||
// Auto-fill API key if not provided in URL
|
||||
if request.api_key.is_none() || request.api_key.as_ref().unwrap().is_empty() {
|
||||
if request.api_key.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
if let Some(token) = env.get("ANTHROPIC_AUTH_TOKEN").and_then(|v| v.as_str()) {
|
||||
request.api_key = Some(token.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-fill endpoint if not provided in URL
|
||||
if request.endpoint.is_none() || request.endpoint.as_ref().unwrap().is_empty() {
|
||||
if request.endpoint.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
if let Some(base_url) = env.get("ANTHROPIC_BASE_URL").and_then(|v| v.as_str()) {
|
||||
request.endpoint = Some(base_url.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-fill homepage from endpoint if not provided
|
||||
if (request.homepage.is_none() || request.homepage.as_ref().unwrap().is_empty())
|
||||
&& request.endpoint.is_some()
|
||||
&& !request.endpoint.as_ref().unwrap().is_empty()
|
||||
{
|
||||
request.homepage = infer_homepage_from_endpoint(request.endpoint.as_ref().unwrap());
|
||||
if request.homepage.is_none() {
|
||||
request.homepage = Some("https://anthropic.com".to_string());
|
||||
if request.homepage.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
if let Some(endpoint) = request.endpoint.as_ref().filter(|s| !s.is_empty()) {
|
||||
request.homepage = infer_homepage_from_endpoint(endpoint);
|
||||
if request.homepage.is_none() {
|
||||
request.homepage = Some("https://anthropic.com".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,7 +467,7 @@ fn merge_codex_config(
|
||||
config: &serde_json::Value,
|
||||
) -> Result<(), AppError> {
|
||||
// Auto-fill API key from auth.OPENAI_API_KEY
|
||||
if request.api_key.is_none() || request.api_key.as_ref().unwrap().is_empty() {
|
||||
if request.api_key.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
if let Some(api_key) = config
|
||||
.get("auth")
|
||||
.and_then(|v| v.get("OPENAI_API_KEY"))
|
||||
@@ -483,7 +482,7 @@ fn merge_codex_config(
|
||||
// Parse TOML config string to extract base_url and model
|
||||
if let Ok(toml_value) = toml::from_str::<toml::Value>(config_str) {
|
||||
// Extract base_url from model_providers section
|
||||
if request.endpoint.is_none() || request.endpoint.as_ref().unwrap().is_empty() {
|
||||
if request.endpoint.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
if let Some(base_url) = extract_codex_base_url(&toml_value) {
|
||||
request.endpoint = Some(base_url);
|
||||
}
|
||||
@@ -499,13 +498,12 @@ fn merge_codex_config(
|
||||
}
|
||||
|
||||
// Auto-fill homepage from endpoint
|
||||
if (request.homepage.is_none() || request.homepage.as_ref().unwrap().is_empty())
|
||||
&& request.endpoint.is_some()
|
||||
&& !request.endpoint.as_ref().unwrap().is_empty()
|
||||
{
|
||||
request.homepage = infer_homepage_from_endpoint(request.endpoint.as_ref().unwrap());
|
||||
if request.homepage.is_none() {
|
||||
request.homepage = Some("https://openai.com".to_string());
|
||||
if request.homepage.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
if let Some(endpoint) = request.endpoint.as_ref().filter(|s| !s.is_empty()) {
|
||||
request.homepage = infer_homepage_from_endpoint(endpoint);
|
||||
if request.homepage.is_none() {
|
||||
request.homepage = Some("https://openai.com".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,13 +516,13 @@ fn merge_gemini_config(
|
||||
config: &serde_json::Value,
|
||||
) -> Result<(), AppError> {
|
||||
// Gemini uses flat env structure
|
||||
if request.api_key.is_none() || request.api_key.as_ref().unwrap().is_empty() {
|
||||
if request.api_key.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
if let Some(api_key) = config.get("GEMINI_API_KEY").and_then(|v| v.as_str()) {
|
||||
request.api_key = Some(api_key.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
if request.endpoint.is_none() || request.endpoint.as_ref().unwrap().is_empty() {
|
||||
if request.endpoint.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
if let Some(base_url) = config.get("GEMINI_BASE_URL").and_then(|v| v.as_str()) {
|
||||
request.endpoint = Some(base_url.to_string());
|
||||
}
|
||||
@@ -538,13 +536,12 @@ fn merge_gemini_config(
|
||||
}
|
||||
|
||||
// Auto-fill homepage from endpoint
|
||||
if (request.homepage.is_none() || request.homepage.as_ref().unwrap().is_empty())
|
||||
&& request.endpoint.is_some()
|
||||
&& !request.endpoint.as_ref().unwrap().is_empty()
|
||||
{
|
||||
request.homepage = infer_homepage_from_endpoint(request.endpoint.as_ref().unwrap());
|
||||
if request.homepage.is_none() {
|
||||
request.homepage = Some("https://ai.google.dev".to_string());
|
||||
if request.homepage.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
if let Some(endpoint) = request.endpoint.as_ref().filter(|s| !s.is_empty()) {
|
||||
request.homepage = infer_homepage_from_endpoint(endpoint);
|
||||
if request.homepage.is_none() {
|
||||
request.homepage = Some("https://ai.google.dev".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ impl PromptService {
|
||||
if !content_exists {
|
||||
let timestamp = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.unwrap_or_default()
|
||||
.as_secs() as i64;
|
||||
let backup_id = format!("backup-{timestamp}");
|
||||
let backup_prompt = Prompt {
|
||||
|
||||
Reference in New Issue
Block a user