use reqwest::Method;
use serde_json::Value;
use crate::GeminiError;
#[derive(Debug, Clone)]
pub struct GeminiFile {
pub file_uri: String,
pub mime_type: String,
}
impl GeminiFile {
pub fn none() -> GeminiFile {
GeminiFile {
file_uri: "".to_string(),
mime_type: "".to_string(),
}
}
}
pub async fn upload_file<'a>(
image_path: &'a str,
mime_type: &'a str,
api_key: &'a str,
) -> Result<GeminiFile, GeminiError<'a>> {
let file = std::fs::File::open(image_path)?;
let file_size = file.metadata().unwrap().len();
let url = format!(
"https://generativelanguage.googleapis.com/upload/v1beta/files?key={0}",
api_key
);
let file_name = image_path
.split("/")
.last()
.unwrap()
.split_once(".")
.unwrap()
.0;
let data = r#"{"file": {"display_name": ""#.to_owned() + file_name + r#""}}"#;
let client = reqwest::Client::new();
let metadata_request = client
.request(Method::POST, &url)
.header("X-Goog-Upload-Protocol", "resumable")
.header("X-Goog-Upload-Command", "start")
.header("X-Goog-Upload-Header-Content-Length", file_size)
.header("X-Goog-Upload-Header-Content-Type", mime_type)
.header("Content-Type", "application/json")
.body(data)
.send()
.await
.unwrap();
let metadata_req_headers = metadata_request.headers();
let upload_url = metadata_req_headers
.get("x-goog-upload-url")
.unwrap()
.to_str()
.unwrap();
let _bytes_request = client
.request(Method::POST, upload_url)
.header("Content-Length", file_size)
.header("X-Goog-Upload-Offset", 0)
.header("X-Goog-Upload-Command", "upload, finalize")
.body(std::fs::read(image_path).unwrap())
.send()
.await;
let file_list_request = client
.request(
Method::GET,
format!(
"https://generativelanguage.googleapis.com/v1beta/files/?key={0}",
std::env::var("GEMINI_API_KEY").unwrap()
),
)
.send()
.await
.unwrap();
let files_list: Value = serde_json::from_str(&file_list_request.text().await.unwrap())?;
let files = files_list["files"].as_array().unwrap();
Ok(GeminiFile {
file_uri: files[0]["uri"].as_str().unwrap().to_string(),
mime_type: mime_type.to_string(),
})
}