libdav 0.10.3

CalDAV and CardDAV client implementations.
Documentation
// Copyright 2024 Hugo Osvaldo Barrera
//
// SPDX-License-Identifier: ISC

//! An example of some basic usage of the `CalDavClient` type.
//!
//! This example uses no authentication.
//!
//! Usage:
//!
//!     cargo run --example=find_calendars_noauth https://example.com
//!     cargo run --example=find_calendars_noauth $SERVER_URL
use http::Uri;
use hyper_rustls::HttpsConnectorBuilder;
use hyper_util::client::legacy::Client;
use hyper_util::rt::TokioExecutor;
use libdav::caldav::{FindCalendarHomeSet, FindCalendars};
use libdav::dav::{GetProperty, ListResources, WebDavClient};
use libdav::{CalDavClient, names};

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let mut arguments = std::env::args();
    arguments.next().expect("arg0 must be defined");
    let base_url: Uri = arguments
        .next()
        .expect("Must specify a $1")
        .parse()
        .expect("$1 must be valid URL");

    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 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;
            println!(
                "📅 name: {name:?}, colour: {color:?}, path: {:?}, etag: {:?}",
                &calendar.href, &calendar.etag
            );
            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());
            }
        }
    }
}