use http::Uri;
use hyper_rustls::HttpsConnectorBuilder;
use hyper_util::client::legacy::Client;
use hyper_util::rt::TokioExecutor;
use libdav::caldav::{FindCalendarHomeSet, FindCalendars, GetSupportedComponents};
use libdav::dav::{GetProperty, ListResources, WebDavClient};
use libdav::{CalDavClient, names};
use tower_http::auth::AddAuthorization;
#[tokio::main(flavor = "current_thread")]
async fn main() {
let mut arguments = std::env::args();
arguments
.next()
.expect("binary has been called with a name");
let base_url: Uri = arguments
.next()
.expect("$1 is defined")
.parse()
.expect("$1 is a valid URL");
let username = arguments.next().expect("$2 is a valid username");
let password = arguments.next().expect("$3 is a valid password");
let https_connector = HttpsConnectorBuilder::new()
.with_native_roots()
.expect("native TLS roots should be available")
.https_or_http()
.enable_http1()
.build();
let https_client = Client::builder(TokioExecutor::new()).build(https_connector);
let https_client = AddAuthorization::basic(https_client, &username, &password);
let webdav = WebDavClient::new(base_url, https_client);
let caldav_client = CalDavClient::bootstrap_via_service_discovery(webdav)
.await
.unwrap();
let urls = match caldav_client.find_current_user_principal().await.unwrap() {
Some(principal) => {
let home_set = caldav_client
.request(FindCalendarHomeSet::new(&principal))
.await
.unwrap()
.home_sets;
if home_set.is_empty() {
vec![caldav_client.base_url().clone()]
} else {
home_set
}
}
None => vec![caldav_client.base_url().clone()],
};
for url in urls {
let calendars = caldav_client
.request(FindCalendars::new(&url))
.await
.unwrap()
.calendars;
println!("found {} calendars...", calendars.len());
for calendar in calendars {
let name = caldav_client
.request(GetProperty::new(&calendar.href, &names::DISPLAY_NAME))
.await
.unwrap()
.value;
let color = caldav_client
.request(GetProperty::new(&calendar.href, &names::CALENDAR_COLOUR))
.await
.unwrap()
.value;
let comps = caldav_client
.request(GetSupportedComponents::new(&calendar.href))
.await
.unwrap()
.components;
let capabilities = if comps.is_empty() {
"(none advertised)".to_string()
} else {
comps
.iter()
.map(|c| c.as_str().to_string())
.collect::<Vec<_>>()
.join(", ")
};
println!(
"📅 name: {name:?}, colour: {color:?}, path: {:?}, etag: {:?}, capabilities: {}",
&calendar.href, &calendar.etag, capabilities
);
let items = caldav_client
.request(ListResources::new(&calendar.href))
.await
.unwrap()
.resources
.into_iter()
.filter(|i| !i.resource_type.is_collection);
for item in items {
println!(" {}, {}", item.href, item.etag.unwrap());
}
}
}
}