- Remove debug event limit to display all events - Add timezone information to event listing output - Update DEVELOPMENT.md with latest changes and debugging cycle documentation - Enhance event parsing with timezone support - Simplify CalDAV client structure and error handling Changes improve debugging capabilities for CalDAV event retrieval and provide better timezone visibility when listing calendar events.
228 lines
6.2 KiB
Rust
228 lines
6.2 KiB
Rust
//! Configuration management for CalDAV synchronizer
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use std::path::Path;
|
|
use anyhow::Result;
|
|
|
|
/// Main configuration structure
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Config {
|
|
/// Server configuration
|
|
pub server: ServerConfig,
|
|
/// Calendar configuration
|
|
pub calendar: CalendarConfig,
|
|
/// Filter configuration
|
|
pub filters: Option<FilterConfig>,
|
|
/// Sync configuration
|
|
pub sync: SyncConfig,
|
|
}
|
|
|
|
/// Server connection configuration
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ServerConfig {
|
|
/// CalDAV server URL
|
|
pub url: String,
|
|
/// Username for authentication
|
|
pub username: String,
|
|
/// Password for authentication
|
|
pub password: String,
|
|
/// Whether to use HTTPS
|
|
pub use_https: bool,
|
|
/// Timeout in seconds
|
|
pub timeout: u64,
|
|
/// Custom headers to send with requests
|
|
pub headers: Option<std::collections::HashMap<String, String>>,
|
|
}
|
|
|
|
/// Calendar-specific configuration
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct CalendarConfig {
|
|
/// Calendar name/path
|
|
pub name: String,
|
|
/// Calendar display name
|
|
pub display_name: Option<String>,
|
|
/// Calendar color
|
|
pub color: Option<String>,
|
|
/// Calendar timezone
|
|
pub timezone: String,
|
|
/// Whether to sync this calendar
|
|
pub enabled: bool,
|
|
}
|
|
|
|
/// Filter configuration for events
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct FilterConfig {
|
|
/// Start date filter (ISO 8601)
|
|
pub start_date: Option<String>,
|
|
/// End date filter (ISO 8601)
|
|
pub end_date: Option<String>,
|
|
/// Event types to include
|
|
pub event_types: Option<Vec<String>>,
|
|
/// Keywords to filter by
|
|
pub keywords: Option<Vec<String>>,
|
|
/// Exclude keywords
|
|
pub exclude_keywords: Option<Vec<String>>,
|
|
}
|
|
|
|
/// Synchronization configuration
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct SyncConfig {
|
|
/// Sync interval in seconds
|
|
pub interval: u64,
|
|
/// Whether to sync on startup
|
|
pub sync_on_startup: bool,
|
|
/// Maximum number of retries
|
|
pub max_retries: u32,
|
|
/// Retry delay in seconds
|
|
pub retry_delay: u64,
|
|
/// Whether to delete events not found on server
|
|
pub delete_missing: bool,
|
|
/// Date range configuration
|
|
pub date_range: DateRangeConfig,
|
|
}
|
|
|
|
/// Date range configuration for event synchronization
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct DateRangeConfig {
|
|
/// Number of days ahead to sync
|
|
pub days_ahead: i64,
|
|
/// Number of days in the past to sync
|
|
pub days_back: i64,
|
|
/// Whether to sync all events regardless of date
|
|
pub sync_all_events: bool,
|
|
}
|
|
|
|
impl Default for Config {
|
|
fn default() -> Self {
|
|
Self {
|
|
server: ServerConfig::default(),
|
|
calendar: CalendarConfig::default(),
|
|
filters: None,
|
|
sync: SyncConfig::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for ServerConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
url: "https://caldav.example.com".to_string(),
|
|
username: String::new(),
|
|
password: String::new(),
|
|
use_https: true,
|
|
timeout: 30,
|
|
headers: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for CalendarConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: "calendar".to_string(),
|
|
display_name: None,
|
|
color: None,
|
|
timezone: "UTC".to_string(),
|
|
enabled: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for SyncConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
interval: 300, // 5 minutes
|
|
sync_on_startup: true,
|
|
max_retries: 3,
|
|
retry_delay: 5,
|
|
delete_missing: false,
|
|
date_range: DateRangeConfig::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for DateRangeConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
days_ahead: 7, // Next week
|
|
days_back: 0, // Today only
|
|
sync_all_events: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Config {
|
|
/// Load configuration from a TOML file
|
|
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
|
|
let content = std::fs::read_to_string(path)?;
|
|
let config: Config = toml::from_str(&content)?;
|
|
Ok(config)
|
|
}
|
|
|
|
/// Save configuration to a TOML file
|
|
pub fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
|
|
let content = toml::to_string_pretty(self)?;
|
|
std::fs::write(path, content)?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Load configuration from environment variables
|
|
pub fn from_env() -> Result<Self> {
|
|
let mut config = Config::default();
|
|
|
|
if let Ok(url) = std::env::var("CALDAV_URL") {
|
|
config.server.url = url;
|
|
}
|
|
if let Ok(username) = std::env::var("CALDAV_USERNAME") {
|
|
config.server.username = username;
|
|
}
|
|
if let Ok(password) = std::env::var("CALDAV_PASSWORD") {
|
|
config.server.password = password;
|
|
}
|
|
if let Ok(calendar) = std::env::var("CALDAV_CALENDAR") {
|
|
config.calendar.name = calendar;
|
|
}
|
|
|
|
Ok(config)
|
|
}
|
|
|
|
/// Validate configuration
|
|
pub fn validate(&self) -> Result<()> {
|
|
if self.server.url.is_empty() {
|
|
anyhow::bail!("Server URL cannot be empty");
|
|
}
|
|
if self.server.username.is_empty() {
|
|
anyhow::bail!("Username cannot be empty");
|
|
}
|
|
if self.server.password.is_empty() {
|
|
anyhow::bail!("Password cannot be empty");
|
|
}
|
|
if self.calendar.name.is_empty() {
|
|
anyhow::bail!("Calendar name cannot be empty");
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_default_config() {
|
|
let config = Config::default();
|
|
assert_eq!(config.server.url, "https://caldav.example.com");
|
|
assert_eq!(config.calendar.name, "calendar");
|
|
assert_eq!(config.sync.interval, 300);
|
|
}
|
|
|
|
#[test]
|
|
fn test_config_validation() {
|
|
let mut config = Config::default();
|
|
assert!(config.validate().is_err()); // Empty username/password
|
|
|
|
config.server.username = "test".to_string();
|
|
config.server.password = "test".to_string();
|
|
assert!(config.validate().is_ok());
|
|
}
|
|
}
|