use crate::config::OpenProjectConfig; use crate::error::GeneralError; use crate::openproject::work::{WorkPackage, WorkPackageWriter}; use reqwest::Response; use serde::Deserialize; use std::error::Error; #[derive(Deserialize, Debug)] pub(crate) struct OpenProjectError { pub(crate) description: String, } impl From for OpenProjectError { fn from(value: reqwest::Error) -> Self { OpenProjectError { description: format!("Error while connecting to openproject instance: {}", value), } } } impl From for GeneralError { fn from(value: OpenProjectError) -> GeneralError { GeneralError { description: value.description, } } } pub(crate) struct Client { pub(crate) base_url: String, pub(crate) token: String, } pub async fn handle_response_status serde::Deserialize<'de>>( response: Response, error_message: &str, ) -> Result { if !response.status().is_success() { let status = response.status().to_string().clone(); let content = response .text() .await .unwrap_or_else(|_| "Impossible to decode".into()) .clone(); return Err(OpenProjectError { description: format!( "{}, status: {}, content: {}", error_message, status, content ), }); } let t = response.json::().await; match t { Ok(t) => Ok(t), Err(e) => Err(OpenProjectError { description: format!( "Error while decoding json: {}, source: {:?}", e.to_string(), e.source() ), }), } } impl Client { pub fn from_config(config: &OpenProjectConfig) -> Client { Client { base_url: config.base_url.clone(), token: config.token.clone(), } } pub async fn create_work_package( &self, work_package: &WorkPackageWriter, project_id: &String, ) -> Result { let client = reqwest::Client::new(); let response = client .post(format!( "{}/api/v3/projects/{}/work_packages", self.base_url, project_id )) .basic_auth("apikey", Some(&self.token)) .json(work_package) .send() .await?; let work_package = handle_response_status(response, "error while retrieving work package").await?; Ok(work_package) } }