fix: update function names and improve key loading logic in adapters
parent
3fd7bf0b00
commit
d7ef92684e
|
@ -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"
|
||||
|
|
10
README.md
10
README.md
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)?;
|
||||
|
|
Loading…
Reference in New Issue