use crate::Error;
use crate::Response;
const URL: &str = "https://api.imgbb.com/1/upload";
pub struct Uploader<'a> {
pub api_key: String,
pub data: Option<String>,
pub expiration: Option<u64>,
pub client: &'a reqwest::Client,
}
impl<'a> Uploader<'a> {
pub fn new<T>(api_key: T, client: &'a reqwest::Client) -> Self
where
T: Into<String>,
{
Self {
api_key: api_key.into(),
data: None,
expiration: None,
client,
}
}
pub fn expiration(&mut self, expiration: u64) -> &Self {
self.expiration = Some(expiration);
self
}
pub async fn upload(&self) -> Result<Response, Error> {
let mut query = vec![("key", self.api_key.as_str())];
let exp_str = self.expiration.as_ref().unwrap_or(&0).to_string();
if self.expiration.is_some() {
query.push(("expiration", exp_str.as_str()));
}
if self.data.is_none() {
return Err(Error::InvalidParameters("Missing image data".to_string()));
}
let form = [("image", self.data.as_ref().unwrap().as_str())];
let res = self.client
.post(URL)
.query(&query)
.form(&form)
.send()
.await?;
let status = res.status().as_u16();
let response: Response = res.json().await?;
if let Some(error) = response.error {
let error_code = error.code.unwrap_or(0);
let error_message = error.message.unwrap_or_else(|| "Unknown error".to_string());
return match error_code {
100 => Err(Error::InvalidApiKey),
120 => Err(Error::InvalidBase64Data),
313 => Err(Error::ImageTooLarge),
400 => Err(Error::InvalidParameters(error_message)),
401 => Err(Error::UnsupportedFormat),
429 => Err(Error::RateLimitExceeded),
_ => Err(Error::ApiError {
message: error_message,
status: Some(status),
code: Some(error_code),
}),
};
}
if response.success != Some(true) {
return Err(Error::ApiError {
message: "Upload failed without specific error".to_string(),
status: Some(status),
code: None,
});
}
Ok(response)
}
}