diff --git a/README.md b/README.md index bc5bb48..e91a064 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,8 @@ -Merges multiple ics files into one stream +todo -Try `cargo run -- ics-debug --tz America/New_York sample-data/nascar.ics sample-data/formula-1.ics` - -Expected output is the next month or so of NASCAR and Formula 1 racing: - -``` -2025-08-03 00:00:00 EDT - NASCAR Cup - Iowa Corn 350 -2025-08-03 00:00:00 EDT - F1 - Lenovo Hungarian Grand Prix -2025-08-10 00:00:00 EDT - NASCAR Cup - Go Bowling At The Glen (Watkins Glen) -2025-08-16 00:00:00 EDT - NASCAR Cup - Cook Out 400 (Richmond) -2025-08-23 00:00:00 EDT - NASCAR Cup - Coke Zero Sugar 400 (Daytona) -2025-08-31 00:00:00 EDT - NASCAR Cup -Playoff- Southern 500 (Darlington) -2025-08-31 00:00:00 EDT - F1 - Heineken Dutch Grand Prix -2025-09-07 00:00:00 EDT - NASCAR Cup -Playoff- Enjoy Illinois 300 (Gateway) -2025-09-07 00:00:00 EDT - F1 - Gran Premio d'Italia -2025-09-13 00:00:00 EDT - NASCAR Cup -Playoff- Bass Pro Shops Night Race (Bristol) -2025-09-21 00:00:00 EDT - F1 - Qatar Airways Azerbaijan Grand Prix -``` - -If the sample data is old, try the iCal links from , e.g. `curl https://calendar.google.com/calendar/ical/fa9bjl6tu13dd10b066stoo5do%40group.calendar.google.com/public/basic.ics > sample-data/formula-1.ics` +- [ ] Rewrite README considering best practices +- [ ] Add dynamic OpenGraph meta tags +- [ ] HTML templating for faster styling +- [ ] Maybe put descriptions behind `details` tag +- [ ] Publish ICS to subscribe to? +- [ ] systemd unit or something diff --git a/src/main.rs b/src/main.rs index ab092e7..44ff1a4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,7 @@ struct ConfigIcal { google_id: Option, /// A canonical webpage we can direct users to - html_url: url::Url, + html_url: Option, /// Very short name for putting on each event short_name: String, @@ -26,10 +26,16 @@ struct ConfigIcal { #[derive(Deserialize)] struct ConfigOutput { + /// Used as the OpenGraph description in meta tags + description: String, + /// Timezone to use for output (e.g. "Antarctica/South_Pole") /// /// timezone: chrono_tz::Tz, + + /// Used as the page title and OpenGraph title in meta tags + title: String, } #[derive(Deserialize)] @@ -359,7 +365,11 @@ fn process_data(data: &Data, now: DateTime) -> Result) -> Result<()> { +fn output_html( + config: &ConfigOutput, + instances: &[EventWithUrl], + now: DateTime, +) -> Result<()> { let today = now.date_naive(); let mut last_month_printed: Option = None; let mut last_date_printed = None; @@ -437,10 +447,16 @@ fn output_html(instances: &[EventWithUrl], now: DateTime) -> Resu li class="past" { (time) " - " (summary) } }); } else { + let calendar_link = if let Some(html_url) = &ei.calendar.html_url { + maud::html! { a href=(html_url) { (ei.calendar.short_name) } } + } else { + maud::html! { (ei.calendar.short_name)} + }; + day_list.push(maud::html! { li { p { (time) " - " (summary) } ul { - li { a href=(ei.calendar.html_url) { (ei.calendar.short_name) } } + li { (calendar_link) " calendar" } @if let Some(location) = location { li { "Location: " (location) } } @@ -476,12 +492,33 @@ fn output_html(instances: &[EventWithUrl], now: DateTime) -> Resu } "#; + + let description = &config.description; + let title = &config.title; + let s = maud::html! { - (maud::PreEscaped(css)) - h1 { "Wide-Angle Calendar" } - p { "Written at: " (now.to_rfc3339()) } - @for entry in html_list { - (entry) + html lang="en" { + head { + meta http-equiv="Content-Type" content="text/html; charset=utf-8" {} + meta name="viewport" content="width=device-width, initial-scale=1" {} + (maud::PreEscaped(css)) + + meta property="og:locale" content="en" {} + meta property="og:type" content="website" {} + + meta property="description" content=(description) {} + meta property="og:description" content=(description) {} + + title { (title) } + met property="og:title" content=(title) {} + } + body { + h1 { (title) } + p { "Written at: " (now.to_rfc3339()) } + @for entry in html_list { + (entry) + } + } } } .into_string(); @@ -525,10 +562,13 @@ async fn do_everything(cli: &CliAuto) -> Result<()> { let tz = &config.output.timezone; let now = Utc::now().with_timezone(tz); let instances = process_data(&data, now)?; - output_html(&instances, now)?; + output_html(&config.output, &instances, now)?; Ok(()) } +/// Seconds to sleep between auto cycles +const SLEEP_SECS: u64 = 9000; + fn main_auto(cli: CliAuto) -> Result<()> { tracing_subscriber::fmt::init(); loop { @@ -539,7 +579,7 @@ fn main_auto(cli: CliAuto) -> Result<()> { })?; rt.shutdown_timeout(Duration::from_secs(10)); tracing::info!("The service is eeping"); - std::thread::sleep(Duration::from_secs(5823)); + std::thread::sleep(Duration::from_secs(SLEEP_SECS)); } } @@ -552,7 +592,7 @@ fn main_ics_debug(cli: CliIcsDebug) -> Result<()> { let tz = &config.output.timezone; let now = Utc::now().with_timezone(tz); let instances = process_data(&data, now)?; - output_html(&instances, now)?; + output_html(&config.output, &instances, now)?; Ok(()) }