Compare commits

...

2 commits

Author SHA1 Message Date
_
6daa02e8ad add context to some errors 2025-09-06 23:34:37 +00:00
_
5d56e8ecc0 can't recall what I was doing 2025-09-06 23:29:05 +00:00
2 changed files with 59 additions and 28 deletions

View file

@ -58,11 +58,15 @@ struct Config {
} }
impl Config { impl Config {
fn downloads(&self) -> impl Iterator<Item = SimpleDownload> { fn downloads(&self, now: DateTime<chrono_tz::Tz>) -> impl Iterator<Item = SimpleDownload> {
self.campfires self.campfires
.iter() .iter()
.map(|cf| cf.dl.clone()) .map(|cf| cf.dl.clone())
.chain(self.common_ninjas.iter().map(|cn| cn.simple_download())) .chain(
self.common_ninjas
.iter()
.map(move |cn| cn.simple_download(now)),
)
.chain(self.icals.iter().map(|ical| ical.dl.clone())) .chain(self.icals.iter().map(|ical| ical.dl.clone()))
} }
} }
@ -434,12 +438,14 @@ static APP_USER_AGENT: &str = concat!(
async fn do_everything(cli: &CliAuto) -> Result<()> { async fn do_everything(cli: &CliAuto) -> Result<()> {
let config = std::fs::read_to_string(&cli.config)?; let config = std::fs::read_to_string(&cli.config)?;
let config: Config = toml::from_str(&config)?; let config: Config = toml::from_str(&config)?;
let tz = &config.output.timezone;
let now = Utc::now().with_timezone(tz);
tracing::info!(?APP_USER_AGENT); tracing::info!(?APP_USER_AGENT);
let client = reqwest::Client::builder() let client = reqwest::Client::builder()
.user_agent(APP_USER_AGENT) .user_agent(APP_USER_AGENT)
.build()?; .build()?;
for dl in config.downloads() { for dl in config.downloads(now) {
let Some(download_url) = &dl.download_url else { let Some(download_url) = &dl.download_url else {
continue; continue;
}; };
@ -456,9 +462,6 @@ async fn do_everything(cli: &CliAuto) -> Result<()> {
} }
let data = read_data_from_disk(&config)?; let data = read_data_from_disk(&config)?;
let tz = &config.output.timezone;
let now = Utc::now().with_timezone(tz);
let instances = process_data(&data, &config.output, now)?; let instances = process_data(&data, &config.output, now)?;
output_html(&config.output, &instances, now)?; output_html(&config.output, &instances, now)?;
Ok(()) Ok(())
@ -484,15 +487,15 @@ fn main_auto(cli: CliAuto) -> Result<()> {
fn main_debug_output(cli: CliDebugOutput) -> Result<()> { fn main_debug_output(cli: CliDebugOutput) -> Result<()> {
tracing_subscriber::fmt::init(); tracing_subscriber::fmt::init();
tracing::info!("Started tracing"); tracing::info!("Started tracing");
let config = std::fs::read_to_string(&cli.config)?; let config = std::fs::read_to_string(&cli.config).context("Failed to read config file")?;
let config: Config = toml::from_str(&config)?; let config: Config = toml::from_str(&config).context("Failed to parse config file")?;
let data = read_data_from_disk(&config)?; let data = read_data_from_disk(&config).context("Failed to read data from disk")?;
let tz = &config.output.timezone; let tz = &config.output.timezone;
let now = Utc::now().with_timezone(tz); let now = Utc::now().with_timezone(tz);
let instances = process_data(&data, &config.output, now)?; let instances = process_data(&data, &config.output, now).context("Failed to process data")?;
output_html(&config.output, &instances, now)?; output_html(&config.output, &instances, now).context("Failed to output HTML")?;
Ok(()) Ok(())
} }

View file

@ -1,16 +1,17 @@
use super::{CalendarUi, EventInstance, Parameters, SimpleDownload}; use super::{CalendarUi, EventInstance, Parameters, SimpleDownload};
use crate::prelude::*; use crate::prelude::*;
use chrono::DateTime;
#[derive(Clone, Default, Deserialize)] #[derive(Clone, Deserialize)]
struct SillyDownloadable { struct SillyDownloadable {
/// URL to scrape to download the file from /// URL to scrape to download the file from
download_url: Option<Url>, download_url: Url,
/// Disk location to cache the file for debugging /// Disk location to cache the file for debugging
file_path: Utf8PathBuf, file_path: Utf8PathBuf,
} }
#[derive(Clone, Default, Deserialize)] #[derive(Clone, Deserialize)]
pub(crate) struct Config { pub(crate) struct Config {
#[serde(flatten)] #[serde(flatten)]
pub(crate) dl: SillyDownloadable, pub(crate) dl: SillyDownloadable,
@ -20,8 +21,15 @@ pub(crate) struct Config {
} }
impl Config { impl Config {
pub(crate) fn simple_download(&self) -> SimpleDownload { pub(crate) fn simple_download(&self, now: DateTime<chrono_tz::Tz>) -> SimpleDownload {
todo!() let date = now.format("%Y-%m-%d").to_string();
let mut url = self.dl.download_url.clone();
url.query_pairs_mut().append_pair("date", &date);
SimpleDownload {
download_url: Some(url),
file_path: self.dl.file_path.clone(),
}
} }
} }
@ -52,7 +60,7 @@ pub(crate) struct Calendar {
impl Calendar { impl Calendar {
fn to_event_instance(&self, params: &Parameters, ev: &Event) -> Result<Option<EventInstance>> { fn to_event_instance(&self, params: &Parameters, ev: &Event) -> Result<Option<EventInstance>> {
let dt = chrono::DateTime::from_timestamp_millis(ev.timestamp) let dt = DateTime::from_timestamp_millis(ev.timestamp)
.context("cannot represent timestamp as a date")? .context("cannot represent timestamp as a date")?
.with_timezone(&params.tz); .with_timezone(&params.tz);
let dtstart = crate::DatePerhapsTime { dt, all_day: false }; let dtstart = crate::DatePerhapsTime { dt, all_day: false };
@ -95,27 +103,47 @@ impl Calendar {
mod tests { mod tests {
use super::*; use super::*;
#[test] fn example_config() -> Config {
fn end_to_end() { Config {
let s = r#"
{"data":{"items":[{"timestamp":1748989800000,"durationInMinutes":90,"title":"Foo Bar","description":""},{"timestamp":1749999600000,"durationInMinutes":30,"title":"Snaf Oo","description":""}]},"success":true,"message":""}
"#;
let cfg = Config {
dl: SillyDownloadable { dl: SillyDownloadable {
download_url: None, download_url: Url::parse("https://www.commoninja.com/api/apps/calendar/get-monthly-events?widgetId=00000000-0000-0000-000000000000").unwrap(),
file_path: ".".into(), file_path: ".".into(),
}, },
ui: CalendarUi { ui: CalendarUi {
html_url: None, html_url: None,
short_name: "asdf".into(), short_name: "asdf".into(),
}, },
}; }
}
#[test]
fn end_to_end() {
let s = r#"
{"data":{"items":[{"timestamp":1748989800000,"durationInMinutes":90,"title":"Foo Bar","description":""},{"timestamp":1749999600000,"durationInMinutes":30,"title":"Snaf Oo","description":""}]},"success":true,"message":""}
"#;
let cfg = example_config();
let cal = Calendar::read_from_str(cfg, s).unwrap(); let cal = Calendar::read_from_str(cfg, s).unwrap();
let params = let params = Parameters::new(
Parameters::new(Utc::now().with_timezone(&chrono_tz::America::Chicago)).unwrap(); DateTime::from_timestamp(1748989700, 0)
.unwrap()
.with_timezone(&chrono_tz::America::Chicago),
)
.unwrap();
let instances = cal.event_instances(&params).unwrap(); let instances = cal.event_instances(&params).unwrap();
assert_eq!(instances.len(), 2); assert_eq!(instances.len(), 2);
} }
#[test]
fn unsillify() {
let dt = DateTime::from_timestamp(1756190298, 0)
.unwrap()
.with_timezone(&chrono_tz::America::Chicago);
let cfg = example_config();
assert_eq!(
cfg.simple_download(dt).download_url.unwrap().to_string(),
"https://www.commoninja.com/api/apps/calendar/get-monthly-events?widgetId=00000000-0000-0000-000000000000&date=2025-08-26"
);
}
} }