fix: update function names and improve key loading logic in adapters
parent
3fd7bf0b00
commit
d7ef92684e
|
@ -1,10 +1,9 @@
|
||||||
input_path = "keys.txt"
|
input_path = "keys.txt"
|
||||||
output_path = "output_keys.txt"
|
|
||||||
backup_path = "backup_keys.txt"
|
backup_path = "backup_keys.txt"
|
||||||
api_host = "https://generativelanguage.googleapis.com/"
|
api_host = "https://generativelanguage.googleapis.com/"
|
||||||
timeout_sec = 20
|
timeout_sec = 20
|
||||||
max_retries = 2
|
max_retries = 2
|
||||||
concurrency = 30
|
concurrency = 50
|
||||||
proxy = "http://username:password@host:port"
|
proxy = "http://username:password@host:port"
|
||||||
enable_multiplexing = true
|
enable_multiplexing = true
|
||||||
log_level = "info"
|
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 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`
|
- **Linux**: `gemini-keychecker-linux-x86_64`
|
||||||
- **Windows**: `gemini-keychecker-windows-x86_64.exe`
|
- **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
|
### Build from Source
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/your-username/Gemini-Keychecker.git
|
git clone https://github.com/Yoo1tic/Gemini-Keychecker.git
|
||||||
cd Gemini-Keychecker
|
cd Gemini-Keychecker
|
||||||
cargo build --release
|
cargo build --release
|
||||||
```
|
```
|
||||||
|
@ -39,6 +39,7 @@ cargo build --release
|
||||||
```
|
```
|
||||||
|
|
||||||
The tool will:
|
The tool will:
|
||||||
|
|
||||||
- Validate all API keys and create output files for valid keys
|
- Validate all API keys and create output files for valid keys
|
||||||
- Generate a backup file (`backup_keys.txt`) containing all processed 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.
|
Create a `Config.toml` file in the same directory. See `Config.toml.example` for reference.
|
||||||
|
|
||||||
|
|
||||||
### Command Line Options
|
### Command Line Options
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -68,10 +68,10 @@ Options:
|
||||||
-h, --help Print help
|
-h, --help Print help
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
#### Basic Usage
|
#### Basic Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Use default settings
|
# Use default settings
|
||||||
./gemini-keychecker
|
./gemini-keychecker
|
||||||
|
@ -84,6 +84,7 @@ Options:
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Performance Tuning
|
#### Performance Tuning
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# High concurrency for fast validation
|
# High concurrency for fast validation
|
||||||
./gemini-keychecker -c 100 -t 10
|
./gemini-keychecker -c 100 -t 10
|
||||||
|
@ -93,6 +94,7 @@ Options:
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Proxy Configuration
|
#### Proxy Configuration
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# HTTP proxy without authentication
|
# HTTP proxy without authentication
|
||||||
./gemini-keychecker -x http://proxy.company.com:8080
|
./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::adapters::output::write_keys_to_file;
|
||||||
|
use crate::error::ValidatorError;
|
||||||
use crate::types::GeminiKey;
|
use crate::types::GeminiKey;
|
||||||
use crate::error::Result;
|
|
||||||
use std::{collections::HashSet, fs, path::Path, str::FromStr};
|
use std::{collections::HashSet, fs, path::Path, str::FromStr};
|
||||||
|
|
||||||
/// Load and validate API keys from a file
|
pub fn load_keys_from_txt(path: &Path) -> Result<Vec<GeminiKey>, ValidatorError> {
|
||||||
/// Returns a vector of unique, valid API keys
|
|
||||||
pub fn load_keys(path: &Path) -> Result<Vec<GeminiKey>> {
|
|
||||||
let keys_txt = fs::read_to_string(path)?;
|
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()
|
.lines()
|
||||||
.map(|line| line.trim())
|
.filter_map(|line| {
|
||||||
.filter(|line| !line.is_empty())
|
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();
|
.collect();
|
||||||
|
|
||||||
let mut keys = Vec::new();
|
if !keys.is_empty() {
|
||||||
let mut valid_keys_for_backup = Vec::new();
|
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") {
|
||||||
for key_str in unique_keys_set {
|
error!("Failed to write backup file: {e}");
|
||||||
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),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
Ok(keys)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod output;
|
pub mod output;
|
||||||
|
|
||||||
pub use input::load_keys;
|
pub use input::load_keys_from_txt;
|
||||||
pub use output::write_validated_key_to_tier_files;
|
pub use output::write_validated_key_to_tier_files;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::types::{GeminiKey, ValidatedKey, KeyTier};
|
use crate::error::ValidatorError;
|
||||||
use crate::error::Result;
|
use crate::types::{GeminiKey, KeyTier, ValidatedKey};
|
||||||
use std::{fs, io::Write};
|
use std::{fs, io::Write};
|
||||||
use tokio::io::{AsyncWriteExt, BufWriter};
|
use tokio::io::{AsyncWriteExt, BufWriter};
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
|
@ -10,20 +10,27 @@ pub async fn write_validated_key_to_tier_files(
|
||||||
free_file: &mut BufWriter<tokio::fs::File>,
|
free_file: &mut BufWriter<tokio::fs::File>,
|
||||||
paid_file: &mut BufWriter<tokio::fs::File>,
|
paid_file: &mut BufWriter<tokio::fs::File>,
|
||||||
validated_key: &ValidatedKey,
|
validated_key: &ValidatedKey,
|
||||||
) -> Result<()> {
|
) -> Result<(), ValidatorError> {
|
||||||
match validated_key.tier {
|
match validated_key.tier {
|
||||||
KeyTier::Free => {
|
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 => {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write valid key to output file in Clewdr format
|
// 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();
|
let mut table = toml::value::Table::new();
|
||||||
table.insert("key".to_string(), Value::String(key.as_ref().to_string()));
|
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
|
// 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");
|
let content = keys.join("\n");
|
||||||
fs::write(filename, content)?;
|
fs::write(filename, content)?;
|
||||||
info!("File '{}' created with {} keys", filename, keys.len());
|
info!("File '{}' created with {} keys", filename, keys.len());
|
||||||
|
|
|
@ -18,7 +18,6 @@ struct Cli {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
input_path: Option<PathBuf>,
|
input_path: Option<PathBuf>,
|
||||||
|
|
||||||
|
|
||||||
#[arg(short = 'b', long)]
|
#[arg(short = 'b', long)]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
backup_path: Option<PathBuf>,
|
backup_path: Option<PathBuf>,
|
||||||
|
@ -50,7 +49,6 @@ pub struct KeyCheckerConfig {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub input_path: PathBuf,
|
pub input_path: PathBuf,
|
||||||
|
|
||||||
|
|
||||||
// Backup file path for all API keys.
|
// Backup file path for all API keys.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub backup_path: PathBuf,
|
pub backup_path: PathBuf,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::key_validator::{test_cache_content_api, test_generate_content_api};
|
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::config::KeyCheckerConfig;
|
||||||
use crate::error::ValidatorError;
|
use crate::error::ValidatorError;
|
||||||
use crate::types::GeminiKey;
|
use crate::types::GeminiKey;
|
||||||
|
@ -102,7 +102,7 @@ pub async fn start_validation() -> Result<(), ValidatorError> {
|
||||||
let config = KeyCheckerConfig::load_config()?;
|
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客户端
|
// 构建HTTP客户端
|
||||||
let client = client_builder(&config)?;
|
let client = client_builder(&config)?;
|
||||||
|
|
Loading…
Reference in New Issue