From 660367d8a37ba7dfdee6fdc74aaecd56eb8499b7 Mon Sep 17 00:00:00 2001 From: Yoo1tic <137816438+Yoo1tic@users.noreply.github.com> Date: Mon, 28 Jul 2025 19:06:37 +0800 Subject: [PATCH] feat: remove anyhow dependency and replace with custom error handling; update validation error types --- Cargo.lock | 7 ------- Cargo.toml | 1 - src/adapters/input/local.rs | 2 +- src/adapters/output/local.rs | 2 +- src/config/config.rs | 6 ++---- src/error.rs | 26 ++++++++++++++++++++++---- src/main.rs | 4 ++-- src/service/http_client.rs | 6 +++--- src/service/key_tester.rs | 6 +++--- src/service/validation.rs | 16 ++++++++-------- 10 files changed, 42 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f68f27a..5f71bd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,12 +76,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "anyhow" -version = "1.0.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" - [[package]] name = "async-stream" version = "0.3.6" @@ -387,7 +381,6 @@ dependencies = [ name = "gemini-keychecker" version = "0.1.0" dependencies = [ - "anyhow", "async-stream", "backon", "clap", diff --git a/Cargo.toml b/Cargo.toml index c673841..43a61b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] mimalloc = { version = "*" } -anyhow = "1.0" backon = "1" clap = { version = "4.5", features = ["derive"] } futures = "0.3" diff --git a/src/adapters/input/local.rs b/src/adapters/input/local.rs index 1f52f9a..b959653 100644 --- a/src/adapters/input/local.rs +++ b/src/adapters/input/local.rs @@ -1,6 +1,6 @@ use crate::adapters::output::write_keys_to_file; use crate::types::GeminiKey; -use anyhow::Result; +use crate::error::Result; use std::{collections::HashSet, fs, path::Path, str::FromStr}; /// Load and validate API keys from a file diff --git a/src/adapters/output/local.rs b/src/adapters/output/local.rs index bf9d62c..937fa2d 100644 --- a/src/adapters/output/local.rs +++ b/src/adapters/output/local.rs @@ -1,5 +1,5 @@ use crate::types::GeminiKey; -use anyhow::Result; +use crate::error::Result; use std::{fs, io::Write}; use tokio::io::{AsyncWriteExt, BufWriter}; use toml::Value; diff --git a/src/config/config.rs b/src/config/config.rs index ea344ae..cc3dae7 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use crate::error::ValidationError; use clap::Parser; use figment::{ Figment, @@ -85,7 +85,7 @@ impl Default for KeyCheckerConfig { } } impl KeyCheckerConfig { - pub fn load_config() -> Result { + pub fn load_config() -> Result { // Define the path to the configuration file static CONFIG_PATH: LazyLock = LazyLock::new(|| "Config.toml".into()); @@ -167,8 +167,6 @@ pub static TEST_MESSAGE_BODY: LazyLock = LazyLock::new(|| { }) }); - - fn default_api_host() -> Url { DEFAULT_CONFIG.api_host.clone() } diff --git a/src/error.rs b/src/error.rs index fb2090d..342538a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,13 +3,31 @@ use thiserror::Error; #[derive(Error, Debug)] pub enum ValidationError { #[error("HTTP error: {0}")] - HttpRequest(#[from] reqwest::Error), + ReqwestError(#[from] reqwest::Error), #[error("Key is unavailable or invalid")] - KeyUnavailable, - + KeyInvalid, + + #[error("IO error: {0}")] + Io(#[from] std::io::Error), + + #[error("Configuration error: {0}")] + ConfigError(#[from] figment::Error), + + #[error("TOML serialization error: {0}")] + TomlSer(#[from] toml::ser::Error), + + #[error("TOML deserialization error: {0}")] + TomlDe(#[from] toml::de::Error), + + #[error("JSON error: {0}")] + Json(#[from] serde_json::Error), + + #[error("URL parse error: {0}")] + UrlParse(#[from] url::ParseError), + #[error("Key validation failed: {0}")] - Invalid(String), + Validation(String), } pub type Result = std::result::Result; diff --git a/src/main.rs b/src/main.rs index 358cc45..4f089f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use gemini_keychecker::error::ValidationError; use gemini_keychecker::{BANNER, config::KeyCheckerConfig, service::start_validation}; use mimalloc::MiMalloc; @@ -8,7 +8,7 @@ static GLOBAL: MiMalloc = MiMalloc; /// Main function - displays banner and starts validation service #[tokio::main] -async fn main() -> Result<()> { +async fn main() -> Result<(), ValidationError> { // Display banner and configuration status at startup println!("{BANNER}"); diff --git a/src/service/http_client.rs b/src/service/http_client.rs index 456ea9b..9455f64 100644 --- a/src/service/http_client.rs +++ b/src/service/http_client.rs @@ -1,8 +1,8 @@ -use crate::config::KeyCheckerConfig; +use crate::{config::KeyCheckerConfig, error::ValidationError}; use reqwest::Client; use std::time::Duration; -pub fn client_builder(config: &KeyCheckerConfig) -> Result { +pub fn client_builder(config: &KeyCheckerConfig) -> Result { // Set the maximum number of connections per host based on concurrency. let pool_size = config.concurrency / 2; @@ -18,5 +18,5 @@ pub fn client_builder(config: &KeyCheckerConfig) -> Result Ok(api_key), StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN - | StatusCode::TOO_MANY_REQUESTS => Err(ValidationError::KeyUnavailable), - _ => Err(ValidationError::HttpRequest( + | StatusCode::TOO_MANY_REQUESTS => Err(ValidationError::KeyInvalid), + _ => Err(ValidationError::ReqwestError( response.error_for_status().unwrap_err(), )), } } - Err(e) => Err(ValidationError::HttpRequest(e)), + Err(e) => Err(ValidationError::ReqwestError(e)), } } diff --git a/src/service/validation.rs b/src/service/validation.rs index 0b64ecb..c9c7f84 100644 --- a/src/service/validation.rs +++ b/src/service/validation.rs @@ -1,12 +1,12 @@ -use anyhow::Result; +use crate::error::ValidationError; use async_stream::stream; use futures::{pin_mut, stream::StreamExt}; use reqwest::Client; use std::time::Instant; use tokio::{fs, io::AsyncWriteExt, sync::mpsc}; -use super::{key_tester::validate_key, http_client::client_builder}; -use crate::adapters::{write_keys_txt_file, load_keys}; +use super::{http_client::client_builder, key_tester::validate_key}; +use crate::adapters::{load_keys, write_keys_txt_file}; use crate::config::KeyCheckerConfig; use crate::types::GeminiKey; @@ -26,7 +26,7 @@ impl ValidationService { } } - pub async fn validate_keys(&self, keys: Vec) -> Result<()> { + pub async fn validate_keys(&self, keys: Vec) -> Result<(), ValidationError> { let start_time = Instant::now(); // Create channel for streaming keys from producer to consumer @@ -74,15 +74,15 @@ impl ValidationService { } /// 启动验证服务 - 封装了所有启动逻辑 -pub async fn start_validation() -> Result<()> { +pub async fn start_validation() -> Result<(), ValidationError> { let config = KeyCheckerConfig::load_config()?; - + // 加载密钥 let keys = load_keys(config.input_path.as_path())?; - + // 构建HTTP客户端 let client = client_builder(&config)?; - + // 创建验证服务并启动 let validation_service = ValidationService::new(config, client); validation_service.validate_keys(keys).await