// SPDX-FileCopyrightText: 2022 Matteo Settenvini // SPDX-License-Identifier: AGPL-3.0-or-later use { crate::config::Config, crate::constants, anyhow::anyhow, anyhow::Result, base64::write::EncoderWriter as Base64Encoder, reqwest::Url, std::io::Write, }; pub struct ApiClient { rest: reqwest::Client, agent: ureq::Agent, base_url: Url, caldav_base_url: Url, username: String, password: String, } impl ApiClient { pub fn new(server_name: &str, configuration: &Config) -> Result { let server = configuration .credentials .servers .get(server_name) .ok_or_else(|| { anyhow!( "Unknown server {}. Did you use '{} init' first? Known servers: {:#?}", server_name, env!("CARGO_BIN_NAME"), configuration.credentials.servers.keys().collect::>() ) })?; use reqwest::header; let mut default_headers = header::HeaderMap::new(); let mut auth_header = b"Basic ".to_vec(); { let mut encoder = Base64Encoder::new(&mut auth_header, base64::STANDARD); write!(encoder, "{}:{}", server.login_name, server.password).unwrap(); } let mut auth_header = header::HeaderValue::from_bytes(&auth_header)?; auth_header.set_sensitive(true); default_headers.insert(header::AUTHORIZATION, auth_header); let rest_client = reqwest::Client::builder() .user_agent(constants::USER_AGENT) .default_headers(default_headers) .build()?; let base_url = Url::parse(&server.url)?; let caldav_base_url = futures::executor::block_on( rest_client .head(base_url.join("/.well-known/caldav")?) .send(), )? .url() .clone(); Ok(ApiClient { base_url, caldav_base_url, username: server.login_name.clone(), password: server.password.clone(), rest: rest_client, agent: ureq::Agent::new(), }) } pub fn rest(&self) -> &reqwest::Client { &self.rest } pub fn base_url(&self) -> &Url { &self.base_url } pub fn username(&self) -> &str { &self.username } pub fn get_calendars( &self, ) -> core::result::Result, minicaldav::Error> { minicaldav::get_calendars( self.agent.clone(), self.username(), &self.password, &self.caldav_base_url, ) } pub fn get_events( &self, calendar: &minicaldav::Calendar, ) -> core::result::Result<(Vec, Vec), minicaldav::Error> { minicaldav::get_events( self.agent.clone(), self.username(), &self.password, calendar, ) } }