diff --git a/src/main.rs b/src/main.rs index 0189611..45e1320 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,6 +51,26 @@ impl Config { ) .chain(self.icals.iter().map(|ical| ical.dl.clone())) } + + fn upstreams(&self) -> Vec { + let Self { + campfires, + common_ninjas, + icals, + output: _, + } = self; + + let mut upstreams: Vec<_> = campfires + .iter() + .map(|cfg| &cfg.ui) + .cloned() + .chain(common_ninjas.iter().map(|cfg| &cfg.ui).cloned()) + .chain(icals.iter().map(|cfg| &cfg.ui).cloned()) + .collect(); + upstreams.sort_by_key(|ui| ui.short_name.clone()); + + upstreams + } } #[derive(clap::Parser)] @@ -238,7 +258,7 @@ async fn do_everything(cli: &CliAuto) -> Result<()> { let data = read_data_from_disk(&config)?; let instances = process_data(&data, &config.output, now)?; - output::write_html(&config.output, &instances, now)?; + output::write_html(&config.output, &config.upstreams(), &instances, now)?; Ok(()) } @@ -276,7 +296,8 @@ fn main_debug_output(cli: CliDebugOutput) -> Result<()> { let tz = &config.output.timezone; let now = Utc::now().with_timezone(tz); let instances = process_data(&data, &config.output, now).context("Failed to process data")?; - output::write_html(&config.output, &instances, now).context("Failed to output HTML")?; + output::write_html(&config.output, &config.upstreams(), &instances, now) + .context("Failed to output HTML")?; Ok(()) } diff --git a/src/output.rs b/src/output.rs index 49498c0..250cb08 100644 --- a/src/output.rs +++ b/src/output.rs @@ -5,6 +5,24 @@ use std::{collections::BTreeSet, io::Write as _}; use crate::{EventInstance, prelude::*}; +const CSS: &str = r#" + +"#; + #[derive(Deserialize)] pub(crate) struct Config { /// Used as the OpenGraph description in meta tags @@ -40,8 +58,17 @@ impl Config { } } +fn calendar_link(calendar_ui: &crate::CalendarUi) -> maud::PreEscaped { + if let Some(html_url) = &calendar_ui.html_url { + maud::html! { a href=(html_url) { (calendar_ui.short_name) } } + } else { + maud::html! { (calendar_ui.short_name)} + } +} + pub(crate) fn write_html( config: &Config, + upstreams: &[crate::CalendarUi], instances: &[EventInstance], now: DateTime, ) -> Result<()> { @@ -118,12 +145,6 @@ pub(crate) fn write_html( li class="past" { (time) " - " (summary) } }); } else { - let calendar_link = if let Some(html_url) = &ei.calendar_ui.html_url { - maud::html! { a href=(html_url) { (ei.calendar_ui.short_name) } } - } else { - maud::html! { (ei.calendar_ui.short_name)} - }; - // This is where the main stuff happens tracing::debug!(uid = ei.uid, summary = ei.summary); @@ -131,7 +152,7 @@ pub(crate) fn write_html( li { details { summary { (time) " - " (summary) } ul { - li { (calendar_link) " calendar" } + li { (calendar_link(&ei.calendar_ui)) " calendar" } @if let Some(location) = &ei.location { li { "Location: " (location) } } @@ -155,7 +176,49 @@ pub(crate) fn write_html( let final_path = "output/calendars.html"; let mut f = std::fs::File::create(temp_path)?; - f.write_all("".as_bytes())?; + let description = "A list of upstream calendars used by this Wide-Angle Calendar instance"; + let title = "Upstream calendars"; + + let s = maud::html! { + (maud::PreEscaped("")) + 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 name="description" content=(description) {} + meta property="description" content=(description) {} + meta property="og:description" content=(description) {} + + title { (title) } + met property="og:title" content=(title) {} + } + body { + h1 { (title) } + p { + a href="index.html" { "Wide-Angle Calendar" } + " / " + a href="calendars.html" { (title) } + } + + p { "Written at: " (now.format("%F %T")) } + p { "These are the calendars that Wide-Angle Calendar pulls from." } + + ol { + @for upstream in upstreams { + li { (calendar_link(upstream)) } + } + } + } + } + } + .into_string(); + + f.write_all(s.as_bytes())?; std::fs::rename(temp_path, final_path)?; } @@ -163,23 +226,6 @@ pub(crate) fn write_html( let temp_path = "output/index.html.tmp"; let final_path = "output/index.html"; let mut f = std::fs::File::create(temp_path)?; - let css = r#" - - "#; let description = &config.description; let title = &config.title; @@ -190,7 +236,7 @@ pub(crate) fn write_html( 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)) + (maud::PreEscaped(CSS)) meta property="og:locale" content="en" {} meta property="og:type" content="website" {} @@ -206,6 +252,7 @@ pub(crate) fn write_html( h1 { (title) } img src="hero.webp" width="700" height="233" {} p { "Written at: " (now.format("%F %T")) } + p { a href = "calendars.html" { "Upstream calendars" } } @for entry in html_list { (entry) } diff --git a/src/wac_campfire.rs b/src/wac_campfire.rs index 49e26ae..8520b21 100644 --- a/src/wac_campfire.rs +++ b/src/wac_campfire.rs @@ -19,11 +19,12 @@ pub(crate) struct Config { #[derive(Deserialize)] struct Event { - description: String, + #[serde(alias = "description")] + _description: String, #[serde(alias = "endDate")] - end_date: Option, + _end_date: Option, #[serde(alias = "endTime")] - end_time: Option, + _end_time: Option, #[serde(alias = "eventName")] event_name: String, location: String, diff --git a/src/wac_common_ninja.rs b/src/wac_common_ninja.rs index 05380d2..6a1d085 100644 --- a/src/wac_common_ninja.rs +++ b/src/wac_common_ninja.rs @@ -36,10 +36,11 @@ impl Config { #[derive(Deserialize)] struct Event { #[serde(alias = "durationInMinutes")] - duration_in_minutes: u32, + _duration_in_minutes: u32, timestamp: i64, title: String, - description: String, + #[serde(alias = "description")] + _description: String, } #[derive(Deserialize)]