use crate::error::{Result, TwoCaptchaError};
use reqwest::{Client, Response, multipart::Form};
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct ApiClient {
post_url: String,
client: Client,
}
impl ApiClient {
pub fn new(post_url: Option<String>) -> Self {
let post_url = post_url.unwrap_or_else(|| "2captcha.com".to_string());
let client = Client::new();
Self { post_url, client }
}
pub async fn in_(
&self,
files: Option<HashMap<String, Vec<u8>>>,
params: HashMap<String, String>,
) -> Result<String> {
let url = format!("https://{}/in.php", self.post_url);
let response = if let Some(files) = files {
let mut form = Form::new();
for (key, value) in params {
form = form.text(key, value);
}
for (key, content) in files {
let part = reqwest::multipart::Part::bytes(content).file_name("file");
form = form.part(key, part);
}
self.client.post(&url).multipart(form).send().await?
} else if params.contains_key("file") {
let file_path = params.get("file").unwrap().clone();
let mut form_params = params.clone();
form_params.remove("file");
let file_content = tokio::fs::read(&file_path).await?;
let mut form = Form::new();
for (key, value) in form_params {
form = form.text(key, value);
}
let part = reqwest::multipart::Part::bytes(file_content).file_name("file");
form = form.part("file", part);
self.client.post(&url).multipart(form).send().await?
} else {
self.client.post(&url).form(¶ms).send().await?
};
self.handle_response(response).await
}
pub async fn res(&self, params: HashMap<String, String>) -> Result<String> {
let url = format!("https://{}/res.php", self.post_url);
let response = self.client.get(&url).query(¶ms).send().await?;
self.handle_response(response).await
}
async fn handle_response(&self, response: Response) -> Result<String> {
if response.status() != 200 {
return Err(TwoCaptchaError::Network(format!(
"bad response: {}",
response.status()
)));
}
let text = response.text().await?;
if text.contains("ERROR") {
return Err(TwoCaptchaError::Api(text));
}
Ok(text)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_api_client_creation() {
let client = ApiClient::new(None);
assert_eq!(client.post_url, "2captcha.com");
let client = ApiClient::new(Some("custom.domain.com".to_string()));
assert_eq!(client.post_url, "custom.domain.com");
}
}