libdav 0.10.3

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

//! Example demonstrating the request-based API.
//!
//! Usage example of the Requests API to interact with a CalDAV server.

use http::Uri;
use hyper_rustls::HttpsConnectorBuilder;
use hyper_util::client::legacy::Client;
use hyper_util::rt::TokioExecutor;
use libdav::CalDavClient;
use libdav::caldav::{CalendarComponent, CreateCalendar};
use libdav::dav::{Delete, GetEtag, WebDavClient};
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");

    // Create HTTP client with TLS and authentication.
    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);

    // Bootstrap the CalDAV client.
    let caldav = CalDavClient::bootstrap_via_service_discovery(webdav)
        .await
        .expect("bootstrapping CalDAV client");

    println!("CalDAV server: {}", caldav.base_url());

    // Example part 1: create a calendar with the requests API.
    println!("\n=== Example 1: Creating a calendar ===");
    let calendar_path = format!(
        "/example-calendar-{}/",
        std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_secs()
    );

    match caldav
        .request(
            CreateCalendar::new(&calendar_path)
                .with_display_name("Example Calendar")
                .with_colour("#FF6B6B")
                .with_order(1)
                .with_components(&[CalendarComponent::VEvent, CalendarComponent::VTodo]),
        )
        .await
    {
        Ok(response) => {
            println!("Calendar created: {}", response.created);
            if let Some(etag) = response.etag {
                println!("   Etag: {etag}");
            }
        }
        Err(e) => {
            println!("Failed to create calendar: {e}");
            return;
        }
    }

    // Example part 2: get the etag of the newly created calendar.
    println!("\n=== Example 2: Getting calendar etag ===");
    match caldav.request(GetEtag::new(&calendar_path)).await {
        Ok(response) => {
            println!("Calendar etag: {}", response.etag);
        }
        Err(e) => {
            println!("Failed to get etag: {e}");
        }
    }

    // Cleanup: delete the example calendar.
    println!("\n=== Cleanup ===");
    match caldav.request(Delete::new(&calendar_path).force()).await {
        Ok(_) => println!("Example calendar deleted"),
        Err(e) => println!("Failed to delete calendar: {e}"),
    }
}