fix: update function names and improve key loading logic in adapters

main
Yoo1tic 2025-08-09 07:50:02 +08:00
parent 3fd7bf0b00
commit d7ef92684e
7 changed files with 48 additions and 42 deletions

View File

@ -1,10 +1,9 @@
input_path = "keys.txt"
output_path = "output_keys.txt"
backup_path = "backup_keys.txt"
api_host = "https://generativelanguage.googleapis.com/"
timeout_sec = 20
max_retries = 2
concurrency = 30
concurrency = 50
proxy = "http://username:password@host:port"
enable_multiplexing = true
log_level = "info"

View File

@ -14,7 +14,7 @@ A high-performance tool to validate Google Gemini API keys with batch processing
### Download Pre-built Binaries
Download the latest release from [GitHub Releases](https://github.com/your-username/Gemini-Keychecker/releases):
Download the latest release from [GitHub Releases](https://github.com/Yoo1tic/Gemini-Keychecker/releases):
- **Linux**: `gemini-keychecker-linux-x86_64`
- **Windows**: `gemini-keychecker-windows-x86_64.exe`
@ -22,7 +22,7 @@ Download the latest release from [GitHub Releases](https://github.com/your-usern
### Build from Source
```bash
git clone https://github.com/your-username/Gemini-Keychecker.git
git clone https://github.com/Yoo1tic/Gemini-Keychecker.git
cd Gemini-Keychecker
cargo build --release
```
@ -39,6 +39,7 @@ cargo build --release
```
The tool will:
- Validate all API keys and create output files for valid keys
- Generate a backup file (`backup_keys.txt`) containing all processed keys
@ -53,7 +54,6 @@ The tool supports three configuration methods (in order of precedence):
Create a `Config.toml` file in the same directory. See `Config.toml.example` for reference.
### Command Line Options
```bash
@ -68,10 +68,10 @@ Options:
-h, --help Print help
```
### Examples
#### Basic Usage
```bash
# Use default settings
./gemini-keychecker
@ -84,6 +84,7 @@ Options:
```
#### Performance Tuning
```bash
# High concurrency for fast validation
./gemini-keychecker -c 100 -t 10
@ -93,6 +94,7 @@ Options:
```
#### Proxy Configuration
```bash
# HTTP proxy without authentication
./gemini-keychecker -x http://proxy.company.com:8080

View File

@ -1,36 +1,36 @@
use tracing::{error, warn};
use crate::adapters::output::write_keys_to_file;
use crate::error::ValidatorError;
use crate::types::GeminiKey;
use crate::error::Result;
use std::{collections::HashSet, fs, path::Path, str::FromStr};
/// Load and validate API keys from a file
/// Returns a vector of unique, valid API keys
pub fn load_keys(path: &Path) -> Result<Vec<GeminiKey>> {
pub fn load_keys_from_txt(path: &Path) -> Result<Vec<GeminiKey>, ValidatorError> {
let keys_txt = fs::read_to_string(path)?;
// Use HashSet to automatically deduplicate keys
let unique_keys_set: HashSet<&str> = keys_txt
let keys: Vec<GeminiKey> = keys_txt
.lines()
.map(|line| line.trim())
.filter(|line| !line.is_empty())
.filter_map(|line| {
let trimmed = line.trim();
(!trimmed.is_empty()).then_some(trimmed)
})
.collect::<HashSet<_>>()
.into_iter()
.filter_map(|key_str| match GeminiKey::from_str(key_str) {
Ok(api_key) => Some(api_key),
Err(e) => {
warn!("Skipping invalid key : {e}");
None
}
})
.collect();
let mut keys = Vec::new();
let mut valid_keys_for_backup = Vec::new();
for key_str in unique_keys_set {
match GeminiKey::from_str(key_str) {
Ok(api_key) => {
keys.push(api_key.clone());
valid_keys_for_backup.push(api_key.inner.clone());
}
Err(e) => eprintln!("Skipping invalid key: {}", e),
if !keys.is_empty() {
let valid_keys_for_backup: Vec<String> = keys.iter().map(|k| k.inner.clone()).collect();
if let Err(e) = write_keys_to_file(&valid_keys_for_backup, "backup.txt") {
error!("Failed to write backup file: {e}");
}
}
// Write validated keys to backup.txt
if let Err(e) = write_keys_to_file(&valid_keys_for_backup, "backup.txt") {
eprintln!("Failed to write backup file: {}", e);
}
Ok(keys)
}

View File

@ -1,5 +1,5 @@
pub mod input;
pub mod output;
pub use input::load_keys;
pub use output::write_validated_key_to_tier_files;
pub use input::load_keys_from_txt;
pub use output::write_validated_key_to_tier_files;

View File

@ -1,5 +1,5 @@
use crate::types::{GeminiKey, ValidatedKey, KeyTier};
use crate::error::Result;
use crate::error::ValidatorError;
use crate::types::{GeminiKey, KeyTier, ValidatedKey};
use std::{fs, io::Write};
use tokio::io::{AsyncWriteExt, BufWriter};
use toml::Value;
@ -10,20 +10,27 @@ pub async fn write_validated_key_to_tier_files(
free_file: &mut BufWriter<tokio::fs::File>,
paid_file: &mut BufWriter<tokio::fs::File>,
validated_key: &ValidatedKey,
) -> Result<()> {
) -> Result<(), ValidatorError> {
match validated_key.tier {
KeyTier::Free => {
free_file.write_all(format!("{}\n", validated_key.key.as_ref()).as_bytes()).await?;
free_file
.write_all(format!("{}\n", validated_key.key.as_ref()).as_bytes())
.await?;
}
KeyTier::Paid => {
paid_file.write_all(format!("{}\n", validated_key.key.as_ref()).as_bytes()).await?;
paid_file
.write_all(format!("{}\n", validated_key.key.as_ref()).as_bytes())
.await?;
}
}
Ok(())
}
// Write valid key to output file in Clewdr format
pub fn write_keys_clewdr_format(file: &mut fs::File, key: &GeminiKey) -> Result<()> {
pub fn write_keys_clewdr_format(
file: &mut fs::File,
key: &GeminiKey,
) -> Result<(), ValidatorError> {
let mut table = toml::value::Table::new();
table.insert("key".to_string(), Value::String(key.as_ref().to_string()));
@ -37,7 +44,7 @@ pub fn write_keys_clewdr_format(file: &mut fs::File, key: &GeminiKey) -> Result<
}
// Write keys to a text file with custom filename
pub fn write_keys_to_file(keys: &[String], filename: &str) -> Result<()> {
pub fn write_keys_to_file(keys: &[String], filename: &str) -> Result<(), ValidatorError> {
let content = keys.join("\n");
fs::write(filename, content)?;
info!("File '{}' created with {} keys", filename, keys.len());

View File

@ -18,7 +18,6 @@ struct Cli {
#[serde(skip_serializing_if = "Option::is_none")]
input_path: Option<PathBuf>,
#[arg(short = 'b', long)]
#[serde(skip_serializing_if = "Option::is_none")]
backup_path: Option<PathBuf>,
@ -50,7 +49,6 @@ pub struct KeyCheckerConfig {
#[serde(default)]
pub input_path: PathBuf,
// Backup file path for all API keys.
#[serde(default)]
pub backup_path: PathBuf,

View File

@ -1,5 +1,5 @@
use super::key_validator::{test_cache_content_api, test_generate_content_api};
use crate::adapters::{load_keys, write_validated_key_to_tier_files};
use crate::adapters::{load_keys_from_txt, write_validated_key_to_tier_files};
use crate::config::KeyCheckerConfig;
use crate::error::ValidatorError;
use crate::types::GeminiKey;
@ -102,7 +102,7 @@ pub async fn start_validation() -> Result<(), ValidatorError> {
let config = KeyCheckerConfig::load_config()?;
// 加载密钥
let keys = load_keys(config.input_path.as_path())?;
let keys = load_keys_from_txt(config.input_path.as_path())?;
// 构建HTTP客户端
let client = client_builder(&config)?;