use anyhow::{Context, Result}; use klog_types::{BatchFilesRequest, FilesMetaResponse}; use crate::config::Config; pub struct KlogClient { base_url: String, token: String, client: reqwest::Client, } impl KlogClient { pub fn new(config: &Config) -> Self { Self { base_url: config.url.trim_end_matches('/').to_string(), token: config.token.clone(), client: reqwest::Client::new(), } } pub async fn list_files(&self) -> Result { Ok(self .client .get(format!("{}/admin/files", self.base_url)) .bearer_auth(&self.token) .send() .await? .error_for_status()? .json::() .await?) } pub async fn get_files(&self, req: &BatchFilesRequest) -> Result> { Ok(self .client .post(format!("{}/admin/files/get", self.base_url)) .bearer_auth(&self.token) .json(req) .send() .await? .error_for_status()? .bytes() .await? .to_vec()) } pub async fn upload_file(&self, path: &std::path::Path) -> Result { let filename = path .file_name() .context("Invalid path: no filename")? .to_string_lossy() .to_string(); let data = tokio::fs::read(path).await?; let part = reqwest::multipart::Part::bytes(data).file_name(filename); let form = reqwest::multipart::Form::new().part("file", part); Ok(self .client .post(format!("{}/files", self.base_url)) .bearer_auth(&self.token) .multipart(form) .send() .await? .error_for_status()? .json::() .await?) } pub async fn delete_files(&self, req: &BatchFilesRequest) -> Result { Ok(self .client .delete(format!("{}/admin/files", self.base_url)) .bearer_auth(&self.token) .json(req) .send() .await? .error_for_status()? .json::() .await?) } }